Add some docs on the lambda stuff
[mono.git] / mcs / docs / compiler.txt
index 388cb17588e0571f8e601eec361a112a0a6b516e..06e993ec2de1a031af101cfd219dcb5b8074f3aa 100755 (executable)
@@ -2,7 +2,7 @@
        
                                Miguel de Icaza
                              (miguel@ximian.com)
-                                     2002
+                                  2002, 2007
 
 * Abstract
 
        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
        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
        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
        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.
        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