Author: miguel
Date: 2007-05-07 00:50:19 -0400 (Mon, 07 May 2007)
New Revision: 76806

Modified:
   trunk/mcs/docs/compiler.txt
Log:
Add some docs on the lambda stuff

Modified: trunk/mcs/docs/compiler.txt
===================================================================
--- trunk/mcs/docs/compiler.txt 2007-05-07 03:25:10 UTC (rev 76805)
+++ trunk/mcs/docs/compiler.txt 2007-05-07 04:50:19 UTC (rev 76806)
@@ -2,7 +2,7 @@
        
                                Miguel de Icaza
                              ([EMAIL PROTECTED])
-                                     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

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to