* Managed.Windows.Forms/System.Windows.Forms/HtmlDocument.cs,
[mono.git] / mcs / docs / compiler.txt
index 330d8a7977b598d365c93e2e7cc96ee9eed08a15..275ff0d9566b0dc5f24843b643d27103f40ec7af 100755 (executable)
        All errors must be reported during the resolution phase
        (DoResolve) and if an error is detected the DoResolve method
        will return null which is used to flag that an error condition
-       has ocurred, this will be used to stop compilation later on.
+       has occurred, this will be used to stop compilation later on.
        This means that anyone that calls Expression.Resolve must
        check the return value for null which would indicate an error
        condition.
 
        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
+       result of the semantic analysis phase for lambda expressions (more
        information in the "Lambda Expressions" section).
 
        But what is important is that expressions and statements that are
 
 ** Statements
 
+*** Invariant meaning in a block
+
+       The seemingly small section in the standard entitled
+       "invariant meaning in a block" has several subtleties
+       involved, especially when we try to implement the semantics
+       efficiently.
+
+       Most of the semantics are trivial, and basically prevent local
+       variables from shadowing parameters and other local variables.
+       However, this notion is not limited to that, but affects all
+       simple name accesses within a block.  And therein lies the rub
+       -- instead of just worrying about the issue when we arrive at
+       variable declarations, we need to verify this property at
+       every use of a simple name within a block.
+
+       The key notion that helps us is to note the bi-directional
+       action of a variable declaration.  The declaration together
+       with anti-shadowing rules can maintain the IMiaB property for
+       the block containing the declaration and all nested sub
+       blocks.  But, the IMiaB property also forces all surrounding
+       blocks to avoid using the name.  We thus need to maintain a
+       blacklist of taboo names in all surrounding blocks -- and we
+       take the expedient of doing so simply: actually maintaining a
+       (superset of the) blacklist in each block data structure, which
+       we call the 'known_variable' list.
+
+       Because we create the 'known_variable' list during the parse
+       process, by the time we do simple name resolution, all the
+       blacklists are fully populated.  So, we can just enforce the
+       rest of the IMiaB property by looking up a couple of lists.
+
+       This turns out to be quite efficient: when we used a block
+       tree walk, a test case took 5-10mins, while with this simple
+       mildly-redundant data structure, the time taken for the same
+       test case came down to a couple of seconds.
+
+       The IKnownVariable interface is a small wrinkle.  Firstly, the
+       IMiaB also applies to parameter names, especially those of
+       anonymous methods.  Secondly, we need more information than
+       just the name in the blacklist -- we need the location of the
+       name and where it's declared.  We use the IKnownVariable
+       interface to abstract out the parser information stored for
+       local variables and parameters.
+
 * The semantic analysis 
 
        Hence, the compiler driver has to parse all the input files.
                        Foo (x => x + 1)
 
 
-       One of the problems that am facing with lambda expressions is
+       One of the problems that we faced with lambda expressions is
        that lambda expressions need to be "probed" with different
        types until a working combination is found.
 
        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.
+       To compile this, we need to hook into the resolution process,
+       but since the resolution process has side effects (calling
+       Resolve can either return instances of the resolved expression
+       type, or can alter field internals) it was necessary to
+       incorporate a framework to "clone" expressions before we
+       probe.
+
+       The support for cloning was added into Statements and
+       Expressions and is only necessary for objects of those types
+       that are created during parsing.   It is not necessary to
+       support these in the classes that are the result of calling
+       Resolve.   This means that SimpleName needs support for
+       Cloning, but FieldExpr does not need it (SimpleName is created
+       by the parser, FieldExpr is created during semantic analysis
+       resolution).   
+
+       The work happens through the public method called "Clone" that
+       clones the given Statement or Expression.  The base method in
+       Statement and Expression merely does a MemberwiseCopy of the
+       elements and then calls the virtual CloneTo method to complete
+       the copy.    By default this method throws an exception, this
+       is useful to catch cases where we forgot to override CloneTo
+       for a given Statement/Expression. 
+
+       With the cloning capability it became possible to call resolve
+       multiple times (once for each Cloned copy) and based on this
+       picking the one implementation that would compile and that
+       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
        implicitly converted to the given delegate type.
 
        And also happens as a result of the generic method parameter
-       type inferrencing. 
+       type inferencing. 
 
 ** Lambda Expressions and Cloning
 
        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