+++ /dev/null
-Index: report.cs
-===================================================================
---- report.cs (revision 63019)
-+++ report.cs (working copy)
-@@ -634,6 +634,10 @@
- : base (message)
- {
- }
-+
-+ public InternalErrorException (string message, params object[] args)
-+ : base (String.Format (message, args))
-+ { }
- }
-
- /// <summary>
-Index: generic.cs
-===================================================================
---- generic.cs (revision 63019)
-+++ generic.cs (working copy)
-@@ -151,11 +151,14 @@
- }
-
- public override string TypeParameter {
-- get {
-- return name;
-- }
-+ get { return name; }
- }
-
-+ public Constraints Clone ()
-+ {
-+ return new Constraints (name, constraints, loc);
-+ }
-+
- GenericParameterAttributes attrs;
- TypeExpr class_constraint;
- ArrayList iface_constraints;
-@@ -739,7 +742,7 @@
- TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb));
- return false;
- }
-- } else if (DeclSpace is Iterator) {
-+ } else if (DeclSpace is CompilerGeneratedClass) {
- TypeParameter[] tparams = DeclSpace.TypeParameters;
- Type[] types = new Type [tparams.Length];
- for (int i = 0; i < tparams.Length; i++)
-@@ -2622,7 +2625,7 @@
-
- Argument a = (Argument) arguments [i];
- if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr) ||
-- (a.Expr is AnonymousMethod))
-+ (a.Expr is AnonymousMethodExpression))
- continue;
-
- arg_types [i] = a.Type;
-Index: typemanager.cs
-===================================================================
---- typemanager.cs (revision 63019)
-+++ typemanager.cs (working copy)
-@@ -71,6 +71,7 @@
- static public Type asynccallback_type;
- static public Type intptr_type;
- static public Type monitor_type;
-+ static public Type interlocked_type;
- static public Type runtime_field_handle_type;
- static public Type runtime_argument_handle_type;
- static public Type attribute_type;
-@@ -974,6 +975,7 @@
- icloneable_type = CoreLookupType ("System", "ICloneable");
- iconvertible_type = CoreLookupType ("System", "IConvertible");
- monitor_type = CoreLookupType ("System.Threading", "Monitor");
-+ interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
- intptr_type = CoreLookupType ("System", "IntPtr");
-
- attribute_type = CoreLookupType ("System", "Attribute");
-Index: parameter.cs
-===================================================================
---- parameter.cs (revision 63019)
-+++ parameter.cs (working copy)
-@@ -208,10 +208,16 @@
- public Expression TypeName;
- public readonly Modifier ModFlags;
- public string Name;
-+ public bool IsCaptured;
- GenericConstraints constraints;
- protected Type parameter_type;
- public readonly Location Location;
-
-+ Variable var;
-+ public Variable Variable {
-+ get { return var; }
-+ }
-+
- IResolveContext resolve_context;
-
- public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
-@@ -335,6 +341,16 @@
- return true;
- }
-
-+ public void ResolveVariable (ToplevelBlock toplevel, int idx)
-+ {
-+ Report.Debug (64, "PARAMETER RESOLVE VARIABLE", ParameterType, Name, Location);
-+ if (toplevel.AnonymousMethodHost != null)
-+ var = toplevel.AnonymousMethodHost.GetCapturedParameter (this);
-+ Report.Debug (64, "PARAMETER RESOLVE VARIABLE #1", var, idx);
-+ if (var == null)
-+ var = new ParameterVariable (this, idx);
-+ }
-+
- public Type ExternalType ()
- {
- if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
-@@ -452,6 +468,78 @@
- return attribute_targets;
- }
- }
-+
-+ protected class ParameterVariable : Variable
-+ {
-+ public readonly Parameter Parameter;
-+ public readonly int Idx;
-+ public readonly bool IsRef;
-+
-+ public ParameterVariable (Parameter par, int idx)
-+ {
-+ this.Parameter = par;
-+ this.Idx = idx;
-+ this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0;
-+ }
-+
-+ public override Type Type {
-+ get { return Parameter.ParameterType; }
-+ }
-+
-+ public override bool HasInstance {
-+ get { return false; }
-+ }
-+
-+ public override bool NeedsTemporary {
-+ get { return false; }
-+ }
-+
-+ public override void EmitInstance (EmitContext ec)
-+ {
-+ }
-+
-+ public override void Emit (EmitContext ec)
-+ {
-+ int arg_idx = Idx;
-+ if (!ec.MethodIsStatic)
-+ arg_idx++;
-+
-+ ParameterReference.EmitLdArg (ec.ig, arg_idx);
-+ }
-+
-+ public override void EmitAssign (EmitContext ec)
-+ {
-+ int arg_idx = Idx;
-+ if (!ec.MethodIsStatic)
-+ arg_idx++;
-+
-+ if (arg_idx <= 255)
-+ ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
-+ else
-+ ec.ig.Emit (OpCodes.Starg, arg_idx);
-+ }
-+
-+ public override void EmitAddressOf (EmitContext ec)
-+ {
-+ int arg_idx = Idx;
-+
-+ if (!ec.MethodIsStatic)
-+ arg_idx++;
-+
-+ if (IsRef) {
-+ if (arg_idx <= 255)
-+ ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
-+ else
-+ ec.ig.Emit (OpCodes.Ldarg, arg_idx);
-+ } else {
-+ if (arg_idx <= 255)
-+ ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
-+ else
-+ ec.ig.Emit (OpCodes.Ldarga, arg_idx);
-+ }
-+ }
-+ }
-+
- }
-
- /// <summary>
-@@ -607,6 +695,14 @@
- return ok;
- }
-
-+ public void ResolveVariable (ToplevelBlock toplevel)
-+ {
-+ for (int i = 0; i < FixedParameters.Length; ++i) {
-+ Parameter p = FixedParameters [i];
-+ p.ResolveVariable (toplevel, i);
-+ }
-+ }
-+
- public CallingConventions CallingConvention
- {
- get {
-@@ -665,7 +761,7 @@
- }
- }
-
-- Parameter this [int pos]
-+ public Parameter this [int pos]
- {
- get {
- if (pos >= count && (HasArglist || HasParams)) {
-Index: modifiers.cs
-===================================================================
---- modifiers.cs (revision 63019)
-+++ modifiers.cs (working copy)
-@@ -36,6 +36,7 @@
- //
- public const int METHOD_YIELDS = 0x8000;
- public const int METHOD_GENERIC = 0x10000;
-+ public const int ANONYMOUS_HOST = 0x20000;
-
- public const int Accessibility =
- PUBLIC | PROTECTED | INTERNAL | PRIVATE;
-Index: rootcontext.cs
-===================================================================
---- rootcontext.cs (revision 63019)
-+++ rootcontext.cs (working copy)
-@@ -377,6 +377,7 @@
- "System.Runtime.CompilerServices.RuntimeHelpers",
- "System.Reflection.DefaultMemberAttribute",
- "System.Threading.Monitor",
-+ "System.Threading.Interlocked",
-
- "System.AttributeUsageAttribute",
- "System.Runtime.InteropServices.DllImportAttribute",
-Index: ecore.cs
-===================================================================
---- ecore.cs (revision 63019)
-+++ ecore.cs (working copy)
-@@ -3146,8 +3146,6 @@
- "this");
- return null;
- }
-- if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
-- ec.CaptureField (this);
- }
- }
-
-@@ -4007,10 +4005,10 @@
- }
- }
-
--
- public class TemporaryVariable : Expression, IMemoryLocation
- {
- LocalInfo li;
-+ Variable var;
-
- public TemporaryVariable (Type type, Location loc)
- {
-@@ -4028,64 +4026,47 @@
- li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
- if (!li.Resolve (ec))
- return null;
-+
-+ if (ec.MustCaptureVariable (li)) {
-+ ScopeInfo scope = li.Block.CreateScopeInfo ();
-+ var = scope.AddLocal (li);
-+ type = var.Type;
-+ }
-
-- AnonymousContainer am = ec.CurrentAnonymousMethod;
-- if ((am != null) && am.IsIterator)
-- ec.CaptureVariable (li);
--
- return this;
- }
-+
-+ public Variable Variable {
-+ get { return var != null ? var : li.Variable; }
-+ }
-
- public override void Emit (EmitContext ec)
- {
-- ILGenerator ig = ec.ig;
--
-- if (li.FieldBuilder != null) {
-- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
-- } else {
-- ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
-- }
-+ Variable.EmitInstance (ec);
-+ Variable.Emit (ec);
- }
-
- public void EmitLoadAddress (EmitContext ec)
- {
-- ILGenerator ig = ec.ig;
--
-- if (li.FieldBuilder != null) {
-- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
-- } else {
-- ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
-- }
-+ Variable.EmitInstance (ec);
-+ Variable.EmitAddressOf (ec);
- }
-
- public void Store (EmitContext ec, Expression right_side)
- {
-- if (li.FieldBuilder != null)
-- ec.ig.Emit (OpCodes.Ldarg_0);
--
-+ Variable.EmitInstance (ec);
- right_side.Emit (ec);
-- if (li.FieldBuilder != null) {
-- ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
-- } else {
-- ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
-- }
-+ Variable.EmitAssign (ec);
- }
-
- public void EmitThis (EmitContext ec)
- {
-- if (li.FieldBuilder != null) {
-- ec.ig.Emit (OpCodes.Ldarg_0);
-- }
-+ Variable.EmitInstance (ec);
- }
-
-- public void EmitStore (ILGenerator ig)
-+ public void EmitStore (EmitContext ec)
- {
-- if (li.FieldBuilder != null)
-- ig.Emit (OpCodes.Stfld, li.FieldBuilder);
-- else
-- ig.Emit (OpCodes.Stloc, li.LocalBuilder);
-+ Variable.EmitAssign (ec);
- }
-
- public void AddressOf (EmitContext ec, AddressOp mode)
-@@ -4093,5 +4074,5 @@
- EmitLoadAddress (ec);
- }
- }
--
-+
- }
-Index: class.cs
-===================================================================
---- class.cs (revision 63019)
-+++ class.cs (working copy)
-@@ -69,8 +69,7 @@
- foreach (MemberCore mc in this) {
- try {
- mc.Define ();
-- }
-- catch (Exception e) {
-+ } catch (Exception e) {
- throw new InternalErrorException (mc.Location, mc.GetSignatureForError (), e);
- }
- }
-@@ -133,7 +132,6 @@
- Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
- }
- }
--
- }
-
- public sealed class IndexerArrayList : MemberCoreArrayList
-@@ -429,8 +427,8 @@
- // Holds the operators
- MemberCoreArrayList operators;
-
-- // Holds the iterators
-- ArrayList iterators;
-+ // Holds the compiler generated classes
-+ ArrayList compiler_generated;
-
- //
- // Pointers to the default constructor and the default static constructor
-@@ -455,6 +453,8 @@
-
- ArrayList type_bases;
-
-+ bool type_populated;
-+ bool type_populated_ok;
- bool members_defined;
- bool members_defined_ok;
-
-@@ -772,12 +772,14 @@
- operators.Add (op);
- }
-
-- public void AddIterator (Iterator i)
-+ public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
- {
-- if (iterators == null)
-- iterators = new ArrayList ();
-+ Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
-
-- iterators.Add (i);
-+ if (compiler_generated == null)
-+ compiler_generated = new ArrayList ();
-+
-+ compiler_generated.Add (c);
- }
-
- public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
-@@ -822,9 +824,9 @@
- }
- }
-
-- public ArrayList Iterators {
-+ public ArrayList CompilerGenerated {
- get {
-- return iterators;
-+ return compiler_generated;
- }
- }
-
-@@ -1202,7 +1204,7 @@
- // Let's do it as soon as possible, since code below can call DefineType() on classes
- // that depend on us to be populated before they are.
- //
-- if (!(this is Iterator))
-+ if (!(this is Iterator) && !(this is CompilerGeneratedClass))
- RootContext.RegisterOrder (this);
-
- if (base_type != null) {
-@@ -1278,11 +1280,53 @@
- part.TypeBuilder = TypeBuilder;
- }
-
-+ if (!CreateAnonymousHelpers ()) {
-+ error = true;
-+ return null;
-+ }
-+
- DefineNestedTypes ();
-
- return TypeBuilder;
- }
-
-+ protected bool CreateAnonymousHelpers ()
-+ {
-+ if (methods != null) {
-+ foreach (Method method in methods) {
-+ if (!method.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-+
-+ if (operators != null) {
-+ foreach (Operator o in operators) {
-+ if (!o.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-+
-+ if (properties != null) {
-+ foreach (PropertyBase p in properties) {
-+ if (!p.Get.IsDummy && !p.Get.CreateAnonymousHelpers ())
-+ return false;
-+ if (!p.Set.IsDummy && !p.Set.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-+
-+ if (indexers != null) {
-+ foreach (PropertyBase p in indexers) {
-+ if (!p.Get.IsDummy && !p.Get.CreateAnonymousHelpers ())
-+ return false;
-+ if (!p.Set.IsDummy && !p.Set.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+ }
-+
- Constraints [] constraints;
- public override void SetParameterInfo (ArrayList constraints_list)
- {
-@@ -1329,6 +1373,20 @@
-
- public bool ResolveType ()
- {
-+ if (!DoResolveType ())
-+ return false;
-+
-+ if (compiler_generated != null) {
-+ foreach (CompilerGeneratedClass c in compiler_generated)
-+ if (!c.ResolveType ())
-+ return false;
-+ }
-+
-+ return true;
-+ }
-+
-+ protected virtual bool DoResolveType ()
-+ {
- if ((base_type != null) &&
- (base_type.ResolveAsTypeTerminal (this, false) == null)) {
- error = true;
-@@ -1413,6 +1471,13 @@
- return false;
- }
-
-+ if (compiler_generated != null) {
-+ foreach (CompilerGeneratedClass c in compiler_generated) {
-+ if (c.DefineType () == null)
-+ return false;
-+ }
-+ }
-+
- return true;
- }
-
-@@ -1462,6 +1527,22 @@
- Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
- }
-
-+ protected bool PopulateType ()
-+ {
-+ if (type_populated)
-+ return type_populated_ok;
-+
-+ type_populated_ok = DoPopulateType ();
-+ type_populated = true;
-+
-+ return type_populated_ok;
-+ }
-+
-+ protected virtual bool DoPopulateType ()
-+ {
-+ return true;
-+ }
-+
- /// <summary>
- /// Populates our TypeBuilder with fields and methods
- /// </summary>
-@@ -1541,18 +1622,7 @@
- part.member_cache = member_cache;
- }
- #endif
-- if (iterators != null) {
-- foreach (Iterator iterator in iterators) {
-- if (iterator.DefineType () == null)
-- return false;
-- }
-
-- foreach (Iterator iterator in iterators) {
-- if (!iterator.DefineMembers ())
-- return false;
-- }
-- }
--
- return true;
- }
-
-@@ -1564,9 +1634,9 @@
-
- public override bool Define ()
- {
-- if (iterators != null) {
-- foreach (Iterator iterator in iterators) {
-- if (!iterator.Define ())
-+ if (compiler_generated != null) {
-+ foreach (CompilerGeneratedClass c in compiler_generated) {
-+ if (!c.Define ())
- return false;
- }
- }
-@@ -2239,7 +2309,7 @@
-
- if (default_static_constructor != null)
- default_static_constructor.Emit ();
--
-+
- if (methods != null){
- foreach (Method m in methods)
- m.Emit ();
-@@ -2282,9 +2352,14 @@
- if (pending.VerifyPendingMethods ())
- return;
-
-- if (iterators != null)
-- foreach (Iterator iterator in iterators)
-- iterator.EmitType ();
-+ if (compiler_generated != null) {
-+ foreach (CompilerGeneratedClass c in compiler_generated) {
-+ if (!c.DefineMembers ())
-+ throw new InternalErrorException ();
-+ }
-+ foreach (CompilerGeneratedClass c in compiler_generated)
-+ c.EmitType ();
-+ }
- }
-
- public override void CloseType ()
-@@ -2324,9 +2399,9 @@
- foreach (Delegate d in Delegates)
- d.CloseType ();
-
-- if (Iterators != null)
-- foreach (Iterator i in Iterators)
-- i.CloseType ();
-+ if (CompilerGenerated != null)
-+ foreach (CompilerGeneratedClass c in CompilerGenerated)
-+ c.CloseType ();
-
- types = null;
- properties = null;
-@@ -2341,7 +2416,7 @@
- events = null;
- indexers = null;
- operators = null;
-- iterators = null;
-+ compiler_generated = null;
- default_constructor = null;
- default_static_constructor = null;
- type_bases = null;
-@@ -3194,7 +3269,7 @@
- }
- }
-
-- public void SetYields ()
-+ public virtual void SetYields ()
- {
- ModFlags |= Modifiers.METHOD_YIELDS;
- }
-@@ -3652,6 +3727,9 @@
- ListDictionary declarative_security;
- protected MethodData MethodData;
-
-+ Iterator iterator;
-+ ArrayList anonymous_methods;
-+
- static string[] attribute_targets = new string [] { "method", "return" };
-
- protected MethodOrOperator (DeclSpace parent, GenericMethod generic, Expression type, int mod,
-@@ -3702,24 +3780,29 @@
- }
- }
-
-- public EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
-+ public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
- {
-- EmitContext ec = new EmitContext (this,
-- tc, this.ds, Location, ig, MemberType, ModFlags, false);
-+ return new EmitContext (
-+ this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
-+ }
-
-- Iterator iterator = tc as Iterator;
-- if (iterator != null)
-- ec.CurrentAnonymousMethod = iterator.Host;
--
-- return ec;
-+ public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
-+ {
-+ if (anonymous_methods == null)
-+ anonymous_methods = new ArrayList ();
-+ anonymous_methods.Add (anonymous);
- }
-
-- public override bool Define ()
-+ bool base_defined;
-+
-+ protected bool DefineGenericMethod ()
- {
-+ if (base_defined)
-+ return true;
-+
- if (!DoDefineBase ())
- return false;
-
-- MethodBuilder mb = null;
- if (GenericMethod != null) {
- string method_name = MemberName.Name;
-
-@@ -3728,12 +3811,49 @@
- '.' + method_name;
- }
-
-- mb = Parent.TypeBuilder.DefineMethod (method_name, flags);
-+ MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
-
-- if (!GenericMethod.Define (mb))
-+ if (!GenericMethod.Define (MethodBuilder))
- return false;
- }
-
-+ base_defined = true;
-+ return true;
-+ }
-+
-+ public bool CreateAnonymousHelpers ()
-+ {
-+ Report.Debug (64, "METHOD DEFINE HELPERS", this, Name,
-+ ModFlags & Modifiers.METHOD_YIELDS,
-+ ModFlags & Modifiers.ANONYMOUS_HOST,
-+ Block);
-+
-+ if (!DefineGenericMethod ())
-+ return false;
-+
-+ if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
-+ iterator = Iterator.CreateIterator (
-+ this, ParentContainer, GenericMethod, ModFlags);
-+
-+ if (iterator == null)
-+ return false;
-+ }
-+
-+ if (anonymous_methods != null) {
-+ foreach (AnonymousMethodExpression ame in anonymous_methods) {
-+ if (!ame.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+ }
-+
-+ public override bool Define ()
-+ {
-+ if (!DefineGenericMethod ())
-+ return false;
-+
- if (!DoDefine ())
- return false;
-
-@@ -3743,7 +3863,8 @@
- if (!CheckBase ())
- return false;
-
-- MethodData = new MethodData (this, ModFlags, flags, this, mb, GenericMethod, base_method);
-+ MethodData = new MethodData (
-+ this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
-
- if (!MethodData.Define (ParentContainer))
- return false;
-@@ -3821,6 +3942,10 @@
- }
- }
-
-+ public Iterator Iterator {
-+ get { return iterator; }
-+ }
-+
- public new Location Location {
- get {
- return base.Location;
-@@ -3961,7 +4086,7 @@
- }
- }
-
-- public class Method : MethodOrOperator, IIteratorContainer {
-+ public class Method : MethodOrOperator, IAnonymousHost {
-
- /// <summary>
- /// Modifiers allowed in a class declaration
-@@ -3978,7 +4103,8 @@
- Modifiers.OVERRIDE |
- Modifiers.ABSTRACT |
- Modifiers.UNSAFE |
-- Modifiers.METHOD_YIELDS |
-+ Modifiers.METHOD_YIELDS |
-+ Modifiers.ANONYMOUS_HOST |
- Modifiers.EXTERN;
-
- const int AllowedInterfaceModifiers =
-@@ -4118,6 +4244,8 @@
- //
- public override bool Define ()
- {
-+ Report.Debug (64, "METHOD DEFINE", this, Name);
-+
- if (!base.Define ())
- return false;
-
-@@ -4132,17 +4260,6 @@
- }
-
- //
-- // Setup iterator if we are one
-- //
-- if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
-- Iterator iterator = new Iterator (
-- this, Parent, GenericMethod, ModFlags);
--
-- if (!iterator.DefineIterator ())
-- return false;
-- }
--
-- //
- // This is used to track the Entry Point,
- //
- if (Name == "Main" &&
-@@ -4179,6 +4296,7 @@
- //
- public override void Emit ()
- {
-+ Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
- MethodData.Emit (Parent);
- base.Emit ();
-
-@@ -4360,6 +4478,10 @@
-
- static string[] attribute_targets = new string [] { "method" };
-
-+ public Iterator Iterator {
-+ get { return null; }
-+ }
-+
- bool has_compliant_args = false;
- //
- // The spec claims that static is not permitted, but
-@@ -4581,6 +4703,13 @@
- ParentContainer.EmitFieldInitializers (ec);
- }
- }
-+
-+ bool unreachable = false;
-+ if (block != null) {
-+ ec.ResolveTopBlock (null, block, ParameterInfo, this, out unreachable);
-+ ec.EmitMeta (block);
-+ }
-+
- if (Initializer != null) {
- Initializer.Emit (ec);
- }
-@@ -4588,7 +4717,8 @@
- if ((ModFlags & Modifiers.STATIC) != 0)
- ParentContainer.EmitFieldInitializers (ec);
-
-- ec.EmitTopBlock (this, block);
-+ if (block != null)
-+ ec.EmitResolvedTopBlock (block, unreachable);
-
- if (source != null)
- source.CloseMethod ();
-@@ -4710,6 +4840,8 @@
- GenericMethod GenericMethod { get; }
- Parameters ParameterInfo { get; }
-
-+ Iterator Iterator { get; }
-+
- Attributes OptAttributes { get; }
- ToplevelBlock Block { get; set; }
-
-@@ -5032,6 +5164,20 @@
-
- SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
-
-+ Report.Debug (64, "METHOD DATA EMIT", this, MethodBuilder,
-+ method, method.Iterator, block);
-+
-+#if FIXME
-+ if (method.Iterator != null) {
-+ if (!method.Iterator.Resolve (ec))
-+ throw new InternalErrorException ();
-+ // method.Iterator.EmitMethod (ec);
-+ }
-+#endif
-+
-+ Report.Debug (64, "METHOD DATA EMIT #1", this, MethodBuilder,
-+ method, method.Iterator, block);
-+
- //
- // Handle destructors specially
- //
-@@ -5860,7 +6006,7 @@
- //
- // `set' and `get' accessors are represented with an Accessor.
- //
-- public class Accessor : IIteratorContainer {
-+ public class Accessor : IAnonymousHost {
- //
- // Null if the accessor is empty, or a Block if not
- //
-@@ -5875,6 +6021,7 @@
- public Location Location;
- public int ModFlags;
- public bool Yields;
-+ public ArrayList AnonymousMethods;
-
- public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
- {
-@@ -5888,6 +6035,13 @@
- {
- Yields = true;
- }
-+
-+ public void AddAnonymousMethod (AnonymousMethodExpression ame)
-+ {
-+ if (AnonymousMethods == null)
-+ AnonymousMethods = new ArrayList ();
-+ AnonymousMethods.Add (ame);
-+ }
- }
-
- // Ooouh Martin, templates are missing here.
-@@ -5934,6 +6088,10 @@
-
- #region IMethodData Members
-
-+ public abstract Iterator Iterator {
-+ get;
-+ }
-+
- public ToplevelBlock Block {
- get {
- return block;
-@@ -6220,6 +6378,8 @@
- {
- protected readonly MethodCore method;
- protected MethodAttributes flags;
-+ Iterator iterator;
-+ ArrayList anonymous_methods;
- bool yields;
-
- public PropertyMethod (MethodCore method, string prefix)
-@@ -6235,12 +6395,17 @@
- this.method = method;
- this.ModFlags = accessor.ModFlags;
- yields = accessor.Yields;
-+ anonymous_methods = accessor.AnonymousMethods;
-
- if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
- Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
- }
- }
-
-+ public override Iterator Iterator {
-+ get { return iterator; }
-+ }
-+
- public override AttributeTargets AttributeTargets {
- get {
- return AttributeTargets.Method;
-@@ -6252,6 +6417,28 @@
- return method.IsClsComplianceRequired ();
- }
-
-+ public bool CreateAnonymousHelpers ()
-+ {
-+ TypeContainer container = ((TypeContainer) Parent).PartialContainer;
-+
-+ if (yields) {
-+ iterator = Iterator.CreateIterator (
-+ this, container, null, ModFlags);
-+
-+ if (iterator == null)
-+ return false;
-+ }
-+
-+ if (anonymous_methods != null) {
-+ foreach (AnonymousMethodExpression ame in anonymous_methods) {
-+ if (!ame.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+ }
-+
- public virtual MethodBuilder Define (DeclSpace parent)
- {
- if (!method.CheckAbstractAndExtern (block != null))
-@@ -6281,16 +6468,6 @@
- flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
- }
-
-- //
-- // Setup iterator if we are one
-- //
-- if (yields) {
-- Iterator iterator = new Iterator (this, Parent as TypeContainer, null, ModFlags);
--
-- if (!iterator.DefineIterator ())
-- return null;
-- }
--
- return null;
- }
-
-@@ -6932,6 +7109,10 @@
- this.method = method;
- }
-
-+ public override Iterator Iterator {
-+ get { return null; }
-+ }
-+
- protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
- {
- if (a.Target == AttributeTargets.Parameter) {
-@@ -7183,7 +7364,7 @@
- }
-
-
-- public class Indexer : PropertyBase, IIteratorContainer {
-+ public class Indexer : PropertyBase {
-
- class GetIndexerMethod : GetMethod
- {
-@@ -7323,10 +7504,10 @@
- // Setup iterator if we are one
- //
- if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
-- Iterator iterator = new Iterator (
-- Get, Parent, null, ModFlags);
-+ Iterator iterator = Iterator.CreateIterator (
-+ Get, (TypeContainer) Parent, null, ModFlags);
-
-- if (!iterator.DefineIterator ())
-+ if (iterator == null)
- return false;
- }
- }
-@@ -7383,7 +7564,7 @@
- }
- }
-
-- public class Operator : MethodOrOperator, IIteratorContainer {
-+ public class Operator : MethodOrOperator, IAnonymousHost {
-
- const int AllowedModifiers =
- Modifiers.PUBLIC |
-Index: decl.cs
-===================================================================
---- decl.cs (revision 63019)
-+++ decl.cs (working copy)
-@@ -525,6 +525,7 @@
- caching_flags |= Flags.ClsCompliantAttributeTrue;
- return true;
- }
-+
- return false;
- }
-
-Index: delegate.cs
-===================================================================
---- delegate.cs (revision 63019)
-+++ delegate.cs (working copy)
-@@ -816,8 +816,8 @@
-
- Expression e = a.Expr;
-
-- if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
-- return ((AnonymousMethod) e).Compatible (ec, type);
-+ if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1)
-+ return ((AnonymousMethodExpression) e).Compatible (ec, type);
-
- MethodGroupExpr mg = e as MethodGroupExpr;
- if (mg != null)
-Index: iterators.cs
-===================================================================
---- iterators.cs (revision 63019)
-+++ iterators.cs (working copy)
-@@ -21,14 +21,6 @@
-
- namespace Mono.CSharp {
-
-- public interface IIteratorContainer {
--
-- //
-- // Invoked if a yield statement is found in the body
-- //
-- void SetYields ();
-- }
--
- public class Yield : Statement {
- Expression expr;
- ArrayList finally_blocks;
-@@ -71,16 +63,19 @@
-
- public override bool Resolve (EmitContext ec)
- {
-+ Report.Debug (64, "RESOLVE YIELD", this, ec, expr, expr.GetType ());
- expr = expr.Resolve (ec);
- if (expr == null)
- return false;
-
-+ Report.Debug (64, "RESOLVE YIELD #1", this, ec, expr, expr.GetType (),
-+ ec.CurrentAnonymousMethod, ec.CurrentIterator);
-+
- if (!CheckContext (ec, loc, false))
- return false;
-
- Iterator iterator = ec.CurrentIterator;
--
-- if (expr.Type != iterator.IteratorType){
-+ if (expr.Type != iterator.IteratorType) {
- expr = Convert.ImplicitConversionRequired (
- ec, expr, iterator.IteratorType, loc);
- if (expr == null)
-@@ -119,13 +114,465 @@
- }
- }
-
-- public class Iterator : Class {
-- protected ToplevelBlock original_block;
-- protected ToplevelBlock block;
-+ public class IteratorHost : AnonymousMethodHost
-+ {
-+ public readonly Iterator Iterator;
-
-- Type original_iterator_type;
- TypeExpr iterator_type_expr;
-- bool is_enumerable;
-+ Field pc_field;
-+ Field current_field;
-+ Method dispose;
-+ MethodInfo dispose_method;
-+
-+ TypeExpr enumerator_type;
-+ TypeExpr enumerable_type;
-+ TypeExpr generic_enumerator_type;
-+ TypeExpr generic_enumerable_type;
-+ TypeArguments generic_args;
-+
-+ public IteratorHost (Iterator iterator)
-+ : base (iterator.Container, iterator.Host, iterator.GenericMethod,
-+ iterator.Location)
-+ {
-+ this.Iterator = iterator;
-+ }
-+
-+ public MethodInfo Dispose {
-+ get { return dispose_method; }
-+ }
-+
-+ public Field PC {
-+ get { return pc_field; }
-+ }
-+
-+ public Field CurrentField {
-+ get { return current_field; }
-+ }
-+
-+ public Type IteratorType {
-+ get { return iterator_type_expr.Type; }
-+ }
-+
-+ public override TypeExpr [] GetClassBases (out TypeExpr base_class)
-+ {
-+ iterator_type_expr = InflateType (Iterator.OriginalIteratorType);
-+
-+ generic_args = new TypeArguments (Location);
-+ generic_args.Add (iterator_type_expr);
-+
-+ ArrayList list = new ArrayList ();
-+ if (Iterator.IsEnumerable) {
-+ enumerable_type = new TypeExpression (
-+ TypeManager.ienumerable_type, Location);
-+ list.Add (enumerable_type);
-+
-+ generic_enumerable_type = new ConstructedType (
-+ TypeManager.generic_ienumerable_type,
-+ generic_args, Location);
-+ list.Add (generic_enumerable_type);
-+ }
-+
-+ enumerator_type = new TypeExpression (
-+ TypeManager.ienumerator_type, Location);
-+ list.Add (enumerator_type);
-+
-+ list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
-+
-+ generic_enumerator_type = new ConstructedType (
-+ TypeManager.generic_ienumerator_type,
-+ generic_args, Location);
-+ list.Add (generic_enumerator_type);
-+
-+ Bases = list;
-+
-+ return base.GetClassBases (out base_class);
-+ }
-+
-+ protected override bool DoDefineMembers ()
-+ {
-+ pc_field = CaptureVariable ("$PC", TypeManager.int32_type);
-+ current_field = CaptureVariable ("$current", Iterator.OriginalIteratorType);
-+
-+ Define_Current (true);
-+ Define_Current (false);
-+ dispose = new DisposeMethod (this);
-+ Define_Reset ();
-+
-+ if (Iterator.IsEnumerable) {
-+ new GetEnumeratorMethod (this, false);
-+ new GetEnumeratorMethod (this, true);
-+ }
-+
-+ if (!base.DoDefineMembers ())
-+ return false;
-+
-+ FetchMethodDispose ();
-+ return true;
-+ }
-+
-+ protected override void EmitScopeConstructor (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+ ec.ig.Emit (OpCodes.Ldarg_1);
-+ ec.ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
-+ base.EmitScopeConstructor (ec);
-+ }
-+
-+ void FetchMethodDispose ()
-+ {
-+ MemberList dispose_list;
-+
-+ dispose_list = FindMembers (
-+ CurrentType != null ? CurrentType : TypeBuilder,
-+ MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
-+ Type.FilterName, "Dispose");
-+
-+ if (dispose_list.Count != 1)
-+ throw new InternalErrorException ("Cannot find Dipose() method.");
-+
-+ dispose_method = (MethodInfo) dispose_list [0];
-+ }
-+
-+ void Define_Current (bool is_generic)
-+ {
-+ MemberName left;
-+ Expression type;
-+
-+ if (is_generic) {
-+ left = new MemberName (
-+ "System.Collections.Generic.IEnumerator",
-+ generic_args, Location);
-+ type = iterator_type_expr;
-+ } else {
-+ left = new MemberName ("System.Collections.IEnumerator", Location);
-+ type = TypeManager.system_object_expr;
-+ }
-+
-+ MemberName name = new MemberName (left, "Current", null, Location);
-+
-+ ToplevelBlock get_block = new ToplevelBlock (Location);
-+ get_block.AddStatement (new CurrentBlock (this, is_generic));
-+
-+ Accessor getter = new Accessor (get_block, 0, null, Location);
-+
-+ Property current = new Property (
-+ this, type, 0, false, name, null, getter, null);
-+ AddProperty (current);
-+ }
-+
-+ void Define_Reset ()
-+ {
-+ Method reset = new Method (
-+ this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
-+ false, new MemberName ("Reset", Location),
-+ Parameters.EmptyReadOnlyParameters, null);
-+ AddMethod (reset);
-+
-+ reset.Block = new ToplevelBlock (Location);
-+ reset.Block.AddStatement (Create_ThrowNotSupported ());
-+ }
-+
-+ Statement Create_ThrowNotSupported ()
-+ {
-+ TypeExpr ex_type = new TypeExpression (
-+ TypeManager.not_supported_exception_type, Location);
-+
-+ return new Throw (new New (ex_type, null, Location), Location);
-+ }
-+
-+ ConstructorInfo GetInvalidOperationException ()
-+ {
-+ MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
-+ TypeBuilder, TypeManager.invalid_operation_exception_type,
-+ ".ctor", Location);
-+ if (mg == null)
-+ throw new InternalErrorException ();
-+ return (ConstructorInfo) mg.Methods [0];
-+ }
-+
-+ MethodInfo GetCompareExchange ()
-+ {
-+ MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
-+ TypeBuilder, TypeManager.interlocked_type,
-+ "CompareExchange", Location);
-+ if (mg == null)
-+ throw new InternalErrorException ();
-+ return (MethodInfo) mg.Methods [0];
-+ }
-+
-+ protected override ScopeInitializerBase CreateScopeInitializer ()
-+ {
-+ return new IteratorHostInitializer (this);
-+ }
-+
-+ protected class IteratorHostInitializer : AnonymousMethodHostInitializer
-+ {
-+ new public readonly IteratorHost Host;
-+ protected Iterator.State state;
-+
-+ public IteratorHostInitializer (IteratorHost host)
-+ : base (host)
-+ {
-+ this.Host = host;
-+ }
-+
-+ protected override bool DoResolveInternal (EmitContext ec)
-+ {
-+ if (this is EnumeratorScopeInitializer)
-+ state = Iterator.State.Running;
-+ else if (Host.Iterator.IsEnumerable)
-+ state = Iterator.State.Uninitialized;
-+ else
-+ state = Iterator.State.Running;
-+
-+ return base.DoResolveInternal (ec);
-+ }
-+
-+ protected override void EmitScopeConstructor (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldc_I4, (int) state);
-+ base.EmitScopeConstructor (ec);
-+ }
-+ }
-+
-+ protected class GetEnumeratorMethod : Method
-+ {
-+ public IteratorHost Host;
-+
-+ static MemberName GetMemberName (IteratorHost host, bool is_generic)
-+ {
-+ MemberName left;
-+ if (is_generic) {
-+ left = new MemberName (
-+ "System.Collections.Generic.IEnumerable",
-+ host.generic_args, host.Location);
-+ } else {
-+ left = new MemberName (
-+ "System.Collections.IEnumerable", host.Location);
-+ }
-+
-+ return new MemberName (left, "GetEnumerator", host.Location);
-+ }
-+
-+ public GetEnumeratorMethod (IteratorHost host, bool is_generic)
-+ : base (host, null, is_generic ?
-+ host.generic_enumerator_type : host.enumerator_type,
-+ 0, false, GetMemberName (host, is_generic),
-+ Parameters.EmptyReadOnlyParameters, null)
-+ {
-+ this.Host = host;
-+
-+ host.AddMethod (this);
-+
-+ Block = new ToplevelBlock (host.Iterator.Container, null, Location);
-+ Block.AddStatement (new GetEnumeratorStatement (host, Type, is_generic));
-+ }
-+
-+ public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
-+ {
-+ EmitContext ec = new EmitContext (
-+ this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
-+
-+ ec.CurrentAnonymousMethod = Host.Iterator;
-+ return ec;
-+ }
-+
-+ protected class GetEnumeratorStatement : Statement
-+ {
-+ IteratorHost host;
-+ Expression type;
-+ bool is_generic;
-+
-+ ExpressionStatement initializer;
-+ Expression cast;
-+ MethodInfo ce;
-+
-+ public GetEnumeratorStatement (IteratorHost host, Expression type,
-+ bool is_generic)
-+ {
-+ this.host = host;
-+ this.type = type;
-+ this.is_generic = is_generic;
-+ loc = host.Location;
-+ }
-+
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ type = type.ResolveAsTypeTerminal (ec, false);
-+ if ((type == null) || (type.Type == null))
-+ return false;
-+
-+ initializer = host.GetEnumeratorInitializer (ec);
-+ if (initializer == null)
-+ return false;
-+
-+ cast = new ClassCast (initializer, type.Type);
-+
-+ ce = host.GetCompareExchange ();
-+
-+ ec.CurrentBranching.CurrentUsageVector.Return ();
-+ return true;
-+ }
-+
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ ILGenerator ig = ec.ig;
-+ Label label_init = ig.DefineLabel ();
-+
-+ ig.Emit (OpCodes.Ldarg_0);
-+ ig.Emit (OpCodes.Ldflda, host.PC.FieldBuilder);
-+ ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Running);
-+ ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Uninitialized);
-+ ig.Emit (OpCodes.Call, ce);
-+
-+ ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Uninitialized);
-+ ig.Emit (OpCodes.Bne_Un, label_init);
-+
-+ ig.Emit (OpCodes.Ldarg_0);
-+ ig.Emit (OpCodes.Ret);
-+
-+ ig.MarkLabel (label_init);
-+
-+ initializer.EmitStatement (ec);
-+ cast.Emit (ec);
-+ ig.Emit (OpCodes.Ret);
-+ }
-+ }
-+ }
-+
-+ protected class DisposeMethod : Method
-+ {
-+ public IteratorHost Host;
-+
-+ public DisposeMethod (IteratorHost host)
-+ : base (host, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
-+ false, new MemberName ("Dispose", host.Location),
-+ Parameters.EmptyReadOnlyParameters, null)
-+ {
-+ this.Host = host;
-+
-+ host.AddMethod (this);
-+
-+ Block = new ToplevelBlock (host.Iterator.Block, null, Location);
-+ Block.AddStatement (new DisposeMethodStatement (Host.Iterator));
-+
-+ Report.Debug (64, "DISPOSE METHOD", host, Block);
-+ }
-+
-+ public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
-+ {
-+ EmitContext ec = new EmitContext (
-+ this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
-+
-+ ec.CurrentAnonymousMethod = Host.Iterator;
-+ return ec;
-+ }
-+
-+ protected class DisposeMethodStatement : Statement
-+ {
-+ Iterator iterator;
-+
-+ public DisposeMethodStatement (Iterator iterator)
-+ {
-+ this.iterator = iterator;
-+ this.loc = iterator.Location;
-+ }
-+
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ return true;
-+ }
-+
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ iterator.EmitDispose (ec);
-+ }
-+ }
-+ }
-+
-+ protected ScopeInitializer GetEnumeratorInitializer (EmitContext ec)
-+ {
-+ ScopeInitializer init = new EnumeratorScopeInitializer (this);
-+ if (init.Resolve (ec) == null)
-+ throw new InternalErrorException ();
-+ return init;
-+ }
-+
-+ protected class EnumeratorScopeInitializer : IteratorHostInitializer
-+ {
-+ IteratorHost host;
-+
-+ public EnumeratorScopeInitializer (IteratorHost host)
-+ : base (host)
-+ {
-+ this.host = host;
-+ }
-+
-+ protected override bool DoResolveInternal (EmitContext ec)
-+ {
-+ type = host.IsGeneric ? host.CurrentType : host.TypeBuilder;
-+ return base.DoResolveInternal (ec);
-+ }
-+
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ DoEmitInstance (ec);
-+ }
-+
-+ protected override void EmitParameterReference (EmitContext ec,
-+ CapturedParameter cp)
-+ {
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+ ec.ig.Emit (OpCodes.Ldfld, cp.Field.FieldBuilder);
-+ }
-+ }
-+
-+ protected class CurrentBlock : Statement {
-+ IteratorHost host;
-+ bool is_generic;
-+
-+ public CurrentBlock (IteratorHost host, bool is_generic)
-+ {
-+ this.host = host;
-+ this.is_generic = is_generic;
-+ loc = host.Location;
-+ }
-+
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ ec.CurrentBranching.CurrentUsageVector.Return ();
-+ return true;
-+ }
-+
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ ILGenerator ig = ec.ig;
-+ Label label_ok = ig.DefineLabel ();
-+
-+ ig.Emit (OpCodes.Ldarg_0);
-+ ig.Emit (OpCodes.Ldfld, host.PC.FieldBuilder);
-+ ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Running);
-+ ig.Emit (OpCodes.Bgt, label_ok);
-+
-+ ig.Emit (OpCodes.Newobj, host.GetInvalidOperationException ());
-+ ig.Emit (OpCodes.Throw);
-+
-+ ig.MarkLabel (label_ok);
-+ ig.Emit (OpCodes.Ldarg_0);
-+ ig.Emit (OpCodes.Ldfld, host.CurrentField.FieldBuilder);
-+ if (!is_generic)
-+ ig.Emit (OpCodes.Box, host.CurrentField.MemberType);
-+ ig.Emit (OpCodes.Ret);
-+ }
-+ }
-+ }
-+
-+ public class Iterator : AnonymousContainer {
-+ protected readonly ToplevelBlock OriginalBlock;
-+ protected readonly IMethodData OriginalMethod;
-+ protected ToplevelBlock block;
-+
-+ public readonly bool IsEnumerable;
- public readonly bool IsStatic;
-
- //
-@@ -139,7 +586,6 @@
- // Context from the original method
- //
- GenericMethod generic_method;
-- TypeContainer container;
- TypeExpr current_type;
- Type this_type;
- Parameters parameters;
-@@ -147,34 +593,33 @@
- IMethodData orig_method;
-
- MethodInfo dispose_method;
-- MoveNextMethod move_next_method;
-+ Method move_next_method;
- Constructor ctor;
-- CaptureContext cc;
-
- Expression enumerator_type;
- Expression enumerable_type;
- Expression generic_enumerator_type;
- Expression generic_enumerable_type;
- TypeArguments generic_args;
-- EmitContext ec;
-
-- protected enum State {
-+ public readonly Type OriginalIteratorType;
-+ public readonly IteratorHost IteratorHost;
-+
-+ public enum State {
- Uninitialized = -2,
- After,
- Running
- }
-
-- static int proxy_count;
--
- public void EmitYieldBreak (ILGenerator ig)
- {
- ig.Emit (OpCodes.Ldarg_0);
- IntConstant.EmitInt (ig, (int) State.After);
-- ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
-+ ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
- ig.Emit (OpCodes.Br, move_next_error);
- }
-
-- public void EmitMoveNext (EmitContext ec)
-+ internal void EmitMoveNext (EmitContext ec, Block original_block)
- {
- ILGenerator ig = ec.ig;
-
-@@ -192,7 +637,7 @@
- resume_points.Add (entry_point);
- entry_point.Define (ig);
-
-- ec.EmitTopBlock (orig_method, original_block);
-+ original_block.Emit (ec);
-
- EmitYieldBreak (ig);
-
-@@ -203,7 +648,7 @@
- labels [i] = ((ResumePoint) resume_points [i]).Label;
-
- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
-+ ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
- ig.Emit (OpCodes.Switch, labels);
-
- Label end = ig.DefineLabel ();
-@@ -221,7 +666,7 @@
- ig.BeginFaultBlock ();
-
- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Callvirt, dispose_method);
-+ ig.Emit (OpCodes.Callvirt, IteratorHost.Dispose);
-
- ig.EndExceptionBlock ();
-
-@@ -264,12 +709,12 @@
-
- ig.MarkLabel (dispatcher);
- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
-+ ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
- ig.Emit (OpCodes.Switch, labels);
-
- ig.Emit (OpCodes.Ldarg_0);
- IntConstant.EmitInt (ig, (int) State.After);
-- ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
-+ ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
-
- ig.MarkLabel (end);
- }
-@@ -305,13 +750,13 @@
- // Store the new current
- ig.Emit (OpCodes.Ldarg_0);
- expr.Emit (ec);
-- ig.Emit (OpCodes.Stfld, current_field.FieldBuilder);
-+ ig.Emit (OpCodes.Stfld, IteratorHost.CurrentField.FieldBuilder);
-
- // increment pc
- pc++;
- ig.Emit (OpCodes.Ldarg_0);
- IntConstant.EmitInt (ig, pc);
-- ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
-+ ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
-
- // Return ok
- ig.Emit (OpCodes.Br, move_next_ok);
-@@ -329,728 +774,94 @@
- pc++;
- ig.Emit (OpCodes.Ldarg_0);
- IntConstant.EmitInt (ig, pc);
-- ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
-+ ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
-
- ResumePoint point = new ResumePoint (finally_blocks);
- resume_points.Add (point);
- point.Define (ig);
- }
-
-- private static MemberName MakeProxyName (string name, GenericMethod generic, Location loc)
-- {
-- int pos = name.LastIndexOf ('.');
-- if (pos > 0)
-- name = name.Substring (pos + 1);
-+ public override bool IsIterator {
-+ get { return true; }
-+ }
-
-- string proxy_name = "<" + name + ">__" + (proxy_count++);
--
-- if (generic != null) {
-- TypeArguments args = new TypeArguments (loc);
-- foreach (TypeParameter tparam in generic.CurrentTypeParameters)
-- args.Add (new SimpleName (tparam.Name, loc));
-- return new MemberName (proxy_name, args, loc);
-- } else
-- return new MemberName (proxy_name, loc);
-+ public override AnonymousMethodHost RootScope {
-+ get { return IteratorHost; }
- }
-
- //
- // Our constructor
- //
-- public Iterator (IMethodData m_container, DeclSpace parent, GenericMethod generic,
-- int modifiers)
-- : base (parent.NamespaceEntry, parent,
-- MakeProxyName (m_container.MethodName.Name, generic, m_container.Location),
-- (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null)
-+ public Iterator (IMethodData m_container, TypeContainer host, GenericMethod generic,
-+ ToplevelBlock container, ToplevelBlock block, int modifiers,
-+ Type iterator_type, bool is_enumerable)
-+ : base (null, host, generic, m_container.ParameterInfo,
-+ block, m_container.Block, TypeManager.bool_type, modifiers,
-+ m_container.Location)
- {
-- this.orig_method = m_container;
-+ this.OriginalBlock = m_container.Block;
-+ this.OriginalMethod = m_container;
-+ this.OriginalIteratorType = iterator_type;
-+ this.IsEnumerable = is_enumerable;
-
-- this.generic_method = generic;
-- this.container = ((TypeContainer) parent).PartialContainer;
-- this.original_parameters = m_container.ParameterInfo;
-- this.original_block = orig_method.Block;
-- this.block = new ToplevelBlock (orig_method.Block, parameters, orig_method.Location);
-+ Report.Debug (64, "NEW ITERATOR", host, generic, OriginalBlock,
-+ Container, Block, block);
-
-- if (generic != null) {
-- ArrayList constraints = new ArrayList ();
-- foreach (TypeParameter tparam in generic.TypeParameters)
-- constraints.Add (tparam.Constraints);
-+ IteratorHost = new IteratorHost (this);
-+ Block.CreateIteratorHost (IteratorHost);
-
-- SetParameterInfo (constraints);
-- }
-+ OriginalBlock.ReParent (Container);
-
-- IsStatic = (modifiers & Modifiers.STATIC) != 0;
-- }
-+ m_container.Block = block;
-
-- public AnonymousContainer Host {
-- get { return move_next_method; }
-+ OriginalBlock.MakeIterator (this);
- }
-
-- public bool DefineIterator ()
-+ protected class TestStatement : Statement
- {
-- ec = new EmitContext (this, this, Location, null, null, ModFlags);
-- ec.CurrentAnonymousMethod = move_next_method;
-- ec.InIterator = true;
--
-- if (!CheckType ()) {
-- Report.Error (1624, Location,
-- "The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",
-- orig_method.GetSignatureForError (), TypeManager.CSharpName (orig_method.ReturnType));
-- return false;
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ return true;
- }
-
-- for (int i = 0; i < original_parameters.Count; i++){
-- Parameter.Modifier mod = original_parameters.ParameterModifier (i);
-- if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
-- Report.Error (
-- 1623, Location,
-- "Iterators cannot have ref or out parameters");
-- return false;
-- }
--
-- if ((mod & Parameter.Modifier.ARGLIST) != 0) {
-- Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");
-- return false;
-- }
--
-- if (original_parameters.ParameterType (i).IsPointer) {
-- Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");
-- return false;
-- }
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Nop);
-+ ec.ig.Emit (OpCodes.Neg);
-+ ec.ig.Emit (OpCodes.Pop);
-+ ec.ig.Emit (OpCodes.Ret);
- }
--
-- if (container.CurrentType != null)
-- this_type = container.CurrentType;
-- else
-- this_type = container.TypeBuilder;
--
-- container.AddIterator (this);
--
-- orig_method.Block = block;
-- return true;
- }
-
-- MethodInfo FetchMethodDispose ()
-+ public override bool Resolve (EmitContext ec)
- {
-- MemberList dispose_list;
-+ Report.Debug (64, "RESOLVE ITERATOR", this, Container, Block);
-
-- dispose_list = FindMembers (
-- current_type.Type,
-- MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
-- Type.FilterName, "Dispose");
--
-- if (dispose_list.Count != 1)
-- throw new InternalErrorException ("Cannot find Dipose() method.");
--
-- return (MethodInfo) dispose_list [0];
-- }
--
-- protected override bool DoDefineMembers ()
-- {
-- ec.InIterator = true;
-- ec.CurrentAnonymousMethod = move_next_method;
-- ec.capture_context = cc;
--
-- if (!base.DoDefineMembers ())
-+ if (!base.Resolve (ec))
- return false;
-
-- dispose_method = FetchMethodDispose ();
-- if (dispose_method == null)
-- return false;
-+ Report.Debug (64, "RESOLVE ITERATOR #1", this, method, method.Parent,
-+ RootScope, ec);
-
-- return true;
-- }
--
-- public override bool Define ()
-- {
-- if (!base.Define ())
-+ if (!RootScope.DefineMembers ())
- return false;
-
-- ec.InIterator = true;
-- ec.CurrentAnonymousMethod = move_next_method;
-- ec.capture_context = cc;
-+ ExpressionStatement scope_init = RootScope.GetScopeInitializer (ec);
-+ Container.AddStatement (new StatementExpression (scope_init));
-+ Expression cast = new ClassCast (scope_init, OriginalMethod.ReturnType);
-+ Container.AddStatement (new NoCheckReturn (cast));
-
-- ec.TypeContainer = ec.TypeContainer.Parent;
--
-- if (ec.TypeContainer.CurrentType != null)
-- ec.ContainerType = ec.TypeContainer.CurrentType;
-- else
-- ec.ContainerType = ec.TypeContainer.TypeBuilder;
--
-- ec.ig = move_next_method.method.MethodBuilder.GetILGenerator ();
--
-- if (!ctor.Define ())
-- return false;
--
-- bool unreachable;
--
-- if (!ec.ResolveTopBlock (null, original_block, parameters, orig_method, out unreachable))
-- return false;
--
-- if (!ec.ResolveTopBlock (null, block, parameters, orig_method, out unreachable))
-- return false;
--
-- original_block.CompleteContexts ();
--
-- cc.EmitAnonymousHelperClasses (ec);
--
- return true;
- }
-
-- TypeExpr InflateType (Type it)
-+ protected override Method DoCreateMethodHost (EmitContext ec)
- {
-- if (generic_method == null)
-- return new TypeExpression (it, Location);
--
-- if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
-- int pos = it.GenericParameterPosition;
-- it = CurrentTypeParameters [pos].Type;
-- } else if (it.IsGenericType) {
-- Type[] args = it.GetGenericArguments ();
--
-- TypeArguments inflated = new TypeArguments (Location);
-- foreach (Type t in args)
-- inflated.Add (InflateType (t));
--
-- return new ConstructedType (it, inflated, Location);
-- } else if (it.IsArray) {
-- TypeExpr et_expr = InflateType (it.GetElementType ());
-- int rank = it.GetArrayRank ();
--
-- Type et = et_expr.ResolveAsTypeTerminal (ec, false).Type;
-- it = et.MakeArrayType (rank);
-- }
--
-- return new TypeExpression (it, Location);
-+ return new AnonymousMethodMethod (
-+ this, null, TypeManager.system_boolean_expr,
-+ Modifiers.PUBLIC, new MemberName ("MoveNext", Location),
-+ Parameters.EmptyReadOnlyParameters);
- }
-
-- Parameter InflateParameter (Parameter param)
-- {
-- TypeExpr te = InflateType (param.ParameterType);
-- return new Parameter (
-- te, param.Name, param.ModFlags, param.OptAttributes, param.Location);
-- }
--
-- Parameters InflateParameters (Parameters parameters, EmitContext ec)
-- {
-- int count = parameters.FixedParameters.Length;
-- if (count == 0)
-- return Parameters.EmptyReadOnlyParameters;
-- Parameter[] fixed_params = new Parameter [count];
-- for (int i = 0; i < count; i++)
-- fixed_params [i] = InflateParameter (parameters.FixedParameters [i]);
--
-- return new Parameters (fixed_params, parameters.HasArglist);
-- }
--
-- public override TypeExpr [] GetClassBases (out TypeExpr base_class)
-- {
-- iterator_type_expr = InflateType (original_iterator_type);
--
-- generic_args = new TypeArguments (Location);
-- generic_args.Add (iterator_type_expr);
--
-- ArrayList list = new ArrayList ();
-- if (is_enumerable) {
-- enumerable_type = new TypeExpression (
-- TypeManager.ienumerable_type, Location);
-- list.Add (enumerable_type);
--
-- generic_enumerable_type = new ConstructedType (
-- TypeManager.generic_ienumerable_type,
-- generic_args, Location);
-- list.Add (generic_enumerable_type);
-- }
--
-- enumerator_type = new TypeExpression (
-- TypeManager.ienumerator_type, Location);
-- list.Add (enumerator_type);
--
-- list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
--
-- generic_enumerator_type = new ConstructedType (
-- TypeManager.generic_ienumerator_type,
-- generic_args, Location);
-- list.Add (generic_enumerator_type);
--
-- Bases = list;
--
-- return base.GetClassBases (out base_class);
-- }
--
-- //
-- // Returns the new block for the method, or null on failure
-- //
-- protected override bool DefineNestedTypes ()
-- {
-- if (CurrentType != null)
-- current_type = new TypeExpression (CurrentType, Location);
-- else
-- current_type = new TypeExpression (TypeBuilder, Location);
--
-- if (IsGeneric) {
-- foreach (TypeParameter tparam in TypeParameters)
-- tparam.InflateConstraints (current_type.Type);
-- }
--
-- parameters = InflateParameters (original_parameters, ec);
-- if (!parameters.Resolve (ec)) {
-- // TODO:
-- }
--
-- Define_Fields ();
-- Define_Current (false);
-- Define_Current (true);
-- Define_MoveNext ();
-- Define_Reset ();
-- Define_Dispose ();
--
-- Define_Constructor ();
--
-- Create_Block ();
--
-- if (is_enumerable) {
-- Define_GetEnumerator (false);
-- Define_GetEnumerator (true);
-- }
--
-- return base.DefineNestedTypes ();
-- }
--
-- Field pc_field;
-- Field current_field;
-- Method dispose;
--
-- void Create_Block ()
-- {
-- original_block.SetHaveAnonymousMethods (Location, move_next_method);
-- block.SetHaveAnonymousMethods (Location, move_next_method);
--
-- cc = original_block.CaptureContext;
--
-- int first = IsStatic ? 0 : 1;
--
-- ArrayList args = new ArrayList ();
-- if (!IsStatic) {
-- Type t = this_type;
-- args.Add (new Argument (
-- new ThisParameterReference (t, Location)));
-- cc.CaptureThis (move_next_method);
-- }
--
-- args.Add (new Argument (new BoolLiteral (false, Location)));
--
-- for (int i = 0; i < parameters.Count; i++) {
-- Type t = original_parameters.ParameterType (i);
-- Type inflated = parameters.ParameterType (i);
-- string name = parameters.ParameterName (i);
--
-- args.Add (new Argument (
-- new SimpleParameterReference (t, first + i, Location)));
--
-- cc.AddParameterToContext (move_next_method, name, inflated, first + i);
-- }
--
-- TypeExpr proxy_type;
-- if (generic_method != null) {
-- TypeArguments new_args = new TypeArguments (Location);
-- if (Parent.IsGeneric) {
-- foreach (TypeParameter tparam in Parent.TypeParameters)
-- new_args.Add (new TypeParameterExpr (tparam, Location));
-- }
-- foreach (TypeParameter tparam in generic_method.TypeParameters)
-- new_args.Add (new TypeParameterExpr (tparam, Location));
-- ConstructedType ct = new ConstructedType (CurrentType, new_args, Location);
-- proxy_type = ct.ResolveAsTypeTerminal (ec, false);
-- } else
-- proxy_type = current_type;
--
-- Expression new_expr = new New (proxy_type, args, Location);
-- block.AddStatement (new NoCheckReturn (new_expr, Location));
-- }
--
-- void Define_Fields ()
-- {
-- pc_field = new Field (
-- this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "$PC",
-- null, Location);
-- AddField (pc_field);
--
-- current_field = new Field (
-- this, iterator_type_expr, Modifiers.PRIVATE, "$current",
-- null, Location);
-- AddField (current_field);
-- }
--
-- void Define_Constructor ()
-- {
-- Parameters ctor_params;
--
-- ArrayList list = new ArrayList ();
--
-- if (!IsStatic)
-- list.Add (new Parameter (
-- new TypeExpression (this_type, Location),
-- "this", Parameter.Modifier.NONE,
-- null, Location));
-- list.Add (new Parameter (
-- TypeManager.bool_type, "initialized",
-- Parameter.Modifier.NONE, null, Location));
--
-- Parameter[] old_fixed = parameters.FixedParameters;
-- list.AddRange (old_fixed);
--
-- Parameter[] fixed_params = new Parameter [list.Count];
-- list.CopyTo (fixed_params);
--
-- ctor_params = new Parameters (fixed_params);
--
-- ctor = new Constructor (
-- this, MemberName.Name, Modifiers.PUBLIC, ctor_params,
-- new GeneratedBaseInitializer (Location),
-- Location);
-- AddConstructor (ctor);
--
-- ctor.Block = new ToplevelBlock (block, parameters, Location);
--
-- int first = IsStatic ? 2 : 3;
--
-- State initial = is_enumerable ? State.Uninitialized : State.Running;
-- ctor.Block.AddStatement (new SetState (this, initial, Location));
--
-- ctor.Block.AddStatement (new If (
-- new SimpleParameterReference (
-- TypeManager.bool_type, first - 1, Location),
-- new SetState (this, State.Running, Location),
-- Location));
--
-- ctor.Block.AddStatement (new InitScope (this, Location));
-- }
--
-- Statement Create_ThrowInvalidOperation ()
-- {
-- TypeExpr ex_type = new TypeExpression (
-- TypeManager.invalid_operation_exception_type, Location);
--
-- return new Throw (new New (ex_type, null, Location), Location);
-- }
--
-- Statement Create_ThrowNotSupported ()
-- {
-- TypeExpr ex_type = new TypeExpression (
-- TypeManager.not_supported_exception_type, Location);
--
-- return new Throw (new New (ex_type, null, Location), Location);
-- }
--
-- void Define_Current (bool is_generic)
-- {
-- MemberName left;
-- Expression type;
-- if (is_generic) {
-- left = new MemberName (
-- "System.Collections.Generic.IEnumerator",
-- generic_args, Location);
-- type = iterator_type_expr;
-- } else {
-- left = new MemberName ("System.Collections.IEnumerator", Location);
-- type = TypeManager.system_object_expr;
-- }
--
-- MemberName name = new MemberName (left, "Current", null, Location);
--
-- ToplevelBlock get_block = new ToplevelBlock (
-- block, parameters, Location);
--
-- get_block.AddStatement (new If (
-- new Binary (
-- Binary.Operator.LessThanOrEqual,
-- new FieldExpression (this, pc_field),
-- new IntLiteral ((int) State.Running, pc_field.Location)),
-- Create_ThrowInvalidOperation (),
-- new Return (
-- new FieldExpression (this, current_field), Location),
-- Location));
--
-- Accessor getter = new Accessor (get_block, 0, null, Location);
--
-- Property current = new Property (
-- this, type, 0, false, name, null, getter, null);
-- AddProperty (current);
-- }
--
-- void Define_MoveNext ()
-- {
-- move_next_method = new MoveNextMethod (this, Location);
--
-- original_block.ReParent (block, move_next_method);
--
-- move_next_method.CreateMethod (ec);
--
-- AddMethod (move_next_method.method);
-- }
--
-- void Define_GetEnumerator (bool is_generic)
-- {
-- MemberName left;
-- Expression type;
-- if (is_generic) {
-- left = new MemberName (
-- "System.Collections.Generic.IEnumerable",
-- generic_args, Location);
-- type = generic_enumerator_type;
-- } else {
-- left = new MemberName ("System.Collections.IEnumerable", Location);
-- type = enumerator_type;
-- }
--
-- MemberName name = new MemberName (left, "GetEnumerator", Location);
--
-- Method get_enumerator = new Method (
-- this, null, type, 0, false, name,
-- Parameters.EmptyReadOnlyParameters, null);
--
-- //
-- // We call append instead of add, as we need to make sure that
-- // this method is resolved after the MoveNext method, as that one
-- // triggers the computation of the AnonymousMethod Scope, which is
-- // required during the code generation of the enumerator
-- //
-- AppendMethod (get_enumerator);
--
-- get_enumerator.Block = new ToplevelBlock (
-- block, parameters, Location);
--
-- get_enumerator.Block.SetHaveAnonymousMethods (Location, move_next_method);
--
-- Expression ce = new MemberAccess (
-- new SimpleName ("System.Threading.Interlocked", Location),
-- "CompareExchange");
--
-- Expression pc = new FieldExpression (this, pc_field);
-- Expression before = new IntLiteral ((int) State.Running, Location);
-- Expression uninitialized = new IntLiteral ((int) State.Uninitialized, Location);
--
-- ArrayList args = new ArrayList ();
-- args.Add (new Argument (pc, Argument.AType.Ref));
-- args.Add (new Argument (before, Argument.AType.Expression));
-- args.Add (new Argument (uninitialized, Argument.AType.Expression));
--
-- get_enumerator.Block.AddStatement (new If (
-- new Binary (
-- Binary.Operator.Equality,
-- new Invocation (ce, args),
-- uninitialized),
-- new Return (new ThisParameterReference (type.Type, Location),
-- Location),
-- Location));
--
-- args = new ArrayList ();
-- if (!IsStatic) {
-- args.Add (new Argument (new CapturedThisReference (this, Location)));
-- }
--
-- args.Add (new Argument (new BoolLiteral (true, Location)));
--
-- for (int i = 0; i < parameters.Count; i++) {
-- Expression cp = new CapturedParameterReference (
-- this, parameters.ParameterType (i),
-- parameters.ParameterName (i), Location);
-- args.Add (new Argument (cp));
-- }
--
-- Expression new_expr = new New (current_type, args, Location);
-- get_enumerator.Block.AddStatement (new Return (new_expr, Location));
-- }
--
-- protected class SimpleParameterReference : Expression
-- {
-- int idx;
--
-- public SimpleParameterReference (Type type, int idx, Location loc)
-- {
-- this.idx = idx;
-- this.loc = loc;
-- this.type = type;
-- eclass = ExprClass.Variable;
-- }
--
-- public override Expression DoResolve (EmitContext ec)
-- {
-- return this;
-- }
--
-- public override void Emit (EmitContext ec)
-- {
-- DoEmit (ec);
-- }
--
-- protected virtual void DoEmit (EmitContext ec)
-- {
-- ParameterReference.EmitLdArg (ec.ig, idx);
-- }
-- }
--
-- protected class ThisParameterReference : SimpleParameterReference, IMemoryLocation
-- {
-- public ThisParameterReference (Type type, Location loc)
-- : base (type, 0, loc)
-- { }
--
-- protected override void DoEmit (EmitContext ec)
-- {
-- base.DoEmit (ec);
-- if (ec.TypeContainer is Struct)
-- ec.ig.Emit (OpCodes.Ldobj, type);
-- }
--
-- public void AddressOf (EmitContext ec, AddressOp mode)
-- {
-- if (ec.TypeContainer is Struct)
-- ec.ig.Emit (OpCodes.Ldarga, 0);
-- else
-- ec.ig.Emit (OpCodes.Ldarg, 0);
-- }
-- }
--
-- protected class CapturedParameterReference : Expression
-- {
-- Iterator iterator;
-- string name;
--
-- public CapturedParameterReference (Iterator iterator, Type type,
-- string name, Location loc)
-- {
-- this.iterator = iterator;
-- this.loc = loc;
-- this.type = type;
-- this.name = name;
-- eclass = ExprClass.Variable;
-- }
--
-- public override Expression DoResolve (EmitContext ec)
-- {
-- return this;
-- }
--
-- public override void Emit (EmitContext ec)
-- {
-- ec.CurrentAnonymousMethod = iterator.move_next_method;
--
-- LocalTemporary dummy = null;
--
-- iterator.cc.EmitParameter (ec, name, false, false, ref dummy);
-- }
-- }
--
-- protected class CapturedThisReference : Expression
-- {
-- public CapturedThisReference (Iterator iterator, Location loc)
-- {
-- this.loc = loc;
-- this.type = iterator.this_type;
-- eclass = ExprClass.Variable;
-- }
--
-- public override Expression DoResolve (EmitContext ec)
-- {
-- return this;
-- }
--
-- public override void Emit (EmitContext ec)
-- {
-- ec.EmitThis (false);
-- }
-- }
--
-- protected class FieldExpression : Expression
-- {
-- Iterator iterator;
-- Field field;
--
-- public FieldExpression (Iterator iterator, Field field)
-- {
-- this.iterator = iterator;
-- this.field = field;
-- this.loc = iterator.Location;
-- }
--
-- public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
-- {
-- FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
-- fexpr.InstanceExpression = new ThisParameterReference (
-- iterator.this_type, loc);
-- return fexpr.ResolveLValue (ec, right_side, loc);
-- }
--
-- public override Expression DoResolve (EmitContext ec)
-- {
-- FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
-- fexpr.InstanceExpression = new ThisParameterReference (
-- iterator.this_type, loc);
-- return fexpr.Resolve (ec);
-- }
--
-- public override void Emit (EmitContext ec)
-- {
-- throw new InvalidOperationException ();
-- }
-- }
--
-- protected class MoveNextMethod : AnonymousContainer
-- {
-- Iterator iterator;
--
-- public MoveNextMethod (Iterator iterator, Location loc)
-- : base (iterator.parameters, iterator.original_block, loc)
-- {
-- this.iterator = iterator;
-- }
--
-- protected override bool CreateMethodHost (EmitContext ec)
-- {
-- method = new Method (
-- iterator, null, TypeManager.system_boolean_expr,
-- Modifiers.PUBLIC, false, new MemberName ("MoveNext", loc),
-- Parameters.EmptyReadOnlyParameters, null);
--
-- method.Block = Block;
--
-- MoveNextStatement inline = new MoveNextStatement (iterator, loc);
-- Block.AddStatement (inline);
--
-- return true;
-- }
--
-- public bool CreateMethod (EmitContext ec)
-- {
-- return CreateMethodHost (ec);
-- }
--
-- public override Iterator Iterator {
-- get { return iterator; }
-- }
--
-- public void ComputeHost ()
-- {
-- ComputeMethodHost ();
-- }
--
-- public override bool IsIterator {
-- get { return true; }
-- }
--
-- public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
-- {
-- scope.ScopeTypeBuilder = iterator.TypeBuilder;
-- scope.ScopeConstructor = iterator.ctor.ConstructorBuilder;
-- }
--
-- public override void Emit (EmitContext ec)
-- {
-- throw new InternalErrorException ();
-- }
-- }
--
- protected class MoveNextStatement : Statement {
- Iterator iterator;
-
-@@ -1062,147 +873,17 @@
-
- public override bool Resolve (EmitContext ec)
- {
-- return true;
-+ return iterator.OriginalBlock.Resolve (ec);
- }
-
- protected override void DoEmit (EmitContext ec)
- {
-- iterator.move_next_method.ComputeHost ();
-- ec.CurrentAnonymousMethod = iterator.move_next_method;
-- ec.InIterator = true;
--
-- iterator.EmitMoveNext (ec);
-+ iterator.EmitMoveNext (ec, iterator.Block);
- }
- }
-
-- protected class DisposeMethod : Statement {
-- Iterator iterator;
--
-- public DisposeMethod (Iterator iterator, Location loc)
-- {
-- this.loc = loc;
-- this.iterator = iterator;
-- }
--
-- public override bool Resolve (EmitContext ec)
-- {
-- return true;
-- }
--
-- protected override void DoEmit (EmitContext ec)
-- {
-- iterator.EmitDispose (ec);
-- }
-- }
--
-- protected class StatementList : Statement {
-- ArrayList statements;
--
-- public StatementList (Location loc)
-- {
-- this.loc = loc;
-- statements = new ArrayList ();
-- }
--
-- public void Add (Statement statement)
-- {
-- statements.Add (statement);
-- }
--
-- public override bool Resolve (EmitContext ec)
-- {
-- foreach (Statement stmt in statements) {
-- if (!stmt.Resolve (ec))
-- return false;
-- }
--
-- return true;
-- }
--
-- protected override void DoEmit (EmitContext ec)
-- {
-- foreach (Statement stmt in statements)
-- stmt.Emit (ec);
-- }
-- }
--
-- protected class SetState : Statement
-- {
-- Iterator iterator;
-- State state;
--
-- public SetState (Iterator iterator, State state, Location loc)
-- {
-- this.iterator = iterator;
-- this.state = state;
-- this.loc = loc;
-- }
--
-- public override bool Resolve (EmitContext ec)
-- {
-- return true;
-- }
--
-- protected override void DoEmit (EmitContext ec)
-- {
-- ec.ig.Emit (OpCodes.Ldarg_0);
-- IntConstant.EmitInt (ec.ig, (int) state);
-- ec.ig.Emit (OpCodes.Stfld, iterator.pc_field.FieldBuilder);
-- }
-- }
--
-- protected class InitScope : Statement
-- {
-- Iterator iterator;
--
-- public InitScope (Iterator iterator, Location loc)
-- {
-- this.iterator = iterator;
-- this.loc = loc;
-- }
--
-- public override bool Resolve (EmitContext ec)
-- {
-- return true;
-- }
--
-- protected override void DoEmit (EmitContext ec)
-- {
-- iterator.cc.EmitInitScope (ec);
-- }
-- }
--
-- void Define_Reset ()
-- {
-- Method reset = new Method (
-- this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
-- false, new MemberName ("Reset", Location),
-- Parameters.EmptyReadOnlyParameters, null);
-- AddMethod (reset);
--
-- reset.Block = new ToplevelBlock (Location);
-- reset.Block = new ToplevelBlock (block, parameters, Location);
-- reset.Block.SetHaveAnonymousMethods (Location, move_next_method);
--
-- reset.Block.AddStatement (Create_ThrowNotSupported ());
-- }
--
-- void Define_Dispose ()
-- {
-- dispose = new Method (
-- this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
-- false, new MemberName ("Dispose", Location),
-- Parameters.EmptyReadOnlyParameters, null);
-- AddMethod (dispose);
--
-- dispose.Block = new ToplevelBlock (block, parameters, Location);
-- dispose.Block.SetHaveAnonymousMethods (Location, move_next_method);
--
-- dispose.Block.AddStatement (new DisposeMethod (this, Location));
-- }
--
- public Type IteratorType {
-- get { return iterator_type_expr.Type; }
-+ get { return IteratorHost.IteratorType; }
- }
-
- //
-@@ -1212,10 +893,10 @@
- class NoCheckReturn : Statement {
- public Expression Expr;
-
-- public NoCheckReturn (Expression expr, Location l)
-+ public NoCheckReturn (Expression expr)
- {
- Expr = expr;
-- loc = l;
-+ loc = expr.Location;
- }
-
- public override bool Resolve (EmitContext ec)
-@@ -1236,10 +917,49 @@
- }
- }
-
-- bool CheckType ()
-+ public static Iterator CreateIterator (IMethodData method, TypeContainer parent,
-+ GenericMethod generic, int modifiers)
- {
-- Type ret = orig_method.ReturnType;
-+ bool is_enumerable;
-+ Type iterator_type;
-
-+ if (!CheckType (method.ReturnType, out iterator_type, out is_enumerable)) {
-+ Report.Error (1624, method.Location,
-+ "The body of `{0}' cannot be an iterator block " +
-+ "because `{1}' is not an iterator interface type",
-+ method.GetSignatureForError (),
-+ TypeManager.CSharpName (method.ReturnType));
-+ return null;
-+ }
-+
-+ Report.Debug (64, "CREATE ITERATOR", parent, method, method.Block);
-+
-+ ToplevelBlock block = new ToplevelBlock (method.ParameterInfo, method.Location);
-+
-+ Iterator iterator = new Iterator (
-+ method, parent, generic, null, block, modifiers,
-+ iterator_type, is_enumerable);
-+
-+#if FIXME
-+ if (!iterator.RootScope.Define ())
-+ return null;
-+ if (iterator.RootScope.DefineType () == null)
-+ return null;
-+ if (!iterator.RootScope.ResolveType ())
-+ return null;
-+#endif
-+
-+ Report.Debug (64, "CREATE ITERATOR #1", iterator, iterator.RootScope,
-+ iterator.RootScope.IsGeneric, iterator.RootScope.TypeBuilder);
-+
-+ return iterator;
-+ }
-+
-+ static bool CheckType (Type ret, out Type original_iterator_type, out bool is_enumerable)
-+ {
-+ original_iterator_type = null;
-+ is_enumerable = false;
-+
- if (ret == TypeManager.ienumerable_type) {
- original_iterator_type = TypeManager.object_type;
- is_enumerable = true;
-Index: cs-parser.jay
-===================================================================
---- cs-parser.jay (revision 63019)
-+++ cs-parser.jay (working copy)
-@@ -35,7 +35,7 @@
- TypeContainer current_container;
- TypeContainer current_class;
-
-- IIteratorContainer iterator_container;
-+ IAnonymousHost anonymous_host;
-
- /// <summary>
- /// Current block is used to add statements as we find
-@@ -45,6 +45,9 @@
-
- Delegate current_delegate;
-
-+ GenericMethod current_generic_method;
-+ AnonymousMethodExpression current_anonymous_method;
-+
- /// <summary>
- /// This is used by the unary_expression code to resolve
- /// a name against a parameter.
-@@ -1064,7 +1067,7 @@
-
- method_declaration
- : method_header {
-- iterator_container = (IIteratorContainer) $1;
-+ anonymous_host = (IAnonymousHost) $1;
- if (RootContext.Documentation != null)
- Lexer.doc_state = XmlCommentState.NotAllowed;
- }
-@@ -1074,8 +1077,9 @@
- method.Block = (ToplevelBlock) $3;
- current_container.AddMethod (method);
-
-+ anonymous_host = null;
-+ current_generic_method = null;
- current_local_parameters = null;
-- iterator_container = null;
-
- if (RootContext.Documentation != null)
- Lexer.doc_state = XmlCommentState.Allowed;
-@@ -1132,7 +1136,9 @@
- method = new Method (current_class, generic, (Expression) $3, (int) $2, false,
- name, (Parameters) $6, (Attributes) $1);
-
-+ anonymous_host = method;
- current_local_parameters = (Parameters) $6;
-+ current_generic_method = generic;
-
- if (RootContext.Documentation != null)
- method.DocComment = Lexer.consume_doc_comment ();
-@@ -1168,7 +1174,9 @@
- method = new Method (current_class, generic, TypeManager.system_void_expr,
- (int) $2, false, name, (Parameters) $6, (Attributes) $1);
-
-+ anonymous_host = method;
- current_local_parameters = (Parameters) $6;
-+ current_generic_method = generic;
-
- if (RootContext.Documentation != null)
- method.DocComment = Lexer.consume_doc_comment ();
-@@ -1444,7 +1452,7 @@
- current_local_parameters = indexer_parameters;
- lexer.PropertyParsing = false;
-
-- iterator_container = SimpleIteratorContainer.GetSimple ();
-+ anonymous_host = SimpleAnonymousHost.GetSimple ();
- }
- accessor_body
- {
-@@ -1457,11 +1465,9 @@
- current_local_parameters = null;
- lexer.PropertyParsing = true;
-
-- if (SimpleIteratorContainer.Simple.Yields)
-- accessor.SetYields ();
-+ SimpleAnonymousHost.Simple.Propagate (accessor);
-+ anonymous_host = null;
-
-- iterator_container = null;
--
- if (RootContext.Documentation != null)
- if (Lexer.doc_state == XmlCommentState.Error)
- Lexer.doc_state = XmlCommentState.NotAllowed;
-@@ -1499,7 +1505,7 @@
-
- lexer.PropertyParsing = false;
-
-- iterator_container = SimpleIteratorContainer.GetSimple ();
-+ anonymous_host = SimpleAnonymousHost.GetSimple ();
- }
- accessor_body
- {
-@@ -1512,11 +1518,9 @@
- current_local_parameters = null;
- lexer.PropertyParsing = true;
-
-- if (SimpleIteratorContainer.Simple.Yields)
-- accessor.SetYields ();
-+ SimpleAnonymousHost.Simple.Propagate (accessor);
-+ anonymous_host = null;
-
-- iterator_container = null;
--
- if (RootContext.Documentation != null
- && Lexer.doc_state == XmlCommentState.Error)
- Lexer.doc_state = XmlCommentState.NotAllowed;
-@@ -1940,7 +1944,7 @@
- operator_declaration
- : opt_attributes opt_modifiers operator_declarator
- {
-- iterator_container = SimpleIteratorContainer.GetSimple ();
-+ anonymous_host = SimpleAnonymousHost.GetSimple ();
- }
- operator_body
- {
-@@ -1965,14 +1969,13 @@
- Lexer.doc_state = XmlCommentState.Allowed;
- }
-
-- if (SimpleIteratorContainer.Simple.Yields)
-- op.SetYields ();
-+ SimpleAnonymousHost.Simple.Propagate (op);
-+ anonymous_host = null;
-
- // Note again, checking is done in semantic analysis
- current_container.AddOperator (op);
-
- current_local_parameters = null;
-- iterator_container = null;
- }
- ;
-
-@@ -2432,7 +2435,7 @@
- parsing_indexer = true;
-
- indexer_parameters = decl.param_list;
-- iterator_container = SimpleIteratorContainer.GetSimple ();
-+ anonymous_host = SimpleAnonymousHost.GetSimple ();
- }
- accessor_declarations
- {
-@@ -3396,6 +3399,7 @@
- if (oob_stack == null)
- oob_stack = new Stack (6);
-
-+ oob_stack.Push (current_anonymous_method);
- oob_stack.Push (current_local_parameters);
- current_local_parameters = (Parameters)$2;
-
-@@ -3403,7 +3407,12 @@
- oob_stack.Push (current_block);
- oob_stack.Push (top_current_block);
- current_block = null;
-- }
-+
-+ Location loc = (Location) $1;
-+ current_anonymous_method = new AnonymousMethodExpression (
-+ current_anonymous_method, current_generic_method, current_container,
-+ (Parameters) $2, (ToplevelBlock) top_current_block, loc);
-+ }
- block
- {
- Location loc = (Location) $1;
-@@ -3416,11 +3425,20 @@
- ToplevelBlock anon_block = (ToplevelBlock) $4;
-
- anon_block.Parent = current_block;
-- $$ = new AnonymousMethod (current_container, (Parameters) $2, (ToplevelBlock) top_current_block,
-- anon_block, loc);
-+
-+ Report.Debug (64, "PARSER", anon_block, current_anonymous_method, anonymous_host,
-+ loc);
-+
-+ current_anonymous_method.Block = anon_block;
-+ if ((anonymous_host != null) && (current_anonymous_method.Parent == null))
-+ anonymous_host.AddAnonymousMethod (current_anonymous_method);
-+
-+ $$ = current_anonymous_method;
- }
-- current_local_parameters = (Parameters) oob_stack.Pop ();
-- }
-+
-+ current_local_parameters = (Parameters) oob_stack.Pop ();
-+ current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
-+ }
- ;
-
- opt_anonymous_method_signature
-@@ -4000,7 +4018,8 @@
- : OPEN_BRACE
- {
- if (current_block == null){
-- current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, (Location) $1);
-+ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters,
-+ current_generic_method, (Location) $1);
- top_current_block = current_block;
- } else {
- current_block = new Block (current_block, (Location) $1, Location.Null);
-@@ -4616,11 +4635,11 @@
- Report.FeatureIsNotStandardized (lt.Location, "yield statement");
- $$ = null;
- }
-- if (iterator_container == null){
-+ if (anonymous_host == null){
- Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
- $$ = null;
- } else {
-- iterator_container.SetYields ();
-+ anonymous_host.SetYields ();
- $$ = new Yield ((Expression) $3, lt.Location);
- }
- }
-@@ -4641,11 +4660,11 @@
- Report.FeatureIsNotStandardized (lt.Location, "yield statement");
- $$ = null;
- }
-- if (iterator_container == null){
-+ if (anonymous_host == null){
- Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
- $$ = null;
- } else {
-- iterator_container.SetYields ();
-+ anonymous_host.SetYields ();
- $$ = new YieldBreak (lt.Location);
- }
- }
-@@ -5006,22 +5025,41 @@
- }
-
- //
--// We use this when we do not have an object in advance that is an IIteratorContainer
-+// We use this when we do not have an object in advance that is an IAnonymousHost
- //
--public class SimpleIteratorContainer : IIteratorContainer {
-- public bool Yields;
-+public class SimpleAnonymousHost : IAnonymousHost {
-+ public static readonly SimpleAnonymousHost Simple = new SimpleAnonymousHost ();
-
-- public static SimpleIteratorContainer Simple = new SimpleIteratorContainer ();
-+ bool yields;
-+ ArrayList anonymous_methods;
-
-- //
-- // Reset and return
-- //
-- public static SimpleIteratorContainer GetSimple () {
-- Simple.Yields = false;
-+ public static SimpleAnonymousHost GetSimple () {
-+ Simple.yields = false;
-+ Simple.anonymous_methods = null;
- return Simple;
- }
-
-- public void SetYields () { Yields = true; }
-+ public void SetYields ()
-+ {
-+ yields = true;
-+ }
-+
-+ public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
-+ {
-+ if (anonymous_methods == null)
-+ anonymous_methods = new ArrayList ();
-+ anonymous_methods.Add (anonymous);
-+ }
-+
-+ public void Propagate (IAnonymousHost real_host)
-+ {
-+ if (yields)
-+ real_host.SetYields ();
-+ if (anonymous_methods != null) {
-+ foreach (AnonymousMethodExpression ame in anonymous_methods)
-+ real_host.AddAnonymousMethod (ame);
-+ }
-+ }
- }
-
- // <summary>
-Index: convert.cs
-===================================================================
---- convert.cs (revision 63019)
-+++ convert.cs (working copy)
-@@ -838,8 +838,8 @@
- if (!TypeManager.IsDelegateType (target_type))
- return false;
-
-- AnonymousMethod am = (AnonymousMethod) expr;
-- return am.ImplicitStandardConversionExists (target_type);
-+ AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
-+ return ame.ImplicitStandardConversionExists (target_type);
- }
-
- return false;
-@@ -1325,10 +1325,11 @@
- return null;
- }
-
-- AnonymousMethod am = (AnonymousMethod) expr;
-+ AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
-+
- int errors = Report.Errors;
-
-- Expression conv = am.Compatible (ec, target_type);
-+ Expression conv = ame.Compatible (ec, target_type);
- if (conv != null)
- return conv;
-
-Index: anonymous.cs
-===================================================================
---- anonymous.cs (revision 63019)
-+++ anonymous.cs (working copy)
-@@ -20,297 +20,742 @@
-
- namespace Mono.CSharp {
-
-- public abstract class AnonymousContainer : Expression
-+ public abstract class CompilerGeneratedClass : Class
- {
-- // Used to generate unique method names.
-- protected static int anonymous_method_count;
--
-- // An array list of AnonymousMethodParameter or null
-- public Parameters Parameters;
--
-- //
-- // The block that makes up the body for the anonymous mehtod
-- //
-- public ToplevelBlock Block;
-+ GenericMethod generic_method;
-+ static int next_index = 0;
-
-- //
-- // The container block for this anonymous method.
-- //
-- public Block ContainingBlock;
-+ private static MemberName MakeProxyName (GenericMethod generic, Location loc)
-+ {
-+ string name = String.Format ("<>c__CompilerGenerated{0}", ++next_index);
-+ if (generic != null) {
-+ TypeArguments args = new TypeArguments (loc);
-+ foreach (TypeParameter tparam in generic.CurrentTypeParameters)
-+ args.Add (new SimpleName (tparam.Name, loc));
-+ return new MemberName (name, args, loc);
-+ } else
-+ return new MemberName (name, loc);
-+ }
-
-- //
-- // The implicit method we create
-- //
-- public Method method;
-+ protected string MakeName (string prefix)
-+ {
-+ return String.Format ("<>c__{0}{1}", prefix, ++next_index);
-+ }
-
-- protected MethodInfo invoke_mb;
--
-- // The emit context for the anonymous method
-- public EmitContext aec;
-- public string[] TypeParameters;
-- public Type[] TypeArguments;
-- protected bool unreachable;
-+ protected CompilerGeneratedClass (TypeContainer parent, GenericMethod generic,
-+ int mod, Location loc)
-+ : base (parent.NamespaceEntry, parent,
-+ MakeProxyName (generic, loc), mod, null)
-+ {
-+ this.generic_method = generic;
-
-- // The method scope
-- ScopeInfo method_scope;
-- bool computed_method_scope = false;
--
-- //
-- // The modifiers applied to the method, we aggregate them
-- //
-- protected int method_modifiers = Modifiers.PRIVATE;
--
-- //
-- // Track the scopes that this method has used. At the
-- // end this is used to determine the ScopeInfo that will
-- // host the method
-- //
-- ArrayList scopes_used = new ArrayList ();
--
-- //
-- // Points to our container anonymous method if its present
-- //
-- public AnonymousContainer ContainerAnonymousMethod;
-+ if (generic != null) {
-+ ArrayList list = new ArrayList ();
-+ foreach (TypeParameter tparam in generic.TypeParameters) {
-+ if (tparam.Constraints != null)
-+ list.Add (tparam.Constraints.Clone ());
-+ }
-+ SetParameterInfo (list);
-+ }
-
-- protected AnonymousContainer (Parameters parameters, ToplevelBlock container,
-- ToplevelBlock block, Location l)
-+ parent.AddCompilerGeneratedClass (this);
-+ }
-+
-+ protected override bool DefineNestedTypes ()
- {
-- Parameters = parameters;
-- Block = block;
-- loc = l;
-+ RootContext.RegisterCompilerGeneratedType (TypeBuilder);
-+ return base.DefineNestedTypes ();
-+ }
-
-- //
-- // The order is important: this setups the CaptureContext tree hierarchy.
-- //
-- if (container == null) {
-- return;
-+ protected override bool DoDefineMembers ()
-+ {
-+ if (!PopulateType ())
-+ throw new InternalErrorException ();
-+
-+ members_defined = true;
-+
-+ if (!base.DoDefineMembers ())
-+ return false;
-+
-+ if (CompilerGenerated != null) {
-+ foreach (CompilerGeneratedClass c in CompilerGenerated) {
-+ if (!c.DefineMembers ())
-+ throw new InternalErrorException ();
-+ }
- }
-- container.SetHaveAnonymousMethods (l, this);
-- block.SetHaveAnonymousMethods (l, this);
-+
-+ return true;
- }
-
-- protected AnonymousContainer (Parameters parameters, ToplevelBlock container,
-- Location l):
-- this (parameters, container, new ToplevelBlock (container, parameters, l), l)
-+ protected override bool DoPopulateType ()
- {
-+ if (CompilerGenerated != null) {
-+ foreach (CompilerGeneratedClass c in CompilerGenerated) {
-+ if (!c.PopulateType ())
-+ return false;
-+ }
-+ }
-+
-+ return true;
- }
-
-- public override Expression DoResolve (EmitContext ec)
-+ public GenericMethod GenericMethod {
-+ get { return generic_method; }
-+ }
-+
-+ protected TypeExpr InflateType (Type it)
- {
-- //
-- // Set class type, set type
-- //
-+ if (generic_method == null)
-+ return new TypeExpression (it, Location);
-
-- eclass = ExprClass.Value;
-+ if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
-+ int pos = it.GenericParameterPosition;
-+ it = CurrentTypeParameters [pos].Type;
-+ } else if (it.IsGenericType) {
-+ Type[] args = it.GetGenericArguments ();
-
-- //
-- // This hack means `The type is not accessible
-- // anywhere', we depend on special conversion
-- // rules.
-- //
-- type = TypeManager.anonymous_method_type;
-+ TypeArguments inflated = new TypeArguments (Location);
-+ foreach (Type t in args)
-+ inflated.Add (InflateType (t));
-
-- return this;
-+ return new ConstructedType (it, inflated, Location);
-+ } else if (it.IsArray) {
-+ TypeExpr et_expr = InflateType (it.GetElementType ());
-+ int rank = it.GetArrayRank ();
-+
-+ Type et = et_expr.ResolveAsTypeTerminal (this, false).Type;
-+ it = et.MakeArrayType (rank);
-+ }
-+
-+ return new TypeExpression (it, Location);
- }
-
-- public void RegisterScope (ScopeInfo scope)
-+ public Field CaptureVariable (string name, Type type)
- {
-- if (scopes_used.Contains (scope))
-- return;
-- scopes_used.Add (scope);
-+ if (members_defined)
-+ throw new InternalErrorException ("Helper class already defined!");
-+ if (type == null)
-+ throw new ArgumentNullException ();
-+
-+ return new CapturedVariable (this, name, InflateType (type));
- }
-
-- // Returns the deepest of two scopes
-- ScopeInfo Deepest (ScopeInfo a, ScopeInfo b)
-+ bool members_defined;
-+
-+ internal void CheckMembersDefined ()
- {
-- ScopeInfo p;
-+ if (members_defined)
-+ throw new InternalErrorException ("Helper class already defined!");
-+ }
-
-- if (a == null)
-- return b;
-- if (b == null)
-- return a;
-- if (a == b)
-- return a;
-+ public override void EmitType ()
-+ {
-+ Report.Debug (64, "COMPILER GENERATED EMIT TYPE", this, CompilerGenerated);
-+ base.EmitType ();
-+ }
-
-- //
-- // 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;
-+ protected class CapturedVariable : Field
-+ {
-+ public CapturedVariable (CompilerGeneratedClass helper, string name,
-+ TypeExpr type)
-+ : base (helper, type, Modifiers.INTERNAL, name, null, helper.Location)
-+ {
-+ helper.AddField (this);
-+ }
-+ }
-+ }
-
-- CaptureContext ca = a.CaptureContext;
-- CaptureContext cb = b.CaptureContext;
-+ public abstract class ScopeInfoBase : CompilerGeneratedClass
-+ {
-+ public Block ScopeBlock;
-
-- for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext)
-- if (c == cb)
-- return a;
-+ protected ScopeInfoBase (TypeContainer parent, GenericMethod generic,
-+ int mod, Location loc)
-+ : base (parent, generic, mod, loc)
-+ { }
-
-- for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext)
-- if (c == ca)
-- return b;
-- throw new Exception ("Should never be reached");
-+ TypeExpr scope_type;
-+ protected Field scope_instance;
-+ protected ScopeInitializerBase scope_initializer;
-+
-+ public abstract AnonymousMethodHost Host {
-+ get;
- }
-
-- //
-- // Determines the proper host for a method considering the
-- // scopes it references
-- //
-- public void ComputeMethodHost ()
-+ public Field ScopeInstance {
-+ get { return scope_instance; }
-+ }
-+
-+ public Type ScopeType {
-+ get { return scope_type.Type; }
-+ }
-+
-+ public void EmitScopeInstance (EmitContext ec)
- {
-- if (computed_method_scope)
-- return;
--
-- method_scope = null;
-- int top = scopes_used.Count;
-- computed_method_scope = true;
-+ if (scope_initializer == null) {
-+ //
-+ // This is needed if someone overwrites the Emit method
-+ // of Statement and manually calls Block.Emit without
-+ // this snippet first:
-+ //
-+ // ec.EmitScopeInitFromBlock (The_Block);
-+ // The_Block.Emit (ec);
-+ //
-+ throw new InternalErrorException ();
-+ }
-
-- if (top == 0)
-+ scope_initializer.Emit (ec);
-+ }
-+
-+ public ExpressionStatement GetScopeInitializer (EmitContext ec)
-+ {
-+ Report.Debug (64, "GET SCOPE INITIALIZER",
-+ this, GetType (), scope_initializer, ScopeBlock);
-+
-+ if (scope_initializer == null) {
-+ scope_initializer = CreateScopeInitializer ();
-+ if (scope_initializer.Resolve (ec) == null)
-+ throw new InternalErrorException ();
-+ }
-+
-+ return scope_initializer;
-+ }
-+
-+ protected abstract ScopeInitializerBase CreateScopeInitializer ();
-+
-+ protected override bool DoPopulateType ()
-+ {
-+ Report.Debug (64, "SCOPE INFO RESOLVE TYPE", this, GetType (), IsGeneric,
-+ Parent.IsGeneric, GenericMethod);
-+
-+ if (IsGeneric) {
-+ TypeArguments targs = new TypeArguments (Location);
-+ if (Parent.IsGeneric)
-+ foreach (TypeParameter t in Parent.TypeParameters)
-+ targs.Add (new TypeParameterExpr (t, Location));
-+ if (GenericMethod != null)
-+ foreach (TypeParameter t in GenericMethod.TypeParameters)
-+ targs.Add (new TypeParameterExpr (t, Location));
-+
-+ scope_type = new ConstructedType (TypeBuilder, targs, Location);
-+ scope_type = scope_type.ResolveAsTypeTerminal (this, false);
-+ if ((scope_type == null) || (scope_type.Type == null))
-+ return false;
-+ } else {
-+ scope_type = new TypeExpression (TypeBuilder, Location);
-+ }
-+
-+ if (Host != this)
-+ scope_instance = Host.CaptureScope (this);
-+
-+ return base.DoPopulateType ();
-+ }
-+
-+ protected abstract class ScopeInitializerBase : ExpressionStatement
-+ {
-+ ScopeInfoBase scope;
-+ LocalBuilder scope_instance;
-+ ConstructorInfo scope_ctor;
-+
-+ bool initialized;
-+
-+ protected ScopeInitializerBase (ScopeInfoBase scope)
-+ {
-+ this.scope = scope;
-+ this.loc = scope.Location;
-+ eclass = ExprClass.Value;
-+ }
-+
-+ public ScopeInfoBase Scope {
-+ get { return scope; }
-+ }
-+
-+ public override Expression DoResolve (EmitContext ec)
-+ {
-+ if (scope_ctor != null)
-+ return this;
-+
-+ Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
-+ ec, ec.CurrentBlock);
-+
-+ type = Scope.ScopeType;
-+
-+ if (!DoResolveInternal (ec))
-+ throw new InternalErrorException ();
-+
-+ return this;
-+ }
-+
-+ protected virtual bool DoResolveInternal (EmitContext ec)
-+ {
-+ MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookupFinal (
-+ ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
-+ AllBindingFlags | BindingFlags.DeclaredOnly, loc);
-+ if (mg == null)
-+ throw new InternalErrorException ();
-+
-+ scope_ctor = (ConstructorInfo) mg.Methods [0];
-+
-+ if (Scope.ScopeInstance == null)
-+ scope_instance = ec.ig.DeclareLocal (type);
-+
-+ return true;
-+ }
-+
-+ static int next_id;
-+ int id = ++next_id;
-+
-+ protected virtual void DoEmit (EmitContext ec)
-+ {
-+ if (ec.CurrentBlock.Toplevel == Scope.ScopeBlock.Toplevel)
-+ DoEmitInstance (ec);
-+ else
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+ }
-+
-+ protected void DoEmitInstance (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldloc, scope_instance);
-+ }
-+
-+ protected virtual void EmitScopeConstructor (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Newobj, scope_ctor);
-+ }
-+
-+ public override void Emit (EmitContext ec)
-+ {
-+ if (!initialized)
-+ throw new InternalErrorException (
-+ "Scope {0} not initialized yet", scope);
-+
-+ DoEmit (ec);
-+ }
-+
-+ public override void EmitStatement (EmitContext ec)
-+ {
-+ if (initialized)
-+ return;
-+
-+ DoEmitStatement (ec);
-+ initialized = true;
-+ }
-+
-+ protected virtual void DoEmitStatement (EmitContext ec)
-+ {
-+ Report.Debug (64, "EMIT SCOPE INIT", this, id,
-+ Scope, scope_instance, ec);
-+
-+ ec.ig.Emit (OpCodes.Nop);
-+ ec.ig.Emit (OpCodes.Ldc_I4, id);
-+ ec.ig.Emit (OpCodes.Pop);
-+ ec.ig.Emit (OpCodes.Nop);
-+
-+ if (Scope != Scope.Host)
-+ Scope.Host.EmitScopeInstance (ec);
-+ else if (Scope.ScopeInstance != null)
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+ EmitScopeConstructor (ec);
-+ if (Scope.ScopeInstance != null)
-+ ec.ig.Emit (OpCodes.Stfld, Scope.ScopeInstance.FieldBuilder);
-+ else
-+ ec.ig.Emit (OpCodes.Stloc, scope_instance);
-+ }
-+ }
-+ }
-+
-+ public class AnonymousMethodHost : ScopeInfo
-+ {
-+ public AnonymousMethodHost (ToplevelBlock toplevel, TypeContainer parent,
-+ GenericMethod generic, Location loc)
-+ : base (toplevel, parent, generic, loc)
-+ {
-+ scopes = new ArrayList ();
-+ }
-+
-+ ArrayList scopes;
-+ TypeExpr parent_type;
-+ CapturedVariable parent_link;
-+ CapturedVariable this_field;
-+ Hashtable captured_params;
-+
-+ public override AnonymousMethodHost Host {
-+ get { return this; }
-+ }
-+
-+ public AnonymousMethodHost ParentHost {
-+ get { return Parent as AnonymousMethodHost; }
-+ }
-+
-+ public Type ParentType {
-+ get { return parent_type.Type; }
-+ }
-+
-+ public Field ParentLink {
-+ get { return parent_link; }
-+ }
-+
-+ public Field THIS {
-+ get { return this_field; }
-+ }
-+
-+ public bool HostsParameters {
-+ get { return captured_params != null; }
-+ }
-+
-+ public Field CaptureThis ()
-+ {
-+ if (ParentHost != null)
-+ return ParentHost.CaptureThis ();
-+
-+ CheckMembersDefined ();
-+ if (this_field == null)
-+ this_field = new CapturedVariable (this, "<>THIS", parent_type);
-+ return this_field;
-+ }
-+
-+ public Field CaptureScope (ScopeInfoBase scope)
-+ {
-+ return CaptureVariable (MakeName ("scope"), scope.ScopeType);
-+ }
-+
-+ public Variable GetCapturedParameter (Parameter par)
-+ {
-+ if (captured_params != null)
-+ return (Variable) captured_params [par];
-+ else
-+ return null;
-+ }
-+
-+ public bool IsParameterCaptured (string name)
-+ {
-+ if (captured_params != null)
-+ return captured_params [name] != null;
-+ return false;
-+ }
-+
-+ public Variable AddParameter (Parameter par, int idx)
-+ {
-+ if (captured_params == null)
-+ captured_params = new Hashtable ();
-+
-+ Variable var = (Variable) captured_params [par];
-+ if (var == null) {
-+ var = new CapturedParameter (this, par, idx);
-+ captured_params.Add (par, var);
-+ par.IsCaptured = true;
-+ }
-+
-+ return var;
-+ }
-+
-+ public void AddScope (ScopeInfo scope)
-+ {
-+ scopes.Add (scope);
-+ }
-+
-+ bool linked;
-+ public void LinkScopes ()
-+ {
-+ if (linked)
- return;
--
-- method_scope = (ScopeInfo) scopes_used [0];
-- if (top == 1)
-- return;
--
-- for (int i = 1; i < top; i++)
-- method_scope = Deepest (method_scope, (ScopeInfo) scopes_used [i]);
-+
-+ linked = true;
-+ if (ParentHost != null)
-+ ParentHost.LinkScopes ();
-+
-+ foreach (ScopeInfo si in scopes) {
-+ if (!si.Define ())
-+ throw new InternalErrorException ();
-+ if (si.DefineType () == null)
-+ throw new InternalErrorException ();
-+ }
- }
-
-- public ScopeInfo Scope {
-- get {
-- if (computed_method_scope)
-- return method_scope;
-+ protected override ScopeInitializerBase CreateScopeInitializer ()
-+ {
-+ return new AnonymousMethodHostInitializer (this);
-+ }
-
-+ protected override bool DefineNestedTypes ()
-+ {
-+ Report.Debug (64, "ANONYMOUS METHOD HOST NESTED",
-+ this, Name, Parent, Parent.Name, Parent.IsGeneric);
-+
-+ if (Parent.IsGeneric) {
-+ parent_type = new ConstructedType (
-+ Parent.TypeBuilder, Parent.TypeParameters, Location);
-+ parent_type = parent_type.ResolveAsTypeTerminal (this, false);
-+ if ((parent_type == null) || (parent_type.Type == null))
-+ return false;
-+ } else {
-+ parent_type = new TypeExpression (Parent.TypeBuilder, Location);
-+ }
-+
-+ CompilerGeneratedClass parent = Parent as CompilerGeneratedClass;
-+ if (parent != null)
-+ parent_link = new CapturedVariable (this, "<>parent", parent_type);
-+
-+ return base.DefineNestedTypes ();
-+ }
-+
-+ protected override bool DoDefineMembers ()
-+ {
-+ Report.Debug (64, "ANONYMOUS METHOD HOST DEFINE MEMBERS",
-+ this, Name, Parent, CompilerGenerated);
-+
-+ ArrayList args = new ArrayList ();
-+ if (this is IteratorHost)
-+ args.Add (new Parameter (
-+ TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
-+ null, Location));
-+
-+ Field pfield = Parent is CompilerGeneratedClass ? parent_link : this_field;
-+ if (pfield != null)
-+ args.Add (new Parameter (
-+ pfield.MemberType, "parent", Parameter.Modifier.NONE,
-+ null, Location));
-+
-+ if (HostsParameters) {
-+ foreach (CapturedParameter cp in captured_params.Values) {
-+ args.Add (new Parameter (
-+ cp.Field.MemberType, cp.Field.Name,
-+ Parameter.Modifier.NONE, null, Location));
-+ }
-+ }
-+
-+ Parameter[] ctor_params = new Parameter [args.Count];
-+ args.CopyTo (ctor_params, 0);
-+ Constructor ctor = new Constructor (
-+ this, MemberName.Name, Modifiers.PUBLIC,
-+ new Parameters (ctor_params),
-+ new GeneratedBaseInitializer (Location),
-+ Location);
-+ AddConstructor (ctor);
-+
-+ ctor.Block = new ToplevelBlock (null, Location);
-+ ctor.Block.AddStatement (new TheCtor (this));
-+
-+ return base.DoDefineMembers ();
-+ }
-+
-+ protected virtual void EmitScopeConstructor (EmitContext ec)
-+ {
-+ int pos = (this is IteratorHost) ? 2 : 1;
-+ Field pfield = Parent is CompilerGeneratedClass ? parent_link : this_field;
-+ if (pfield != null) {
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+ ec.ig.Emit (OpCodes.Ldarg, pos);
-+ ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
-+ pos++;
-+ }
-+
-+ if (HostsParameters) {
-+ foreach (CapturedParameter cp in captured_params.Values) {
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+ ParameterReference.EmitLdArg (ec.ig, pos++);
-+ ec.ig.Emit (OpCodes.Stfld, cp.Field.FieldBuilder);
-+ }
-+ }
-+ }
-+
-+ protected class TheCtor : Statement
-+ {
-+ AnonymousMethodHost host;
-+
-+ public TheCtor (AnonymousMethodHost host)
-+ {
-+ this.host = host;
-+ }
-+
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ return true;
-+ }
-+
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ host.EmitScopeConstructor (ec);
-+ }
-+ }
-+
-+ protected class AnonymousMethodHostInitializer : ScopeInitializer
-+ {
-+ AnonymousMethodHost host;
-+
-+ public AnonymousMethodHostInitializer (AnonymousMethodHost host)
-+ : base (host)
-+ {
-+ this.host = host;
-+ }
-+
-+ public AnonymousMethodHost Host {
-+ get { return host; }
-+ }
-+
-+ protected override bool DoResolveInternal (EmitContext ec)
-+ {
-+ Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
-+ this, Host, Host.ScopeType, Host.ParentType, loc);
-+
- //
-- // This means that ComputeMethodHost is not being called, most
-- // likely by someone who overwrote the CreateMethodHost method
-+ // Copy the parameter values, if any
- //
-- throw new Exception ("Internal error, AnonymousContainer.Scope is being used before its container is computed");
-+ if (Host.HostsParameters) {
-+ foreach (CapturedParameter cp in Host.captured_params.Values) {
-+ FieldExpr fe = (FieldExpr) Expression.MemberLookup (
-+ ec.ContainerType, type, cp.Field.Name, loc);
-+ if (fe == null)
-+ throw new InternalErrorException ();
-+
-+ fe.InstanceExpression = this;
-+ cp.FieldInstance = fe;
-+ }
-+ }
-+
-+ return base.DoResolveInternal (ec);
- }
-+
-+ protected override void EmitScopeConstructor (EmitContext ec)
-+ {
-+ if ((host.THIS != null) || (host.ParentLink != null))
-+ ec.ig.Emit (OpCodes.Ldarg_0);
-+
-+ if (Host.HostsParameters) {
-+ foreach (CapturedParameter cp in Host.captured_params.Values) {
-+ EmitParameterReference (ec, cp);
-+ }
-+ }
-+
-+ base.EmitScopeConstructor (ec);
-+ }
- }
--
--
-- protected abstract bool CreateMethodHost (EmitContext ec);
-
-- public abstract void CreateScopeType (EmitContext ec, ScopeInfo scope);
-+ }
-
-- public abstract Iterator Iterator {
-+ public interface IAnonymousContainer
-+ {
-+ ToplevelBlock Container {
- get;
- }
-
-- public abstract bool IsIterator {
-+ GenericMethod GenericMethod {
- get;
- }
-+
-+ AnonymousMethodHost RootScope {
-+ get;
-+ }
-+
-+ bool IsIterator {
-+ get;
-+ }
- }
-
-- public class AnonymousMethod : AnonymousContainer
-+ public interface IAnonymousHost
- {
-- TypeContainer host;
-+ //
-+ // Invoked if a yield statement is found in the body
-+ //
-+ void SetYields ();
-
- //
-- // The value return by the Compatible call, this ensure that
-- // the code works even if invoked more than once (Resolve called
-- // more than once, due to the way Convert.ImplicitConversion works
-+ // Invoked if an anonymous method is found in the body
- //
-- Expression anonymous_delegate;
-+ void AddAnonymousMethod (AnonymousMethodExpression anonymous);
-+ }
-
-- public AnonymousMethod (TypeContainer host, Parameters parameters, ToplevelBlock container,
-- ToplevelBlock block, Location l)
-- : base (parameters, container, block, l)
-- {
-- this.host = host;
-+ public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
-+ {
-+ public readonly AnonymousMethodExpression Parent;
-+ public readonly TypeContainer Host;
-+ public readonly Parameters Parameters;
-+
-+ public ToplevelBlock Block;
-+ protected AnonymousMethod anonymous;
-+
-+ protected readonly ToplevelBlock container;
-+ protected readonly GenericMethod generic;
-+
-+ public ToplevelBlock Container {
-+ get { return container; }
- }
-
-- public override Iterator Iterator {
-- get { return null; }
-+ public GenericMethod GenericMethod {
-+ get { return generic; }
- }
-
-- public override bool IsIterator {
-- get { return false; }
-+ public AnonymousMethod AnonymousMethod {
-+ get { return anonymous; }
- }
-
-- public override void Emit (EmitContext ec)
-- {
-- // nothing, as we only exist to not do anything.
-+ public AnonymousMethodHost RootScope {
-+ get { return root_scope; }
- }
-
-- //
-- // Creates the host for the anonymous method
-- //
-- protected override bool CreateMethodHost (EmitContext ec)
-+ public AnonymousMethodExpression (AnonymousMethodExpression parent,
-+ GenericMethod generic, TypeContainer host,
-+ Parameters parameters, ToplevelBlock container,
-+ Location loc)
- {
-- ComputeMethodHost ();
-+ this.Parent = parent;
-+ this.generic = parent != null ? null : generic;
-+ this.Host = host;
-+ this.Parameters = parameters;
-+ this.container = container;
-+ this.loc = loc;
-
-- //
-- // 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;
-+ Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
-+ container, loc);
-
-- if (current_type == null)
-- throw new Exception ("The current_type is null");
--
-- if (type_host == null)
-- throw new Exception (String.Format ("Type host is null, method_host is {0}", Scope == null ? "null" : "Not null"));
-+ if (parent != null)
-+ parent.AddAnonymousMethod (this);
-+ }
-
-- if (current_type != type_host)
-- method_modifiers = Modifiers.INTERNAL;
-+ ArrayList children;
-+ AnonymousMethodHost root_scope;
-
-- if (current_type == type_host && ec.IsStatic){
-- method_modifiers |= Modifiers.STATIC;
-- current_type = null;
-- }
-+ void IAnonymousHost.SetYields ()
-+ {
-+ throw new InvalidOperationException ();
-+ }
-
-- string name = "<#AnonymousMethod>" + anonymous_method_count++;
-- MemberName member_name;
-+ public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
-+ {
-+ if (children == null)
-+ children = new ArrayList ();
-+ children.Add (anonymous);
-+ }
-
-- GenericMethod generic_method = null;
-- if (TypeParameters != null) {
-- TypeArguments args = new TypeArguments (loc);
-- foreach (string t in TypeParameters)
-- args.Add (new SimpleName (t, loc));
-+ public bool CreateAnonymousHelpers ()
-+ {
-+ Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
-+ this, Host, container, loc);
-
-- member_name = new MemberName (name, args, loc);
-+ if (container != null)
-+ root_scope = container.CreateAnonymousMethodHost (Host);
-
-- generic_method = new GenericMethod (
-- ec.DeclContainer.NamespaceEntry,
-- (TypeContainer) ec.TypeContainer, member_name,
-- new TypeExpression (invoke_mb.ReturnType, loc),
-- Parameters);
-+ if (children != null) {
-+ foreach (AnonymousMethodExpression child in children) {
-+ if (!child.CreateAnonymousHelpers ())
-+ return false;
-+ }
-+ }
-
-- generic_method.SetParameterInfo (null);
-- } else
-- member_name = new MemberName (name, loc);
-+ return true;
-+ }
-
-- method = new Method (
-- (TypeContainer) ec.TypeContainer, generic_method,
-- new TypeExpression (invoke_mb.ReturnType, loc),
-- method_modifiers, false, member_name, Parameters, null);
-- 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;
-+ public override string ExprClassName {
-+ get {
-+ return "anonymous method";
-+ }
- }
-
- void Error_ParameterMismatch (Type t)
- {
- Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
-- "{0}' since there is a parameter mismatch", TypeManager.CSharpName (t));
-+ "{0}' since there is a parameter mismatch",
-+ TypeManager.CSharpName (t));
- }
-
- public bool ImplicitStandardConversionExists (Type delegate_type)
-@@ -318,8 +763,9 @@
- if (Parameters == null)
- return true;
-
-- MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (host.TypeBuilder, delegate_type, loc);
-- invoke_mb = (MethodInfo) invoke_mg.Methods [0];
-+ MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
-+ Host.TypeBuilder, delegate_type, loc);
-+ MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
- ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
-
- if (Parameters.Count != invoke_pd.Count)
-@@ -338,31 +784,20 @@
- //
- public Expression Compatible (EmitContext ec, Type delegate_type)
- {
-- if (anonymous_delegate != null)
-- return anonymous_delegate;
--
-+ if (anonymous != null)
-+ return anonymous.AnonymousDelegate;
-+
- //
- // At this point its the first time we know the return type that is
- // needed for the anonymous method. We create the method here.
- //
-
-- MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (ec.ContainerType, delegate_type, loc);
-- invoke_mb = (MethodInfo) invoke_mg.Methods [0];
-+ MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
-+ ec.ContainerType, delegate_type, loc);
-+ MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
- ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
-
-- if (delegate_type.IsGenericType) {
-- Type def = delegate_type.GetGenericTypeDefinition ();
--
-- if (def != delegate_type) {
-- Type[] tparam = TypeManager.GetTypeArguments (def);
--
-- TypeArguments = TypeManager.GetTypeArguments (delegate_type);
-- TypeParameters = new string [tparam.Length];
-- for (int i = 0; i < tparam.Length; i++)
-- TypeParameters [i] = tparam [i].Name;
-- }
-- }
--
-+ Parameters parameters;
- if (Parameters == null) {
- //
- // We provide a set of inaccessible parameters
-@@ -375,7 +810,9 @@
- "+" + i, invoke_pd.ParameterModifier (i), null, loc);
- }
-
-- Parameters = new Parameters (fixedpars);
-+ parameters = new Parameters (fixedpars);
-+ if (!parameters.Resolve (ec))
-+ return null;
- } else {
- if (Parameters.Count != invoke_pd.Count) {
- Report.SymbolRelatedToPreviousError (delegate_type);
-@@ -407,8 +844,10 @@
- return null;
- }
- }
-+
-+ parameters = Parameters;
- }
--
-+
- //
- // Second: the return type of the delegate must be compatible with
- // the anonymous type. Instead of doing a pass to examine the block
-@@ -419,135 +858,309 @@
- //MethodBuilder builder = method_data.MethodBuilder;
- //ILGenerator ig = builder.GetILGenerator ();
-
-- aec = new EmitContext (ec.ResolveContext,
-- ec.TypeContainer, ec.DeclContainer, loc, null,
-- invoke_mb.ReturnType,
-- /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
-- (ec.InUnsafe ? Modifiers.UNSAFE : 0) |
-- (ec.IsStatic ? Modifiers.STATIC : 0),
-- /* No constructor */ false);
-+ Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
-+ Container, Block, invoke_mb.ReturnType, delegate_type,
-+ delegate_type.IsGenericType, loc);
-
-- aec.CurrentAnonymousMethod = this;
-- ContainerAnonymousMethod = ec.CurrentAnonymousMethod;
-- ContainingBlock = ec.CurrentBlock;
-+ anonymous = new AnonymousMethod (
-+ Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
-+ GenericMethod, parameters, Container, Block, invoke_mb.ReturnType,
-+ delegate_type, loc);
-
-- if (aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable)){
-- anonymous_delegate = new AnonymousDelegate (
-- this, delegate_type, loc).Resolve (ec);
-- return anonymous_delegate;
-- }
-- return null;
-+ if (!anonymous.Resolve (ec))
-+ return null;
-+
-+ return anonymous.AnonymousDelegate;
- }
-
- public override Expression DoResolve (EmitContext ec)
- {
-- if (!ec.IsAnonymousMethodAllowed) {
-- Report.Error (1706, loc, "Anonymous methods are not allowed in the attribute declaration");
-- return null;
-- }
-+ //
-+ // Set class type, set type
-+ //
-
-- if (Parameters != null && !Parameters.Resolve (ec)) {
-+ eclass = ExprClass.Value;
-+
-+ //
-+ // This hack means `The type is not accessible
-+ // anywhere', we depend on special conversion
-+ // rules.
-+ //
-+ type = TypeManager.anonymous_method_type;
-+
-+ if ((Parameters != null) && !Parameters.Resolve (ec))
- return null;
-- }
-
-- return base.DoResolve (ec);
-+ return this;
- }
-
-+ public override void Emit (EmitContext ec)
-+ {
-+ // nothing, as we only exist to not do anything.
-+ }
-
-- public override string ExprClassName {
-- get {
-- return "anonymous method";
-- }
-+ public bool IsIterator {
-+ get { return false; }
- }
-+ }
-
-- public MethodInfo GetMethodBuilder ()
-+ public abstract class AnonymousContainer : IAnonymousContainer
-+ {
-+ // Used to generate unique method names.
-+ protected static int anonymous_method_count;
-+
-+ public readonly Location Location;
-+
-+ // An array list of AnonymousMethodParameter or null
-+ public readonly Parameters Parameters;
-+
-+ //
-+ // The block that makes up the body for the anonymous mehtod
-+ //
-+ public readonly ToplevelBlock Block;
-+
-+ public readonly Type ReturnType;
-+ public readonly TypeContainer Host;
-+
-+ //
-+ // The implicit method we create
-+ //
-+ protected Method method;
-+ protected EmitContext aec;
-+
-+ // The emit context for the anonymous method
-+ protected bool unreachable;
-+ protected readonly Location loc;
-+ protected readonly ToplevelBlock container;
-+ protected readonly GenericMethod generic;
-+
-+ //
-+ // Points to our container anonymous method if its present
-+ //
-+ public readonly AnonymousContainer ContainerAnonymousMethod;
-+
-+ protected AnonymousContainer (AnonymousContainer parent, TypeContainer host,
-+ GenericMethod generic, Parameters parameters,
-+ ToplevelBlock container, ToplevelBlock block,
-+ Type return_type, int mod, Location loc)
- {
-- MethodInfo builder = method.MethodBuilder;
-- if (TypeArguments != null)
-- return builder.MakeGenericMethod (TypeArguments);
-- else
-- return builder;
-+ this.ContainerAnonymousMethod = parent;
-+ this.ReturnType = return_type;
-+ this.Host = host;
-+
-+ this.container = container;
-+ this.generic = parent != null ? null : generic;
-+ this.Parameters = parameters;
-+ this.Block = block;
-+ this.loc = loc;
- }
-
-- public override string GetSignatureForError ()
-+ public Method Method {
-+ get { return method; }
-+ }
-+
-+ public abstract AnonymousMethodHost RootScope {
-+ get;
-+ }
-+
-+ public string GetSignatureForError ()
- {
-- string s = TypeManager.CSharpSignature (invoke_mb);
-- return s.Substring (0, s.IndexOf (".Invoke("));
-+ return RootScope.GetSignatureForError ();
- }
--
-- public bool EmitMethod (EmitContext ec)
-+
-+ public virtual bool Resolve (EmitContext ec)
- {
-- if (!CreateMethodHost (ec))
-+ if (!ec.IsAnonymousMethodAllowed) {
-+ Report.Error (1706, loc,
-+ "Anonymous methods are not allowed in the " +
-+ "attribute declaration");
- return false;
-+ }
-
-- MethodBuilder builder = method.MethodBuilder;
-- ILGenerator ig = builder.GetILGenerator ();
-- aec.ig = ig;
-+ Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, loc, ec,
-+ RootScope, Parameters, ec.IsStatic);
-
-- Parameters.ApplyAttributes (builder);
-+ aec = new EmitContext (
-+ ec.ResolveContext, ec.TypeContainer,
-+ RootScope != null ? RootScope : Host, loc, null, ReturnType,
-+ /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
-+ (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
-
-- //
-- // Adjust based on the computed state of the
-- // method from CreateMethodHost
--
-- aec.MethodIsStatic = (method_modifiers & Modifiers.STATIC) != 0;
--
-- aec.EmitMeta (Block);
-- aec.EmitResolvedTopBlock (Block, unreachable);
-- return true;
-+ aec.CurrentAnonymousMethod = this;
-+
-+ Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, loc, ec, aec,
-+ RootScope, Parameters, Block);
-+
-+ bool unreachable;
-+ if (!aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable))
-+ return false;
-+
-+ Report.Debug (64, "RESOLVE ANONYMOUS METHOD #3", this, ec, aec, Block);
-+
-+ method = DoCreateMethodHost (ec);
-+
-+ if (RootScope == null)
-+ return method.Define ();
-+ else
-+ return true;
- }
-
-- public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
-- {
-- TypeBuilder container = ec.TypeContainer.TypeBuilder;
-- string name = String.Format ("<>AnonHelp<{0}>", scope.id);
-+ protected abstract Method DoCreateMethodHost (EmitContext ec);
-
-- scope.ScopeTypeBuilder = container.DefineNestedType (name,
-- TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit | TypeAttributes.NestedPrivate,
-- TypeManager.object_type);
-+ public ToplevelBlock Container {
-+ get { return container; }
-+ }
-
-- Type [] constructor_types = Type.EmptyTypes;
-- ConstructorBuilder ctor = scope.ScopeTypeBuilder.DefineConstructor (
-- MethodAttributes.Public | MethodAttributes.HideBySig |
-- MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
-- CallingConventions.HasThis, constructor_types);
-- TypeManager.RegisterMethod (ctor, Parameters.EmptyReadOnlyParameters);
-+ public GenericMethod GenericMethod {
-+ get { return generic; }
-+ }
-
-- ILGenerator cig = ctor.GetILGenerator ();
-- cig.Emit (OpCodes.Ldarg_0);
-- cig.Emit (OpCodes.Call, TypeManager.object_ctor);
-- cig.Emit (OpCodes.Ret);
-+ public abstract bool IsIterator {
-+ get;
-+ }
-
-- if (ec.TypeContainer.IsGeneric) {
-- TypeParameter[] tparam = ec.TypeContainer.TypeParameters;
-- string[] names = new string [tparam.Length];
-- Type[] types = new Type [tparam.Length];
-+#if FIXME
-+ public override string ToString ()
-+ {
-+ return String.Format ("{0} ({1})", GetType (), Name);
-+ }
-+#endif
-
-- for (int i = 0; i < names.Length; i++) {
-- names [i] = tparam [i].Name;
-- types [i] = tparam [i].Type;
-+ protected class AnonymousMethodMethod : Method
-+ {
-+ public AnonymousContainer AnonymousMethod;
-+
-+ public AnonymousMethodMethod (AnonymousContainer am, GenericMethod generic,
-+ TypeExpr return_type, int mod, MemberName name,
-+ Parameters parameters)
-+ : base (am.RootScope != null ? am.RootScope : am.Host,
-+ generic, return_type, mod, false, name, parameters, null)
-+ {
-+ this.AnonymousMethod = am;
-+
-+ if (am.RootScope != null) {
-+ am.RootScope.CheckMembersDefined ();
-+ am.RootScope.AddMethod (this);
-+ } else {
-+ ModFlags |= Modifiers.STATIC;
-+ am.Host.AddMethod (this);
- }
-+ Block = am.Block;
-+ }
-
-- scope.ScopeTypeBuilder.DefineGenericParameters (names);
-- scope.ScopeTypeBuilder.GetGenericTypeDefinition ();
-+ public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
-+ {
-+ EmitContext aec = AnonymousMethod.aec;
-+ aec.ig = ig;
-+ return aec;
-+ }
-+ }
-+ }
-
-- scope.ScopeType = scope.ScopeTypeBuilder.MakeGenericType (types);
-+ public class AnonymousMethod : AnonymousContainer
-+ {
-+ public readonly Type DelegateType;
-+
-+ //
-+ // The value return by the Compatible call, this ensure that
-+ // the code works even if invoked more than once (Resolve called
-+ // more than once, due to the way Convert.ImplicitConversion works
-+ //
-+ Expression anonymous_delegate;
-+ AnonymousMethodHost root_scope;
-+
-+ public AnonymousMethod (AnonymousMethod parent, AnonymousMethodHost root_scope,
-+ TypeContainer host, GenericMethod generic,
-+ Parameters parameters, ToplevelBlock container,
-+ ToplevelBlock block, Type return_type, Type delegate_type,
-+ Location loc)
-+ : base (parent, host, generic, parameters, container, block,
-+ return_type, 0, loc)
-+ {
-+ this.DelegateType = delegate_type;
-+ this.root_scope = root_scope;
-+ }
-+
-+ public override AnonymousMethodHost RootScope {
-+ get { return root_scope; }
-+ }
-+
-+ public override bool IsIterator {
-+ get { return false; }
-+ }
-+
-+ public Expression AnonymousDelegate {
-+ get { return anonymous_delegate; }
-+ }
-+
-+ //
-+ // Creates the host for the anonymous method
-+ //
-+ protected override Method DoCreateMethodHost (EmitContext ec)
-+ {
-+ string name = "<>c__AnonymousMethod" + anonymous_method_count++;
-+ MemberName member_name;
-+
-+ GenericMethod generic_method = null;
-+ if (DelegateType.IsGenericType) {
-+ TypeArguments args = new TypeArguments (loc);
-+
-+ Type[] tparam = TypeManager.GetTypeArguments (DelegateType);
-+ for (int i = 0; i < tparam.Length; i++)
-+ args.Add (new SimpleName (tparam [i].Name, loc));
-+
-+ member_name = new MemberName (name, args, loc);
-+
-+ generic_method = new GenericMethod (
-+ RootScope.NamespaceEntry, RootScope, member_name,
-+ new TypeExpression (ReturnType, loc), Parameters);
-+
-+ generic_method.SetParameterInfo (null);
- } else
-- scope.ScopeType = scope.ScopeTypeBuilder;
-+ member_name = new MemberName (name, loc);
-
-+ return new AnonymousMethodMethod (
-+ this, generic_method, new TypeExpression (ReturnType, loc),
-+ Modifiers.INTERNAL, member_name, Parameters);
-+ }
-
-- if (ec.TypeContainer.IsGeneric)
-- scope.ScopeConstructor = TypeBuilder.GetConstructor (
-- scope.ScopeType, ctor);
-- else
-- scope.ScopeConstructor = ctor;
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ if (!base.Resolve (ec))
-+ return false;
-+
-+ anonymous_delegate = new AnonymousDelegate (this, DelegateType, loc).Resolve (ec);
-+ if (anonymous_delegate == null)
-+ return false;
-+
-+ return true;
- }
-
-+ public MethodInfo GetMethodBuilder (EmitContext ec)
-+ {
-+ MethodInfo builder = method.MethodBuilder;
-+ if ((RootScope != null) && RootScope.IsGeneric) {
-+ MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
-+ ec.ContainerType, RootScope.ScopeType, builder.Name, loc);
-+
-+ if (mg == null)
-+ throw new InternalErrorException ();
-+ builder = (MethodInfo) mg.Methods [0];
-+ }
-+
-+ if (!DelegateType.IsGenericType)
-+ return builder;
-+
-+ Type[] targs = TypeManager.GetTypeArguments (DelegateType);
-+ return builder.MakeGenericMethod (targs);
-+ }
-+
- public static void Error_AddressOfCapturedVar (string name, Location loc)
- {
- Report.Error (1686, loc,
-- "Local variable `{0}' or its members cannot have their address taken and be used inside an anonymous method block",
-- name);
-+ "Local variable `{0}' or its members cannot have their " +
-+ "address taken and be used inside an anonymous method block",
-+ name);
- }
- }
-
-@@ -573,138 +1186,84 @@
-
- public override void Emit (EmitContext ec)
- {
-- if (!am.EmitMethod (ec))
-- return;
-+ Report.Debug (64, "ANONYMOUS DELEGATE", this, am, ec.ContainerType, type,
-+ ec, loc);
-
- //
- // Now emit the delegate creation.
- //
-- if ((am.method.ModFlags & Modifiers.STATIC) == 0)
-- delegate_instance_expression = new AnonymousInstance (am);
--
-+ if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
-+ delegate_instance_expression = am.RootScope.GetScopeInitializer (ec);
-+
-+ if (delegate_instance_expression == null)
-+ throw new InternalErrorException ();
-+ }
-+
- Expression ml = Expression.MemberLookup (ec.ContainerType, type, ".ctor", loc);
- constructor_method = ((MethodGroupExpr) ml).Methods [0];
-- delegate_method = am.GetMethodBuilder ();
-+ delegate_method = am.GetMethodBuilder (ec);
-+ Report.Debug (64, "ANONYMOUS DELEGATE #1", constructor_method, delegate_method,
-+ delegate_method, delegate_instance_expression);
- 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;
--
-+ public class ScopeInfo : ScopeInfoBase {
-+ public readonly AnonymousMethodHost RootScope;
-+
- // For tracking the number of scopes created.
- public int id;
- static int count;
-- bool inited = false;
-
-- ArrayList locals = new ArrayList ();
-- ArrayList children = new ArrayList ();
-+ Hashtable locals = new Hashtable ();
-
-- //
-- // The types and fields generated
-- //
-- public TypeBuilder ScopeTypeBuilder;
-- public Type ScopeType;
-- public ConstructorInfo ScopeConstructor;
-- public FieldBuilder THIS;
-- public FieldBuilder ParentLink;
--
-- //
-- // Points to the object of type `ScopeTypeBuilder' that
-- // holds the data for the scope
-- //
-- LocalBuilder scope_instance;
--
-- public ScopeInfo (CaptureContext cc, Block b)
-+ public ScopeInfo (AnonymousMethodHost root, Block block)
-+ : base (root, null, Modifiers.PUBLIC, block.StartLocation)
- {
-- CaptureContext = cc;
-- ScopeBlock = b;
-+ this.RootScope = root;
-+ ScopeBlock = block;
- id = count++;
-
-- cc.RegisterCaptureContext ();
-+ Report.Debug (64, "NEW SCOPE", this);
-+
-+ root.AddScope (this);
- }
-
-- public void AddLocal (LocalInfo li)
-+ public ScopeInfo (ToplevelBlock toplevel, TypeContainer parent,
-+ GenericMethod generic, Location loc)
-+ : base (parent, generic, 0, loc)
- {
-- if (locals.Contains (li))
-- return;
-+ RootScope = (AnonymousMethodHost) this;
-+ ScopeBlock = toplevel;
-+ id = count++;
-
-- locals.Add (li);
--}
--
-- public bool IsCaptured (LocalInfo li)
-- {
-- return locals.Contains (li);
-+ Report.Debug (64, "NEW ROOT SCOPE", this);
- }
--
-- internal void AddChild (ScopeInfo si)
-- {
-- if (children.Contains (si))
-- return;
-
-- //
-- // If any of the current children should be a children of `si', move them there
-- //
-- ArrayList move_queue = null;
-- foreach (ScopeInfo child in children){
-- if (child.ScopeBlock.IsChildOf (si.ScopeBlock)){
-- if (move_queue == null)
-- move_queue = new ArrayList ();
-- move_queue.Add (child);
-- child.ParentScope = si;
-- si.AddChild (child);
-- }
-- }
--
-- children.Add (si);
-+ public override AnonymousMethodHost Host {
-+ get { return RootScope; }
-+ }
-
-- if (move_queue != null){
-- foreach (ScopeInfo child in move_queue){
-- children.Remove (child);
-- }
-+ public Variable AddLocal (LocalInfo local)
-+ {
-+ Variable var = (Variable) locals [local];
-+ if (var == null) {
-+ var = new CapturedLocal (this, local);
-+ locals.Add (local, var);
-+ local.IsCaptured = true;
- }
-- }
-+ return var;
-+ }
-
-+ public Variable GetCapturedVariable (LocalInfo local)
-+ {
-+ return (Variable) locals [local];
-+ }
-+
- static int indent = 0;
-
- void Pad ()
-@@ -719,204 +1278,28 @@
- Pad ();
- Console.WriteLine ("START");
- indent++;
-- Pad ();
-- Console.WriteLine ("NeedThis=" + NeedThis);
-- foreach (LocalInfo li in locals){
-+ foreach (LocalInfo li in locals.Values){
- Pad ();
- Console.WriteLine ("var {0}", MakeFieldName (li.Name));
- }
-
-- foreach (ScopeInfo si in children)
-- si.EmitDebug ();
- indent--;
- Pad ();
- Console.WriteLine ("END");
- }
-
-- private string MakeFieldName (string local_name)
-+ protected string MakeFieldName (string local_name)
- {
- return "<" + id + ":" + local_name + ">";
- }
-
-- public void EmitScopeType (EmitContext ec)
-+ protected override ScopeInitializerBase CreateScopeInitializer ()
- {
-- // EmitDebug ();
--
-- if (ScopeTypeBuilder != null)
-- return;
--
-- Type container;
-- if (ec.TypeContainer.CurrentType != null)
-- container = ec.TypeContainer.CurrentType;
-- else
-- container = ec.TypeContainer.TypeBuilder;
--
-- CaptureContext.Host.CreateScopeType (ec, this);
--
-- 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));
-- }
--
-- if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder)
-- ParentLink = ScopeTypeBuilder.DefineField (
-- "<>parent", ParentScope.ScopeType, 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 (
-- MakeFieldName (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;
-- }
-- }
--
-- foreach (ScopeInfo si in children){
-- si.EmitScopeType (ec);
-- }
-+ return new ScopeInitializer (this);
- }
-
-- public void CloseTypes ()
-- {
-- RootContext.RegisterCompilerGeneratedType (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;
--
-- if (ScopeConstructor == null)
-- throw new Exception ("ScopeConstructor is null for" + this.ToString ());
--
-- if (!CaptureContext.Host.IsIterator) {
-- scope_instance = ig.DeclareLocal (ScopeType);
-- ig.Emit (OpCodes.Newobj, ScopeConstructor);
-- ig.Emit (OpCodes.Stloc, scope_instance);
-- }
--
-- if (THIS != null){
-- if (CaptureContext.Host.IsIterator) {
-- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Ldarg_1);
-- } else {
-- ig.Emit (OpCodes.Ldloc, scope_instance);
-- ig.Emit (OpCodes.Ldarg_0);
-- }
-- ig.Emit (OpCodes.Stfld, THIS);
-- }
--
-- //
-- // Copy the parameter values, if any
-- //
-- int extra = ec.IsStatic ? 0 : 1;
-- if (CaptureContext.Host.IsIterator)
-- extra++;
-- if (HostsParameters){
-- Hashtable captured_parameters = CaptureContext.captured_parameters;
--
-- foreach (DictionaryEntry de in captured_parameters){
-- CapturedParameter cp = (CapturedParameter) de.Value;
--
-- EmitScopeInstance (ig);
-- ParameterReference.EmitLdArg (ig, cp.Idx + extra);
-- ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
-- }
-- }
--
-- if (ParentScope != null){
-- if (!ParentScope.inited)
-- ParentScope.EmitInitScope (ec);
--
-- if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder) {
-- //
-- // Only emit initialization in our capturecontext world
-- //
-- if (ParentScope.CaptureContext == CaptureContext){
-- EmitScopeInstance (ig);
-- ParentScope.EmitScopeInstance (ig);
-- ig.Emit (OpCodes.Stfld, ParentLink);
-- } else {
-- EmitScopeInstance (ig);
-- ig.Emit (OpCodes.Ldarg_0);
-- ig.Emit (OpCodes.Stfld, ParentLink);
-- }
-- }
-- }
-- inited = true;
-- }
--
-- public void EmitScopeInstance (ILGenerator ig)
-- {
-- if (CaptureContext.Host.IsIterator)
-- ig.Emit (OpCodes.Ldarg_0);
-- else {
-- if (scope_instance == null){
-- //
-- // This is needed if someone overwrites the Emit method
-- // of Statement and manually calls Block.Emit without
-- // this snippet first:
-- //
-- // ec.EmitScopeInitFromBlock (The_Block);
-- // The_Block.Emit (ec);
-- //
--
-- Console.WriteLine (
-- "The scope_instance has not been emitted, this typically means\n" +
-- "that inside the compiler someone is calling Block.Emit without\n" +
-- "first calling EmitScopeInitFromBlock for the block. See compiler" +
-- "source code for an explanation");
-- throw new Exception ("Internal compiler error");
--
-- }
-- ig.Emit (OpCodes.Ldloc, scope_instance);
-- }
-- }
--
-- public static void CheckCycles (string msg, ScopeInfo s)
-- {
-- ArrayList l = new ArrayList ();
-- int n = 0;
--
-- for (ScopeInfo p = s; p != null; p = p.ParentScope,n++){
-- if (l.Contains (p)){
-- Console.WriteLine ("Loop detected {0} in {1}", n, msg);
-- throw new Exception ();
-- }
-- l.Add (p);
-- }
-- }
--
- static void DoPath (StringBuilder sb, ScopeInfo start)
- {
-- CheckCycles ("print", start);
--
-- if (start.ParentScope != null){
-- DoPath (sb, start.ParentScope);
-- sb.Append (", ");
-- }
- sb.Append ((start.id).ToString ());
- }
-
-@@ -925,614 +1308,146 @@
- 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;
-- public Location loc;
--
-- //
-- // Points to the toplevel block that owns this CaptureContext
-- //
-- ToplevelBlock toplevel_owner;
--
-- //
-- // All the scopes we capture
-- //
-- Hashtable scopes = new Hashtable ();
--
-- //
-- // All the root scopes
-- //
-- ArrayList roots = new ArrayList ();
--
-- bool have_captured_vars = false;
-- bool referenced_this = false;
--
-- //
-- // Captured fields
-- //
-- Hashtable captured_fields = new Hashtable ();
-- Hashtable captured_variables = new Hashtable ();
-- public Hashtable captured_parameters = new Hashtable ();
-- public AnonymousContainer Host;
--
-- public CaptureContext (ToplevelBlock toplevel_owner, Location loc,
-- AnonymousContainer host)
-+ protected abstract class CapturedLocalOrParameter : Variable
- {
-- cc_id = count++;
-- this.toplevel_owner = toplevel_owner;
-- this.loc = loc;
-+ public readonly ScopeInfo Scope;
-+ public readonly Field Field;
-
-- if (host != null)
-- Host = host;
-- }
-+ public FieldExpr FieldInstance;
-
-- void DoPath (StringBuilder sb, CaptureContext cc)
-- {
-- if (cc.ParentCaptureContext != null){
-- DoPath (sb, cc.ParentCaptureContext);
-- sb.Append (".");
-+ protected CapturedLocalOrParameter (ScopeInfo scope, string name, Type type)
-+ {
-+ this.Scope = scope;
-+ this.Field = scope.CaptureVariable (
-+ scope.MakeFieldName (name), type);
- }
-- sb.Append (cc.cc_id.ToString ());
-- }
-
-- public void ReParent (ToplevelBlock new_toplevel, AnonymousContainer new_host)
-- {
-- toplevel_owner = new_toplevel;
-- Host = new_host;
--
-- for (CaptureContext cc = ParentCaptureContext; cc != null;
-- cc = cc.ParentCaptureContext) {
-- cc.Host = new_host;
-+ public override Type Type {
-+ get { return Field.MemberType; }
- }
-- }
--
-- public override string ToString ()
-- {
-- StringBuilder sb = new StringBuilder ();
-- sb.Append ("[");
-- DoPath (sb, this);
-- sb.Append ("]");
-- return sb.ToString ();
-- }
-
-- public ToplevelBlock ParentToplevel {
-- get {
-- return toplevel_owner.Container;
-+ public override bool HasInstance {
-+ get { return true; }
- }
-- }
-
-- public CaptureContext ParentCaptureContext {
-- get {
-- ToplevelBlock parent = ParentToplevel;
--
-- return (parent == null) ? null : parent.CaptureContext;
-+ public override bool NeedsTemporary {
-+ get { return true; }
- }
-- }
-
-- ScopeInfo GetScopeForBlock (Block block)
-- {
-- ScopeInfo si = (ScopeInfo) scopes [block.ID];
-- if (si != null)
-- return si;
-- si = new ScopeInfo (this, block);
-- scopes [block.ID] = si;
-- return si;
-- }
--
-- public void AddLocal (AnonymousContainer am, LocalInfo li)
-- {
-- if (li.Block.Toplevel != toplevel_owner){
-- ParentCaptureContext.AddLocal (am, li);
-- return;
-+ protected FieldInfo GetField (EmitContext ec)
-+ {
-+ if (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)
-+ return Field.FieldBuilder;
-+ else
-+ return FieldInstance.FieldInfo;
- }
-- ScopeInfo scope = GetScopeForBlock (li.Block);
-
-- //
-- // Adjust the owner
-- //
-- if (Host != null)
-- Host.RegisterScope (scope);
--
-- //
-- // Adjust the user
-- //
-- am.RegisterScope (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;
-+ public override void EmitInstance (EmitContext ec)
-+ {
-+ ec.CurrentBlock.Toplevel.EmitScopeInstance (ec, Scope);
- }
-- 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, AnonymousContainer 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
-- //
-- public void AddParameterToContext (AnonymousContainer am, string name, Type t, int idx)
-- {
-- if (captured_parameters == null)
-- captured_parameters = new Hashtable ();
-- if (captured_parameters [name] == null)
-- captured_parameters [name] = new CapturedParameter (t, idx);
--
-- ScopeInfo scope = GetScopeForBlock (toplevel_owner);
-- scope.HostsParameters = true;
-- am.RegisterScope (scope);
-- }
--
-- //
-- // 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 (EmitContext ec, AnonymousContainer am, 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 (ec, am, fe);
-- return;
-+ public override void Emit (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
- }
-
-- ScopeInfo scope = GetScopeForBlock (toplevel_owner);
-- am.RegisterScope (scope);
-- }
--
-- public void CaptureThis (AnonymousContainer am)
-- {
-- if (am == null)
-- throw new Exception ("Internal Compiler error: Capturethis called with a null method");
-- CaptureContext parent = ParentCaptureContext;
-- if (parent != null) {
-- parent.CaptureThis (am);
-- return;
-+ public override void EmitAssign (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Stfld, GetField (ec));
- }
-- referenced_this = true;
-
-- ScopeInfo scope = GetScopeForBlock (toplevel_owner);
-- am.RegisterScope (scope);
-- }
--
-- public bool HaveCapturedVariables {
-- get {
-- return have_captured_vars;
-+ public override void EmitAddressOf (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
- }
- }
--
-- 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;
-- }
-+ protected class CapturedParameter : CapturedLocalOrParameter {
-+ public readonly Parameter Parameter;
-+ public readonly int Idx;
-
-- //
-- // 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 EmitAnonymousHelperClasses (EmitContext ec)
-- {
-- if (roots.Count != 0){
-- foreach (ScopeInfo root in roots){
-- //
-- // FIXME: We really should do this in a per-ScopeInfo
-- // basis, instead of having the NeedThis applied to
-- // all of the roots.
-- //
-- root.NeedThis = HaveCapturedFields || referenced_this;
--
-- root.EmitScopeType (ec);
-- }
-- }
-- }
--
-- public void CloseAnonymousHelperClasses ()
-- {
-- if (roots.Count != 0)
-- foreach (ScopeInfo root in roots)
-- root.CloseTypes ();
-- }
--
-- public void EmitInitScope (EmitContext ec)
-- {
-- EmitAnonymousHelperClasses (ec);
-- if (roots.Count != 0)
-- foreach (ScopeInfo root in roots)
-- root.EmitInitScope (ec); }
--
-- //
-- // This is called externally when we start emitting code for a block
-- // if the block has a ScopeInfo associated, emit the init code
-- //
-- public void EmitScopeInitFromBlock (EmitContext ec, Block b)
-- {
-- ScopeInfo si = (ScopeInfo) scopes [b.ID];
-- if (si == null)
-- return;
--
-- si.EmitInitScope (ec);
-- }
--
-- //
-- // Emits the opcodes necessary to load the instance of the captured
-- // variable in `li'
-- //
-- public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li,
-- AnonymousContainer am)
-- {
-- ILGenerator ig = ec.ig;
-- ScopeInfo si;
--
-- if (li.Block.Toplevel == toplevel_owner){
-- si = (ScopeInfo) scopes [li.Block.ID];
-- si.EmitScopeInstance (ig);
-- return;
-+ public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
-+ : base (scope, par.Name, par.ParameterType)
-+ {
-+ this.Parameter = par;
-+ this.Idx = idx;
- }
-
-- si = am.Scope;
-- ig.Emit (OpCodes.Ldarg_0);
-- if (si != null){
-- if (am.IsIterator && (si.ScopeBlock.Toplevel == li.Block.Toplevel)) {
-- return;
-- }
--
-- while (si.ScopeBlock.ID != li.Block.ID){
-- if (si.ParentLink != null)
-- ig.Emit (OpCodes.Ldfld, si.ParentLink);
-- si = si.ParentScope;
-- if (si == null) {
-- si = am.Scope;
-- Console.WriteLine ("Target: {0} {1}", li.Block.ID, li.Name);
-- while (si.ScopeBlock.ID != li.Block.ID){
-- Console.WriteLine ("Trying: {0}", si.ScopeBlock.ID);
-- si = si.ParentScope;
-- }
--
-- 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));
-- }
-- }
-+ public override string ToString ()
-+ {
-+ return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
-+ Parameter.Name, Idx);
- }
- }
-
-- //
-- // 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;
-- }
-+ protected class CapturedLocal : CapturedLocalOrParameter {
-+ public readonly LocalInfo Local;
-
-- CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
-- if (par_info != null){
-- //
-- // FIXME: implementing this.
-- //
-+ public CapturedLocal (ScopeInfo scope, LocalInfo local)
-+ : base (scope, local.Name, local.VariableType)
-+ {
-+ this.Local = local;
- }
-- ILGenerator ig = ec.ig;
-
-- ScopeInfo si;
--
-- if (ec.CurrentBlock.Toplevel == toplevel_owner) {
-- si = (ScopeInfo) scopes [toplevel_owner.ID];
-- si.EmitScopeInstance (ig);
-- } else {
-- si = ec.CurrentAnonymousMethod.Scope;
-- ig.Emit (OpCodes.Ldarg_0);
-+ public override string ToString ()
-+ {
-+ return String.Format ("{0} ({1}:{2})", GetType (), Field,
-+ Local.Name);
- }
--
-- 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, bool leave_copy, bool prepared, ref LocalTemporary temp)
-+ protected class ScopeInitializer : ScopeInitializerBase
- {
-- CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
-- if (cc != this){
-- cc.EmitParameter (ec, name, leave_copy, prepared, ref temp);
-- return;
-- }
-- if (!prepared)
-- EmitParameterInstance (ec, name);
-- CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
-- if (par_info != null){
-- //
-- // FIXME: implementing this.
-- //
-- }
-- ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
-+ ScopeInfo scope;
-
-- if (leave_copy){
-- ec.ig.Emit (OpCodes.Dup);
-- temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
-- temp.Store (ec);
-+ public ScopeInitializer (ScopeInfo scope)
-+ : base (scope)
-+ {
-+ this.scope = scope;
- }
-- }
-
-- //
-- // 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, ref LocalTemporary temp)
-- {
-- CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
-- if (cc != this){
-- cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load, ref temp);
-- return;
-+ new public ScopeInfo Scope {
-+ get { return scope; }
- }
-- ILGenerator ig = ec.ig;
-- CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
-
-- EmitParameterInstance (ec, name);
-- if (prepare_for_load)
-- ig.Emit (OpCodes.Dup);
-- source.Emit (ec);
-- if (leave_copy){
-- ig.Emit (OpCodes.Dup);
-- temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
-- temp.Store (ec);
-- }
-- ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
-- if (temp != null)
-- temp.Emit (ec);
-- }
-+ protected override bool DoResolveInternal (EmitContext ec)
-+ {
-+ Report.Debug (64, "RESOLVE SCOPE INITIALIZER", this, Scope,
-+ Scope.ScopeType, ec,
-+ ec.TypeContainer.Name, ec.DeclContainer,
-+ ec.DeclContainer.Name, ec.DeclContainer.IsGeneric);
-
-- //
-- // 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);
-- }
-+ foreach (CapturedLocal local in Scope.locals.Values) {
-+ FieldExpr fe = (FieldExpr) Expression.MemberLookup (
-+ ec.ContainerType, type, local.Field.Name, loc);
-+ Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
-+ Scope, ec, ec.ContainerType, type,
-+ local.Field, local.Field.Name, loc, fe);
-+ if (fe == null)
-+ throw new InternalErrorException ();
-
-- //
-- // The following methods are only invoked on the host for the
-- // anonymous method.
-- //
-- public void EmitMethodHostInstance (EmitContext target, AnonymousContainer am)
-- {
-- ILGenerator ig = target.ig;
-- ScopeInfo si = am.Scope;
--
-- AnonymousContainer container = am.ContainerAnonymousMethod;
--
-- if ((si == null) || ((container != null) && (si == container.Scope))) {
-- ig.Emit (OpCodes.Ldarg_0);
-- return;
-- }
--
-- si.EmitInitScope (target);
-- si.EmitScopeInstance (ig);
-- }
--
-- public void RegisterCaptureContext ()
-- {
-- toplevel_owner.RegisterCaptureContext (this);
-- }
--
-- //
-- // Returs true if `probe' is an ancestor of `scope' in the
-- // scope chain
-- //
-- bool IsAncestor (ScopeInfo probe, ScopeInfo scope)
-- {
-- for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
-- if (probe.ScopeBlock == b)
-- return true;
-- }
-- return false;
-- }
--
-- //
-- // Returns an ArrayList of ScopeInfos that enumerates all the ancestors
-- // of `scope' found in `scope_list'.
-- //
-- // The value returned is either a ScopeInfo or an Arraylist of ScopeInfos
-- //
-- object GetAncestorScopes (ScopeInfo scope, ScopeInfo [] scope_list)
-- {
-- object ancestors = null;
--
-- for (int i = 0; i < scope_list.Length; i++){
-- // Ignore the same scope
-- if (scope_list [i] == scope)
-- continue;
--
-- if (IsAncestor (scope_list [i], scope)){
-- if (ancestors == null){
-- ancestors = scope_list [i];
-- continue;
-- }
--
-- if (ancestors is ScopeInfo){
-- object old = ancestors;
-- ancestors = new ArrayList (4);
-- ((ArrayList)ancestors).Add (old);
-- }
--
-- ((ArrayList)ancestors).Add (scope_list [i]);
-+ fe.InstanceExpression = this;
-+ local.FieldInstance = fe;
- }
-- }
-- return ancestors;
-- }
-
-- //
-- // Returns the immediate parent of `scope' from all the captured
-- // scopes found in `scope_list', or null if this is a toplevel scope.
-- //
-- ScopeInfo GetParentScope (ScopeInfo scope, ScopeInfo [] scope_list)
-- {
-- object ancestors = GetAncestorScopes (scope, scope_list);
-- if (ancestors == null)
-- return null;
--
-- // Single match, thats the parent.
-- if (ancestors is ScopeInfo)
-- return (ScopeInfo) ancestors;
--
-- ArrayList candidates = (ArrayList) ancestors;
-- ScopeInfo parent = (ScopeInfo) candidates [0];
-- for (int i = 1; i < candidates.Count; i++){
-- if (IsAncestor (parent, (ScopeInfo) candidates [i]))
-- parent = (ScopeInfo) candidates [i];
-+ return base.DoResolveInternal (ec);
- }
-- return parent;
-- }
--
-- //
-- // Links all the scopes
-- //
-- bool linked;
-- public void LinkScopes ()
-- {
-- if (linked)
-- return;
--
-- linked = true;
-- if (ParentCaptureContext != null)
-- ParentCaptureContext.LinkScopes ();
-
-- int scope_count = scopes.Keys.Count;
-- ScopeInfo [] scope_list = new ScopeInfo [scope_count];
-- scopes.Values.CopyTo (scope_list, 0);
--
-- for (int i = 0; i < scope_count; i++){
-- ScopeInfo parent = GetParentScope (scope_list [i], scope_list);
--
-- if (parent == null){
-- roots.Add (scope_list [i]);
-- continue;
-- }
--
-- scope_list [i].ParentScope = parent;
-- parent.AddChild (scope_list [i]);
-+ protected virtual void EmitParameterReference (EmitContext ec,
-+ CapturedParameter cp)
-+ {
-+ int extra = ec.IsStatic ? 0 : 1;
-+ ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
- }
-
-- //
-- // Link the roots to their parent containers if any.
-- //
-- if (ParentCaptureContext != null && roots.Count != 0){
-- ScopeInfo one_root = (ScopeInfo) roots [0];
-- bool found = false;
--
-- foreach (ScopeInfo a_parent_root in ParentCaptureContext.roots){
-- if (!IsAncestor (a_parent_root, one_root))
-- continue;
--
-- found = true;
--
-- // Found, link all the roots to this root
-- foreach (ScopeInfo root in roots){
-- root.ParentScope = a_parent_root;
-- a_parent_root.AddChild (root);
-- }
-- break;
-- }
-- if (!found){
-- //
-- // This is to catch a condition in which it is
-- // not possible to determine the containing ScopeInfo
-- // from an encapsulating CaptureContext
-- //
-- throw new Exception ("Internal compiler error: Did not find the parent for the root in the chain");
-- }
-- }
- }
- }
- }
-Index: expression.cs
-===================================================================
---- expression.cs (revision 63019)
-+++ expression.cs (working copy)
-@@ -457,8 +457,7 @@
- }
-
- ParameterReference pr = Expr as ParameterReference;
-- if ((pr != null) && (ec.capture_context != null) &&
-- ec.capture_context.IsParameterCaptured (pr.Name)) {
-+ if ((pr != null) && pr.Parameter.IsCaptured) {
- AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
- return null;
- }
-@@ -3309,6 +3308,7 @@
- bool is_readonly;
- bool prepared;
- LocalTemporary temp;
-+ Variable variable;
-
- public LocalVariableReference (Block block, string name, Location l)
- {
-@@ -3363,20 +3363,19 @@
- if (!VerifyAssigned (ec))
- return null;
-
-- 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.CurrentAnonymousMethod.IsIterator)
-- {
-- if (local_info.AddressTaken){
-- AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
-- return null;
-- }
-- ec.CaptureVariable (local_info);
-+ //
-+ // If we are referencing a variable from the external block
-+ // flag it for capturing
-+ //
-+ if (ec.MustCaptureVariable (local_info)) {
-+ if (local_info.AddressTaken){
-+ AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
-+ return null;
- }
-+
-+ ScopeInfo scope = local_info.Block.CreateScopeInfo ();
-+ variable = scope.AddLocal (local_info);
-+ type = variable.Type;
- }
-
- return this;
-@@ -3439,90 +3438,57 @@
- return Name == lvr.Name && Block == lvr.Block;
- }
-
-+ public Variable Variable {
-+ get { return variable != null ? variable : local_info.Variable; }
-+ }
-+
- public override void Emit (EmitContext ec)
- {
-- ILGenerator ig = ec.ig;
--
-- 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);
-- }
-+ Report.Debug (64, "EMIT LOCAL VARIABLE REFERENCE", this, ec, Variable, loc);
-+ if (!prepared)
-+ Variable.EmitInstance (ec);
-+ Variable.Emit (ec);
- }
-
- 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){
-+ if (Variable.NeedsTemporary) {
- temp = new LocalTemporary (Type);
- temp.Store (ec);
- }
- }
- }
--
-- public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
-+
-+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
-+ bool prepare_for_load)
- {
- 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);
-+ Report.Debug (64, "LOCAL VAR REF EMIT ASSIGN", this, source, loc);
-+ Variable.EmitInstance (ec);
-+ if (prepare_for_load && Variable.HasInstance)
-+ ig.Emit (OpCodes.Dup);
-+ source.Emit (ec);
-+ if (leave_copy) {
-+ ig.Emit (OpCodes.Dup);
-+ if (Variable.NeedsTemporary) {
- temp = new LocalTemporary (Type);
- temp.Store (ec);
- }
-- ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
-- if (temp != null)
-- temp.Emit (ec);
- }
-+ Variable.EmitAssign (ec);
-+ if (temp != null)
-+ temp.Emit (ec);
- }
-
- public void AddressOf (EmitContext ec, AddressOp mode)
- {
-- ILGenerator ig = ec.ig;
--
-- 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);
-- }
-+ Variable.EmitInstance (ec);
-+ Variable.EmitAddressOf (ec);
- }
-
- public override string ToString ()
-@@ -3561,7 +3527,14 @@
- }
- }
-
-+ public Parameter Parameter {
-+ get {
-+ return par;
-+ }
-+ }
-+
- LocalTemporary temp;
-+ Variable variable;
-
- public ParameterReference (Parameter par, Block block, int idx, Location loc)
- {
-@@ -3577,6 +3550,10 @@
- get { return vi; }
- }
-
-+ public Variable Variable {
-+ get { return variable != null ? variable : par.Variable; }
-+ }
-+
- public bool VerifyFixed ()
- {
- // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
-@@ -3630,23 +3607,33 @@
- if (is_out)
- vi = block.ParameterMap [idx];
-
-- if (ec.CurrentAnonymousMethod != null){
-- if (is_ref && !block.Toplevel.IsLocalParameter (name)){
-- Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block",
-- par.Name);
-- return false;
-- }
-+ AnonymousContainer am = ec.CurrentAnonymousMethod;
-+ if (am == null)
-+ return true;
-
-- //
-- // 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.Toplevel.IsLocalParameter (name)){
-- ec.CaptureParameter (name, type, idx);
-+ if (is_ref && !block.Toplevel.IsLocalParameter (name)){
-+ Report.Error (1628, Location,
-+ "Cannot use ref or out parameter `{0}' inside an " +
-+ "anonymous method block", par.Name);
-+ return false;
-+ }
-+
-+ if (!am.IsIterator && block.Toplevel.IsLocalParameter (name))
-+ return true;
-+
-+ AnonymousMethodHost host = null;
-+ ToplevelBlock toplevel = block.Toplevel;
-+ while (toplevel != null) {
-+ if (toplevel.IsLocalParameter (name)) {
-+ host = toplevel.AnonymousMethodHost;
-+ break;
- }
-+
-+ toplevel = toplevel.Container;
- }
-
-+ variable = host.AddParameter (par, idx);
-+ type = variable.Type;
- return true;
- }
-
-@@ -3681,7 +3668,8 @@
- if (!DoResolveBase (ec))
- return null;
-
-- if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
-+ if (is_out && ec.DoFlowAnalysis &&
-+ (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
- return null;
-
- return this;
-@@ -3731,7 +3719,7 @@
- // FIXME: Review for anonymous methods
- //
- }
--
-+
- public override void Emit (EmitContext ec)
- {
- Emit (ec, false);
-@@ -3739,19 +3727,10 @@
-
- public void Emit (EmitContext ec, bool leave_copy)
- {
-- ILGenerator ig = ec.ig;
-- int arg_idx = idx;
-+ if (!prepared)
-+ Variable.EmitInstance (ec);
-+ Variable.Emit (ec);
-
-- if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-- ec.EmitParameter (name, leave_copy, prepared, ref temp);
-- return;
-- }
--
-- if (!ec.MethodIsStatic)
-- arg_idx++;
--
-- EmitLdArg (ig, arg_idx);
--
- if (is_ref) {
- if (prepared)
- ec.ig.Emit (OpCodes.Dup);
-@@ -3760,84 +3739,51 @@
- // If we are a reference, we loaded on the stack a pointer
- // Now lets load the real value
- //
-- LoadFromPtr (ig, type);
-+ LoadFromPtr (ec.ig, type);
- }
--
-+
- if (leave_copy) {
- ec.ig.Emit (OpCodes.Dup);
--
-- if (is_ref) {
-- temp = new LocalTemporary (type);
-+
-+ if (is_ref || Variable.NeedsTemporary) {
-+ temp = new LocalTemporary (Type);
- temp.Store (ec);
- }
- }
- }
--
-- public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
-+
-+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
-+ bool prepare_for_load)
- {
-+ ILGenerator ig = ec.ig;
- prepared = prepare_for_load;
-- if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-- ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp);
-- return;
-- }
-
-- ILGenerator ig = ec.ig;
-- int arg_idx = idx;
--
--
--
-- if (!ec.MethodIsStatic)
-- arg_idx++;
-+ Variable.EmitInstance (ec);
-+ if (prepare_for_load && Variable.HasInstance)
-+ ig.Emit (OpCodes.Dup);
-+ else if (is_ref)
-+ Variable.Emit (ec);
-
-- if (is_ref && !prepared)
-- EmitLdArg (ig, arg_idx);
--
- source.Emit (ec);
--
-- if (leave_copy)
-- ec.ig.Emit (OpCodes.Dup);
--
-- if (is_ref) {
-- if (leave_copy) {
-- temp = new LocalTemporary (type);
-+ if (leave_copy) {
-+ ig.Emit (OpCodes.Dup);
-+ if (Variable.NeedsTemporary) {
-+ temp = new LocalTemporary (Type);
- temp.Store (ec);
- }
--
-- StoreFromPtr (ig, type);
--
-- if (temp != null)
-- temp.Emit (ec);
-- } else {
-- if (arg_idx <= 255)
-- ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
-- else
-- ig.Emit (OpCodes.Starg, arg_idx);
- }
-+ if (is_ref)
-+ StoreFromPtr (ig, type);
-+ else
-+ Variable.EmitAssign (ec);
-+ if (temp != null)
-+ temp.Emit (ec);
- }
--
-+
- public void AddressOf (EmitContext ec, AddressOp mode)
- {
-- if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-- ec.EmitAddressOfParameter (name);
-- return;
-- }
--
-- int arg_idx = idx;
--
-- if (!ec.MethodIsStatic)
-- arg_idx++;
--
-- if (is_ref){
-- if (arg_idx <= 255)
-- ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
-- else
-- ec.ig.Emit (OpCodes.Ldarg, arg_idx);
-- } else {
-- if (arg_idx <= 255)
-- ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
-- else
-- ec.ig.Emit (OpCodes.Ldarga, arg_idx);
-- }
-+ Variable.EmitInstance (ec);
-+ Variable.EmitAddressOf (ec);
- }
-
- public override string ToString ()
-@@ -6649,11 +6595,14 @@
- return false;
- }
-
-- if (block != null && block.Toplevel.ThisVariable != null)
-- variable_info = block.Toplevel.ThisVariable.VariableInfo;
-+ if (block != null) {
-+ if (block.Toplevel.ThisVariable != null)
-+ variable_info = block.Toplevel.ThisVariable.VariableInfo;
-
-- if (ec.CurrentAnonymousMethod != null)
-- ec.CaptureThis ();
-+ AnonymousMethodHost host = block.Toplevel.AnonymousMethodHost;
-+ if (host != null)
-+ host.CaptureThis ();
-+ }
-
- return true;
- }
-Index: codegen.cs
-===================================================================
---- codegen.cs (revision 63019)
-+++ codegen.cs (working copy)
-@@ -9,7 +9,7 @@
- //
-
- #if !DEBUG
-- #define PRODUCTION
-+// #define PRODUCTION
- #endif
-
- using System;
-@@ -350,25 +350,13 @@
- /// </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;
--
- public readonly IResolveContext ResolveContext;
-
- /// <summary>
- /// The current iterator
- /// </summary>
- public Iterator CurrentIterator {
-- get {
-- if (CurrentAnonymousMethod != null)
-- return CurrentAnonymousMethod.Iterator;
-- else
-- return null;
-- }
-+ get { return CurrentAnonymousMethod as Iterator; }
- }
-
- /// <summary>
-@@ -390,8 +378,8 @@
-
- public override string ToString ()
- {
-- return String.Format ("EmitContext ({0}:{1}:{2})", id,
-- CurrentIterator, capture_context, loc);
-+ return String.Format ("EmitContext ({0}:{1})", id,
-+ CurrentAnonymousMethod, loc);
- }
-
- public EmitContext (IResolveContext rc, DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
-@@ -525,16 +513,6 @@
- get { return current_flow_branching; }
- }
-
-- public bool HaveCaptureInfo {
-- get { return capture_context != null; }
-- }
--
-- public void EmitScopeInitFromBlock (Block b)
-- {
-- if (capture_context != null)
-- capture_context.EmitScopeInitFromBlock (this, b);
-- }
--
- // <summary>
- // Starts a new code branching. This inherits the state of all local
- // variables and parameters from the current branching.
-@@ -618,84 +596,17 @@
- current_flow_branching = current_flow_branching.Parent;
- }
-
-- public void CaptureVariable (LocalInfo li)
-+ public bool MustCaptureVariable (LocalInfo local)
- {
-- capture_context.AddLocal (CurrentAnonymousMethod, li);
-- li.IsCaptured = true;
-+ if (CurrentAnonymousMethod == null)
-+ return false;
-+ if (CurrentAnonymousMethod.IsIterator)
-+ return true;
-+ return local.Block.Toplevel != CurrentBlock.Toplevel;
- }
--
-- public void CaptureParameter (string name, Type t, int idx)
-- {
-- capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
-- }
--
-- public void CaptureThis ()
-- {
-- capture_context.CaptureThis (CurrentAnonymousMethod);
-- }
-
--
-- //
-- // Use to register a field as captured
-- //
-- public void CaptureField (FieldExpr fe)
-- {
-- capture_context.AddField (this, CurrentAnonymousMethod, 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)
- {
-- if (capture_context != null)
-- capture_context.EmitAnonymousHelperClasses (this);
- b.EmitMeta (this);
-
- if (HasReturnLabel)
-@@ -734,8 +645,6 @@
- if (resolved)
- return true;
-
-- capture_context = block.CaptureContext;
--
- if (!loc.IsNull)
- CurrentFile = loc.File;
-
-@@ -745,6 +654,11 @@
- if (!block.ResolveMeta (this, ip))
- return false;
-
-+ if ((md != null) && (md.Iterator != null)) {
-+ if (!md.Iterator.Resolve (this))
-+ throw new InternalErrorException ();
-+ }
-+
- using (this.With (EmitContext.Flags.DoFlowAnalysis, true)) {
- FlowBranchingToplevel top_level;
- if (anonymous_method_host != null)
-@@ -783,12 +697,14 @@
- return false;
- } else if (!CurrentAnonymousMethod.IsIterator) {
- Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
-- CurrentAnonymousMethod.GetSignatureForError ());
-+ CurrentAnonymousMethod.GetSignatureForError ());
- return false;
- }
- }
-
-- block.CompleteContexts ();
-+ if (!block.CompleteContexts (this))
-+ return false;
-+
- resolved = true;
- return true;
- }
-@@ -829,12 +745,6 @@
- ig.Emit (OpCodes.Ret);
- }
- }
--
-- //
-- // Close pending helper classes if we are the toplevel
-- //
-- if (capture_context != null && capture_context.ParentToplevel == null)
-- capture_context.CloseAnonymousHelperClasses ();
- }
-
- /// <summary>
-@@ -1002,50 +912,24 @@
- public void EmitThis (bool need_address)
- {
- ig.Emit (OpCodes.Ldarg_0);
-- 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){
-- if (need_address && TypeManager.IsValueType (si.THIS.FieldType))
-- ig.Emit (OpCodes.Ldflda, si.THIS);
-- else
-- ig.Emit (OpCodes.Ldfld, si.THIS);
-- break;
-- }
-- si = si.ParentScope;
-+ if (CurrentAnonymousMethod == null)
-+ return;
-+
-+ AnonymousMethodHost host = CurrentAnonymousMethod.RootScope;
-+ while (host != null) {
-+ if (host.ParentLink != null)
-+ ig.Emit (OpCodes.Ldfld, host.ParentLink.FieldBuilder);
-+ if (host.THIS != null) {
-+ if (need_address && TypeManager.IsValueType (host.THIS.MemberType))
-+ ig.Emit (OpCodes.Ldflda, host.THIS.FieldBuilder);
-+ else
-+ ig.Emit (OpCodes.Ldfld, host.THIS.FieldBuilder);
-+ break;
- }
-- }
-+ host = host.ParentHost;
-+ }
- }
-
-- //
-- // Emits the code necessary to load the instance required
-- // to access the captured LocalInfo
-- //
-- public void EmitCapturedVariableInstance (LocalInfo li)
-- {
-- 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, bool leave_copy, bool prepared, ref LocalTemporary temp)
-- {
-- capture_context.EmitParameter (this, name, leave_copy, prepared, ref temp);
-- }
--
-- public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
-- {
-- capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load, ref temp);
-- }
--
-- public void EmitAddressOfParameter (string name)
-- {
-- capture_context.EmitAddressOfParameter (this, name);
-- }
--
- public Expression GetThis (Location loc)
- {
- This my_this;
-Index: statement.cs
-===================================================================
---- statement.cs (revision 63019)
-+++ statement.cs (working copy)
-@@ -962,23 +962,35 @@
- }
- }
-
-+ public abstract class Variable
-+ {
-+ public abstract Type Type {
-+ get;
-+ }
-+
-+ public abstract bool HasInstance {
-+ get;
-+ }
-+
-+ public abstract bool NeedsTemporary {
-+ get;
-+ }
-+
-+ public abstract void EmitInstance (EmitContext ec);
-+
-+ public abstract void Emit (EmitContext ec);
-+
-+ public abstract void EmitAssign (EmitContext ec);
-+
-+ public abstract void EmitAddressOf (EmitContext ec);
-+ }
-+
- //
- // 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 (variables that have been
-- // hoisted by iterators or by anonymous methods). The context of the field will
-- // be stored in the EmitContext
-- //
-- //
-- public LocalBuilder LocalBuilder;
-- public FieldBuilder FieldBuilder;
--
- public Type VariableType;
- public readonly string Name;
- public readonly Location Location;
-@@ -986,6 +998,11 @@
-
- public VariableInfo VariableInfo;
-
-+ Variable var;
-+ public Variable Variable {
-+ get { return var; }
-+ }
-+
- [Flags]
- enum Flags : byte {
- Used = 1,
-@@ -1022,18 +1039,27 @@
- Location = l;
- }
-
-- public void DeclareLocal (ILGenerator ig)
-+ public void ResolveVariable (EmitContext ec)
- {
-- if (Pinned) {
-- //
-- // This is needed to compile on both .NET 1.x and .NET 2.x
-- // the later introduced `DeclareLocal (Type t, bool pinned)'
-- //
-- LocalBuilder = TypeManager.DeclareLocalPinned (ig, VariableType);
-- return;
-+ Block theblock = Block;
-+ while (theblock.Implicit)
-+ theblock = theblock.Parent;
-+ if (theblock.ScopeInfo != null)
-+ var = theblock.ScopeInfo.GetCapturedVariable (this);
-+
-+ if (var == null) {
-+ LocalBuilder builder;
-+ if (Pinned)
-+ //
-+ // This is needed to compile on both .NET 1.x and .NET 2.x
-+ // the later introduced `DeclareLocal (Type t, bool pinned)'
-+ //
-+ builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType);
-+ else
-+ builder = ec.ig.DeclareLocal (VariableType);
-+
-+ var = new LocalVariable (this, builder);
- }
-- if (!IsThis && !IsConstant)
-- LocalBuilder = ig.DeclareLocal (VariableType);
- }
-
- public bool IsThisAssigned (EmitContext ec, Location loc)
-@@ -1185,6 +1211,50 @@
- flags = value ? (flags | Flags.IsThis) : (flags & ~Flags.IsThis);
- }
- }
-+
-+ protected class LocalVariable : Variable
-+ {
-+ public readonly LocalInfo LocalInfo;
-+ LocalBuilder builder;
-+
-+ public LocalVariable (LocalInfo local, LocalBuilder builder)
-+ {
-+ this.LocalInfo = local;
-+ this.builder = builder;
-+ }
-+
-+ public override Type Type {
-+ get { return LocalInfo.VariableType; }
-+ }
-+
-+ public override bool HasInstance {
-+ get { return false; }
-+ }
-+
-+ public override bool NeedsTemporary {
-+ get { return false; }
-+ }
-+
-+ public override void EmitInstance (EmitContext ec)
-+ {
-+ // Do nothing.
-+ }
-+
-+ public override void Emit (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldloc, builder);
-+ }
-+
-+ public override void EmitAssign (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Stloc, builder);
-+ }
-+
-+ public override void EmitAddressOf (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldloca, builder);
-+ }
-+ }
- }
-
- /// <summary>
-@@ -1239,7 +1309,7 @@
- //
- // The statements in this block
- //
-- ArrayList statements;
-+ protected ArrayList statements;
- int num_statements;
-
- //
-@@ -1275,6 +1345,8 @@
- //
- Block switch_block;
-
-+ ExpressionStatement scope_init;
-+
- protected static int id;
-
- int this_id;
-@@ -1589,6 +1661,8 @@
-
- public LocalInfo AddTemporaryVariable (TypeExpr te, Location loc)
- {
-+ Report.Debug (64, "ADD TEMPORARY", this, Toplevel, loc);
-+
- if (temporary_variables == null)
- temporary_variables = new ArrayList ();
-
-@@ -1679,6 +1753,19 @@
- }
- }
-
-+ public ScopeInfo ScopeInfo;
-+
-+ public ScopeInfo CreateScopeInfo ()
-+ {
-+ if (Implicit)
-+ return Parent.CreateScopeInfo ();
-+
-+ if (ScopeInfo == null)
-+ ScopeInfo = new ScopeInfo (Toplevel.AnonymousMethodHost, this);
-+
-+ return ScopeInfo;
-+ }
-+
- /// <summary>
- /// Emits the variable declarations and labels.
- /// </summary>
-@@ -1688,6 +1775,8 @@
- /// </remarks>
- public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, Parameters ip)
- {
-+ Report.Debug (64, "BLOCK RESOLVE META", this, Parent, toplevel);
-+
- // If some parent block was unsafe, we remain unsafe even if this block
- // isn't explicitly marked as such.
- using (ec.With (EmitContext.Flags.InUnsafe, ec.InUnsafe | Unsafe)) {
-@@ -1791,39 +1880,23 @@
- //
- // Emits the local variable declarations for a block
- //
-- public void EmitMeta (EmitContext ec)
-+ public virtual void EmitMeta (EmitContext ec)
- {
-- ILGenerator ig = ec.ig;
--
-+ Report.Debug (64, "BLOCK EMIT META", this, Toplevel, ScopeInfo, ec);
-+ if (ScopeInfo != null) {
-+ scope_init = ScopeInfo.GetScopeInitializer (ec);
-+ Report.Debug (64, "BLOCK EMIT META #1", this, Toplevel, ScopeInfo,
-+ ec, scope_init);
-+ }
-+
- if (variables != null){
-- bool have_captured_vars = ec.HaveCapturedVariables ();
--
-- foreach (DictionaryEntry de in variables){
-- LocalInfo vi = (LocalInfo) de.Value;
--
-- if (have_captured_vars && ec.IsCaptured (vi))
-- continue;
--
-- vi.DeclareLocal (ig);
-- }
-+ foreach (LocalInfo vi in variables.Values)
-+ vi.ResolveVariable (ec);
- }
-
- if (temporary_variables != null) {
-- AnonymousContainer am = ec.CurrentAnonymousMethod;
-- TypeBuilder scope = null;
-- if ((am != null) && am.IsIterator) {
-- scope = am.Scope.ScopeTypeBuilder;
-- if (scope == null)
-- throw new InternalErrorException ();
-- }
-- foreach (LocalInfo vi in temporary_variables) {
-- if (scope != null) {
-- if (vi.FieldBuilder == null)
-- vi.FieldBuilder = scope.DefineField (
-- vi.Name, vi.VariableType, FieldAttributes.Assembly);
-- } else
-- vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
-- }
-+ foreach (LocalInfo vi in temporary_variables)
-+ vi.ResolveVariable (ec);
- }
-
- if (children != null){
-@@ -2031,15 +2104,19 @@
- string name = (string) de.Key;
- LocalInfo vi = (LocalInfo) de.Value;
-
-+#if FIXME
- if (vi.LocalBuilder == null)
- continue;
-
- ec.DefineLocalVariable (name, vi.LocalBuilder);
-+#endif
- }
- }
- }
- ec.Mark (StartLocation, true);
-- ec.EmitScopeInitFromBlock (this);
-+ Report.Debug (64, "BLOCK EMIT", this, Toplevel, ec, scope_init);
-+ if (scope_init != null)
-+ scope_init.EmitStatement (ec);
- DoEmit (ec);
- ec.Mark (EndLocation, true);
-
-@@ -2083,13 +2160,11 @@
- // Pointer to the host of this anonymous method, or null
- // if we are the topmost block
- //
-- ToplevelBlock container;
-- CaptureContext capture_context;
-+ GenericMethod generic;
-+ ToplevelBlock container, child;
- FlowBranchingToplevel top_level_branching;
-+ AnonymousMethodHost anonymous_method_host;
-
-- Hashtable capture_contexts;
-- ArrayList children;
--
- public bool HasVarargs {
- get { return (flags & Flags.HasVarargs) != 0; }
- set { flags |= Flags.HasVarargs; }
-@@ -2103,39 +2178,37 @@
- get { return parameters; }
- }
-
-- public void RegisterCaptureContext (CaptureContext cc)
-+ public bool CompleteContexts (EmitContext ec)
- {
-- if (capture_contexts == null)
-- capture_contexts = new Hashtable ();
-- capture_contexts [cc] = cc;
-- }
-+ Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS", this,
-+ container, anonymous_method_host);
-
-- public void CompleteContexts ()
-- {
-- if (capture_contexts == null)
-- return;
-+ if (anonymous_method_host != null)
-+ anonymous_method_host.LinkScopes ();
-
-- foreach (CaptureContext cc in capture_contexts.Keys){
-- cc.LinkScopes ();
-+ if ((container == null) && (anonymous_method_host != null)) {
-+ Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS #1", this,
-+ anonymous_method_host);
-+
-+ if (anonymous_method_host.DefineType () == null)
-+ return false;
-+ if (!anonymous_method_host.ResolveType ())
-+ return false;
-+ if (!anonymous_method_host.DefineMembers ())
-+ return false;
- }
-+
-+ return true;
- }
-
-- public CaptureContext ToplevelBlockCaptureContext {
-- get { return capture_context; }
-+ public GenericMethod GenericMethod {
-+ get { return generic; }
- }
-
- public ToplevelBlock Container {
- get { return container; }
- }
-
-- protected void AddChild (ToplevelBlock block)
-- {
-- if (children == null)
-- children = new ArrayList ();
--
-- children.Add (block);
-- }
--
- //
- // Parent is only used by anonymous blocks to link back to their
- // parents
-@@ -2144,6 +2217,13 @@
- this (container, (Flags) 0, parameters, start)
- {
- }
-+
-+ public ToplevelBlock (ToplevelBlock container, Parameters parameters, GenericMethod generic,
-+ Location start) :
-+ this (container, parameters, start)
-+ {
-+ this.generic = generic;
-+ }
-
- public ToplevelBlock (Parameters parameters, Location start) :
- this (null, (Flags) 0, parameters, start)
-@@ -2160,25 +2240,69 @@
- {
- this.parameters = parameters == null ? Parameters.EmptyReadOnlyParameters : parameters;
- this.container = container;
--
-- if (container != null)
-- container.AddChild (this);
- }
-
- public ToplevelBlock (Location loc) : this (null, (Flags) 0, null, loc)
- {
- }
-
-- public void SetHaveAnonymousMethods (Location loc, AnonymousContainer host)
-+ public AnonymousMethodHost CreateAnonymousMethodHost (TypeContainer host)
- {
-- if (capture_context == null)
-- capture_context = new CaptureContext (this, loc, host);
-+ if (anonymous_method_host != null)
-+ return anonymous_method_host;
-+
-+ if (container != null)
-+ anonymous_method_host = new AnonymousMethodHost (
-+ this, container.anonymous_method_host, null, StartLocation);
-+ else
-+ anonymous_method_host = new AnonymousMethodHost (
-+ this, host, generic, StartLocation);
-+
-+ ScopeInfo = anonymous_method_host;
-+ return anonymous_method_host;
- }
-
-- public CaptureContext CaptureContext {
-- get { return capture_context; }
-+ public void CreateIteratorHost (AnonymousMethodHost root_scope)
-+ {
-+ Report.Debug (64, "CREATE ITERATOR HOST", this, root_scope,
-+ container, anonymous_method_host);
-+
-+ if ((container != null) || (anonymous_method_host != null))
-+ throw new InternalErrorException ();
-+
-+ ScopeInfo = anonymous_method_host = root_scope;
- }
-
-+ public AnonymousMethodHost AnonymousMethodHost {
-+ get {
-+ if (anonymous_method_host != null)
-+ return anonymous_method_host;
-+ else if (container != null)
-+ return container.AnonymousMethodHost;
-+ else
-+ return null;
-+ }
-+ }
-+
-+ public void EmitScopeInstance (EmitContext ec, ScopeInfo scope)
-+ {
-+ AnonymousMethodHost root_scope = AnonymousMethodHost;
-+
-+ root_scope.EmitScopeInstance (ec);
-+ while (root_scope != scope.Host) {
-+ ec.ig.Emit (OpCodes.Ldfld, root_scope.ParentLink.FieldBuilder);
-+ root_scope = root_scope.ParentHost;
-+
-+ if (root_scope == null)
-+ throw new InternalErrorException (
-+ "Never found scope {0} starting at block {1}",
-+ scope, ec.CurrentBlock.ID);
-+ }
-+
-+ if (scope != scope.Host)
-+ ec.ig.Emit (OpCodes.Ldfld, scope.ScopeInstance.FieldBuilder);
-+ }
-+
- public FlowBranchingToplevel TopLevelBranching {
- get { return top_level_branching; }
- }
-@@ -2192,15 +2316,12 @@
- // null. Later on, when resolving the iterator, we need to move the
- // anonymous method into that iterator.
- //
-- public void ReParent (ToplevelBlock new_parent, AnonymousContainer new_host)
-+ public void ReParent (ToplevelBlock new_parent)
- {
-- foreach (ToplevelBlock block in children) {
-- if (block.CaptureContext == null)
-- continue;
--
-- block.container = new_parent;
-- block.CaptureContext.ReParent (new_parent, new_host);
-- }
-+ Report.Debug (64, "TOPLEVEL REPARENT", this, Parent, new_parent);
-+ container = new_parent;
-+ Parent = new_parent;
-+ new_parent.child = this;
- }
-
- //
-@@ -2290,10 +2411,58 @@
-
- ResolveMeta (this, ec, ip);
-
-+ if (child != null)
-+ child.ResolveMeta (this, ec, ip);
-+
- top_level_branching = ec.StartFlowBranching (this);
-
- return Report.Errors == errors;
- }
-+
-+ public override void EmitMeta (EmitContext ec)
-+ {
-+ base.EmitMeta (ec);
-+ parameters.ResolveVariable (this);
-+ }
-+
-+ public void MakeIterator (Iterator iterator)
-+ {
-+ Report.Debug (64, "TOPLEVEL MAKE ITERATOR", this, statements);
-+
-+ Block block = new Block (this);
-+ foreach (Statement stmt in statements)
-+ block.AddStatement (stmt);
-+ statements = new ArrayList ();
-+ statements.Add (new MoveNextStatement (iterator, block));
-+ }
-+
-+ protected class MoveNextStatement : Statement {
-+ Iterator iterator;
-+ Block block;
-+
-+ public MoveNextStatement (Iterator iterator, Block block)
-+ {
-+ this.iterator = iterator;
-+ this.block = block;
-+ this.loc = iterator.Location;
-+ }
-+
-+ public override bool Resolve (EmitContext ec)
-+ {
-+ return block.Resolve (ec);
-+ }
-+
-+ protected override void DoEmit (EmitContext ec)
-+ {
-+ iterator.EmitMoveNext (ec, block);
-+ }
-+ }
-+
-+ public override string ToString ()
-+ {
-+ return String.Format ("{0} ({1}:{2}{3})", GetType (), ID, StartLocation,
-+ anonymous_method_host);
-+ }
- }
-
- public class SwitchLabel {
-@@ -3299,7 +3468,7 @@
- }
-
- public abstract void Emit (EmitContext ec);
-- public abstract void EmitExit (ILGenerator ig);
-+ public abstract void EmitExit (EmitContext ec);
- }
-
- class ExpressionEmitter : Emitter {
-@@ -3313,14 +3482,14 @@
- // Store pointer in pinned location
- //
- converted.Emit (ec);
-- ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-+ vi.Variable.EmitAssign (ec);
- }
-
-- public override void EmitExit (ILGenerator ig)
-+ public override void EmitExit (EmitContext ec)
- {
-- ig.Emit (OpCodes.Ldc_I4_0);
-- ig.Emit (OpCodes.Conv_U);
-- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-+ ec.ig.Emit (OpCodes.Ldc_I4_0);
-+ ec.ig.Emit (OpCodes.Conv_U);
-+ vi.Variable.EmitAssign (ec);
- }
- }
-
-@@ -3350,13 +3519,13 @@
- return;
-
- converted.Emit (ec);
-- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-+ vi.Variable.EmitAssign (ec);
- }
-
-- public override void EmitExit(ILGenerator ig)
-+ public override void EmitExit (EmitContext ec)
- {
-- ig.Emit (OpCodes.Ldnull);
-- ig.Emit (OpCodes.Stloc, pinned_string);
-+ ec.ig.Emit (OpCodes.Ldnull);
-+ ec.ig.Emit (OpCodes.Stloc, pinned_string);
- }
- }
-
-@@ -3554,13 +3723,11 @@
- if (has_ret)
- return;
-
-- ILGenerator ig = ec.ig;
--
- //
- // Clear the pinned variable
- //
- for (int i = 0; i < data.Length; i++) {
-- data [i].EmitExit (ig);
-+ data [i].EmitExit (ec);
- }
- }
- }
-@@ -3772,22 +3939,24 @@
-
- ig.BeginCatchBlock (c.CatchType);
-
-+#if FIXME
- if (c.VarBlock != null)
- ec.EmitScopeInitFromBlock (c.VarBlock);
-+#endif
- if (c.Name != null){
- vi = c.Block.GetLocalInfo (c.Name);
- if (vi == null)
- throw new Exception ("Variable does not exist in this block");
-
-- if (vi.IsCaptured){
-+ if (vi.Variable.NeedsTemporary) {
- LocalBuilder e = ig.DeclareLocal (vi.VariableType);
- ig.Emit (OpCodes.Stloc, e);
--
-- ec.EmitCapturedVariableInstance (vi);
-+
-+ vi.Variable.EmitInstance (ec);
- ig.Emit (OpCodes.Ldloc, e);
-- ig.Emit (OpCodes.Stfld, vi.FieldBuilder);
-+ vi.Variable.EmitAssign (ec);
- } else
-- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-+ vi.Variable.EmitAssign (ec);
- } else
- ig.Emit (OpCodes.Pop);
-
-@@ -4164,7 +4333,7 @@
-
- Type var_type = texpr.Type;
-
-- if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethod) {
-+ if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
- Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
- expr.ExprClassName);
- return false;
-@@ -4220,7 +4389,7 @@
- {
- EmitThis (ec);
- ec.ig.Emit (OpCodes.Ldc_I4_0);
-- EmitStore (ec.ig);
-+ EmitStore (ec);
- }
-
- public void Increment (EmitContext ec)
-@@ -4229,7 +4398,7 @@
- Emit (ec);
- ec.ig.Emit (OpCodes.Ldc_I4_1);
- ec.ig.Emit (OpCodes.Add);
-- EmitStore (ec.ig);
-+ EmitStore (ec);
- }
- }
-
-@@ -4323,7 +4492,7 @@
-
- lengths [i].EmitThis (ec);
- ((ArrayAccess) access).EmitGetLength (ec, i);
-- lengths [i].EmitStore (ig);
-+ lengths [i].EmitStore (ec);
- }
-
- for (int i = 0; i < rank; i++) {