diff options
Diffstat (limited to 'mcs/docs')
-rwxr-xr-x | mcs/docs/compiler.txt | 149 |
1 files changed, 141 insertions, 8 deletions
diff --git a/mcs/docs/compiler.txt b/mcs/docs/compiler.txt index 388cb17588e..06e993ec2de 100755 --- a/mcs/docs/compiler.txt +++ b/mcs/docs/compiler.txt @@ -2,7 +2,7 @@ Miguel de Icaza (miguel@ximian.com) - 2002 + 2002, 2007 * Abstract @@ -323,12 +323,25 @@ represents the "expression classification" (from the C# specs) and the type of the expression. - Expressions have to be resolved before they are can be used. + During parsing, the compiler will create the various trees of + expressions. These expressions have to be resolved before they + are can be used. The semantic analysis is implemented by + resolving each of the expressions created during parsing and + creating fully resolved expressions. + + A common pattern that you will notice in the compiler is this: + + Expression expr; + ... + + expr = expr.Resolve (ec); + if (expr == null) + // There was an error, stop processing by returning + The resolution process is implemented by overriding the - `DoResolve' method. The DoResolve method has to set the - `eclass' field and the `type', perform all error checking and - computations that will be required for code generation at this - stage. + `DoResolve' method. The DoResolve method has to set the `eclass' + field and the `type', perform all error checking and computations + that will be required for code generation at this stage. The return value from DoResolve is an expression. Most of the time an Expression derived class will return itself (return @@ -358,6 +371,18 @@ the Expression class. No error checking must be performed during this stage. + We take advantage of the distinction between the expressions that + are generated by the parser and the expressions that are the + result of the semantic analysis phase for lambda expresions (more + information in the "Lambda Expressions" section). + + But what is important is that expressions and statements that are + generated by the parser should implement the cloning + functionality. This is used lambda expressions require the + compiler to attempt to resolve a given block of code with + different possible types for parameters that have their types + implicitly inferred. + ** Simple Names, MemberAccess One of the most important classes in the compiler is @@ -398,7 +423,6 @@ things like SimpleNames and does a different kind of error checking than the one used by regular expressions. - ** Constants Constants in the Mono C# compiler are represented by the @@ -620,6 +644,92 @@ A detailed description of anonymous methods and iterators is on the new-anonymous-design.txt file in this directory. +* Lambda Expressions + + One of the problems that am facing with lambda expressions is + that lambda expressions need to be "probed" with different + types until a working combination is found. + + For example: + + x => x.i + + The above expression could mean vastly different things depending + on the type of "x". The compiler determines the type of "x" (left + hand side "x") at the moment the above expression is "bound", + which means that during the compilation process it will try to + match the above lambda with all the possible types available, for + example: + + delegate int di (int x); + delegate string ds (string s); + .. + Foo (di x) {} + Foo (ds x) {} + ... + Foo (x => "string") + + In the above example, overload resolution will try "x" as an "int" + and will try "x" as a string. And if one of them "compiles" thats + the one it picks (and it also copes with ambiguities if there was + more than one matching method). + + To support this, we extended the compiler to support "cloning" + blocks of code (ToplevelBlocks, Blocks, Statements, Expressions) + doing a complete pass at resolving the expression and picking the + one that would compile and would not be ambiguous. + + The cloning process is basically a deep copy that happens in the + LambdaExpression class and it clones the top-level block for the + lambda expression. The cloning has the side effect of cloning + the entire containing block as well. + + This happens inside this method: + + public override bool ImplicitStandardConversionExists (Type delegate_type) + + This is used to determine if the current Lambda expression can be + implicitly converted to the given delegate type. + + And also happens as a result of the generic method parameter + type inferrencing. + +** Lambda Expressions and Cloning + + All statements that are created during the parsing method should + implement the CloneTo method: + + protected virtual void CloneTo (CloneContext clonectx, Statement target) + + This method is called by the Statement.Clone method after it has + done a shallow-copy of all the fields in the statement, and they + should typically Clone any child statements. + + Expressions should implement the CloneTo method as well: + + protected virtual void CloneTo (CloneContext clonectx, Expression target) + +** Lambda Expressions and Contextual Return + + When an expression is parsed as a lambda expression, the parser + inserts a call to a special statement, the contextual return. + + The expression: + + a => a+1 + + Is actually compiled as: + + a => contextual_return (a+1) + + The contextual_return statement will behave differently depending + on the return type of the delegate that the expression will be + converted to. + + If the delegate return type is void, the above will basically turn + into an empty operation. Otherwise the above will become + a return statement that can infer return types. + * Miscellaneous ** Error Processing. @@ -669,7 +779,30 @@ You can use this with -warnaserror to obtain the same effect with warnings. +* Debugging the Parser. + + A useful trick while debugging the parser is to pass the -v + command line option to the compiler. + + The -v command line option will dump the various Yacc states + as well as the tokens that are being returned from the + tokenizer to the compiler. + + This is useful when tracking down problems when the compiler + is not able to parse an expression correctly. + + You can match the states reported with the contents of the + y.output file, a file that contains the parsing tables and + human-readable information about the generated parser. + * Editing the compiler sources The compiler sources are intended to be edited with 134 columns of width -
\ No newline at end of file + +* Quick Hacks + + Once you have a full build of mcs, you can improve your + development time by just issuing make in the `mcs' directory or + using `make qh' in the gmcs directory. + +
\ No newline at end of file |