Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs/docs
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@gnome.org>2007-05-07 08:50:19 +0400
committerMiguel de Icaza <miguel@gnome.org>2007-05-07 08:50:19 +0400
commitfd317528caefd7b1c9177902a180a6c047354eef (patch)
tree87473f442dac42194767d3799859459660fe0c2d /mcs/docs
parentb3c1ae398b38a1c754695566959f98b442fb8aa3 (diff)
Add some docs on the lambda stuff
svn path=/trunk/mcs/; revision=76806
Diffstat (limited to 'mcs/docs')
-rwxr-xr-xmcs/docs/compiler.txt149
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