2004-10-17 Miguel de Icaza <miguel@ximian.com>
authorMiguel de Icaza <miguel@gnome.org>
Tue, 26 Oct 2004 23:14:11 +0000 (23:14 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Tue, 26 Oct 2004 23:14:11 +0000 (23:14 -0000)
* expression.cs (LocalVariableReference.DoResolveBase, Emit):
Remove the tests for `ec.RemapToProxy' from here, and encapsulate
all of this information into
EmitContext.EmitCapturedVariableInstance.

* codegen.cs (EmitCapturedVariableInstance): move here the
funcionality of emitting an ldarg.0 in the presence of a
remapping.   This centralizes the instance emit code.

(EmitContext.EmitThis): If the ScopeInfo contains a THIS field,
then emit a load of this: it means that we have reached the
topmost ScopeInfo: the one that contains the pointer to the
instance of the class hosting the anonymous method.

* anonymous.cs (AddField, HaveCapturedFields): Propagate field
captures to the topmost CaptureContext.

2004-10-12  Miguel de Icaza  <miguel@ximian.com>

* expression.cs (LocalVariableReference): Move the knowledge about
the iterators into codegen's EmitCapturedVariableInstance.

2004-10-11  Miguel de Icaza  <miguel@ximian.com>

* codegen.cs (EmitContext.ResolveTopBlock): Emit a 1643 when not
all code paths return a value from an anonymous method (it is the
same as the 161 error, but for anonymous methods).

2004-10-08  Miguel de Icaza  <miguel@ximian.com>

The introduction of anonymous methods in the compiler changed
various ways of doing things in the compiler.  The most
significant one is the hard split between the resolution phase
and the emission phases of the compiler.

For instance, routines that referenced local variables no
longer can safely create temporary variables during the
resolution phase: they must do so from the emission phase,
since the variable might have been "captured", hence access to
it can not be done with the local-variable operations from the runtime.

* statement.cs

(Block.Flags): New flag `IsTopLevel' to indicate that this block
is a toplevel block.

(ToplevelBlock): A new kind of Block, these are the blocks that
are created by the parser for all toplevel method bodies.  These
include methods, accessors and anonymous methods.

These contain some extra information not found in regular blocks:
A pointer to an optional CaptureContext (for tracking captured
local variables and parameters).  A pointer to the parent
ToplevelBlock.

(Return.Resolve): Catch missmatches when returning a value from an
anonymous method (error 1662).
Invoke NeedReturnLabel from the Resolve phase instead of the emit
phase.

(Break.Resolve): ditto.

(SwitchLabel): instead of defining the labels during the
resolution phase, we now turned the public ILLabel and ILLabelCode
labels into methods called GetILLabelCode() and GetILLabel() that
only define the label during the Emit phase.

(GotoCase): Track the SwitchLabel instead of the computed label
(its contained therein).  Emit the code by using
SwitchLabel.GetILLabelCode ().

(LocalInfo.Flags.Captured): A new flag has been introduce to track
whether the Local has been captured or not.

(LocalInfo.IsCaptured): New property, used to tell whether the
local has been captured.

* anonymous.cs: Vastly updated to contain the anonymous method
support.

The main classes here are: CaptureContext which tracks any
captured information for a toplevel block and ScopeInfo used to
track the activation frames for various local variables.

Each toplevel block has an optional capture context associated
with it.  When a method contains an anonymous method both the
toplevel method and the anonymous method will create a capture
context.   When variables or parameters are captured, they are
recorded on the CaptureContext that owns them, for example:

void Demo () {
     int a;
     MyDelegate d = delegate {
         a = 1;
     }
}

Here `a' will be recorded as captured on the toplevel
CapturedContext, the inner captured context will not have anything
(it will only have data if local variables or parameters from it
are captured in a nested anonymous method.

The ScopeInfo is used to track the activation frames for local
variables, for example:

for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++){
   MyDelegate d = delegate {
    call (i, j);
   }
}

At runtime this captures a single captured variable `i', but it
captures 10 different versions of the variable `j'.  The variable
`i' will be recorded on the toplevel ScopeInfo, while `j' will be
recorded on a child.

The toplevel ScopeInfo will also track information like the `this'
pointer if instance variables were referenced (this is necessary
as the anonymous method lives inside a nested class in the host
type of the method).

(AnonymousMethod): Expanded to track the Toplevel, implement
`AnonymousMethod.Compatible' to tell whether an anonymous method
can be converted to a target delegate type.

The routine now also produces the anonymous method content

(AnonymousDelegate): A helper class that derives from
DelegateCreation, this is used to generate the code necessary to
produce the delegate for the anonymous method that was created.

* assign.cs: API adjustments for new changes in
Convert.ImplicitStandardConversionExists.

* class.cs: Adjustments to cope with the fact that now toplevel
blocks are of type `ToplevelBlock'.

* cs-parser.jay: Now we produce ToplevelBlocks for toplevel blocks
insteda of standard blocks.

Flag errors if params arguments are passed to anonymous methods.

* codegen.cs (EmitContext): Replace `InAnonymousMethod' with
`CurrentAnonymousMethod' which points to the current Anonymous
Method.  The variable points to the AnonymousMethod class that
holds the code being compiled.  It is set in the new EmitContext
created for the anonymous method.

(EmitContext.Phase): Introduce a variable and an enumeration to
assist in enforcing some rules about when and where we are allowed
to invoke certain methods (EmitContext.NeedsReturnLabel is the
only one that enfonces this right now).

(EmitContext.HaveCaptureInfo): new helper method that returns
whether we have a CapturedContext initialized.

(EmitContext.CaptureVariable): New method used to register that a
LocalInfo must be flagged for capturing.

(EmitContext.CapturedParameter): New method used to register that a
parameters must be flagged for capturing.

(EmitContext.CapturedField): New method used to register that a
field must be flagged for capturing.

(EmitContext.HaveCapturedVariables,
EmitContext.HaveCapturedFields): Return whether there are captured
variables or fields.

(EmitContext.EmitMethodHostInstance): This is used to emit the
instance for the anonymous method.  The instance might be null
(static methods), this (for anonymous methods that capture nothing
and happen to live side-by-side with the current method body) or a
more complicated expression if the method has a CaptureContext.

(EmitContext.EmitTopBlock): Routine that drives the emission of
code: it will first resolve the top block, then emit any metadata
and then emit the code.  The split is done so that we can extract
any anonymous methods and flag any captured variables/parameters.

(EmitContext.ResolveTopBlock): Triggers the resolution phase,
during this phase, the ILGenerator should not be used as labels
and local variables declared here might not be accessible to any
code that is part of an anonymous method.

Exceptions to this include the temporary variables that are
created by some statements internally for holding temporary
variables.

(EmitContext.EmitMeta): New routine, in charge of emitting all the
metadata for a cb

(EmitContext.TemporaryReturn): This method is typically called
from the Emit phase, and its the only place where we allow the
ReturnLabel to be defined other than the EmitMeta.  The reason is
that otherwise we would have to duplicate a lot of logic in the
Resolve phases of various methods that today is on the Emit
phase.

(EmitContext.NeedReturnLabel): This no longer creates the label,
as the ILGenerator is not valid during the resolve phase.

(EmitContext.EmitThis): Extended the knowledge in this class to
work in anonymous methods in addition to iterators.

(EmitContext.EmitCapturedVariableInstance): This emits whatever
code is necessary on the stack to access the instance to a local
variable (the variable will be accessed as a field).

(EmitContext.EmitParameter, EmitContext.EmitAssignParameter,
EmitContext.EmitAddressOfParameter): Routines to support
parameters (not completed at this point).

Removals: Removed RemapLocal and RemapLocalLValue.  We probably
will also remove the parameters.

* convert.cs (Convert): Define a `ConstantEC' which points to a
null.  This is just to prefity some code that uses
ImplicitStandardConversion code and do not have an EmitContext
handy.

The idea is to flag explicitly that at that point in time, it is
known that the conversion will not trigger the delegate checking
code in implicit conversions (which requires a valid
EmitContext).

Everywhere: pass new EmitContext parameter since
ImplicitStandardConversionExists now requires it to check for
anonymous method conversions.

(Convert.ImplicitStandardConversionExists): If the type of an
expression is the anonymous_method_type, and the type is a
delegate, we invoke the AnonymousMethod.Compatible method to check
whether an implicit conversion is possible.

(Convert.ImplicitConversionStandard): Only do implicit method
group conversions if the language level is not ISO_1.

* delegate.cs (Delegate.GetInvokeMethod): Common method to get the
MethodInfo for the Invoke method.  used by Delegate and
AnonymousDelegate.

* expression.cs (Binary.DoNumericPromotions): only allow anonymous
method conversions if the target type is a delegate.

Removed extra debugging nops.

(LocalVariableReference): Turn the `local_info' into a public
field.

Add `prepared' field, the same hack used for FieldExprs to cope
with composed assignments, as Local variables do not necessarily
operate purely on the stack as they used to: they can be captured
fields.

Add `temp' for a temporary result, like fields.

Refactor DoResolve and DoResolveLValue into DoResolveBase.

It now copes with Local variables that are captured and emits the
proper instance variable to load it from a field in the captured
case.

(ParameterReference.DoResolveBase): During the resolve phase,
capture parameters if we are in an anonymous method.

(ParameterReference.Emit, ParameterReference.AddressOf): If in an
anonymous method, use the EmitContext helper routines to emit the
parameter reference.

* iterators.cs: Set RemapToProxy to true/false during the
EmitDispose class.

* parameters.cs (GetParameterByName): New helper method.

* typemanager.cs (anonymous_method_type) a new type that
represents an anonyous method.  This is always an internal type,
used as a fencepost to test against the anonymous-methodness of an
expression.

svn path=/trunk/mcs/; revision=35340

16 files changed:
mcs/mcs/ChangeLog
mcs/mcs/TODO
mcs/mcs/anonymous.cs
mcs/mcs/assign.cs
mcs/mcs/class.cs
mcs/mcs/codegen.cs
mcs/mcs/const.cs
mcs/mcs/convert.cs
mcs/mcs/cs-parser.jay
mcs/mcs/delegate.cs
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/iterators.cs
mcs/mcs/parameter.cs
mcs/mcs/statement.cs
mcs/mcs/typemanager.cs

index 2522683ccde08aca4ef27bc0122aea2c5cbb7f7b..7817d7528d7c70c9cf7daa5d8de4ba082ce7bbc4 100755 (executable)
@@ -1,3 +1,286 @@
+2004-10-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (LocalVariableReference.DoResolveBase, Emit):
+       Remove the tests for `ec.RemapToProxy' from here, and encapsulate
+       all of this information into
+       EmitContext.EmitCapturedVariableInstance.
+       
+       * codegen.cs (EmitCapturedVariableInstance): move here the
+       funcionality of emitting an ldarg.0 in the presence of a
+       remapping.   This centralizes the instance emit code.
+
+       (EmitContext.EmitThis): If the ScopeInfo contains a THIS field,
+       then emit a load of this: it means that we have reached the
+       topmost ScopeInfo: the one that contains the pointer to the
+       instance of the class hosting the anonymous method.
+
+       * anonymous.cs (AddField, HaveCapturedFields): Propagate field
+       captures to the topmost CaptureContext.
+
+2004-10-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (LocalVariableReference): Move the knowledge about
+       the iterators into codegen's EmitCapturedVariableInstance.
+
+2004-10-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (EmitContext.ResolveTopBlock): Emit a 1643 when not
+       all code paths return a value from an anonymous method (it is the
+       same as the 161 error, but for anonymous methods).
+
+2004-10-08  Miguel de Icaza  <miguel@ximian.com>
+
+       The introduction of anonymous methods in the compiler changed
+       various ways of doing things in the compiler.  The most
+       significant one is the hard split between the resolution phase
+       and the emission phases of the compiler.
+
+       For instance, routines that referenced local variables no
+       longer can safely create temporary variables during the
+       resolution phase: they must do so from the emission phase,
+       since the variable might have been "captured", hence access to
+       it can not be done with the local-variable operations from the runtime.
+       
+       * statement.cs 
+
+       (Block.Flags): New flag `IsTopLevel' to indicate that this block
+       is a toplevel block.
+
+       (ToplevelBlock): A new kind of Block, these are the blocks that
+       are created by the parser for all toplevel method bodies.  These
+       include methods, accessors and anonymous methods.
+
+       These contain some extra information not found in regular blocks:
+       A pointer to an optional CaptureContext (for tracking captured
+       local variables and parameters).  A pointer to the parent
+       ToplevelBlock.
+       
+       (Return.Resolve): Catch missmatches when returning a value from an
+       anonymous method (error 1662).
+       Invoke NeedReturnLabel from the Resolve phase instead of the emit
+       phase.
+
+       (Break.Resolve): ditto.
+
+       (SwitchLabel): instead of defining the labels during the
+       resolution phase, we now turned the public ILLabel and ILLabelCode
+       labels into methods called GetILLabelCode() and GetILLabel() that
+       only define the label during the Emit phase.
+
+       (GotoCase): Track the SwitchLabel instead of the computed label
+       (its contained therein).  Emit the code by using
+       SwitchLabel.GetILLabelCode ().
+
+       (LocalInfo.Flags.Captured): A new flag has been introduce to track
+       whether the Local has been captured or not.
+
+       (LocalInfo.IsCaptured): New property, used to tell whether the
+       local has been captured.
+       
+       * anonymous.cs: Vastly updated to contain the anonymous method
+       support.
+
+       The main classes here are: CaptureContext which tracks any
+       captured information for a toplevel block and ScopeInfo used to
+       track the activation frames for various local variables.   
+
+       Each toplevel block has an optional capture context associated
+       with it.  When a method contains an anonymous method both the
+       toplevel method and the anonymous method will create a capture
+       context.   When variables or parameters are captured, they are
+       recorded on the CaptureContext that owns them, for example:
+
+       void Demo () {
+            int a;
+            MyDelegate d = delegate {
+                a = 1;
+            }
+       }
+
+       Here `a' will be recorded as captured on the toplevel
+       CapturedContext, the inner captured context will not have anything
+       (it will only have data if local variables or parameters from it
+       are captured in a nested anonymous method.
+
+       The ScopeInfo is used to track the activation frames for local
+       variables, for example:
+
+       for (int i = 0; i < 10; i++)
+               for (int j = 0; j < 10; j++){
+                  MyDelegate d = delegate {
+                       call (i, j);
+                  }
+               }
+
+       At runtime this captures a single captured variable `i', but it
+       captures 10 different versions of the variable `j'.  The variable
+       `i' will be recorded on the toplevel ScopeInfo, while `j' will be
+       recorded on a child.  
+
+       The toplevel ScopeInfo will also track information like the `this'
+       pointer if instance variables were referenced (this is necessary
+       as the anonymous method lives inside a nested class in the host
+       type of the method). 
+
+       (AnonymousMethod): Expanded to track the Toplevel, implement
+       `AnonymousMethod.Compatible' to tell whether an anonymous method
+       can be converted to a target delegate type. 
+
+       The routine now also produces the anonymous method content
+
+       (AnonymousDelegate): A helper class that derives from
+       DelegateCreation, this is used to generate the code necessary to
+       produce the delegate for the anonymous method that was created. 
+
+       * assign.cs: API adjustments for new changes in
+       Convert.ImplicitStandardConversionExists.
+
+       * class.cs: Adjustments to cope with the fact that now toplevel
+       blocks are of type `ToplevelBlock'. 
+
+       * cs-parser.jay: Now we produce ToplevelBlocks for toplevel blocks
+       insteda of standard blocks.
+
+       Flag errors if params arguments are passed to anonymous methods.
+
+       * codegen.cs (EmitContext): Replace `InAnonymousMethod' with
+       `CurrentAnonymousMethod' which points to the current Anonymous
+       Method.  The variable points to the AnonymousMethod class that
+       holds the code being compiled.  It is set in the new EmitContext
+       created for the anonymous method.
+
+       (EmitContext.Phase): Introduce a variable and an enumeration to
+       assist in enforcing some rules about when and where we are allowed
+       to invoke certain methods (EmitContext.NeedsReturnLabel is the
+       only one that enfonces this right now).
+
+       (EmitContext.HaveCaptureInfo): new helper method that returns
+       whether we have a CapturedContext initialized.
+
+       (EmitContext.CaptureVariable): New method used to register that a
+       LocalInfo must be flagged for capturing. 
+
+       (EmitContext.CapturedParameter): New method used to register that a
+       parameters must be flagged for capturing. 
+       
+       (EmitContext.CapturedField): New method used to register that a
+       field must be flagged for capturing. 
+
+       (EmitContext.HaveCapturedVariables,
+       EmitContext.HaveCapturedFields): Return whether there are captured
+       variables or fields. 
+
+       (EmitContext.EmitMethodHostInstance): This is used to emit the
+       instance for the anonymous method.  The instance might be null
+       (static methods), this (for anonymous methods that capture nothing
+       and happen to live side-by-side with the current method body) or a
+       more complicated expression if the method has a CaptureContext.
+
+       (EmitContext.EmitTopBlock): Routine that drives the emission of
+       code: it will first resolve the top block, then emit any metadata
+       and then emit the code.  The split is done so that we can extract
+       any anonymous methods and flag any captured variables/parameters.
+       
+       (EmitContext.ResolveTopBlock): Triggers the resolution phase,
+       during this phase, the ILGenerator should not be used as labels
+       and local variables declared here might not be accessible to any
+       code that is part of an anonymous method.  
+
+       Exceptions to this include the temporary variables that are
+       created by some statements internally for holding temporary
+       variables. 
+       
+       (EmitContext.EmitMeta): New routine, in charge of emitting all the
+       metadata for a cb
+
+       (EmitContext.TemporaryReturn): This method is typically called
+       from the Emit phase, and its the only place where we allow the
+       ReturnLabel to be defined other than the EmitMeta.  The reason is
+       that otherwise we would have to duplicate a lot of logic in the
+       Resolve phases of various methods that today is on the Emit
+       phase. 
+
+       (EmitContext.NeedReturnLabel): This no longer creates the label,
+       as the ILGenerator is not valid during the resolve phase.
+
+       (EmitContext.EmitThis): Extended the knowledge in this class to
+       work in anonymous methods in addition to iterators. 
+
+       (EmitContext.EmitCapturedVariableInstance): This emits whatever
+       code is necessary on the stack to access the instance to a local
+       variable (the variable will be accessed as a field).
+
+       (EmitContext.EmitParameter, EmitContext.EmitAssignParameter,
+       EmitContext.EmitAddressOfParameter): Routines to support
+       parameters (not completed at this point). 
+       
+       Removals: Removed RemapLocal and RemapLocalLValue.  We probably
+       will also remove the parameters.
+
+       * convert.cs (Convert): Define a `ConstantEC' which points to a
+       null.  This is just to prefity some code that uses
+       ImplicitStandardConversion code and do not have an EmitContext
+       handy.
+
+       The idea is to flag explicitly that at that point in time, it is
+       known that the conversion will not trigger the delegate checking
+       code in implicit conversions (which requires a valid
+       EmitContext). 
+
+       Everywhere: pass new EmitContext parameter since
+       ImplicitStandardConversionExists now requires it to check for
+       anonymous method conversions. 
+
+       (Convert.ImplicitStandardConversionExists): If the type of an
+       expression is the anonymous_method_type, and the type is a
+       delegate, we invoke the AnonymousMethod.Compatible method to check
+       whether an implicit conversion is possible. 
+
+       (Convert.ImplicitConversionStandard): Only do implicit method
+       group conversions if the language level is not ISO_1.
+
+       * delegate.cs (Delegate.GetInvokeMethod): Common method to get the
+       MethodInfo for the Invoke method.  used by Delegate and
+       AnonymousDelegate.
+
+       * expression.cs (Binary.DoNumericPromotions): only allow anonymous
+       method conversions if the target type is a delegate.
+
+       Removed extra debugging nops.
+
+       (LocalVariableReference): Turn the `local_info' into a public
+       field. 
+
+       Add `prepared' field, the same hack used for FieldExprs to cope
+       with composed assignments, as Local variables do not necessarily
+       operate purely on the stack as they used to: they can be captured
+       fields. 
+
+       Add `temp' for a temporary result, like fields.
+
+       Refactor DoResolve and DoResolveLValue into DoResolveBase.
+
+       It now copes with Local variables that are captured and emits the
+       proper instance variable to load it from a field in the captured
+       case. 
+
+       (ParameterReference.DoResolveBase): During the resolve phase,
+       capture parameters if we are in an anonymous method.
+
+       (ParameterReference.Emit, ParameterReference.AddressOf): If in an
+       anonymous method, use the EmitContext helper routines to emit the
+       parameter reference.
+
+       * iterators.cs: Set RemapToProxy to true/false during the
+       EmitDispose class.
+
+       * parameters.cs (GetParameterByName): New helper method. 
+
+       * typemanager.cs (anonymous_method_type) a new type that
+       represents an anonyous method.  This is always an internal type,
+       used as a fencepost to test against the anonymous-methodness of an
+       expression. 
+       
 2004-10-24  Marek Safar  <marek.safar@seznam.cz>
 
        Fixed bugs #63705, #67130
index a83bfed13d55bb4d69e1cacb9c3fbab3c2bc77d0..403163702fcf9ac60f5d9a825e0dc918bd9044a8 100644 (file)
@@ -1,3 +1,4 @@
+
 NEW NOTES:
 ----------
 
@@ -45,7 +46,6 @@ Error Reporting:
 
 Iterators
 ---------
-
        * Reset should throw not implemented now.
 
 Optimization ideas
index e32d9f78294c617d7fae3f8428355d796cae05ef..1dc3671764ed507307a38f926e0bfe595850862b 100644 (file)
@@ -4,10 +4,16 @@
 // Author:
 //   Miguel de Icaza (miguel@ximain.com)
 //
-// (C) 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
+//
+// TODO: Ideally, we should have the helper classes emited as a hierarchy to map
+// their nesting, and have the visibility set to private, instead of NestedAssembly
+//
+//
 //
 
 using System;
+using System.Text;
 using System.Collections;
 using System.Reflection;
 using System.Reflection.Emit;
@@ -15,15 +21,62 @@ using System.Reflection.Emit;
 namespace Mono.CSharp {
 
        public class AnonymousMethod : Expression {
+               // Used to generate unique method names.
+               static int anonymous_method_count;
+                   
                // An array list of AnonymousMethodParameter or null
-               Parameters parameters;
-               Block block;
+               public Parameters Parameters;
+
+               //
+               // The block that makes up the body for the anonymous mehtod
+               //
+               public ToplevelBlock Block;
+
+               //
+               // The container block for this anonymous method.
+               //
+               public Block ContainingBlock;
+
+               //
+               // The implicit method we create
+               //
+               public Method method;
+
+               MethodInfo invoke_mb;
+               
+               // The emit context for the anonymous method
+               public EmitContext aec;
+               public InternalParameters amp;
+               bool unreachable;
+
+               //
+               // The modifiers applied to the method, we aggregate them
+               //
+               int method_modifiers = Modifiers.INTERNAL;
                
-               public AnonymousMethod (Parameters parameters, Block block, Location l)
+               //
+               // During the resolve stage of the anonymous method body,
+               // we discover the actual scope where we are hosted, or
+               // null to host the method in the same class
+               //
+               public ScopeInfo Scope;
+
+               //
+               // Points to our container anonymous method if its present
+               //
+               public AnonymousMethod ContainerAnonymousMethod;
+               
+               public AnonymousMethod (Parameters parameters, ToplevelBlock container, ToplevelBlock block, Location l)
                {
-                       this.parameters = parameters;
-                       this.block = block;
+                       Parameters = parameters;
+                       Block = block;
                        loc = l;
+
+                       //
+                       // The order is important: this setups the CaptureContext tree hierarchy.
+                       //
+                       container.SetHaveAnonymousMethods (l, this);
+                       block.SetHaveAnonymousMethods (l, this);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -33,13 +86,14 @@ namespace Mono.CSharp {
                        //
 
                        eclass = ExprClass.Value;
-
+                       
                        //
                        // This hack means `The type is not accessible
                        // anywhere', we depend on special conversion
                        // rules.
                        // 
-                       type = typeof (AnonymousMethod);
+                       type = TypeManager.anonymous_method_type;
+
                        return this;
                }
 
@@ -47,6 +101,1037 @@ namespace Mono.CSharp {
                {
                        // nothing, as we only exist to not do anything.
                }
+
+               //
+               // Creates the host for the anonymous method
+               //
+               bool CreateMethodHost (EmitContext ec, Type return_type)
+               {
+                       //
+                       // Crude hack follows: we replace the TypeBuilder during the
+                       // definition to get the method hosted in the right class
+                       //
+                       
+                       TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
+                       TypeBuilder type_host = Scope == null ? current_type : Scope.ScopeTypeBuilder;
+
+                       if (current_type == null)
+                               throw new Exception ("The current_type is null");
+                       
+                       if (type_host == null)
+                               throw new Exception ("Type host is null");
+                       
+                       if (current_type == type_host && ec.IsStatic){
+                               if (ec.IsStatic)
+                                       method_modifiers |= Modifiers.STATIC;
+                               current_type = null;
+                       } 
+
+                       method = new Method (
+                               (TypeContainer) ec.TypeContainer,
+                               new TypeExpression (return_type, loc),
+                               method_modifiers, false, new MemberName ("<#AnonymousMethod>" + anonymous_method_count++),
+                               Parameters, null, loc);
+                       method.Block = Block;
+
+                       
+                       //
+                       // Swap the TypeBuilder while we define the method, then restore
+                       //
+                       if (current_type != null)
+                               ec.TypeContainer.TypeBuilder = type_host;
+                       bool res = method.Define ();
+                       if (current_type != null)
+                               ec.TypeContainer.TypeBuilder = current_type;
+                       return res;
+               }
+               
+               void Error_ParameterMismatch (Type t)
+               {
+                       Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
+                                     "{0}' since there is a parameter mismatch", t);
+               }
+
+               //
+               // Returns true if this anonymous method can be implicitly
+               // converted to the delegate type `delegate_type'
+               //
+               public Expression Compatible (EmitContext ec, Type delegate_type, bool probe)
+               {
+                       //
+                       // At this point its the first time we know the return type that is 
+                       // needed for the anonymous method.  We create the method here.
+                       //
+
+                       invoke_mb = (MethodInfo) Delegate.GetInvokeMethod (ec, delegate_type, loc);
+                       ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+
+                       //
+                       // If implicit parameters are set, then we must check for out in the parameters
+                       // and flag it accordingly.
+                       //
+                       bool out_invalid_check = false;
+                       
+                       if (Parameters == null){
+                               int i, j;
+                               out_invalid_check = true;
+                               
+                               //
+                               // We provide a set of inaccessible parameters
+                               //
+                               int params_idx = -1;
+                               for (i = 0; i < invoke_pd.Count; i++){
+                                       if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
+                                               params_idx = i;
+                               }
+                               int n = invoke_pd.Count - (params_idx != -1 ? 1 : 0);
+                               Parameter [] fixedpars = new Parameter [n];
+                               
+                               for (i =  j = 0; i < invoke_pd.Count; i++){
+                                       if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
+                                               continue;
+                                       fixedpars [j] = new Parameter (
+                                               new TypeExpression (invoke_pd.ParameterType (i), loc),
+                                               "+" + j, invoke_pd.ParameterModifier (i), null);
+                                       j++;
+                               }
+                               
+                               Parameter variable = null;
+                               if (params_idx != -1){
+                                       variable = new Parameter (
+                                               new TypeExpression (invoke_pd.ParameterType (params_idx), loc),
+                                               "+" + params_idx, invoke_pd.ParameterModifier (params_idx), null);
+                               }
+
+                               Parameters = new Parameters (fixedpars, variable, loc);
+                       }
+                       
+                       //
+                       // First, parameter types of `delegate_type' must be compatible
+                       // with the anonymous method.
+                       //
+                       amp = new InternalParameters (Parameters.GetParameterInfo (ec), Parameters);
+                       
+                       if (amp.Count != invoke_pd.Count){
+                               if (!probe){
+                                       Report.Error (1593, loc, 
+                                             "Anonymous method has {0} parameters, while delegate requires {1}",
+                                             amp.Count, invoke_pd.Count);
+                                       Error_ParameterMismatch (delegate_type);
+                               }
+                               return null;
+                       }
+                       
+                       for (int i = 0; i < amp.Count; i++){
+                               Parameter.Modifier amp_mod = amp.ParameterModifier (i);
+                               if (amp_mod != invoke_pd.ParameterModifier (i)){
+                                       if (!probe){
+                                               Report.Error (1676, loc, 
+                                                     "Signature mismatch in parameter modifier for parameter #0", i + 1);
+                                               Error_ParameterMismatch (delegate_type);
+                                       }
+                                       return null;
+                               }
+                               
+                               if (amp.ParameterType (i) != invoke_pd.ParameterType (i)){
+                                       if (!probe){
+                                               Report.Error (1678, loc, 
+                                                                     "Signature mismatch in parameter {0}: need `{1}' got `{2}'", i + 1,
+                                                                     TypeManager.CSharpName (invoke_pd.ParameterType (i)),
+                                                                     TypeManager.CSharpName (amp.ParameterType (i)));
+                                               Error_ParameterMismatch (delegate_type);
+                                       }
+                                       return null;
+                               }
+                               
+                               if (out_invalid_check && (invoke_pd.ParameterModifier (i) & Parameter.Modifier.OUT) != 0){
+                                       if (!probe){
+                                               Report.Error (1676, loc,"Parameter {0} must include the `out' modifier ", i+1);
+                                               Error_ParameterMismatch (delegate_type);
+                                       }
+                                       return null;
+                               }
+                       }
+
+                       //
+                       // If we are only probing, return ourselves
+                       //
+                       if (probe)
+                               return this;
+                       
+                       //
+                       // Second: the return type of the delegate must be compatible with 
+                       // the anonymous type.   Instead of doing a pass to examine the block
+                       // we satisfy the rule by setting the return type on the EmitContext
+                       // to be the delegate type return type.
+                       //
+
+                       //MethodBuilder builder = method_data.MethodBuilder;
+                       //ILGenerator ig = builder.GetILGenerator ();
+
+                       
+                       aec = new EmitContext (
+                               ec.TypeContainer, ec.DeclSpace, loc, null,
+                               invoke_mb.ReturnType,
+                               /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
+                               (ec.InUnsafe ? Modifiers.UNSAFE : 0),
+                               /* No constructor */ false);
+
+                       aec.CurrentAnonymousMethod = this;
+                       ContainerAnonymousMethod = ec.CurrentAnonymousMethod;
+                       ContainingBlock = ec.CurrentBlock;
+               
+                       if (aec.ResolveTopBlock (ec, Block, amp, loc, out unreachable))
+                               return new AnonymousDelegate (this, delegate_type, loc).Resolve (ec);
+
+                       return null;
+               }
+
+               public MethodBuilder GetMethodBuilder ()
+               {
+                       return method.MethodData.MethodBuilder;
+               }
+               
+               public void EmitMethod (EmitContext ec)
+               {
+                       if (!CreateMethodHost (ec, invoke_mb.ReturnType))
+                               return;
+
+                       MethodBuilder builder = GetMethodBuilder ();
+                       ILGenerator ig = builder.GetILGenerator ();
+                       aec.ig = ig;
+                       
+                       Parameters.LabelParameters (aec, builder, loc);
+
+                       //
+                       // Adjust based on the computed state of the
+                       // method from CreateMethodHost
+                       
+                       if ((method_modifiers & Modifiers.STATIC) != 0)
+                               aec.IsStatic = true;
+                       
+                       aec.EmitMeta (Block, amp);
+                       aec.EmitResolvedTopBlock (Block, unreachable);
+               }
+       }
+
+       //
+       // This will emit the code for the delegate, as well delegate creation on the host
+       //
+       public class AnonymousDelegate : DelegateCreation {
+               AnonymousMethod am;
+
+               public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
+               {
+                       type = target_type;
+                       loc = l;
+                       this.am = am;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       am.EmitMethod (ec);
+
+                       //
+                       // Now emit the delegate creation.
+                       //
+                       if ((am.method.ModFlags & Modifiers.STATIC) == 0)
+                               delegate_instance_expression = new AnonymousInstance (am);
+                       
+                       Expression ml = Expression.MemberLookup (ec, type, ".ctor", loc);
+                       constructor_method = ((MethodGroupExpr) ml).Methods [0];
+                       delegate_method = am.GetMethodBuilder ();
+                       base.Emit (ec);
+               }
+
+               class AnonymousInstance : Expression {
+                       AnonymousMethod am;
+                       
+                       public AnonymousInstance (AnonymousMethod am)
+                       {
+                               this.am = am;
+                               eclass = ExprClass.Value;
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               return this;
+                       }
+                       
+                       public override void Emit (EmitContext ec)
+                       {
+                               am.aec.EmitMethodHostInstance (ec, am);
+                       }
+               }
+       }
+
+       class CapturedParameter {
+               public Type Type;
+               public FieldBuilder FieldBuilder;
+               public int Idx;
+
+               public CapturedParameter (Type type, int idx)
+               {
+                       Type = type;
+                       Idx = idx;
+               }
+       }
+
+       //
+       // Here we cluster all the variables captured on a given scope, we also
+       // keep some extra information that might be required on each scope.
+       //
+       public class ScopeInfo {
+               public CaptureContext CaptureContext;
+               public ScopeInfo ParentScope;
+               public Block ScopeBlock;
+               public bool NeedThis = false;
+               public bool HostsParameters = false;
+               
+               // For tracking the number of scopes created.
+               public int id;
+               static int count;
+               bool inited = false;
+               
+               ArrayList locals = new ArrayList ();
+               ArrayList children = new ArrayList ();
+
+               //
+               // The types and fields generated
+               //
+               public TypeBuilder ScopeTypeBuilder;
+               public ConstructorBuilder ScopeConstructor;
+               public FieldBuilder THIS;
+               public FieldBuilder ParentLink;
+
+               //
+               // Points to the object of type `ScopeTypeBuilder' that
+               // holds the data for the scope
+               //
+               public LocalBuilder ScopeInstance;
+
+               
+               public ScopeInfo (CaptureContext cc, Block b)
+               {
+                       CaptureContext = cc;
+                       ScopeBlock = b;
+                       id = count++;
+
+                       cc.AddScope (this);
+               }
+
+               public void AddLocal (LocalInfo li)
+               {
+                       if (locals.Contains (li))
+                               return;
+
+                       locals.Add (li);
+               }
+
+               public bool IsCaptured (LocalInfo li)
+               {
+                       return locals.Contains (li);
+               }
+               
+               public void AddChild (ScopeInfo si)
+               {
+                       if (children.Contains (si))
+                               return;
+                       children.Add (si);
+               }
+
+               static int indent = 0;
+
+               void Pad ()
+               {
+                       for (int i = 0; i < indent; i++)
+                               Console.Write ("    ");
+               }
+
+               void EmitDebug ()
+               {
+                       //Console.WriteLine (Environment.StackTrace);
+                       Pad ();
+                       Console.WriteLine ("START");
+                       indent++;
+                       Pad ();
+                       Console.WriteLine ("NeedThis=" + NeedThis);
+                       foreach (LocalInfo li in locals){
+                               Pad ();
+                               Console.WriteLine ("var {0}", li.Name);
+                       }
+                       
+                       foreach (ScopeInfo si in children)
+                               si.EmitDebug ();
+                       indent--;
+                       Pad ();
+                       Console.WriteLine ("END");
+               }
+               
+               public string MakeHelperName ()
+               {
+                       return String.Format ("<>AnonHelp<{0}>", id);
+               }
+
+               public void EmitScopeConstructor ()
+               {
+                       Type [] constructor_types = TypeManager.NoTypes;
+                       Parameters constructor_parameters = Parameters.EmptyReadOnlyParameters;
+                       ScopeConstructor = ScopeTypeBuilder.DefineConstructor (
+                               MethodAttributes.Public | MethodAttributes.HideBySig |
+                               MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
+                               CallingConventions.HasThis, constructor_types);
+                       InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
+                       TypeManager.RegisterMethod (ScopeConstructor, parameter_info, constructor_types);
+
+                       ILGenerator cig = ScopeConstructor.GetILGenerator ();
+                       cig.Emit (OpCodes.Ldarg_0);
+                       cig.Emit (OpCodes.Call, TypeManager.object_ctor);
+                       cig.Emit (OpCodes.Ret);
+               }
+               
+               public void EmitScopeType (EmitContext ec)
+               {
+                       //EmitDebug ();
+
+                       if (ScopeTypeBuilder != null)
+                               return;
+                       
+                       ILGenerator ig = ec.ig;
+                       TypeBuilder container = ec.TypeContainer.TypeBuilder;
+
+                       ScopeTypeBuilder = container.DefineNestedType (
+                               MakeHelperName (), TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.NestedAssembly,
+                               TypeManager.object_type, null);
+
+                       if (NeedThis)
+                               THIS = ScopeTypeBuilder.DefineField ("<>THIS", container, FieldAttributes.Assembly);
+
+                       if (ParentScope != null){
+                               if (ParentScope.ScopeTypeBuilder == null){
+                                       throw new Exception (String.Format ("My parent has not been initialized {0} and {1}", ParentScope, this));
+                               }
+                               
+                               ParentLink = ScopeTypeBuilder.DefineField ("<>parent", ParentScope.ScopeTypeBuilder,
+                                                                          FieldAttributes.Assembly);
+                       }
+                       
+                       if (NeedThis && ParentScope != null)
+                               throw new Exception ("I was not expecting THIS && having a parent");
+
+                       foreach (LocalInfo info in locals){
+                               info.FieldBuilder = ScopeTypeBuilder.DefineField (
+                                       info.Name, info.VariableType, FieldAttributes.Assembly);
+                       }
+
+                       if (HostsParameters){
+                               Hashtable captured_parameters = CaptureContext.captured_parameters;
+                               
+                               foreach (DictionaryEntry de in captured_parameters){
+                                       string name = (string) de.Key;
+                                       CapturedParameter cp = (CapturedParameter) de.Value;
+                                       FieldBuilder fb;
+                                       
+                                       fb = ScopeTypeBuilder.DefineField ("<p:" + name + ">", cp.Type, FieldAttributes.Assembly);
+                                       cp.FieldBuilder = fb;
+                               }
+                       }
+
+                       EmitScopeConstructor ();
+                       foreach (ScopeInfo si in children){
+                               si.EmitScopeType (ec);
+                       }
+               }
+
+               public void CloseTypes ()
+               {
+                       RootContext.RegisterHelperClass (ScopeTypeBuilder);
+                       foreach (ScopeInfo si in children)
+                               si.CloseTypes ();
+               }
+
+               //
+               // Emits the initialization code for the scope
+               //
+               public void EmitInitScope (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       if (inited)
+                               return;
+
+                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) ScopeConstructor);
+                       ScopeInstance = ig.DeclareLocal (ScopeTypeBuilder);
+                       ig.Emit (OpCodes.Stloc, ScopeInstance);
+
+                       if (THIS != null){
+                               ig.Emit (OpCodes.Ldloc, ScopeInstance);
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Stfld, THIS);
+                       }
+
+                       //
+                       // Copy the parameter values, if any
+                       //
+                       int extra = ec.IsStatic ? 0 : 1;
+                       if (HostsParameters){
+                               Hashtable captured_parameters = CaptureContext.captured_parameters;
+                               
+                               foreach (DictionaryEntry de in captured_parameters){
+                                       string name = (string) de.Key;
+                                       CapturedParameter cp = (CapturedParameter) de.Value;
+
+                                       ig.Emit (OpCodes.Ldloc, ScopeInstance);
+                                       ParameterReference.EmitLdArg (ig, cp.Idx + extra);
+                                       ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
+                               }
+                       }
+                       
+                       if (ParentScope != null){
+                               //
+                               // Only emit initialization in our capturecontext world
+                               //
+                               if (ParentScope.CaptureContext == CaptureContext){
+                                       ig.Emit (OpCodes.Ldloc, ScopeInstance);
+                                       ig.Emit (OpCodes.Ldloc, ParentScope.ScopeInstance);
+                                       ig.Emit (OpCodes.Stfld, ParentLink);
+                               } else {
+                                       ig.Emit (OpCodes.Ldloc, ScopeInstance);
+                                       ig.Emit (OpCodes.Ldarg_0);
+                                       ig.Emit (OpCodes.Stfld, ParentLink);
+                               }
+                       }
+                       inited = true;
+               }
+
+               static void DoPath (StringBuilder sb, ScopeInfo start)
+               {
+                       if (start.ParentScope != null){
+                               DoPath (sb, start.ParentScope);
+                               sb.Append (", ");
+                       }
+                       sb.Append ((start.id).ToString ());
+               }
+               
+               public override string ToString ()
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       
+                       sb.Append ("{");
+                       if (CaptureContext != null){
+                               sb.Append (CaptureContext.ToString ());
+                               sb.Append (":");
+                       }
+
+                       DoPath (sb, this);
+                       sb.Append ("}");
+
+                       return sb.ToString ();
+               }
+       }
+
+       //
+       // CaptureContext objects are created on demand if a method has
+       // anonymous methods and kept on the ToplevelBlock.
+       //
+       // If they exist, all ToplevelBlocks in the containing block are
+       // linked together (children pointing to their parents).
+       //
+       public class CaptureContext {
+               public static int count;
+               public int cc_id;
+               Location loc;
+               
+               //
+               // Points to the toplevel block that owns this CaptureContext
+               //
+               ToplevelBlock toplevel_owner;
+               Hashtable scopes = new Hashtable ();
+               bool have_captured_vars = false;
+               ScopeInfo topmost = null;
+
+               //
+               // Captured fields
+               //
+               Hashtable captured_fields = new Hashtable ();
+               Hashtable captured_variables = new Hashtable ();
+               public Hashtable captured_parameters = new Hashtable ();
+               public AnonymousMethod Host;
+               
+               public CaptureContext (ToplevelBlock toplevel_owner, Location loc, AnonymousMethod host)
+               {
+                       cc_id = count++;
+                       this.toplevel_owner = toplevel_owner;
+                       this.loc = loc;
+
+                       if (host != null)
+                               Host = host;
+               }
+
+               void DoPath (StringBuilder sb, CaptureContext cc)
+               {
+                       if (cc.ParentCaptureContext != null){
+                               DoPath (sb, cc.ParentCaptureContext);
+                               sb.Append (".");
+                       }
+                       sb.Append (cc_id.ToString ());
+               }
+               
+               public override string ToString ()
+               {
+                       ToplevelBlock parent = ParentToplevel;
+                       StringBuilder sb = new StringBuilder ();
+
+                       sb.Append ("[");
+                       DoPath (sb, this);
+                       sb.Append ("]");
+                       return sb.ToString ();
+               }
+
+               public ToplevelBlock ParentToplevel {
+                       get {
+                               return toplevel_owner.Container;
+                       }
+               }
+
+               public CaptureContext ParentCaptureContext {
+                       get {
+                               ToplevelBlock parent = ParentToplevel;
+                               
+                               return (parent == null) ? null : parent.CaptureContext;
+                       }
+               }
+
+               // Returns the deepest of two scopes
+               public ScopeInfo Deepest (ScopeInfo a, ScopeInfo b)
+               {
+                       ScopeInfo p;
+
+                       if (a == null)
+                               return b;
+                       if (b == null)
+                               return a;
+                       if (a == b)
+                               return a;
+
+                       //
+                       // If they Scopes are on the same CaptureContext, we do the double
+                       // checks just so if there is an invariant change in the future,
+                       // we get the exception at the end
+                       //
+                       for (p = a; p != null; p = p.ParentScope)
+                               if (p == b)
+                                       return a;
+                       
+                       for (p = b; p != null; p = p.ParentScope)
+                               if (p == a)
+                                       return b;
+
+                       CaptureContext ca = a.CaptureContext;
+                       CaptureContext cb = b.CaptureContext;
+
+                       for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext)
+                               if (c == cb)
+                                       return a;
+
+                       for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext)
+                               if (c == ca)
+                                       return b;
+                       throw new Exception ("Should never be reached");
+               }
+
+               void AdjustMethodScope (AnonymousMethod am, ScopeInfo scope)
+               {
+                       am.Scope = Deepest (am.Scope, scope);
+               }
+
+               void LinkScope (ScopeInfo scope, int id)
+               {
+                       ScopeInfo parent = (ScopeInfo) scopes [id];
+                       scope.ParentScope = parent;
+                       parent.AddChild (scope);
+
+                       if (scope == topmost)
+                               topmost = parent;
+               }
+               
+               public void AddLocal (AnonymousMethod am, LocalInfo li)
+               {
+                       if (li.Block.Toplevel != toplevel_owner){
+                               ParentCaptureContext.AddLocal (am, li);
+                               return;
+                       }
+                       int block_id = li.Block.ID;
+                       ScopeInfo scope;
+                       if (scopes [block_id] == null){
+                               scope = new ScopeInfo (this, li.Block);
+                               scopes [block_id] = scope;
+                       } else
+                               scope = (ScopeInfo) scopes [block_id];
+
+                       if (topmost == null){
+                               topmost = scope;
+                       } else {
+                               // Link to parent
+                               for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
+                                       if (scopes [b.ID] != null){
+                                               LinkScope (scope, b.ID);
+                                               break;
+                                       }
+                               }
+
+                               if (scope.ParentScope == null && ParentCaptureContext != null){
+                                       CaptureContext pcc = ParentCaptureContext;
+                                       
+                                       for (Block b = am.ContainingBlock; b != null; b = b.Parent){
+                                               if (pcc.scopes [b.ID] != null){
+                                                       pcc.LinkScope (scope, b.ID);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+
+                       //
+                       // Adjust the owner
+                       //
+                       if (Host != null)
+                               AdjustMethodScope (Host, topmost);
+
+                       //
+                       // Adjust the user
+                       //
+                       AdjustMethodScope (am, scope);
+                       
+                       if (captured_variables [li] != null)
+                               return;
+                       
+                       have_captured_vars = true;
+                       captured_variables [li] = li;
+                       scope.AddLocal (li);
+               }
+
+               //
+               // Retursn the CaptureContext for the block that defines the parameter `name'
+               //
+               static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
+               {
+                       ToplevelBlock container = current.Container;
+                       if (container != null){
+                               CaptureContext cc = _ContextForParameter (container, name);
+                               if (cc != null)
+                                       return cc;
+                       }
+                       if (current.IsParameterReference (name))
+                               return current.ToplevelBlockCaptureContext;
+                       return null;
+               }
+
+               static CaptureContext ContextForParameter (ToplevelBlock current, string name)
+               {
+                       CaptureContext cc = _ContextForParameter (current, name);
+                       if (cc == null)
+                               throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
+                       return cc;
+               }
+               
+               //
+               // Records the captured parameter at the appropriate CaptureContext
+               //
+               public void AddParameter (EmitContext ec, AnonymousMethod am, string name, Type t, int idx)
+               {
+                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+
+                       cc.AddParameterToContext (am, name, t, idx);
+               }
+
+               //
+               // Records the parameters in the context
+               //
+               void AddParameterToContext (AnonymousMethod am, string name, Type t, int idx)
+               {
+                       if (captured_parameters == null)
+                               captured_parameters = new Hashtable ();
+                       if (captured_parameters [name] != null)
+                               return;
+                       captured_parameters [name] = new CapturedParameter (t, idx);
+
+                       if (topmost == null){
+                               //
+                               // Create one ScopeInfo, if there are none.
+                               //
+                               topmost = new ScopeInfo (this, toplevel_owner);
+                               scopes [toplevel_owner.ID] = topmost;
+                       } else {
+                               //
+                               // If the topmost ScopeInfo is not at the topblock level, insert
+                               // a new ScopeInfo there.
+                               //
+                               if (topmost.ScopeBlock != toplevel_owner){
+                                       ScopeInfo par_si = new ScopeInfo (this, toplevel_owner);
+                                       scopes [toplevel_owner.ID] = topmost;
+                                       topmost.ParentScope = par_si;
+                                       topmost = par_si;
+                               }
+                       }
+                       
+                       topmost.HostsParameters = true;
+                       AdjustMethodScope (am, topmost);
+               }
+
+               //
+               // Captured fields are only recorded on the topmost CaptureContext, because that
+               // one is the one linked to the owner of instance fields
+               //
+               public void AddField (FieldExpr fe)
+               {
+                       if (fe.FieldInfo.IsStatic)
+                               throw new Exception ("Attempt to register a static field as a captured field");
+                       
+                       CaptureContext parent = ParentCaptureContext;
+                       if (parent != null)
+                               parent.AddField (fe);
+                       else
+                               captured_fields [fe] = fe;
+               }
+               
+
+               public bool HaveCapturedVariables {
+                       get {
+                               return have_captured_vars;
+                       }
+               }
+               
+               public bool HaveCapturedFields {
+                       get {
+                               CaptureContext parent = ParentCaptureContext;
+                               if (parent != null)
+                                       return parent.HaveCapturedFields;
+                               return captured_fields.Count > 0;
+                       }
+               }
+
+               public bool IsCaptured (LocalInfo local)
+               {
+                       foreach (ScopeInfo si in scopes.Values){
+                               if (si.IsCaptured (local))
+                                       return true;
+                       }
+                       return false;
+               }
+
+               //
+               // Returns whether the parameter is captured
+               //
+               public bool IsParameterCaptured (string name)
+               {
+                       if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
+                               return true;
+                       
+                       if (captured_parameters != null)
+                               return captured_parameters [name] != null;
+                       return false;
+               }
+
+               public void EmitHelperClasses (EmitContext ec)
+               {
+                       if (topmost != null){
+                               topmost.NeedThis = HaveCapturedFields;
+                               topmost.EmitScopeType (ec);
+                       } 
+               }
+
+               public void CloseHelperClasses ()
+               {
+                       if (topmost != null)
+                               topmost.CloseTypes ();
+               }
+
+               ScopeInfo GetScopeFromBlock (EmitContext ec, Block b)
+               {
+                       ScopeInfo si;
+                       
+                       si = (ScopeInfo) scopes [b.ID];
+                       if (si == null)
+                               throw new Exception ("Si is null for block " + b.ID);
+                       si.EmitInitScope (ec);
+
+                       return si;
+               }
+
+               //
+               // Emits the opcodes necessary to load the instance of the captured
+               // variable in `li'
+               //
+               public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li, AnonymousMethod am)
+               {
+                       ILGenerator ig = ec.ig;
+                       ScopeInfo si;
+                       
+                       if (li.Block.Toplevel == toplevel_owner){
+                               si = GetScopeFromBlock (ec, li.Block);
+                               ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
+                               return;
+                       }
+
+                       si = am.Scope;
+                       ig.Emit (OpCodes.Ldarg_0);
+                       if (si != null){
+                               while (si.ScopeBlock.ID != li.Block.ID){
+                                       if (si.ParentLink != null)
+                                               ig.Emit (OpCodes.Ldfld, si.ParentLink);
+                                       si = si.ParentScope;
+                                       if (si == null) 
+                                               throw new Exception (
+                                                            String.Format ("Never found block {0} starting at {1} while looking up {2}",
+                                                                           li.Block.ID, am.Scope.ScopeBlock.ID, li.Name));
+                               }
+                       }
+               }
+
+               //
+               // Internal routine that loads the instance to reach parameter `name'
+               //
+               void EmitParameterInstance (EmitContext ec, string name)
+               {
+                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+                       if (cc != this){
+                               cc.EmitParameterInstance (ec, name);
+                               return;
+                       }
+                       Block invocation_block = ec.CurrentBlock;
+                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+                       ILGenerator ig = ec.ig;
+
+                       ScopeInfo si;
+                       if (ec.CurrentBlock == toplevel_owner){
+                               si = GetScopeFromBlock (ec, toplevel_owner);
+                               ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
+                               return;
+                       }
+                       
+                       si = ec.CurrentAnonymousMethod.Scope;
+                       ig.Emit (OpCodes.Ldarg_0);
+                       if (si != null){
+                               while (si.ParentLink != null) {
+                                       ig.Emit (OpCodes.Ldfld, si.ParentLink);
+                                       si = si.ParentScope;
+                               } 
+                       }
+               }
+
+               //
+               // Emits the code necessary to load the parameter named `name' within
+               // an anonymous method.
+               //
+               public void EmitParameter (EmitContext ec, string name)
+               {
+                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+                       if (cc != this){
+                               cc.EmitParameter (ec, name);
+                               return;
+                       }
+                       EmitParameterInstance (ec, name);
+                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+                       ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
+               }
+
+               //
+               // Implements the assignment of `source' to the paramenter named `name' within
+               // an anonymous method.
+               //
+               public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load)
+               {
+                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+                       if (cc != this){
+                               cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load);
+                               return;
+                       }
+                       ILGenerator ig = ec.ig;
+                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+
+                       EmitParameterInstance (ec, name);
+                       source.Emit (ec);
+                       if (leave_copy)
+                               ig.Emit (OpCodes.Dup);
+                       ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
+               }
+
+               //
+               // Emits the address for the parameter named `name' within
+               // an anonymous method.
+               //
+               public void EmitAddressOfParameter (EmitContext ec, string name)
+               {
+                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+                       if (cc != this){
+                               cc.EmitAddressOfParameter (ec, name);
+                               return;
+                       }
+                       EmitParameterInstance (ec, name);
+                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+                       ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder);
+               }
+
+               //
+               // The following methods are only invoked on the host for the
+               // anonymous method.
+               //
+               public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
+               {
+                       ILGenerator ig = target.ig;
+                       ScopeInfo si = am.Scope;
+                       
+                       if (si == null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               return;
+                       }
+
+                       si.EmitInitScope (target);
+                       ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
+               }
+
+               ArrayList all_scopes = new ArrayList ();
+               
+               public void AddScope (ScopeInfo si)
+               {
+                       all_scopes.Add (si);
+                       toplevel_owner.RegisterCaptureContext (this);
+               }
+
+               //
+               // Links any scopes that were not linked previously
+               //
+               public void AdjustScopes ()
+               {
+                       foreach (ScopeInfo scope in all_scopes){
+                               if (scope.ParentScope != null)
+                                       continue;
+
+                               for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
+                                       if (scopes [b.ID] != null){
+                                               LinkScope (scope, b.ID);
+                                               break;
+                                       }
+                               }
+
+                               if (scope.ParentScope == null && ParentCaptureContext != null){
+                                       CaptureContext pcc = ParentCaptureContext;
+                                       
+                                       for (Block b = Host.ContainingBlock; b != null; b = b.Parent){
+                                               if (pcc.scopes [b.ID] != null){
+                                                       pcc.LinkScope (scope, b.ID);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 }
-       
index 2d53bc09c6721686bc0d6ea4483165bca03f2b0e..aecb5d9dd8d5a49788481485d9b8344b907c56a9 100755 (executable)
@@ -360,6 +360,7 @@ namespace Mono.CSharp {
                                type = target_type;
                        eclass = ExprClass.Value;
 
+
                        if (target is EventExpr) {
                                EventInfo ei = ((EventExpr) target).EventInfo;
 
@@ -442,7 +443,7 @@ namespace Mono.CSharp {
                                        // 2. and the original right side is implicitly convertible to
                                        // the type of target
                                        //
-                                       if (Convert.ImplicitStandardConversionExists (a.original_source, target_type))
+                                       if (Convert.ImplicitStandardConversionExists (ec, a.original_source, target_type))
                                                return this;
 
                                        //
index 2795ef6704ef72ff552986260d7b838e2419b47c..57c97c900437cd4b5b3dab85ec2323db85e7cf9a 100755 (executable)
@@ -2890,7 +2890,7 @@ namespace Mono.CSharp {
 
        public abstract class MethodCore : MemberBase {
                public readonly Parameters Parameters;
-               protected Block block;
+               protected ToplevelBlock block;
                
                //
                // Parameters, cached for semantic analysis.
@@ -2934,7 +2934,7 @@ namespace Mono.CSharp {
                        }
                }
                
-               public Block Block {
+               public ToplevelBlock Block {
                        get {
                                return block;
                        }
@@ -4320,7 +4320,7 @@ namespace Mono.CSharp {
                Type ReturnType { get; }
 
                Attributes OptAttributes { get; }
-               Block Block { get; }
+               ToplevelBlock Block { get; }
 
                EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
                ObsoleteAttribute GetObsoleteAttribute ();
@@ -4555,7 +4555,8 @@ namespace Mono.CSharp {
                        if (member is MethodCore)
                                ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
 
-                       Block block = method.Block;
+                       SymbolWriter sw = CodeGen.SymbolWriter;
+                       ToplevelBlock block = method.Block;
                        
                        //
                        // abstract or extern methods have no bodies
@@ -4611,7 +4612,7 @@ namespace Mono.CSharp {
                                source.CloseMethod ();
                }
 
-               void EmitDestructor (EmitContext ec, Block block)
+               void EmitDestructor (EmitContext ec, ToplevelBlock block)
                {
                        ILGenerator ig = ec.ig;
                        
@@ -4941,7 +4942,10 @@ namespace Mono.CSharp {
                public Status status;
 
                [Flags]
-               public enum Status : byte { ASSIGNED = 1, USED = 2 }
+               public enum Status : byte {
+                       ASSIGNED = 1,
+                       USED = 2
+               }
 
                static string[] attribute_targets = new string [] { "field" };
 
@@ -4994,6 +4998,7 @@ namespace Mono.CSharp {
                }
 
                protected readonly Object init;
+
                // Private.
                Expression init_expr;
                bool init_expr_initialized = false;
@@ -5292,11 +5297,11 @@ namespace Mono.CSharp {
                //
                // Null if the accessor is empty, or a Block if not
                //
-               public Block Block;
+               public ToplevelBlock Block;
                public Attributes Attributes;
                public Location Location;
                
-               public Accessor (Block b, Attributes attrs, Location loc)
+               public Accessor (ToplevelBlock b, Attributes attrs, Location loc)
                {
                        Block = b;
                        Attributes = attrs;
@@ -5309,7 +5314,7 @@ namespace Mono.CSharp {
        // When it will be possible move here a lot of child code and template method type.
        public abstract class AbstractPropertyEventMethod: MemberCore, IMethodData {
                protected MethodData method_data;
-               protected Block block;
+               protected ToplevelBlock block;
 
                // The accessor are created event if they are not wanted.
                // But we need them because their names are reserved.
@@ -5350,7 +5355,7 @@ namespace Mono.CSharp {
 
                #region IMethodData Members
 
-               public Block Block {
+               public ToplevelBlock Block {
                        get {
                                return block;
                        }
@@ -6747,7 +6752,7 @@ namespace Mono.CSharp {
 
                public Operator (TypeContainer parent, OpType type, Expression ret_type,
                                 int mod_flags, Parameters parameters,
-                                Block block, Attributes attrs, Location loc)
+                                ToplevelBlock block, Attributes attrs, Location loc)
                        : base (parent, ret_type, mod_flags, AllowedModifiers, false,
                                new MemberName ("op_" + type), attrs, parameters, loc)
                {
index 4a413272e0e0ff41c63894f941a0b72720cb7ebc..ac0cb453123c8271b0f568263c3c4206cec66563 100755 (executable)
@@ -4,9 +4,10 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //
-// (C) 2001 Ximian, Inc.
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2004 Novell, Inc.
 //
-
+//#define PRODUCTION
 using System;
 using System.IO;
 using System.Collections;
@@ -252,7 +253,7 @@ namespace Mono.CSharp {
                        ig.Emit (value_type_call ? OpCodes.Call : OpCodes.Callvirt, mi);
                }
        }
-       
+
        /// <summary>
        ///   An Emit Context is created for each body of code (from methods,
        ///   properties bodies, indexer bodies or constructor bodies)
@@ -367,7 +368,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///  Whether we are inside an anonymous method.
                /// </summary>
-               public bool InAnonymousMethod;
+               public AnonymousMethod CurrentAnonymousMethod;
                
                /// <summary>
                ///   Location for this EmitContext
@@ -391,16 +392,37 @@ namespace Mono.CSharp {
                /// </summary>
                public bool InEnumContext;
 
+               /// <summary>
+               ///   Anonymous methods can capture local variables and fields,
+               ///   this object tracks it.  It is copied from the TopLevelBlock
+               ///   field.
+               /// </summary>
+               public CaptureContext capture_context;
+
                /// <summary>
                /// Trace when method is called and is obsolete then this member suppress message
                /// when call is inside next [Obsolete] method or type.
                /// </summary>
                public bool TestObsoleteMethodUsage = true;
 
+               /// <summary>
+               ///    The current iterator
+               /// </summary>
                public Iterator CurrentIterator;
 
-               FlowBranching current_flow_branching;
+               /// <summary>
+               ///    Whether we are in the resolving stage or not
+               /// </summary>
+               enum Phase {
+                       Created,
+                       Resolving,
+                       Emitting
+               }
+               
+               Phase current_phase;
                
+               FlowBranching current_flow_branching;
+
                public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
                                    Type return_type, int code_flags, bool is_constructor)
                {
@@ -410,7 +432,7 @@ namespace Mono.CSharp {
                        DeclSpace = ds;
                        CheckState = RootContext.Checked;
                        ConstantCheckState = true;
-                       
+
                        IsStatic = (code_flags & Modifiers.STATIC) != 0;
                        InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0;
                        RemapToProxy = InIterator;
@@ -418,6 +440,7 @@ namespace Mono.CSharp {
                        IsConstructor = is_constructor;
                        CurrentBlock = null;
                        CurrentFile = 0;
+                       current_phase = Phase.Created;
                        
                        if (parent != null){
                                // Can only be null for the ResolveType contexts.
@@ -428,7 +451,7 @@ namespace Mono.CSharp {
                                        InUnsafe = (code_flags & Modifiers.UNSAFE) != 0;
                        }
                        loc = l;
-                       
+
                        if (ReturnType == TypeManager.void_type)
                                ReturnType = null;
                }
@@ -451,6 +474,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool HaveCaptureInfo {
+                       get {
+                               return capture_context != null;
+                       }
+               }
+
                // <summary>
                //   Starts a new code branching.  This inherits the state of all local
                //   variables and parameters from the current branching.
@@ -517,30 +546,141 @@ namespace Mono.CSharp {
                        current_flow_branching = current_flow_branching.Parent;
                }
 
-               public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
+               public void CaptureVariable (LocalInfo li)
                {
-                       bool unreachable = false;
+                       capture_context.AddLocal (CurrentAnonymousMethod, li);
+                       li.IsCaptured = true;
+               }
+
+               public void CaptureParameter (string name, Type t, int idx)
+               {
+                       
+                       capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
+               }
+               
+               //
+               // Use to register a field as captured
+               //
+               public void CaptureField (FieldExpr fe)
+               {
+                       capture_context.AddField (fe);
+               }
+
+               //
+               // Whether anonymous methods have captured variables
+               //
+               public bool HaveCapturedVariables ()
+               {
+                       if (capture_context != null)
+                               return capture_context.HaveCapturedVariables;
+                       return false;
+               }
+
+               //
+               // Whether anonymous methods have captured fields or this.
+               //
+               public bool HaveCapturedFields ()
+               {
+                       if (capture_context != null)
+                               return capture_context.HaveCapturedFields;
+                       return false;
+               }
+
+               //
+               // Emits the instance pointer for the host method
+               //
+               public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
+               {
+                       if (capture_context != null)
+                               capture_context.EmitMethodHostInstance (target, am);
+                       else if (IsStatic)
+                               target.ig.Emit (OpCodes.Ldnull);
+                       else
+                               target.ig.Emit (OpCodes.Ldarg_0);
+               }
+
+               //
+               // Returns whether the `local' variable has been captured by an anonymous
+               // method
+               //
+               public bool IsCaptured (LocalInfo local)
+               {
+                       return capture_context.IsCaptured (local);
+               }
+
+               public bool IsParameterCaptured (string name)
+               {
+                       if (capture_context != null)
+                               return capture_context.IsParameterCaptured (name);
+                       return false;
+               }
+               
+               public void EmitMeta (ToplevelBlock b, InternalParameters ip)
+               {
+                       if (capture_context != null)
+                               capture_context.EmitHelperClasses (this);
+                       b.EmitMeta (this);
+
+                       if (HasReturnLabel)
+                               ReturnLabel = ig.DefineLabel ();
+               }
+
+               //
+               // Here until we can fix the problem with Mono.CSharp.Switch, which
+               // currently can not cope with ig == null during resolve (which must
+               // be fixed for switch statements to work on anonymous methods).
+               //
+               public void EmitTopBlock (ToplevelBlock block, InternalParameters ip, Location loc)
+               {
+                       if (block == null)
+                               return;
+                       
+                       bool unreachable;
+                       
+                       if (ResolveTopBlock (null, block, ip, loc, out unreachable)){
+                               EmitMeta (block, ip);
 
+                               current_phase = Phase.Emitting;
+                               EmitResolvedTopBlock (block, unreachable);
+                       }
+               }
+
+               public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,
+                                            InternalParameters ip, Location loc, out bool unreachable)
+               {
+                       current_phase = Phase.Resolving;
+                       
+                       unreachable = false;
+
+                       capture_context = block.CaptureContext;
+                       
                        if (!Location.IsNull (loc))
                                CurrentFile = loc.File;
 
-                       if (block != null){
-                           try {
+#if PRODUCTION
+                       try {
+#endif
                                int errors = Report.Errors;
 
-                               block.EmitMeta (this, ip);
+                               block.ResolveMeta (block, this, ip);
 
+                               
                                if (Report.Errors == errors){
                                        bool old_do_flow_analysis = DoFlowAnalysis;
                                        DoFlowAnalysis = true;
 
-                                       current_flow_branching = FlowBranching.CreateBranching (
-                                               null, FlowBranching.BranchingType.Block, block, loc);
+                                       if (anonymous_method_host != null)
+                                               current_flow_branching = FlowBranching.CreateBranching (
+                                               anonymous_method_host.CurrentBranching, FlowBranching.BranchingType.Block,
+                                               block, loc);
+                                       else 
+                                               current_flow_branching = FlowBranching.CreateBranching (
+                                                       null, FlowBranching.BranchingType.Block, block, loc);
 
                                        if (!block.Resolve (this)) {
                                                current_flow_branching = null;
                                                DoFlowAnalysis = old_do_flow_analysis;
-                                               return;
+                                               return false;
                                        }
 
                                        FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
@@ -548,14 +688,13 @@ namespace Mono.CSharp {
                                        
                                        DoFlowAnalysis = old_do_flow_analysis;
 
-                                       block.Emit (this);
-
                                        if (reachability.AlwaysReturns ||
                                            reachability.AlwaysThrows ||
                                            reachability.IsUnreachable)
                                                unreachable = true;
                                }
-                           } catch (Exception e) {
+#if PRODUCTION
+                       } catch (Exception e) {
                                        Console.WriteLine ("Exception caught by the compiler while compiling:");
                                        Console.WriteLine ("   Block that caused the problem begin at: " + loc);
                                        
@@ -564,21 +703,35 @@ namespace Mono.CSharp {
                                                                   CurrentBlock.StartLocation, CurrentBlock.EndLocation);
                                        }
                                        Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
-                                       Console.WriteLine (Report.FriendlyStackTrace (e));
-                                       
-                                       Environment.Exit (1);
-                           }
+                                       throw;
                        }
+#endif
 
                        if (ReturnType != null && !unreachable){
                                if (!InIterator){
-                                       Report.Error (161, loc, "Not all code paths return a value");
-                                       return;
+                                       if (CurrentAnonymousMethod != null){
+                                               Report.Error (1643, loc, "Not all code paths return a value in anonymous method of type `{0}'",
+                                                             CurrentAnonymousMethod.Type);
+                                       } else {
+                                               Report.Error (161, loc, "Not all code paths return a value");
+                                       }
+                                       
+                                       return false;
                                }
                        }
+                       block.CompleteContexts ();
+                       
+                       return true;
+               }
 
+               public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
+               {
+                       if (block != null)
+                               block.Emit (this);
+                       
                        if (HasReturnLabel)
                                ig.MarkLabel (ReturnLabel);
+                       
                        if (return_value != null){
                                ig.Emit (OpCodes.Ldloc, return_value);
                                ig.Emit (OpCodes.Ret);
@@ -604,6 +757,12 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Ret);
                                }
                        }
+
+                       //
+                       // Close pending helper classes if we are the toplevel
+                       //
+                       if (capture_context != null && capture_context.ParentToplevel == null)
+                               capture_context.CloseHelperClasses ();
                }
 
                /// <summary>
@@ -710,24 +869,42 @@ namespace Mono.CSharp {
                ///   return value from the function.  By default this is not
                ///   used.  This is only required when returns are found inside
                ///   Try or Catch statements.
+               ///
+               ///   This method is typically invoked from the Emit phase, so
+               ///   we allow the creation of a return label if it was not
+               ///   requested during the resolution phase.   Could be cleaned
+               ///   up, but it would replicate a lot of logic in the Emit phase
+               ///   of the code that uses it.
                /// </summary>
                public LocalBuilder TemporaryReturn ()
                {
                        if (return_value == null){
                                return_value = ig.DeclareLocal (ReturnType);
-                               ReturnLabel = ig.DefineLabel ();
-                               HasReturnLabel = true;
+                               if (!HasReturnLabel){
+                                       ReturnLabel = ig.DefineLabel ();
+                                       HasReturnLabel = true;
+                               }
                        }
 
                        return return_value;
                }
 
+               /// <summary>
+               ///   This method is used during the Resolution phase to flag the
+               ///   need to define the ReturnLabel
+               /// </summary>
                public void NeedReturnLabel ()
                {
-                       if (!InIterator && !HasReturnLabel) {
-                               ReturnLabel = ig.DefineLabel ();
-                               HasReturnLabel = true;
+                       if (current_phase != Phase.Resolving){
+                               //
+                               // The reason is that the `ReturnLabel' is declared between
+                               // resolution and emission
+                               // 
+                               throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve");
                        }
+                       
+                       if (!InIterator && !HasReturnLabel) 
+                               HasReturnLabel = true;
                }
 
                //
@@ -741,24 +918,6 @@ namespace Mono.CSharp {
                        throw new Exception ("MapVariable for an unknown state");
                }
 
-               //
-               // Invoke this routine to remap a VariableInfo into the
-               // proper MemberAccess expression
-               //
-               public Expression RemapLocal (LocalInfo local_info)
-               {
-                       FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
-                       fe.InstanceExpression = new ProxyInstance ();
-                       return fe.DoResolve (this);
-               }
-
-               public Expression RemapLocalLValue (LocalInfo local_info, Expression right_side)
-               {
-                       FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
-                       fe.InstanceExpression = new ProxyInstance ();
-                       return fe.DoResolveLValue (this, right_side);
-               }
-
                public Expression RemapParameter (int idx)
                {
                        FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc);
@@ -780,15 +939,60 @@ namespace Mono.CSharp {
                public void EmitThis ()
                {
                        ig.Emit (OpCodes.Ldarg_0);
-                       if (InIterator && !IsStatic){
-                               FieldBuilder this_field = CurrentIterator.this_field.FieldBuilder;
-                               if (TypeManager.IsValueType (this_field.FieldType))
-                                       ig.Emit (OpCodes.Ldflda, this_field);
-                               else
-                                       ig.Emit (OpCodes.Ldfld, this_field);
+                       if (InIterator){
+                               if (!IsStatic){
+                                       FieldBuilder this_field = CurrentIterator.this_field.FieldBuilder;
+                                       if (TypeManager.IsValueType (this_field.FieldType))
+                                               ig.Emit (OpCodes.Ldflda, this_field);
+                                       else
+                                               ig.Emit (OpCodes.Ldfld, this_field);
+                               } 
+                       } else if (capture_context != null && CurrentAnonymousMethod != null){
+                               ScopeInfo si = CurrentAnonymousMethod.Scope;
+                               while (si != null){
+                                       if (si.ParentLink != null)
+                                               ig.Emit (OpCodes.Ldfld, si.ParentLink);
+                                       if (si.THIS != null){
+                                               ig.Emit (OpCodes.Ldfld, si.THIS);
+                                               break;
+                                       }
+                                       si = si.ParentScope;
+                               }
+                       } 
+               }
+
+               //
+               // Emits the code necessary to load the instance required
+               // to access the captured LocalInfo
+               //
+               public void EmitCapturedVariableInstance (LocalInfo li)
+               {
+                       if (RemapToProxy){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               return;
                        }
+                       
+                       if (capture_context == null)
+                               throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
+                       
+                       capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
                }
 
+               public void EmitParameter (string name)
+               {
+                       capture_context.EmitParameter (this, name);
+               }
+
+               public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load)
+               {
+                       capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load);
+               }
+
+               public void EmitAddressOfParameter (string name)
+               {
+                       capture_context.EmitAddressOfParameter (this, name);
+               }
+               
                public Expression GetThis (Location loc)
                {
                        This my_this;
index 1e0b00b2f44f83f886b5cc44c98920c570d88faa..fbab41568ecf0ae6ca93c517a0ccc785b121ad9f 100755 (executable)
@@ -111,7 +111,7 @@ namespace Mono.CSharp {
                        if (expr is NullLiteral && !type.IsValueType && !TypeManager.IsEnumType (type))
                                return NullLiteral.Null;
 
-                       if (!Convert.ImplicitStandardConversionExists (expr, type)){
+                       if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, expr, type)){
                                Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
                                return null;
                        }
index e28cb26370ab9d3b1ae2b4cc44d5f9dad5169c54..0290f53bc0be9dec6a8ead518800674aa389b2b5 100644 (file)
@@ -19,6 +19,13 @@ namespace Mono.CSharp {
        // A container class for all the conversion operations
        //
        public class Convert {
+               //
+               // This is used to prettify the code: a null argument is allowed
+               // for ImplicitStandardConversion as long as it is known that
+               // no anonymous method will play a role.
+               //
+               public const EmitContext ConstantEC = null;
+               
                static public void Error_CannotConvertType (Location loc, Type source, Type target)
                {
                        Report.Error (30, loc, "Cannot convert type '" +
@@ -53,8 +60,11 @@ namespace Mono.CSharp {
 
                                if (expr_type.IsValueType)
                                        return new BoxedCast (expr);
-                               if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type)
+                               if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
+                                       if (target_type == TypeManager.anonymous_method_type)
+                                               return null;
                                        return new EmptyCast (expr, target_type);
+                               }
 
                                return null;
                        } else if (target_type == TypeManager.value_type) {
@@ -133,7 +143,7 @@ namespace Mono.CSharp {
                                        Type target_element_type = TypeManager.GetElementType (target_type);
 
                                        if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
-                                               if (ImplicitStandardConversionExists (MyEmptyExpr,
+                                               if (ImplicitStandardConversionExists (ConstantEC, MyEmptyExpr,
                                                                                      target_element_type))
                                                        return new EmptyCast (expr, target_type);
                                }
@@ -173,7 +183,8 @@ namespace Mono.CSharp {
                        if (target_type == TypeManager.object_type) {
                                if (expr_type.IsClass || expr_type.IsValueType ||
                                    expr_type.IsInterface || expr_type == TypeManager.enum_type)
-                                       return true;
+                                       if (target_type != TypeManager.anonymous_method_type)
+                                               return true;
 
                                return false;
                        } else if (expr_type.IsSubclassOf (target_type)) 
@@ -206,7 +217,7 @@ namespace Mono.CSharp {
                                        Type target_element_type = TypeManager.GetElementType (target_type);
                                                
                                        if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
-                                               if (ImplicitStandardConversionExists (MyEmptyExpr,
+                                               if (ImplicitStandardConversionExists (ConstantEC, MyEmptyExpr,
                                                                                      target_element_type))
                                                        return true;
                                }
@@ -410,7 +421,7 @@ namespace Mono.CSharp {
                /// </summary>
                public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
                {
-                       if (ImplicitStandardConversionExists (expr, target_type))
+                       if (ImplicitStandardConversionExists (ec, expr, target_type))
                                return true;
 
                        Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
@@ -431,8 +442,10 @@ namespace Mono.CSharp {
                /// <summary>
                ///  Determines if a standard implicit conversion exists from
                ///  expr_type to target_type
+               ///
+               ///  ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
                /// </summary>
-               public static bool ImplicitStandardConversionExists (Expression expr, Type target_type)
+               public static bool ImplicitStandardConversionExists (EmitContext ec, Expression expr, Type target_type)
                {
                        Type expr_type = expr.Type;
 
@@ -609,6 +622,18 @@ namespace Mono.CSharp {
                        if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
                                return true;
 
+                       if (expr_type == TypeManager.anonymous_method_type){
+                               if (!TypeManager.IsDelegateType (target_type))
+                                       return false;
+
+                               AnonymousMethod am = (AnonymousMethod) expr;
+                               int errors = Report.Errors;
+
+                               Expression conv = am.Compatible (ec, target_type, true);
+                               if (conv != null)
+                                       return true;
+                       }
+                       
                        return false;
                }
 
@@ -623,7 +648,7 @@ namespace Mono.CSharp {
                ///  Finds "most encompassed type" according to the spec (13.4.2)
                ///  amongst the methods in the MethodGroupExpr
                /// </summary>
-               static Type FindMostEncompassedType (ArrayList types)
+               static Type FindMostEncompassedType (EmitContext ec, ArrayList types)
                {
                        Type best = null;
 
@@ -638,7 +663,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
                                
-                               if (ImplicitStandardConversionExists (priv_fmet_param, best))
+                               if (ImplicitStandardConversionExists (ec, priv_fmet_param, best))
                                        best = t;
                        }
 
@@ -656,7 +681,7 @@ namespace Mono.CSharp {
                ///  Finds "most encompassing type" according to the spec (13.4.2)
                ///  amongst the types in the given set
                /// </summary>
-               static Type FindMostEncompassingType (ArrayList types)
+               static Type FindMostEncompassingType (EmitContext ec, ArrayList types)
                {
                        Type best = null;
 
@@ -671,7 +696,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if (ImplicitStandardConversionExists (priv_fmee_ret, t))
+                               if (ImplicitStandardConversionExists (ec, priv_fmee_ret, t))
                                        best = t;
                        }
                        
@@ -688,8 +713,8 @@ namespace Mono.CSharp {
                ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
                ///   for explicit and implicit conversion operators.
                /// </summary>
-               static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source,
-                                                          bool apply_explicit_conv_rules,
+               static public Type FindMostSpecificSource (EmitContext ec, MethodGroupExpr me,
+                                                          Expression source, bool apply_explicit_conv_rules,
                                                           Location loc)
                {
                        ArrayList src_types_set = new ArrayList ();
@@ -718,17 +743,17 @@ namespace Mono.CSharp {
                                        // or encompassed by S to a type encompassing or encompassed by T
                                        //
                                        priv_fms_expr.SetType (param_type);
-                                       if (ImplicitStandardConversionExists (priv_fms_expr, source_type))
+                                       if (ImplicitStandardConversionExists (ec, priv_fms_expr, source_type))
                                                src_types_set.Add (param_type);
                                        else {
-                                               if (ImplicitStandardConversionExists (source, param_type))
+                                               if (ImplicitStandardConversionExists (ec, source, param_type))
                                                        src_types_set.Add (param_type);
                                        }
                                } else {
                                        //
                                        // Only if S is encompassed by param_type
                                        //
-                                       if (ImplicitStandardConversionExists (source, param_type))
+                                       if (ImplicitStandardConversionExists (ec, source, param_type))
                                                src_types_set.Add (param_type);
                                }
                        }
@@ -740,21 +765,21 @@ namespace Mono.CSharp {
                                ArrayList candidate_set = new ArrayList ();
 
                                foreach (Type param_type in src_types_set){
-                                       if (ImplicitStandardConversionExists (source, param_type))
+                                       if (ImplicitStandardConversionExists (ec, source, param_type))
                                                candidate_set.Add (param_type);
                                }
 
                                if (candidate_set.Count != 0)
-                                       return FindMostEncompassedType (candidate_set);
+                                       return FindMostEncompassedType (ec, candidate_set);
                        }
 
                        //
                        // Final case
                        //
                        if (apply_explicit_conv_rules)
-                               return FindMostEncompassingType (src_types_set);
+                               return FindMostEncompassingType (ec, src_types_set);
                        else
-                               return FindMostEncompassedType (src_types_set);
+                               return FindMostEncompassedType (ec, src_types_set);
                }
 
                //
@@ -765,8 +790,8 @@ namespace Mono.CSharp {
                /// <summary>
                ///  Finds the most specific target Tx according to section 13.4.4
                /// </summary>
-               static public Type FindMostSpecificTarget (MethodGroupExpr me, Type target,
-                                                          bool apply_explicit_conv_rules,
+               static public Type FindMostSpecificTarget (EmitContext ec, MethodGroupExpr me,
+                                                          Type target, bool apply_explicit_conv_rules,
                                                           Location loc)
                {
                        ArrayList tgt_types_set = new ArrayList ();
@@ -794,11 +819,11 @@ namespace Mono.CSharp {
                                        // or encompassed by S to a type encompassing or encompassed by T
                                        //
                                        priv_fms_expr.SetType (ret_type);
-                                       if (ImplicitStandardConversionExists (priv_fms_expr, target))
+                                       if (ImplicitStandardConversionExists (ec, priv_fms_expr, target))
                                                tgt_types_set.Add (ret_type);
                                        else {
                                                priv_fms_expr.SetType (target);
-                                               if (ImplicitStandardConversionExists (priv_fms_expr, ret_type))
+                                               if (ImplicitStandardConversionExists (ec, priv_fms_expr, ret_type))
                                                        tgt_types_set.Add (ret_type);
                                        }
                                } else {
@@ -806,7 +831,7 @@ namespace Mono.CSharp {
                                        // Only if T is encompassed by param_type
                                        //
                                        priv_fms_expr.SetType (ret_type);
-                                       if (ImplicitStandardConversionExists (priv_fms_expr, target))
+                                       if (ImplicitStandardConversionExists (ec, priv_fms_expr, target))
                                                tgt_types_set.Add (ret_type);
                                }
                        }
@@ -820,21 +845,21 @@ namespace Mono.CSharp {
                                foreach (Type ret_type in tgt_types_set){
                                        priv_fmt_expr.SetType (ret_type);
                                        
-                                       if (ImplicitStandardConversionExists (priv_fmt_expr, target))
+                                       if (ImplicitStandardConversionExists (ec, priv_fmt_expr, target))
                                                candidate_set.Add (ret_type);
                                }
 
                                if (candidate_set.Count != 0)
-                                       return FindMostEncompassingType (candidate_set);
+                                       return FindMostEncompassingType (ec, candidate_set);
                        }
                        
                        //
                        // Okay, final case !
                        //
                        if (apply_explicit_conv_rules)
-                               return FindMostEncompassedType (tgt_types_set);
+                               return FindMostEncompassedType (ec, tgt_types_set);
                        else 
-                               return FindMostEncompassingType (tgt_types_set);
+                               return FindMostEncompassingType (ec, tgt_types_set);
                }
                
                /// <summary>
@@ -948,11 +973,11 @@ namespace Mono.CSharp {
                        
                        Type most_specific_source, most_specific_target;
 
-                       most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
+                       most_specific_source = FindMostSpecificSource (ec, union, source, look_for_explicit, loc);
                        if (most_specific_source == null)
                                return null;
 
-                       most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc);
+                       most_specific_target = FindMostSpecificTarget (ec, union, target, look_for_explicit, loc);
                        if (most_specific_target == null) 
                                return null;
 
@@ -1043,16 +1068,19 @@ namespace Mono.CSharp {
 
                        if (expr.eclass == ExprClass.MethodGroup){
                                if (!TypeManager.IsDelegateType (target_type)){
-                                       Report.Error (428, loc,
-                                                     String.Format (
-                                                          "Cannot convert method group to `{0}', since it is not a delegate",
-                                                          TypeManager.CSharpName (target_type)));
                                        return null;
                                }
-
-                               return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+                               
+                               //
+                               // Only allow anonymous method conversions on post ISO_1
+                               //
+                               if (RootContext.Version != LanguageVersion.ISO_1){
+                                       MethodGroupExpr mg = expr as MethodGroupExpr;
+                                       if (mg != null)
+                                               return ImplicitDelegateCreation.Create (ec, mg, target_type, loc);
+                               }
                        }
-                       
+
                        if (expr_type == target_type && !(expr is NullLiteral))
                                return expr;
 
@@ -1068,7 +1096,7 @@ namespace Mono.CSharp {
                             target_type.IsSubclassOf (TypeManager.enum_type)) &&
                            expr is IntLiteral){
                                IntLiteral i = (IntLiteral) expr;
-
+                               
                                if (i.Value == 0)
                                        return new EnumConstant ((Constant) expr, target_type);
                        }
@@ -1097,6 +1125,30 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (expr_type == TypeManager.anonymous_method_type){
+                               if (!TypeManager.IsDelegateType (target_type)){
+                                       Report.Error (1660, loc,
+                                                             "Cannot convert anonymous method to `{0}', since it is not a delegate",
+                                                             TypeManager.CSharpName (target_type));
+                                       return null;
+                               }
+
+                               AnonymousMethod am = (AnonymousMethod) expr;
+                               int errors = Report.Errors;
+
+                               Expression conv = am.Compatible (ec, target_type, false);
+                               if (conv != null)
+                                       return conv;
+                               
+                               //
+                               // We return something instead of null, to avoid
+                               // the duplicate error, since am.Compatible would have
+                               // reported that already
+                               //
+                               if (errors != Report.Errors)
+                                       return new EmptyCast (expr, target_type);
+                       }
+                       
                        return null;
                }
 
@@ -1157,11 +1209,10 @@ namespace Mono.CSharp {
 
                static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
                {
-                       string msg = "Cannot convert implicitly from `"+
-                               TypeManager.CSharpName (source) + "' to `" +
-                               TypeManager.CSharpName (target) + "'";
-
-                       Report.Error (29, loc, msg);
+                       Report.Error (29, loc, "Cannot convert implicitly from {0} to `{1}'",
+                                     source == TypeManager.anonymous_method_type ?
+                                     "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
+                                     TypeManager.CSharpName (target));
                }
 
                /// <summary>
@@ -1213,7 +1264,7 @@ namespace Mono.CSharp {
                        if (TypeManager.IsEnumType (real_target_type))
                                real_target_type = TypeManager.EnumToUnderlying (real_target_type);
 
-                       if (ImplicitStandardConversionExists (expr, real_target_type)){
+                       if (ImplicitStandardConversionExists (ec, expr, real_target_type)){
                                Expression ce = ImplicitConversionStandard (ec, expr, real_target_type, loc);
 
                                if (real_target_type != target_type)
index f99e7f63dbf5180da6fde0a33552f23c0bc43521..95d5061f61041a9641ff303b62c33e2a33948ff3 100755 (executable)
@@ -40,14 +40,8 @@ namespace Mono.CSharp
                ///   Current block is used to add statements as we find
                ///   them.  
                /// </summary>
-               Block      current_block;
+               Block      current_block, top_current_block;
 
-               /// <summary>
-                ///   If true, creates a toplevel block in the block production
-                ///   This is flagged by the delegate creation
-                /// </summary>
-                bool       create_toplevel_block;
-       
                /// <summary>
                ///   This is used by the unary_expression code to resolve
                ///   a name against a parameter.  
@@ -943,7 +937,7 @@ method_declaration
                        }
                }
 
-               method.Block = (Block) $3;
+               method.Block = (ToplevelBlock) $3;
                current_container.AddMethod (method);
 
                current_local_parameters = null;
@@ -1216,7 +1210,7 @@ get_accessor_declaration
          }
           accessor_body
          {
-               $$ = new Accessor ((Block) $4, (Attributes) $1, lexer.Location);
+               $$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1, lexer.Location);
                current_local_parameters = null;
                lexer.PropertyParsing = true;
          }
@@ -1253,7 +1247,7 @@ set_accessor_declaration
          }
          accessor_body
          {
-               $$ = new Accessor ((Block) $4, (Attributes) $1, lexer.Location);
+               $$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1, lexer.Location);
                current_local_parameters = null;
                lexer.PropertyParsing = true;
          }
@@ -1472,7 +1466,7 @@ operator_declaration
                Operator op = new Operator (
                        current_class, decl.optype, decl.ret_type, (int) $2, 
                        new Parameters (param_list, null, decl.location),
-                       (Block) $5, (Attributes) $1, decl.location);
+                       (ToplevelBlock) $5, (Attributes) $1, decl.location);
 
                if (SimpleIteratorContainer.Simple.Yields)
                        op.SetYields ();
@@ -1601,7 +1595,7 @@ constructor_declaration
          constructor_body
          { 
                Constructor c = (Constructor) $3;
-               c.Block = (Block) $4;
+               c.Block = (ToplevelBlock) $4;
                c.OptAttributes = (Attributes) $1;
                c.ModFlags = (int) $2;
        
@@ -1716,7 +1710,7 @@ destructor_declaration
                                current_class, TypeManager.system_void_expr, m, "Finalize", 
                                new Parameters (null, null, l), (Attributes) $1, l);
                  
-                       d.Block = (Block) $7;
+                       d.Block = (ToplevelBlock) $7;
                        current_container.AddMethod (d);
                }
          }
@@ -1812,7 +1806,7 @@ add_accessor_declaration
          }
           block
          {
-               $$ = new Accessor ((Block) $4, (Attributes) $1, lexer.Location);
+               $$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1, lexer.Location);
                lexer.EventParsing = true;
          }
        | opt_attributes ADD error {
@@ -1836,7 +1830,7 @@ remove_accessor_declaration
          }
           block
          {
-               $$ = new Accessor ((Block) $4, (Attributes) $1, lexer.Location);
+               $$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1, lexer.Location);
                lexer.EventParsing = true;
          }
        | opt_attributes REMOVE error {
@@ -2588,25 +2582,32 @@ anonymous_method_expression
        : DELEGATE opt_anonymous_method_signature {
                oob_stack.Push (current_local_parameters);
                current_local_parameters = (Parameters)$2;
-               create_toplevel_block = true;
+
+               // Force the next block to be created as a ToplevelBlock
+               oob_stack.Push (current_block);
+               oob_stack.Push (top_current_block);
+               oob_stack.Push (lexer.Location);
+               current_block = null;
          } block {
-               if (true){
-                       Report.Error (-213, lexer.Location, "Anonymous methods are not supported in this branch");
+               Location loc = (Location) oob_stack.Pop ();
+               top_current_block = (Block) oob_stack.Pop ();
+               current_block = (Block) oob_stack.Pop ();
+               if (RootContext.Version == LanguageVersion.ISO_1){
+                       Report.FeatureIsNotStandardized (lexer.Location, "anonymous methods");
                        $$ = null;
-               } else {
-                       create_toplevel_block = false;
-                       if (RootContext.Version == LanguageVersion.ISO_1){
-                               Report.FeatureIsNotStandardized (lexer.Location, "anonymous methods");
-                               $$ = null;
-                       } else 
-                               $$ = new AnonymousMethod ((Parameters) $2, (Block) $4, lexer.Location);
-                       current_local_parameters = (Parameters) oob_stack.Pop ();
+               } else  {
+                       ToplevelBlock anon_block = (ToplevelBlock) $4;
+
+                       anon_block.Parent = current_block;
+                       $$ = new AnonymousMethod ((Parameters) $2, (ToplevelBlock) top_current_block, 
+                               anon_block, loc);
                }
+               current_local_parameters = (Parameters) oob_stack.Pop ();
          }
        ;
 
 opt_anonymous_method_signature
-       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
+       : /* empty */                   { $$ = null; } 
        | anonymous_method_signature
        ;
 
@@ -2625,7 +2626,7 @@ anonymous_method_signature
        ;
 
 opt_anonymous_method_parameter_list
-       : /* empty */   { $$ = null; } 
+       : /* empty */                      { $$ = null; } 
        | anonymous_method_parameter_list  { $$ = $1; }
        ;
 
@@ -2646,7 +2647,11 @@ anonymous_method_parameter_list
 
 anonymous_method_parameter
        : opt_parameter_modifier type IDENTIFIER {
-               $$ = new Parameter ((Expression) $2, (string) $2, (Parameter.Modifier) $1, null);
+               $$ = new Parameter ((Expression) $2, (string) $3, (Parameter.Modifier) $1, null);
+         }
+       | PARAMS type IDENTIFIER {
+               Report.Error (-221, lexer.Location, "params modifier not allowed in anonymous method declaration");
+               $$ = null;
          }
        ;
 
@@ -3095,8 +3100,9 @@ class_base
 block
        : OPEN_BRACE 
          {
-               if (current_block == null || create_toplevel_block){
-                       current_block = new ToplevelBlock (current_local_parameters, lexer.Location);
+               if (current_block == null){
+                       current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location);
+                       top_current_block = current_block;
                } else {
                current_block = new Block (current_block, current_local_parameters,
                                           lexer.Location, Location.Null);
@@ -3109,6 +3115,8 @@ block
                $$ = current_block;
                current_block.SetEndLocation (lexer.Location);
                current_block = current_block.Parent;
+               if (current_block == null)
+                       top_current_block = null;
          }
        ;
 
index c2c52ba5c9512c3a42d12a4f34efd8e566836bd9..ce1ef17f17b7c3bdc9e2bb152f2899110d465378 100644 (file)
@@ -389,6 +389,23 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               //
+               // Returns the MethodBase for "Invoke" from a delegate type, this is used
+               // to extract the signature of a delegate.
+               //
+               public static MethodInfo GetInvokeMethod (EmitContext ec, Type delegate_type, Location loc)
+               {
+                       Expression ml = Expression.MemberLookup (
+                               ec, delegate_type, "Invoke", loc);
+
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return null;
+                       }
+
+                       return (MethodInfo) (((MethodGroupExpr) ml).Methods [0]);
+               }
+               
                /// <summary>
                ///  Verifies whether the method in question is compatible with the delegate
                ///  Returns the method itself if okay and null if not.
@@ -400,15 +417,9 @@ namespace Mono.CSharp {
 
                        int pd_count = pd.Count;
 
-                       Expression ml = Expression.MemberLookup (
-                               ec, delegate_type, "Invoke", loc);
-
-                       if (!(ml is MethodGroupExpr)) {
-                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                       MethodBase invoke_mb = GetInvokeMethod (ec, delegate_type, loc);
+                       if (invoke_mb == null)
                                return null;
-                       }
-
-                       MethodBase invoke_mb = ((MethodGroupExpr) ml).Methods [0];
 
                        ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
 
@@ -464,8 +475,8 @@ namespace Mono.CSharp {
 
                        if (!params_method && pd_count != arg_count) {
                                Report.Error (1593, loc,
-                                             "Delegate '" + delegate_type.ToString ()
-                                             + "' does not take '" + arg_count + "' arguments");
+                                             "Delegate '{0}' does not take {1} arguments",
+                                             delegate_type.ToString (), arg_count);
                                return false;
                        }
 
@@ -790,7 +801,7 @@ namespace Mono.CSharp {
                                return null;
                }
        }
-       
+
        //
        // A delegate-creation-expression, invoked from the `New' class 
        //
index 98673cf003a4eb537f0fae9e89f02d182fc2e172..ac3518f8bbe6c831a417e681fdc803e76956610f 100755 (executable)
@@ -885,7 +885,7 @@ namespace Mono.CSharp {
                /// </summary>
                public static object ConvertIntLiteral (Constant c, Type target_type, Location loc)
                {
-                       if (!Convert.ImplicitStandardConversionExists (c, target_type)){
+                       if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, c, target_type)){
                                Convert.Error_CannotImplicitConversion (loc, c.Type, target_type);
                                return null;
                        }
@@ -2108,21 +2108,12 @@ namespace Mono.CSharp {
                                                return var.Resolve (ec);
                                }
 
-                               int idx = -1;
-                               Parameter par = null;
-                               Parameters pars = current_block.Parameters;
-                               if (pars != null)
-                                       par = pars.GetParameterByName (Name, out idx);
-
-                               if (par != null) {
-                                       ParameterReference param;
-                                       
-                                       param = new ParameterReference (pars, current_block, idx, Name, loc);
-
+                               ParameterReference pref = current_block.GetParameterReference (Name, loc);
+                               if (pref != null) {
                                        if (right_side != null)
-                                               return param.ResolveLValue (ec, right_side);
+                                               return pref.ResolveLValue (ec, right_side);
                                        else
-                                               return param.Resolve (ec);
+                                               return pref.Resolve (ec);
                                }
                        }
                        
@@ -2664,6 +2655,16 @@ namespace Mono.CSharp {
                                        AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
                        }
 
+                       if (ec.CurrentAnonymousMethod != null){
+                               if (!FieldInfo.IsStatic){
+                                       if (ec.TypeContainer is Struct){
+                                               Report.Error (1673, loc, "Can not reference instance variables in anonymous methods hosted in structs");
+                                               return null;
+                                       }
+                                       ec.CaptureField (this);
+                               } 
+                       }
+                       
                        // If the instance expression is a local variable or parameter.
                        IVariable var = instance_expr as IVariable;
                        if ((var == null) || (var.VariableInfo == null))
@@ -2770,7 +2771,7 @@ namespace Mono.CSharp {
                                
                                ig.Emit (OpCodes.Ldfld, FieldInfo);
                        }
-                       
+
                        if (leave_copy) {       
                                ec.ig.Emit (OpCodes.Dup);
                                if (!FieldInfo.IsStatic) {
index 4665a6d4a29ca10760691c70dccfbb8bac7b8ce1..a98022bdb765406c04be32d616cf780eb31e2234 100755 (executable)
@@ -2374,8 +2374,8 @@ namespace Mono.CSharp {
                                        //
                                        // Also, a standard conversion must exist from either one
                                        //
-                                       if (!(Convert.ImplicitStandardConversionExists (left, r) ||
-                                             Convert.ImplicitStandardConversionExists (right, l))){
+                                       if (!(Convert.ImplicitStandardConversionExists (ec, left, r) ||
+                                             Convert.ImplicitStandardConversionExists (ec, right, l))){
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
@@ -2407,15 +2407,17 @@ namespace Mono.CSharp {
                        //
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
                                if (l.IsSubclassOf (TypeManager.delegate_type)){
-                                       if ((right.eclass == ExprClass.MethodGroup) &&
-                                           (RootContext.Version != LanguageVersion.ISO_1)){
-                                               Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
-                                               if (tmp == null)
-                                                       return null;
-                                               right = tmp;
-                                               r = right.Type;
+                                       if (((right.eclass == ExprClass.MethodGroup) ||
+                                            (r == TypeManager.anonymous_method_type))){
+                                               if ((RootContext.Version != LanguageVersion.ISO_1)){
+                                                       Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+                                                       if (tmp == null)
+                                                               return null;
+                                                       right = tmp;
+                                                       r = right.Type;
+                                               }
                                        }
-                               
+                                       
                                        if (r.IsSubclassOf (TypeManager.delegate_type)){
                                                MethodInfo method;
                                                ArrayList args = new ArrayList (2);
@@ -3312,8 +3314,6 @@ namespace Mono.CSharp {
                        Label false_target = ig.DefineLabel ();
                        Label end_target = ig.DefineLabel ();
 
-                       ig.Emit (OpCodes.Nop);
-
                        left.Emit (ec);
                        left_temp.Store (ec);
 
@@ -3323,8 +3323,6 @@ namespace Mono.CSharp {
                        ig.MarkLabel (false_target);
                        op.Emit (ec);
                        ig.MarkLabel (end_target);
-
-                       ig.Emit (OpCodes.Nop);
                }
        }
 
@@ -3539,8 +3537,10 @@ namespace Mono.CSharp {
        public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
                public readonly string Name;
                public readonly Block Block;
-               LocalInfo local_info;
+               public LocalInfo local_info;
                bool is_readonly;
+               bool prepared;
+               LocalTemporary temp;
                
                public LocalVariableReference (Block block, string name, Location l)
                {
@@ -3550,8 +3550,10 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Variable;
                }
 
+               //
                // Setting `is_readonly' to false will allow you to create a writable
                // reference to a read-only variable.  This is used by foreach and using.
+               //
                public LocalVariableReference (Block block, string name, Location l,
                                               LocalInfo local_info, bool is_readonly)
                        : this (block, name, l)
@@ -3561,7 +3563,9 @@ namespace Mono.CSharp {
                }
 
                public VariableInfo VariableInfo {
-                       get { return local_info.VariableInfo; }
+                       get {
+                               return local_info.VariableInfo;
+                       }
                }
 
                public bool IsReadOnly {
@@ -3570,7 +3574,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected void DoResolveBase (EmitContext ec)
+               protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side)
                {
                        if (local_info == null) {
                                local_info = Block.GetLocalInfo (Name);
@@ -3578,14 +3582,18 @@ namespace Mono.CSharp {
                        }
 
                        type = local_info.VariableType;
-#if false
-                       if (ec.InAnonymousMethod)
-                               Block.LiftVariable (local_info);
-#endif
-               }
 
-               protected Expression DoResolve (EmitContext ec, bool is_lvalue)
-               {
+                       VariableInfo variable_info = local_info.VariableInfo;
+                       if (lvalue_right_side != null){
+                               if (is_readonly){
+                                       Error (1604, "cannot assign to `" + Name + "' because it is readonly");
+                                       return null;
+                               }
+                               
+                               if (variable_info != null)
+                                       variable_info.SetAssigned (ec);
+                       }
+                       
                        Expression e = Block.GetConstantExpression (Name);
                        if (e != null) {
                                local_info.Used = true;
@@ -3593,50 +3601,34 @@ namespace Mono.CSharp {
                                return e.Resolve (ec);
                        }
 
-                       VariableInfo variable_info = local_info.VariableInfo; 
                        if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
                                return null;
 
-                       if (!is_lvalue)
+                       if (lvalue_right_side == null)
                                local_info.Used = true;
 
-                       if (local_info.LocalBuilder == null)
-                               return ec.RemapLocal (local_info);
-                       
+                       if (ec.CurrentAnonymousMethod != null){
+                               //
+                               // If we are referencing a variable from the external block
+                               // flag it for capturing
+                               //
+                               if (local_info.Block.Toplevel != ec.CurrentBlock.Toplevel){
+                                       ec.CaptureVariable (local_info);
+                                       //Console.WriteLine ("Capturing at " + loc);
+                               }
+                       }
+
                        return this;
                }
                
                public override Expression DoResolve (EmitContext ec)
                {
-                       DoResolveBase (ec);
-
-                       return DoResolve (ec, false);
+                       return DoResolveBase (ec, null);
                }
 
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       DoResolveBase (ec);
-
-                       VariableInfo variable_info = local_info.VariableInfo; 
-                       if (variable_info != null)
-                               variable_info.SetAssigned (ec);
-
-                       Expression e = DoResolve (ec, right_side != EmptyExpression.Null);
-
-                       if (e == null)
-                               return null;
-
-                       if (is_readonly){
-                               Error (1604, "cannot assign to `" + Name + "' because it is readonly");
-                               return null;
-                       }
-
-                       CheckObsoleteAttribute (e.Type);
-
-                       if (local_info.LocalBuilder == null)
-                               return ec.RemapLocalLValue (local_info, right_side);
-                       
-                       return this;
+                       return DoResolveBase (ec, right_side);
                }
 
                public bool VerifyFixed (bool is_expression)
@@ -3648,29 +3640,86 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+                       if (local_info.FieldBuilder == null){
+                               //
+                               // A local variable on the local CLR stack
+                               //
+                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+                       } else {
+                               //
+                               // A local variable captured by anonymous methods.
+                               //
+                               if (!prepared)
+                                       ec.EmitCapturedVariableInstance (local_info);
+                               
+                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
+                       }
                }
                
                public void Emit (EmitContext ec, bool leave_copy)
                {
                        Emit (ec);
-                       if (leave_copy)
+                       if (leave_copy){
                                ec.ig.Emit (OpCodes.Dup);
+                               if (local_info.FieldBuilder != null){
+                                       temp = new LocalTemporary (ec, Type);
+                                       temp.Store (ec);
+                               }
+                       }
                }
                
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       source.Emit (ec);
-                       if (leave_copy)
-                               ec.ig.Emit (OpCodes.Dup);
-                       ec.ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+                       ILGenerator ig = ec.ig;
+                       prepared = prepare_for_load;
+
+                       if (local_info.FieldBuilder == null){
+                               //
+                               // A local variable on the local CLR stack
+                               //
+                               if (local_info.LocalBuilder == null)
+                                       throw new Exception ("This should not happen: both Field and Local are null");
+                               
+                               source.Emit (ec);
+                               if (leave_copy)
+                                       ec.ig.Emit (OpCodes.Dup);
+                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+                       } else {
+                               //
+                               // A local variable captured by anonymous methods or itereators.
+                               //
+                               ec.EmitCapturedVariableInstance (local_info);
+
+                               if (prepare_for_load)
+                                       ig.Emit (OpCodes.Dup);
+                               source.Emit (ec);
+                               if (leave_copy){
+                                       ig.Emit (OpCodes.Dup);
+                                       temp = new LocalTemporary (ec, Type);
+                                       temp.Store (ec);
+                               }
+                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
+                               if (temp != null)
+                                       temp.Emit (ec);
+                       }
                }
                
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ILGenerator ig = ec.ig;
-                       
-                       ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+
+                       if (local_info.FieldBuilder == null){
+                               //
+                               // A local variable on the local CLR stack
+                               //
+                               ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+                       } else {
+                               //
+                               // A local variable captured by anonymous methods or iterators
+                               //
+                               ec.EmitCapturedVariableInstance (local_info);
+                               ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
+                       }
                }
 
                public override string ToString ()
@@ -3691,6 +3740,19 @@ namespace Mono.CSharp {
                VariableInfo vi;
                public Parameter.Modifier mod;
                public bool is_ref, is_out, prepared;
+
+               public bool IsOut {
+                       get {
+                               return is_out;
+                       }
+               }
+
+               public bool IsRef {
+                       get {
+                               return is_ref;
+                       }
+               }
+
                LocalTemporary temp;
                
                public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc)
@@ -3714,8 +3776,7 @@ namespace Mono.CSharp {
 
                public bool IsAssigned (EmitContext ec, Location loc)
                {
-                       if (!ec.DoFlowAnalysis || !is_out ||
-                           ec.CurrentBranching.IsAssigned (vi))
+                       if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsAssigned (vi))
                                return true;
 
                        Report.Error (165, loc,
@@ -3725,8 +3786,7 @@ namespace Mono.CSharp {
 
                public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
                {
-                       if (!ec.DoFlowAnalysis || !is_out ||
-                           ec.CurrentBranching.IsFieldAssigned (vi, field_name))
+                       if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsFieldAssigned (vi, field_name))
                                return true;
 
                        Report.Error (170, loc,
@@ -3740,7 +3800,7 @@ namespace Mono.CSharp {
                                ec.CurrentBranching.SetAssigned (vi);
                }
 
-               public void SetFieldAssigned (EmitContext ec, string field_name)
+               public void SetFieldAssigned (EmitContext ec, string field_name)        
                {
                        if (is_out && ec.DoFlowAnalysis)
                                ec.CurrentBranching.SetFieldAssigned (vi, field_name);
@@ -3755,6 +3815,23 @@ namespace Mono.CSharp {
 
                        if (is_out)
                                vi = block.ParameterMap [idx];
+
+                       if (ec.CurrentAnonymousMethod != null){
+                               if (is_ref){
+                                       Report.Error (1628, Location,
+                                                     "Can not reference a ref or out parameter in an anonymous method");
+                                       return;
+                               }
+                               
+                               //
+                               // If we are referencing the parameter from the external block
+                               // flag it for capturing
+                               //
+                               //Console.WriteLine ("Is parameter `{0}' local? {1}", name, block.IsLocalParameter (name));
+                               if (!block.IsLocalParameter (name)){
+                                       ec.CaptureParameter (name, type, idx);
+                               }
+                       }
                }
 
                //
@@ -3823,17 +3900,25 @@ namespace Mono.CSharp {
                                arg_idx++;
 
                        EmitLdArg (ig, arg_idx);
+
+                       //
+                       // FIXME: Review for anonymous methods
+                       //
                }
                
                public override void Emit (EmitContext ec)
                {
+                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+                               ec.EmitParameter (name);
+                               return;
+                       }
+                       
                        Emit (ec, false);
                }
                
                public void Emit (EmitContext ec, bool leave_copy)
                {
                        ILGenerator ig = ec.ig;
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3864,6 +3949,11 @@ namespace Mono.CSharp {
                
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
+                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+                               ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load);
+                               return;
+                       }
+
                        ILGenerator ig = ec.ig;
                        int arg_idx = idx;
                        
@@ -3900,6 +3990,11 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
+                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+                               ec.EmitAddressOfParameter (name);
+                               return;
+                       }
+                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -4075,7 +4170,7 @@ namespace Mono.CSharp {
                                if (Expr is ParameterReference){
                                        ParameterReference pr = (ParameterReference) Expr;
 
-                                       if (pr.is_ref)
+                                       if (pr.IsRef)
                                                pr.EmitLoad (ec);
                                        else {
                                                
@@ -4474,10 +4569,10 @@ namespace Mono.CSharp {
 
                                Argument a = (Argument) arguments [i];
 
-                               Parameter.Modifier a_mod = a.GetParameterModifier () &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier a_mod = a.GetParameterModifier () & 
+                                       (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)));
                                Parameter.Modifier p_mod = pd.ParameterModifier (i) &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                                       (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)));
 
                                if (a_mod == p_mod) {
 
@@ -4546,9 +4641,9 @@ namespace Mono.CSharp {
                                Argument a = (Argument) arguments [i];
 
                                Parameter.Modifier a_mod = a.GetParameterModifier () &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                                       unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
                                Parameter.Modifier p_mod = pd.ParameterModifier (i) &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                                       unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
 
 
                                if (a_mod == p_mod ||
@@ -4912,9 +5007,9 @@ namespace Mono.CSharp {
                                }
 
                                Parameter.Modifier a_mod = a.GetParameterModifier () &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                                       unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
                                Parameter.Modifier p_mod = pd.ParameterModifier (j) &
-                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                                       unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
                                
                                if (a_mod != p_mod &&
                                    pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
index abfd159a130ce09fbef5a129bd13b94294ebf656..855fab12ea586014a6dfff5b4607a15eb2bb2a7c 100644 (file)
@@ -51,9 +51,8 @@ namespace Mono.CSharp {
                                              "catch clause");
                                return false;
                        }
-                       if (ec.InAnonymousMethod){
-                               Report.Error (1621, loc, "yield statement can not appear " +
-                                             "inside an anonymoud method");
+                       if (ec.CurrentAnonymousMethod != null){
+                               Report.Error (1621, loc, "yield statement can not appear inside an anonymoud method");
                                return false;
                        }
 
@@ -112,9 +111,9 @@ namespace Mono.CSharp {
        }
 
        public class Iterator : Class {
+               ToplevelBlock original_block;
+               ToplevelBlock block;
                string original_name;
-               Block original_block;
-               Block block;
 
                Type iterator_type;
                TypeExpr iterator_type_expr;
@@ -217,6 +216,7 @@ namespace Mono.CSharp {
                        Label dispatcher = ig.DefineLabel ();
                        ig.Emit (OpCodes.Br, dispatcher);
 
+                       ec.RemapToProxy = true;
                        Label [] labels = new Label [resume_points.Count];
                        for (int i = 0; i < labels.Length; i++) {
                                ResumePoint point = (ResumePoint) resume_points [i];
@@ -240,7 +240,8 @@ namespace Mono.CSharp {
                                ig.EndExceptionBlock ();
                                ig.Emit (OpCodes.Br, end);
                        }
-
+                       ec.RemapToProxy = false;
+                       
                        ig.MarkLabel (dispatcher);
                        ig.Emit (OpCodes.Ldarg_0);
                        ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
@@ -349,7 +350,7 @@ namespace Mono.CSharp {
                //
                public Iterator (TypeContainer container, string name, Type return_type,
                                 Type [] param_types, InternalParameters parameters,
-                                int modifiers, Block block, Location loc)
+                                int modifiers, ToplevelBlock block, Location loc)
                        : base (container.NamespaceEntry, container, MakeProxyName (name),
                                Modifiers.PRIVATE, null, loc)
                {
@@ -359,7 +360,7 @@ namespace Mono.CSharp {
                        this.parameters = parameters;
                        this.original_name = name;
                        this.original_block = block;
-                       this.block = new Block (null);
+                       this.block = new ToplevelBlock (loc);
 
                        fields = new Hashtable ();
 
@@ -522,7 +523,7 @@ namespace Mono.CSharp {
                                Location);
                        AddConstructor (ctor);
 
-                       Block block = ctor.Block = new Block (null);
+                       ToplevelBlock block = ctor.Block = new ToplevelBlock (Location);
 
                        if (!is_static) {
                                Type t = container.TypeBuilder;
@@ -576,11 +577,10 @@ namespace Mono.CSharp {
 
                void Define_Current ()
                {
+                       ToplevelBlock get_block = new ToplevelBlock (Location);
                        MemberName left = new MemberName ("System.Collections.IEnumerator");
                        MemberName name = new MemberName (left, "Current");
 
-                       Block get_block = new Block (null);
-
                        get_block.AddStatement (new If (
                                new Binary (
                                        Binary.Operator.LessThanOrEqual,
@@ -608,7 +608,7 @@ namespace Mono.CSharp {
                                Location.Null);
                        AddMethod (move_next);
 
-                       Block block = move_next.Block = new Block (null);
+                       ToplevelBlock block = move_next.Block = new ToplevelBlock (Location);
 
                        MoveNextMethod inline = new MoveNextMethod (this, Location);
                        block.AddStatement (inline);
@@ -627,7 +627,7 @@ namespace Mono.CSharp {
                                Location.Null);
                        AddMethod (get_enumerator);
 
-                       get_enumerator.Block = new Block (null);
+                       get_enumerator.Block = new ToplevelBlock (Location);
 
                        Expression ce = new MemberAccess (
                                new SimpleName ("System.Threading.Interlocked", Location),
@@ -844,7 +844,7 @@ namespace Mono.CSharp {
                                Parameters.EmptyReadOnlyParameters, null, Location);
                        AddMethod (reset);
 
-                       reset.Block = new Block (null);
+                       reset.Block = new ToplevelBlock (Location);
                        reset.Block.AddStatement (Create_ThrowNotSupported ());
                }
 
@@ -856,11 +856,11 @@ namespace Mono.CSharp {
                                Parameters.EmptyReadOnlyParameters, null, Location);
                        AddMethod (dispose);
 
-                       dispose.Block = new Block (null);
+                       dispose.Block = new ToplevelBlock (Location);
                        dispose.Block.AddStatement (new DisposeMethod (this, Location));
                }
 
-               public Block Block {
+               public ToplevelBlock Block {
                        get { return block; }
                }
 
index c515e6efcf5c5512c6daf2734acf25efe6f21c55..0e5f20162e27e916a34758280625b864a82cf757 100755 (executable)
@@ -252,7 +252,7 @@ namespace Mono.CSharp {
                        else
                                typeName = TypeName.ToString ();
 
-                       switch (ModFlags & ~Modifier.ISBYREF) {
+                       switch (ModFlags & unchecked (~Modifier.ISBYREF)) {
                                case Modifier.OUT:
                                        return "out " + typeName;
                                case Modifier.PARAMS:
@@ -427,6 +427,13 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               public Parameter GetParameterByName (string name)
+               {
+                       int idx;
+
+                       return GetParameterByName (name, out idx);
+               }
+               
                bool ComputeParameterTypes (EmitContext ec)
                {
                        int extra = (ArrayParameter != null) ? 1 : 0;
index 6ff86a4f87378f45ff7d2552ea3bb7f66fb3cb4b..09ede9f6778da91f8812f4f50f21f691b9df0013 100755 (executable)
@@ -6,6 +6,7 @@
 //   Martin Baulig (martin@gnome.org)
 //
 // (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 
 using System;
@@ -559,6 +560,11 @@ namespace Mono.CSharp {
                {
                        if (ec.ReturnType == null){
                                if (Expr != null){
+                                       if (ec.CurrentAnonymousMethod != null){
+                                               Report.Error (1662, loc, String.Format (
+                                                       "Anonymous method could not be converted to delegate " +
+                                                       "since the return value does not match the delegate value"));
+                                       }
                                        Error (127, "Return with a value not allowed here");
                                        return false;
                                }
@@ -598,6 +604,9 @@ namespace Mono.CSharp {
                        } else
                                vector.CheckOutParameters (ec.CurrentBranching);
 
+                       if (!in_exc)
+                               ec.NeedReturnLabel ();
+
                        ec.CurrentBranching.CurrentUsageVector.Return ();
                        return true;
                }
@@ -611,12 +620,10 @@ namespace Mono.CSharp {
                                        ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
                        }
 
-                       if (in_exc) {
-                               ec.NeedReturnLabel ();
+                       if (in_exc)
                                ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
-                       } else {
+                       else
                                ec.ig.Emit (OpCodes.Ret);
-                       }
                }
        }
 
@@ -755,7 +762,7 @@ namespace Mono.CSharp {
        /// </summary>
        public class GotoCase : Statement {
                Expression expr;
-               Label label;
+               SwitchLabel sl;
                
                public GotoCase (Expression e, Location l)
                {
@@ -785,7 +792,7 @@ namespace Mono.CSharp {
                        if (val == null)
                                return false;
                                        
-                       SwitchLabel sl = (SwitchLabel) ec.Switch.Elements [val];
+                       sl = (SwitchLabel) ec.Switch.Elements [val];
 
                        if (sl == null){
                                Report.Error (
@@ -794,15 +801,13 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       label = sl.ILLabelCode;
-
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Br, label);
+                       ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
                }
        }
        
@@ -891,6 +896,9 @@ namespace Mono.CSharp {
 
                        crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
 
+                       if (!crossing_exc)
+                               ec.NeedReturnLabel ();
+
                        ec.CurrentBranching.CurrentUsageVector.Break ();
                        return true;
                }
@@ -902,7 +910,6 @@ namespace Mono.CSharp {
                        if (crossing_exc)
                                ig.Emit (OpCodes.Leave, ec.LoopEnd);
                        else {
-                               ec.NeedReturnLabel ();
                                ig.Emit (OpCodes.Br, ec.LoopEnd);
                        }
                }
@@ -945,13 +952,17 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // The information about a user-perceived local variable
+       //
        public class LocalInfo {
                public Expression Type;
 
                //
                // Most of the time a variable will be stored in a LocalBuilder
                //
-               // But sometimes, it will be stored in a field.  The context of the field will
+               // But sometimes, it will be stored in a field (variables that have been
+               // hoisted by iterators or by anonymous methods).  The context of the field will
                // be stored in the EmitContext
                //
                //
@@ -969,7 +980,8 @@ namespace Mono.CSharp {
                        Used = 1,
                        ReadOnly = 2,
                        Pinned = 4,
-                       IsThis = 8      
+                       IsThis = 8,
+                       Captured = 16
                }
 
                Flags flags;
@@ -1047,6 +1059,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsCaptured {
+                       get {
+                               return (flags & Flags.Captured) != 0;
+                       }
+
+                       set {
+                               flags |= Flags.Captured;
+                       }
+               }
+
                public override string ToString ()
                {
                        return String.Format ("LocalInfo ({0},{1},{2},{3})",
@@ -1058,7 +1080,7 @@ namespace Mono.CSharp {
                                return (flags & Flags.Used) != 0;
                        }
                        set {
-                               flags = value ? (flags | Flags.Used) : (flags & ~Flags.Used);
+                               flags = value ? (flags | Flags.Used) : (unchecked (flags & ~Flags.Used));
                        }
                }
 
@@ -1067,7 +1089,7 @@ namespace Mono.CSharp {
                                return (flags & Flags.ReadOnly) != 0;
                        }
                        set {
-                               flags = value ? (flags | Flags.ReadOnly) : (flags & ~Flags.ReadOnly);
+                               flags = value ? (flags | Flags.ReadOnly) : (unchecked (flags & ~Flags.ReadOnly));
                        }
                }
 
@@ -1109,12 +1131,12 @@ namespace Mono.CSharp {
        ///   they contain extra information that is not necessary on normal blocks.
        /// </remarks>
        public class Block : Statement {
-               public readonly Block     Parent;
+               public Block    Parent;
                public readonly Location  StartLocation;
-               public Location           EndLocation = Location.Null;
+               public Location EndLocation = Location.Null;
 
                [Flags]
-               public enum Flags : byte {
+               public enum Flags {
                        Implicit  = 1,
                        Unchecked = 2,
                        BlockUsed = 4,
@@ -1122,7 +1144,8 @@ namespace Mono.CSharp {
                        HasRet = 16,
                        IsDestructor = 32,
                        HasVarargs = 64,
-                       Unsafe = 128,
+                       IsToplevel = 128,
+                       Unsafe = 256
                }
                Flags flags;
 
@@ -1191,12 +1214,17 @@ namespace Mono.CSharp {
                // Keeps track of constants
                Hashtable constants;
 
+               //
+               // The parameters for the block, this is only needed on the toplevel block really
+               // TODO: move `parameters' into ToplevelBlock
+               Parameters parameters;
+               
                //
                // If this is a switch section, the enclosing switch block.
                //
                Block switch_block;
 
-               static int id;
+               protected static int id;
 
                int this_id;
                
@@ -1564,17 +1592,79 @@ namespace Mono.CSharp {
                        
                        return e != null;
                }
-               
-               Parameters parameters = null;
-               public Parameters Parameters {
-                       get {
-                               Block b = this;
-                               while (b.Parent != null)
-                                       b = b.Parent;
-                               return b.parameters;
-                       }
+
+               //
+               // Returns a `ParameterReference' for the given name, or null if there
+               // is no such parameter
+               //
+               public ParameterReference GetParameterReference (string name, Location loc)
+               {
+                       Block b = this;
+
+                       do {
+                               Parameters pars = b.parameters;
+                               
+                               if (pars != null){
+                                       Parameter par;
+                                       int idx;
+                                       
+                                       par = pars.GetParameterByName (name, out idx);
+                                       if (par != null){
+                                               ParameterReference pr;
+
+                                               pr = new ParameterReference (pars, this, idx, name, loc);
+                                               return pr;
+                                       }
+                               }
+                               b = b.Parent;
+                       } while (b != null);
+                       return null;
                }
 
+               //
+               // Whether the parameter named `name' is local to this block, 
+               // or false, if the parameter belongs to an encompassing block.
+               //
+               public bool IsLocalParameter (string name)
+               {
+                       Block b = this;
+                       int toplevel_count = 0;
+
+                       do {
+                               if (this is ToplevelBlock)
+                                       toplevel_count++;
+
+                               Parameters pars = b.parameters;
+                               if (pars != null){
+                                       if (pars.GetParameterByName (name) != null)
+                                               return true;
+                                       return false;
+                               }
+                               if (toplevel_count > 0)
+                                       return false;
+                               b = b.Parent;
+                       } while (b != null);
+                       return false;
+               }
+               
+               //
+               // Whether the `name' is a parameter reference
+               //
+               public bool IsParameterReference (string name)
+               {
+                       Block b = this;
+
+                       do {
+                               Parameters pars = b.parameters;
+                               
+                               if (pars != null)
+                                       if (pars.GetParameterByName (name) != null)
+                                               return true;
+                               b = b.Parent;
+                       } while (b != null);
+                       return false;
+               }
+               
                /// <returns>
                ///   A list of labels that were not used within this block
                /// </returns>
@@ -1623,7 +1713,7 @@ namespace Mono.CSharp {
                public VariableMap ParameterMap {
                        get {
                                if ((flags & Flags.VariablesInitialized) == 0)
-                                       throw new Exception ();
+                                       throw new Exception ("Variables have not been initialized yet");
 
                                return param_map;
                        }
@@ -1632,17 +1722,12 @@ namespace Mono.CSharp {
                public VariableMap LocalMap {
                        get {
                                if ((flags & Flags.VariablesInitialized) == 0)
-                                       throw new Exception ();
+                                       throw new Exception ("Variables have not been initialized yet");
 
                                return local_map;
                        }
                }
 
-               public bool LiftVariable (LocalInfo local_info)
-               {
-                       return false;
-               }
-               
                /// <summary>
                ///   Emits the variable declarations and labels.
                /// </summary>
@@ -1650,7 +1735,7 @@ namespace Mono.CSharp {
                ///   tc: is our typecontainer (to resolve type references)
                ///   ig: is the code generator:
                /// </remarks>
-               public void EmitMeta (EmitContext ec, InternalParameters ip)
+               public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)
                {
                        ILGenerator ig = ec.ig;
 
@@ -1687,8 +1772,7 @@ namespace Mono.CSharp {
 
                        bool old_check_state = ec.ConstantCheckState;
                        ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
-                       bool remap_locals = ec.RemapToProxy;
-                               
+                       
                        //
                        // Process this block variables
                        //
@@ -1713,6 +1797,7 @@ namespace Mono.CSharp {
                                                        continue;
                                        }
 
+#if false
                                        if (remap_locals)
                                                vi.FieldBuilder = ec.MapVariable (name, vi.VariableType);
                                        else if (vi.Pinned)
@@ -1723,6 +1808,7 @@ namespace Mono.CSharp {
                                                vi.LocalBuilder = TypeManager.DeclareLocalPinned (ig, vi.VariableType);
                                        else if (!vi.IsThis)
                                                vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+#endif
 
                                        if (constants == null)
                                                continue;
@@ -1761,12 +1847,49 @@ namespace Mono.CSharp {
                        //
                        if (children != null){
                                foreach (Block b in children)
-                                       b.EmitMeta (ec, ip);
+                                       b.ResolveMeta (toplevel, ec, ip);
                        }
-
                        ec.InUnsafe = old_unsafe;
                }
 
+               //
+               // Emits the local variable declarations for a block
+               //
+               public void EmitMeta (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (variables != null){
+                               bool have_captured_vars = ec.HaveCapturedVariables ();
+                               bool remap_locals = ec.RemapToProxy;
+                               
+                               foreach (DictionaryEntry de in variables){
+                                       LocalInfo vi = (LocalInfo) de.Value;
+
+                                       if (have_captured_vars && ec.IsCaptured (vi))
+                                               continue;
+
+                                       if (remap_locals){
+                                               vi.FieldBuilder = ec.MapVariable (vi.Name, vi.VariableType);
+                                       } else {
+                                               if (vi.Pinned)
+                                                       //
+                                                       // This is needed to compile on both .NET 1.x and .NET 2.x
+                                                       // the later introduced `DeclareLocal (Type t, bool pinned)'
+                                                       //
+                                                       vi.LocalBuilder = TypeManager.DeclareLocalPinned (ig, vi.VariableType);
+                                               else if (!vi.IsThis)
+                                                       vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+                                       }
+                               }
+                       }
+
+                       if (children != null){
+                               foreach (Block b in children)
+                                       b.EmitMeta (ec);
+                       }
+               }
+
                void UsageWarning (FlowBranching.UsageVector vector)
                {
                        string name;
@@ -1934,28 +2057,128 @@ namespace Mono.CSharp {
 
                        ec.CurrentBlock = prev_block;
                }
+
+               public ToplevelBlock Toplevel {
+                       get {
+                               Block b = this;
+                               while (b.Parent != null){
+                                       if ((b.flags & Flags.IsToplevel) != 0)
+                                               break;
+                                       b = b.Parent;
+                               }
+
+                               return (ToplevelBlock) b;
+                       }
+               }
+
+               //
+               // Returns true if we ar ea child of `b'.
+               //
+               public bool IsChildOf (Block b)
+               {
+                       Block current = this;
+                       
+                       do {
+                               if (current.Parent == b)
+                                       return true;
+                               current = current.Parent;
+                       } while (current != null);
+                       return false;
+               }
        }
 
        //
+       // A toplevel block contains extra information, the split is done
+       // only to separate information that would otherwise bloat the more
+       // lightweight Block.
+       //
+       // In particular, this was introduced when the support for Anonymous
+       // Methods was implemented. 
        // 
        public class ToplevelBlock : Block {
+               //
+               // Pointer to the host of this anonymous method, or null
+               // if we are the topmost block
+               //
+               public ToplevelBlock Container;
+               CaptureContext capture_context;
+
+               Hashtable capture_contexts;
+
+               static int did = 0;
+               
+               int my_id = did++;
+
+                       
+               public void RegisterCaptureContext (CaptureContext cc)
+               {
+                       if (capture_contexts == null)
+                               capture_contexts = new Hashtable ();
+                       capture_contexts [cc] = cc;
+               }
+
+               public void CompleteContexts ()
+               {
+                       if (capture_contexts == null)
+                               return;
+
+                       foreach (CaptureContext cc in capture_contexts.Keys){
+                               cc.AdjustScopes ();
+                       }
+               }
+               
+               public CaptureContext ToplevelBlockCaptureContext {
+                       get {
+                               return capture_context;
+                       }
+               }
+               
+               //
+               // Parent is only used by anonymous blocks to link back to their
+               // parents
+               //
+               public ToplevelBlock (ToplevelBlock container, Parameters parameters, Location start) :
+                       base (null, Flags.IsToplevel, parameters, start, Location.Null)
+               {
+                       Container = container;
+               }
+               
                public ToplevelBlock (Parameters parameters, Location start) :
-                       base (null, parameters, start, Location.Null)
+                       base (null, Flags.IsToplevel, parameters, start, Location.Null)
                {
                }
 
                public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
-                       base (null, flags, parameters, start, Location.Null)
+                       base (null, flags | Flags.IsToplevel, parameters, start, Location.Null)
                {
                }
+
+               public ToplevelBlock (Location loc) : base (null, Flags.IsToplevel, loc, loc)
+               {
+               }
+
+               public void SetHaveAnonymousMethods (Location loc, AnonymousMethod host)
+               {
+                       if (capture_context == null)
+                               capture_context = new CaptureContext (this, loc, host);
+               }
+
+               public CaptureContext CaptureContext {
+                       get {
+                               return capture_context;
+                       }
+               }
        }
        
        public class SwitchLabel {
                Expression label;
                object converted;
                public Location loc;
-               public Label ILLabel;
-               public Label ILLabelCode;
+
+               Label il_label;
+               bool  il_label_set;
+               Label il_label_code;
+               bool  il_label_code_set;
 
                //
                // if expr == null, then it is the default case.
@@ -1978,15 +2201,30 @@ namespace Mono.CSharp {
                        }
                }
 
+               public Label GetILLabel (EmitContext ec)
+               {
+                       if (!il_label_set){
+                               il_label = ec.ig.DefineLabel ();
+                               il_label_set = true;
+                       }
+                       return il_label;
+               }
+
+               public Label GetILLabelCode (EmitContext ec)
+               {
+                       if (!il_label_code_set){
+                               il_label_code = ec.ig.DefineLabel ();
+                               il_label_code_set = true;
+                       }
+                       return il_label_code;
+               }                               
+               
                //
                // Resolves the expression, reduces it to a literal if possible
                // and then converts it to the requested type.
                //
                public bool ResolveAndReduce (EmitContext ec, Type required_type)
                {
-                       ILLabel = ec.ig.DefineLabel ();
-                       ILLabelCode = ec.ig.DefineLabel ();
-
                        if (label == null)
                                return true;
                        
@@ -2003,7 +2241,6 @@ namespace Mono.CSharp {
                        if (e is StringConstant || e is NullLiteral){
                                if (required_type == TypeManager.string_type){
                                        converted = e;
-                                       ILLabel = ec.ig.DefineLabel ();
                                        return true;
                                }
                        }
@@ -2470,7 +2707,7 @@ namespace Mono.CSharp {
                                                ig.Emit (OpCodes.Ldloc, val);
                                                EmitObjectInteger (ig, key);
                                                SwitchLabel sl = (SwitchLabel) Elements [key];
-                                               ig.Emit (OpCodes.Beq, sl.ILLabel);
+                                               ig.Emit (OpCodes.Beq, sl.GetILLabel (ec));
                                        }
                                }
                                else
@@ -2526,7 +2763,7 @@ namespace Mono.CSharp {
                                                if (System.Convert.ToInt64 (key) == kb.nFirst + iJump)
                                                {
                                                        SwitchLabel sl = (SwitchLabel) Elements [key];
-                                                       rgLabels [iJump] = sl.ILLabel;
+                                                       rgLabels [iJump] = sl.GetILLabel (ec);
                                                        iKey++;
                                                }
                                                else
@@ -2554,8 +2791,8 @@ namespace Mono.CSharp {
                        {
                                foreach (SwitchLabel sl in ss.Labels)
                                {
-                                       ig.MarkLabel (sl.ILLabel);
-                                       ig.MarkLabel (sl.ILLabelCode);
+                                       ig.MarkLabel (sl.GetILLabel (ec));
+                                       ig.MarkLabel (sl.GetILLabelCode (ec));
                                        if (sl.Label == null)
                                        {
                                                ig.MarkLabel (lblDefault);
@@ -2613,7 +2850,7 @@ namespace Mono.CSharp {
                                null_found = false;
                                for (int label = 0; label < label_count; label++){
                                        SwitchLabel sl = (SwitchLabel) ss.Labels [label];
-                                       ig.MarkLabel (sl.ILLabel);
+                                       ig.MarkLabel (sl.GetILLabel (ec));
                                        
                                        if (!first_test){
                                                ig.MarkLabel (next_test);
@@ -2655,7 +2892,7 @@ namespace Mono.CSharp {
                                        ig.MarkLabel (null_target);
                                ig.MarkLabel (sec_begin);
                                foreach (SwitchLabel sl in ss.Labels)
-                                       ig.MarkLabel (sl.ILLabelCode);
+                                       ig.MarkLabel (sl.GetILLabelCode (ec));
 
                                if (mark_default)
                                        ig.MarkLabel (default_target);
@@ -4205,7 +4442,7 @@ namespace Mono.CSharp {
 
                        if (ec.InIterator){
                                conv.Emit (ec);
-                               ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                               ig.Emit (OpCodes.Stfld, ((LocalVariableReference) variable).local_info.FieldBuilder);
                        } else 
                                ((IAssignMethod)variable).EmitAssign (ec, conv, false, false);
                                
@@ -4311,7 +4548,7 @@ namespace Mono.CSharp {
                                ArrayAccess.EmitLoadOpcode (ig, element_type);
                                if (ec.InIterator){
                                        conv.Emit (ec);
-                                       ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                                       ig.Emit (OpCodes.Stfld, ((LocalVariableReference) variable).local_info.FieldBuilder);
                                } else 
                                        ((IAssignMethod)variable).EmitAssign (ec, conv, false, false);
 
@@ -4391,7 +4628,7 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Call, get);
                                if (ec.InIterator){
                                        conv.Emit (ec);
-                                       ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                                       ig.Emit (OpCodes.Stfld, ((LocalVariableReference) variable).local_info.FieldBuilder);
                                } else 
                                        ((IAssignMethod)variable).EmitAssign (ec, conv, false, false);
                                statement.Emit (ec);
index 358266661f95f6eae45d1d8874c8432075b235ed..6f7f2154b43c54c6e93640f378617bf7750a4410 100755 (executable)
@@ -87,6 +87,7 @@ public class TypeManager {
        static public Type obsolete_attribute_type;
        static public Type conditional_attribute_type;
        static public Type in_attribute_type;
+       static public Type anonymous_method_type;
        static public Type cls_compliant_attribute_type;
        static public Type typed_reference_type;
        static public Type arg_iterator_type;
@@ -1241,6 +1242,11 @@ public class TypeManager {
                system_asynccallback_expr.Type = asynccallback_type;
                system_iasyncresult_expr.Type = iasyncresult_type;
                system_valuetype_expr.Type = value_type;
+
+               //
+               // These are only used for compare purposes
+               //
+               anonymous_method_type = typeof (AnonymousMethod);
        }
 
        //