2 ===================================================================
3 --- report.cs (revision 63019)
4 +++ report.cs (working copy)
10 + public InternalErrorException (string message, params object[] args)
11 + : base (String.Format (message, args))
17 ===================================================================
18 --- generic.cs (revision 63019)
19 +++ generic.cs (working copy)
23 public override string TypeParameter {
27 + get { return name; }
30 + public Constraints Clone ()
32 + return new Constraints (name, constraints, loc);
35 GenericParameterAttributes attrs;
36 TypeExpr class_constraint;
37 ArrayList iface_constraints;
39 TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb));
42 - } else if (DeclSpace is Iterator) {
43 + } else if (DeclSpace is CompilerGeneratedClass) {
44 TypeParameter[] tparams = DeclSpace.TypeParameters;
45 Type[] types = new Type [tparams.Length];
46 for (int i = 0; i < tparams.Length; i++)
49 Argument a = (Argument) arguments [i];
50 if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr) ||
51 - (a.Expr is AnonymousMethod))
52 + (a.Expr is AnonymousMethodExpression))
55 arg_types [i] = a.Type;
57 ===================================================================
58 --- typemanager.cs (revision 63019)
59 +++ typemanager.cs (working copy)
61 static public Type asynccallback_type;
62 static public Type intptr_type;
63 static public Type monitor_type;
64 + static public Type interlocked_type;
65 static public Type runtime_field_handle_type;
66 static public Type runtime_argument_handle_type;
67 static public Type attribute_type;
69 icloneable_type = CoreLookupType ("System", "ICloneable");
70 iconvertible_type = CoreLookupType ("System", "IConvertible");
71 monitor_type = CoreLookupType ("System.Threading", "Monitor");
72 + interlocked_type = CoreLookupType ("System.Threading", "Interlocked");
73 intptr_type = CoreLookupType ("System", "IntPtr");
75 attribute_type = CoreLookupType ("System", "Attribute");
77 ===================================================================
78 --- parameter.cs (revision 63019)
79 +++ parameter.cs (working copy)
81 public Expression TypeName;
82 public readonly Modifier ModFlags;
84 + public bool IsCaptured;
85 GenericConstraints constraints;
86 protected Type parameter_type;
87 public readonly Location Location;
90 + public Variable Variable {
94 IResolveContext resolve_context;
96 public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
101 + public void ResolveVariable (ToplevelBlock toplevel, int idx)
103 + Report.Debug (64, "PARAMETER RESOLVE VARIABLE", ParameterType, Name, Location);
104 + if (toplevel.AnonymousMethodHost != null)
105 + var = toplevel.AnonymousMethodHost.GetCapturedParameter (this);
106 + Report.Debug (64, "PARAMETER RESOLVE VARIABLE #1", var, idx);
108 + var = new ParameterVariable (this, idx);
111 public Type ExternalType ()
113 if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
115 return attribute_targets;
119 + protected class ParameterVariable : Variable
121 + public readonly Parameter Parameter;
122 + public readonly int Idx;
123 + public readonly bool IsRef;
125 + public ParameterVariable (Parameter par, int idx)
127 + this.Parameter = par;
129 + this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0;
132 + public override Type Type {
133 + get { return Parameter.ParameterType; }
136 + public override bool HasInstance {
137 + get { return false; }
140 + public override bool NeedsTemporary {
141 + get { return false; }
144 + public override void EmitInstance (EmitContext ec)
148 + public override void Emit (EmitContext ec)
151 + if (!ec.MethodIsStatic)
154 + ParameterReference.EmitLdArg (ec.ig, arg_idx);
157 + public override void EmitAssign (EmitContext ec)
160 + if (!ec.MethodIsStatic)
163 + if (arg_idx <= 255)
164 + ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
166 + ec.ig.Emit (OpCodes.Starg, arg_idx);
169 + public override void EmitAddressOf (EmitContext ec)
173 + if (!ec.MethodIsStatic)
177 + if (arg_idx <= 255)
178 + ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
180 + ec.ig.Emit (OpCodes.Ldarg, arg_idx);
182 + if (arg_idx <= 255)
183 + ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
185 + ec.ig.Emit (OpCodes.Ldarga, arg_idx);
197 + public void ResolveVariable (ToplevelBlock toplevel)
199 + for (int i = 0; i < FixedParameters.Length; ++i) {
200 + Parameter p = FixedParameters [i];
201 + p.ResolveVariable (toplevel, i);
205 public CallingConventions CallingConvention
212 - Parameter this [int pos]
213 + public Parameter this [int pos]
216 if (pos >= count && (HasArglist || HasParams)) {
218 ===================================================================
219 --- modifiers.cs (revision 63019)
220 +++ modifiers.cs (working copy)
223 public const int METHOD_YIELDS = 0x8000;
224 public const int METHOD_GENERIC = 0x10000;
225 + public const int ANONYMOUS_HOST = 0x20000;
227 public const int Accessibility =
228 PUBLIC | PROTECTED | INTERNAL | PRIVATE;
229 Index: rootcontext.cs
230 ===================================================================
231 --- rootcontext.cs (revision 63019)
232 +++ rootcontext.cs (working copy)
234 "System.Runtime.CompilerServices.RuntimeHelpers",
235 "System.Reflection.DefaultMemberAttribute",
236 "System.Threading.Monitor",
237 + "System.Threading.Interlocked",
239 "System.AttributeUsageAttribute",
240 "System.Runtime.InteropServices.DllImportAttribute",
242 ===================================================================
243 --- ecore.cs (revision 63019)
244 +++ ecore.cs (working copy)
245 @@ -3146,8 +3146,6 @@
249 - if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
250 - ec.CaptureField (this);
254 @@ -4007,10 +4005,10 @@
259 public class TemporaryVariable : Expression, IMemoryLocation
264 public TemporaryVariable (Type type, Location loc)
266 @@ -4028,64 +4026,47 @@
267 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
268 if (!li.Resolve (ec))
271 + if (ec.MustCaptureVariable (li)) {
272 + ScopeInfo scope = li.Block.CreateScopeInfo ();
273 + var = scope.AddLocal (li);
277 - AnonymousContainer am = ec.CurrentAnonymousMethod;
278 - if ((am != null) && am.IsIterator)
279 - ec.CaptureVariable (li);
284 + public Variable Variable {
285 + get { return var != null ? var : li.Variable; }
288 public override void Emit (EmitContext ec)
290 - ILGenerator ig = ec.ig;
292 - if (li.FieldBuilder != null) {
293 - ig.Emit (OpCodes.Ldarg_0);
294 - ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
296 - ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
298 + Variable.EmitInstance (ec);
299 + Variable.Emit (ec);
302 public void EmitLoadAddress (EmitContext ec)
304 - ILGenerator ig = ec.ig;
306 - if (li.FieldBuilder != null) {
307 - ig.Emit (OpCodes.Ldarg_0);
308 - ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
310 - ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
312 + Variable.EmitInstance (ec);
313 + Variable.EmitAddressOf (ec);
316 public void Store (EmitContext ec, Expression right_side)
318 - if (li.FieldBuilder != null)
319 - ec.ig.Emit (OpCodes.Ldarg_0);
321 + Variable.EmitInstance (ec);
322 right_side.Emit (ec);
323 - if (li.FieldBuilder != null) {
324 - ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
326 - ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
328 + Variable.EmitAssign (ec);
331 public void EmitThis (EmitContext ec)
333 - if (li.FieldBuilder != null) {
334 - ec.ig.Emit (OpCodes.Ldarg_0);
336 + Variable.EmitInstance (ec);
339 - public void EmitStore (ILGenerator ig)
340 + public void EmitStore (EmitContext ec)
342 - if (li.FieldBuilder != null)
343 - ig.Emit (OpCodes.Stfld, li.FieldBuilder);
345 - ig.Emit (OpCodes.Stloc, li.LocalBuilder);
346 + Variable.EmitAssign (ec);
349 public void AddressOf (EmitContext ec, AddressOp mode)
350 @@ -4093,5 +4074,5 @@
351 EmitLoadAddress (ec);
358 ===================================================================
359 --- class.cs (revision 63019)
360 +++ class.cs (working copy)
362 foreach (MemberCore mc in this) {
366 - catch (Exception e) {
367 + } catch (Exception e) {
368 throw new InternalErrorException (mc.Location, mc.GetSignatureForError (), e);
372 Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
378 public sealed class IndexerArrayList : MemberCoreArrayList
380 // Holds the operators
381 MemberCoreArrayList operators;
383 - // Holds the iterators
384 - ArrayList iterators;
385 + // Holds the compiler generated classes
386 + ArrayList compiler_generated;
389 // Pointers to the default constructor and the default static constructor
392 ArrayList type_bases;
394 + bool type_populated;
395 + bool type_populated_ok;
396 bool members_defined;
397 bool members_defined_ok;
399 @@ -772,12 +772,14 @@
403 - public void AddIterator (Iterator i)
404 + public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
406 - if (iterators == null)
407 - iterators = new ArrayList ();
408 + Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
411 + if (compiler_generated == null)
412 + compiler_generated = new ArrayList ();
414 + compiler_generated.Add (c);
417 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
422 - public ArrayList Iterators {
423 + public ArrayList CompilerGenerated {
426 + return compiler_generated;
430 @@ -1202,7 +1204,7 @@
431 // Let's do it as soon as possible, since code below can call DefineType() on classes
432 // that depend on us to be populated before they are.
434 - if (!(this is Iterator))
435 + if (!(this is Iterator) && !(this is CompilerGeneratedClass))
436 RootContext.RegisterOrder (this);
438 if (base_type != null) {
439 @@ -1278,11 +1280,53 @@
440 part.TypeBuilder = TypeBuilder;
443 + if (!CreateAnonymousHelpers ()) {
448 DefineNestedTypes ();
453 + protected bool CreateAnonymousHelpers ()
455 + if (methods != null) {
456 + foreach (Method method in methods) {
457 + if (!method.CreateAnonymousHelpers ())
462 + if (operators != null) {
463 + foreach (Operator o in operators) {
464 + if (!o.CreateAnonymousHelpers ())
469 + if (properties != null) {
470 + foreach (PropertyBase p in properties) {
471 + if (!p.Get.IsDummy && !p.Get.CreateAnonymousHelpers ())
473 + if (!p.Set.IsDummy && !p.Set.CreateAnonymousHelpers ())
478 + if (indexers != null) {
479 + foreach (PropertyBase p in indexers) {
480 + if (!p.Get.IsDummy && !p.Get.CreateAnonymousHelpers ())
482 + if (!p.Set.IsDummy && !p.Set.CreateAnonymousHelpers ())
490 Constraints [] constraints;
491 public override void SetParameterInfo (ArrayList constraints_list)
493 @@ -1329,6 +1373,20 @@
495 public bool ResolveType ()
497 + if (!DoResolveType ())
500 + if (compiler_generated != null) {
501 + foreach (CompilerGeneratedClass c in compiler_generated)
502 + if (!c.ResolveType ())
509 + protected virtual bool DoResolveType ()
511 if ((base_type != null) &&
512 (base_type.ResolveAsTypeTerminal (this, false) == null)) {
514 @@ -1413,6 +1471,13 @@
518 + if (compiler_generated != null) {
519 + foreach (CompilerGeneratedClass c in compiler_generated) {
520 + if (c.DefineType () == null)
528 @@ -1462,6 +1527,22 @@
529 Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
532 + protected bool PopulateType ()
534 + if (type_populated)
535 + return type_populated_ok;
537 + type_populated_ok = DoPopulateType ();
538 + type_populated = true;
540 + return type_populated_ok;
543 + protected virtual bool DoPopulateType ()
549 /// Populates our TypeBuilder with fields and methods
551 @@ -1541,18 +1622,7 @@
552 part.member_cache = member_cache;
555 - if (iterators != null) {
556 - foreach (Iterator iterator in iterators) {
557 - if (iterator.DefineType () == null)
561 - foreach (Iterator iterator in iterators) {
562 - if (!iterator.DefineMembers ())
570 @@ -1564,9 +1634,9 @@
572 public override bool Define ()
574 - if (iterators != null) {
575 - foreach (Iterator iterator in iterators) {
576 - if (!iterator.Define ())
577 + if (compiler_generated != null) {
578 + foreach (CompilerGeneratedClass c in compiler_generated) {
583 @@ -2239,7 +2309,7 @@
585 if (default_static_constructor != null)
586 default_static_constructor.Emit ();
589 if (methods != null){
590 foreach (Method m in methods)
592 @@ -2282,9 +2352,14 @@
593 if (pending.VerifyPendingMethods ())
596 - if (iterators != null)
597 - foreach (Iterator iterator in iterators)
598 - iterator.EmitType ();
599 + if (compiler_generated != null) {
600 + foreach (CompilerGeneratedClass c in compiler_generated) {
601 + if (!c.DefineMembers ())
602 + throw new InternalErrorException ();
604 + foreach (CompilerGeneratedClass c in compiler_generated)
609 public override void CloseType ()
610 @@ -2324,9 +2399,9 @@
611 foreach (Delegate d in Delegates)
614 - if (Iterators != null)
615 - foreach (Iterator i in Iterators)
617 + if (CompilerGenerated != null)
618 + foreach (CompilerGeneratedClass c in CompilerGenerated)
623 @@ -2341,7 +2416,7 @@
628 + compiler_generated = null;
629 default_constructor = null;
630 default_static_constructor = null;
632 @@ -3194,7 +3269,7 @@
636 - public void SetYields ()
637 + public virtual void SetYields ()
639 ModFlags |= Modifiers.METHOD_YIELDS;
641 @@ -3652,6 +3727,9 @@
642 ListDictionary declarative_security;
643 protected MethodData MethodData;
646 + ArrayList anonymous_methods;
648 static string[] attribute_targets = new string [] { "method", "return" };
650 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, Expression type, int mod,
651 @@ -3702,24 +3780,29 @@
655 - public EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
656 + public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
658 - EmitContext ec = new EmitContext (this,
659 - tc, this.ds, Location, ig, MemberType, ModFlags, false);
660 + return new EmitContext (
661 + this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
664 - Iterator iterator = tc as Iterator;
665 - if (iterator != null)
666 - ec.CurrentAnonymousMethod = iterator.Host;
669 + public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
671 + if (anonymous_methods == null)
672 + anonymous_methods = new ArrayList ();
673 + anonymous_methods.Add (anonymous);
676 - public override bool Define ()
679 + protected bool DefineGenericMethod ()
684 if (!DoDefineBase ())
687 - MethodBuilder mb = null;
688 if (GenericMethod != null) {
689 string method_name = MemberName.Name;
691 @@ -3728,12 +3811,49 @@
695 - mb = Parent.TypeBuilder.DefineMethod (method_name, flags);
696 + MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
698 - if (!GenericMethod.Define (mb))
699 + if (!GenericMethod.Define (MethodBuilder))
703 + base_defined = true;
707 + public bool CreateAnonymousHelpers ()
709 + Report.Debug (64, "METHOD DEFINE HELPERS", this, Name,
710 + ModFlags & Modifiers.METHOD_YIELDS,
711 + ModFlags & Modifiers.ANONYMOUS_HOST,
714 + if (!DefineGenericMethod ())
717 + if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
718 + iterator = Iterator.CreateIterator (
719 + this, ParentContainer, GenericMethod, ModFlags);
721 + if (iterator == null)
725 + if (anonymous_methods != null) {
726 + foreach (AnonymousMethodExpression ame in anonymous_methods) {
727 + if (!ame.CreateAnonymousHelpers ())
735 + public override bool Define ()
737 + if (!DefineGenericMethod ())
743 @@ -3743,7 +3863,8 @@
747 - MethodData = new MethodData (this, ModFlags, flags, this, mb, GenericMethod, base_method);
748 + MethodData = new MethodData (
749 + this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
751 if (!MethodData.Define (ParentContainer))
753 @@ -3821,6 +3942,10 @@
757 + public Iterator Iterator {
758 + get { return iterator; }
761 public new Location Location {
763 return base.Location;
764 @@ -3961,7 +4086,7 @@
768 - public class Method : MethodOrOperator, IIteratorContainer {
769 + public class Method : MethodOrOperator, IAnonymousHost {
772 /// Modifiers allowed in a class declaration
773 @@ -3978,7 +4103,8 @@
777 - Modifiers.METHOD_YIELDS |
778 + Modifiers.METHOD_YIELDS |
779 + Modifiers.ANONYMOUS_HOST |
782 const int AllowedInterfaceModifiers =
783 @@ -4118,6 +4244,8 @@
785 public override bool Define ()
787 + Report.Debug (64, "METHOD DEFINE", this, Name);
792 @@ -4132,17 +4260,6 @@
796 - // Setup iterator if we are one
798 - if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
799 - Iterator iterator = new Iterator (
800 - this, Parent, GenericMethod, ModFlags);
802 - if (!iterator.DefineIterator ())
807 // This is used to track the Entry Point,
809 if (Name == "Main" &&
810 @@ -4179,6 +4296,7 @@
812 public override void Emit ()
814 + Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
815 MethodData.Emit (Parent);
818 @@ -4360,6 +4478,10 @@
820 static string[] attribute_targets = new string [] { "method" };
822 + public Iterator Iterator {
823 + get { return null; }
826 bool has_compliant_args = false;
828 // The spec claims that static is not permitted, but
829 @@ -4581,6 +4703,13 @@
830 ParentContainer.EmitFieldInitializers (ec);
834 + bool unreachable = false;
835 + if (block != null) {
836 + ec.ResolveTopBlock (null, block, ParameterInfo, this, out unreachable);
837 + ec.EmitMeta (block);
840 if (Initializer != null) {
841 Initializer.Emit (ec);
843 @@ -4588,7 +4717,8 @@
844 if ((ModFlags & Modifiers.STATIC) != 0)
845 ParentContainer.EmitFieldInitializers (ec);
847 - ec.EmitTopBlock (this, block);
849 + ec.EmitResolvedTopBlock (block, unreachable);
852 source.CloseMethod ();
853 @@ -4710,6 +4840,8 @@
854 GenericMethod GenericMethod { get; }
855 Parameters ParameterInfo { get; }
857 + Iterator Iterator { get; }
859 Attributes OptAttributes { get; }
860 ToplevelBlock Block { get; set; }
862 @@ -5032,6 +5164,20 @@
864 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
866 + Report.Debug (64, "METHOD DATA EMIT", this, MethodBuilder,
867 + method, method.Iterator, block);
870 + if (method.Iterator != null) {
871 + if (!method.Iterator.Resolve (ec))
872 + throw new InternalErrorException ();
873 + // method.Iterator.EmitMethod (ec);
877 + Report.Debug (64, "METHOD DATA EMIT #1", this, MethodBuilder,
878 + method, method.Iterator, block);
881 // Handle destructors specially
883 @@ -5860,7 +6006,7 @@
885 // `set' and `get' accessors are represented with an Accessor.
887 - public class Accessor : IIteratorContainer {
888 + public class Accessor : IAnonymousHost {
890 // Null if the accessor is empty, or a Block if not
892 @@ -5875,6 +6021,7 @@
893 public Location Location;
896 + public ArrayList AnonymousMethods;
898 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
900 @@ -5888,6 +6035,13 @@
905 + public void AddAnonymousMethod (AnonymousMethodExpression ame)
907 + if (AnonymousMethods == null)
908 + AnonymousMethods = new ArrayList ();
909 + AnonymousMethods.Add (ame);
913 // Ooouh Martin, templates are missing here.
914 @@ -5934,6 +6088,10 @@
916 #region IMethodData Members
918 + public abstract Iterator Iterator {
922 public ToplevelBlock Block {
925 @@ -6220,6 +6378,8 @@
927 protected readonly MethodCore method;
928 protected MethodAttributes flags;
930 + ArrayList anonymous_methods;
933 public PropertyMethod (MethodCore method, string prefix)
934 @@ -6235,12 +6395,17 @@
935 this.method = method;
936 this.ModFlags = accessor.ModFlags;
937 yields = accessor.Yields;
938 + anonymous_methods = accessor.AnonymousMethods;
940 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
941 Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
945 + public override Iterator Iterator {
946 + get { return iterator; }
949 public override AttributeTargets AttributeTargets {
951 return AttributeTargets.Method;
952 @@ -6252,6 +6417,28 @@
953 return method.IsClsComplianceRequired ();
956 + public bool CreateAnonymousHelpers ()
958 + TypeContainer container = ((TypeContainer) Parent).PartialContainer;
961 + iterator = Iterator.CreateIterator (
962 + this, container, null, ModFlags);
964 + if (iterator == null)
968 + if (anonymous_methods != null) {
969 + foreach (AnonymousMethodExpression ame in anonymous_methods) {
970 + if (!ame.CreateAnonymousHelpers ())
978 public virtual MethodBuilder Define (DeclSpace parent)
980 if (!method.CheckAbstractAndExtern (block != null))
981 @@ -6281,16 +6468,6 @@
982 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
986 - // Setup iterator if we are one
989 - Iterator iterator = new Iterator (this, Parent as TypeContainer, null, ModFlags);
991 - if (!iterator.DefineIterator ())
998 @@ -6932,6 +7109,10 @@
999 this.method = method;
1002 + public override Iterator Iterator {
1003 + get { return null; }
1006 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
1008 if (a.Target == AttributeTargets.Parameter) {
1009 @@ -7183,7 +7364,7 @@
1013 - public class Indexer : PropertyBase, IIteratorContainer {
1014 + public class Indexer : PropertyBase {
1016 class GetIndexerMethod : GetMethod
1018 @@ -7323,10 +7504,10 @@
1019 // Setup iterator if we are one
1021 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
1022 - Iterator iterator = new Iterator (
1023 - Get, Parent, null, ModFlags);
1024 + Iterator iterator = Iterator.CreateIterator (
1025 + Get, (TypeContainer) Parent, null, ModFlags);
1027 - if (!iterator.DefineIterator ())
1028 + if (iterator == null)
1032 @@ -7383,7 +7564,7 @@
1036 - public class Operator : MethodOrOperator, IIteratorContainer {
1037 + public class Operator : MethodOrOperator, IAnonymousHost {
1039 const int AllowedModifiers =
1042 ===================================================================
1043 --- decl.cs (revision 63019)
1044 +++ decl.cs (working copy)
1046 caching_flags |= Flags.ClsCompliantAttributeTrue;
1054 ===================================================================
1055 --- delegate.cs (revision 63019)
1056 +++ delegate.cs (working copy)
1059 Expression e = a.Expr;
1061 - if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
1062 - return ((AnonymousMethod) e).Compatible (ec, type);
1063 + if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1)
1064 + return ((AnonymousMethodExpression) e).Compatible (ec, type);
1066 MethodGroupExpr mg = e as MethodGroupExpr;
1069 ===================================================================
1070 --- iterators.cs (revision 63019)
1071 +++ iterators.cs (working copy)
1074 namespace Mono.CSharp {
1076 - public interface IIteratorContainer {
1079 - // Invoked if a yield statement is found in the body
1081 - void SetYields ();
1084 public class Yield : Statement {
1086 ArrayList finally_blocks;
1089 public override bool Resolve (EmitContext ec)
1091 + Report.Debug (64, "RESOLVE YIELD", this, ec, expr, expr.GetType ());
1092 expr = expr.Resolve (ec);
1096 + Report.Debug (64, "RESOLVE YIELD #1", this, ec, expr, expr.GetType (),
1097 + ec.CurrentAnonymousMethod, ec.CurrentIterator);
1099 if (!CheckContext (ec, loc, false))
1102 Iterator iterator = ec.CurrentIterator;
1104 - if (expr.Type != iterator.IteratorType){
1105 + if (expr.Type != iterator.IteratorType) {
1106 expr = Convert.ImplicitConversionRequired (
1107 ec, expr, iterator.IteratorType, loc);
1109 @@ -119,13 +114,465 @@
1113 - public class Iterator : Class {
1114 - protected ToplevelBlock original_block;
1115 - protected ToplevelBlock block;
1116 + public class IteratorHost : AnonymousMethodHost
1118 + public readonly Iterator Iterator;
1120 - Type original_iterator_type;
1121 TypeExpr iterator_type_expr;
1122 - bool is_enumerable;
1124 + Field current_field;
1126 + MethodInfo dispose_method;
1128 + TypeExpr enumerator_type;
1129 + TypeExpr enumerable_type;
1130 + TypeExpr generic_enumerator_type;
1131 + TypeExpr generic_enumerable_type;
1132 + TypeArguments generic_args;
1134 + public IteratorHost (Iterator iterator)
1135 + : base (iterator.Container, iterator.Host, iterator.GenericMethod,
1136 + iterator.Location)
1138 + this.Iterator = iterator;
1141 + public MethodInfo Dispose {
1142 + get { return dispose_method; }
1146 + get { return pc_field; }
1149 + public Field CurrentField {
1150 + get { return current_field; }
1153 + public Type IteratorType {
1154 + get { return iterator_type_expr.Type; }
1157 + public override TypeExpr [] GetClassBases (out TypeExpr base_class)
1159 + iterator_type_expr = InflateType (Iterator.OriginalIteratorType);
1161 + generic_args = new TypeArguments (Location);
1162 + generic_args.Add (iterator_type_expr);
1164 + ArrayList list = new ArrayList ();
1165 + if (Iterator.IsEnumerable) {
1166 + enumerable_type = new TypeExpression (
1167 + TypeManager.ienumerable_type, Location);
1168 + list.Add (enumerable_type);
1170 + generic_enumerable_type = new ConstructedType (
1171 + TypeManager.generic_ienumerable_type,
1172 + generic_args, Location);
1173 + list.Add (generic_enumerable_type);
1176 + enumerator_type = new TypeExpression (
1177 + TypeManager.ienumerator_type, Location);
1178 + list.Add (enumerator_type);
1180 + list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
1182 + generic_enumerator_type = new ConstructedType (
1183 + TypeManager.generic_ienumerator_type,
1184 + generic_args, Location);
1185 + list.Add (generic_enumerator_type);
1189 + return base.GetClassBases (out base_class);
1192 + protected override bool DoDefineMembers ()
1194 + pc_field = CaptureVariable ("$PC", TypeManager.int32_type);
1195 + current_field = CaptureVariable ("$current", Iterator.OriginalIteratorType);
1197 + Define_Current (true);
1198 + Define_Current (false);
1199 + dispose = new DisposeMethod (this);
1202 + if (Iterator.IsEnumerable) {
1203 + new GetEnumeratorMethod (this, false);
1204 + new GetEnumeratorMethod (this, true);
1207 + if (!base.DoDefineMembers ())
1210 + FetchMethodDispose ();
1214 + protected override void EmitScopeConstructor (EmitContext ec)
1216 + ec.ig.Emit (OpCodes.Ldarg_0);
1217 + ec.ig.Emit (OpCodes.Ldarg_1);
1218 + ec.ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1219 + base.EmitScopeConstructor (ec);
1222 + void FetchMethodDispose ()
1224 + MemberList dispose_list;
1226 + dispose_list = FindMembers (
1227 + CurrentType != null ? CurrentType : TypeBuilder,
1228 + MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
1229 + Type.FilterName, "Dispose");
1231 + if (dispose_list.Count != 1)
1232 + throw new InternalErrorException ("Cannot find Dipose() method.");
1234 + dispose_method = (MethodInfo) dispose_list [0];
1237 + void Define_Current (bool is_generic)
1243 + left = new MemberName (
1244 + "System.Collections.Generic.IEnumerator",
1245 + generic_args, Location);
1246 + type = iterator_type_expr;
1248 + left = new MemberName ("System.Collections.IEnumerator", Location);
1249 + type = TypeManager.system_object_expr;
1252 + MemberName name = new MemberName (left, "Current", null, Location);
1254 + ToplevelBlock get_block = new ToplevelBlock (Location);
1255 + get_block.AddStatement (new CurrentBlock (this, is_generic));
1257 + Accessor getter = new Accessor (get_block, 0, null, Location);
1259 + Property current = new Property (
1260 + this, type, 0, false, name, null, getter, null);
1261 + AddProperty (current);
1264 + void Define_Reset ()
1266 + Method reset = new Method (
1267 + this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
1268 + false, new MemberName ("Reset", Location),
1269 + Parameters.EmptyReadOnlyParameters, null);
1270 + AddMethod (reset);
1272 + reset.Block = new ToplevelBlock (Location);
1273 + reset.Block.AddStatement (Create_ThrowNotSupported ());
1276 + Statement Create_ThrowNotSupported ()
1278 + TypeExpr ex_type = new TypeExpression (
1279 + TypeManager.not_supported_exception_type, Location);
1281 + return new Throw (new New (ex_type, null, Location), Location);
1284 + ConstructorInfo GetInvalidOperationException ()
1286 + MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1287 + TypeBuilder, TypeManager.invalid_operation_exception_type,
1288 + ".ctor", Location);
1290 + throw new InternalErrorException ();
1291 + return (ConstructorInfo) mg.Methods [0];
1294 + MethodInfo GetCompareExchange ()
1296 + MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1297 + TypeBuilder, TypeManager.interlocked_type,
1298 + "CompareExchange", Location);
1300 + throw new InternalErrorException ();
1301 + return (MethodInfo) mg.Methods [0];
1304 + protected override ScopeInitializerBase CreateScopeInitializer ()
1306 + return new IteratorHostInitializer (this);
1309 + protected class IteratorHostInitializer : AnonymousMethodHostInitializer
1311 + new public readonly IteratorHost Host;
1312 + protected Iterator.State state;
1314 + public IteratorHostInitializer (IteratorHost host)
1320 + protected override bool DoResolveInternal (EmitContext ec)
1322 + if (this is EnumeratorScopeInitializer)
1323 + state = Iterator.State.Running;
1324 + else if (Host.Iterator.IsEnumerable)
1325 + state = Iterator.State.Uninitialized;
1327 + state = Iterator.State.Running;
1329 + return base.DoResolveInternal (ec);
1332 + protected override void EmitScopeConstructor (EmitContext ec)
1334 + ec.ig.Emit (OpCodes.Ldc_I4, (int) state);
1335 + base.EmitScopeConstructor (ec);
1339 + protected class GetEnumeratorMethod : Method
1341 + public IteratorHost Host;
1343 + static MemberName GetMemberName (IteratorHost host, bool is_generic)
1347 + left = new MemberName (
1348 + "System.Collections.Generic.IEnumerable",
1349 + host.generic_args, host.Location);
1351 + left = new MemberName (
1352 + "System.Collections.IEnumerable", host.Location);
1355 + return new MemberName (left, "GetEnumerator", host.Location);
1358 + public GetEnumeratorMethod (IteratorHost host, bool is_generic)
1359 + : base (host, null, is_generic ?
1360 + host.generic_enumerator_type : host.enumerator_type,
1361 + 0, false, GetMemberName (host, is_generic),
1362 + Parameters.EmptyReadOnlyParameters, null)
1366 + host.AddMethod (this);
1368 + Block = new ToplevelBlock (host.Iterator.Container, null, Location);
1369 + Block.AddStatement (new GetEnumeratorStatement (host, Type, is_generic));
1372 + public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1374 + EmitContext ec = new EmitContext (
1375 + this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
1377 + ec.CurrentAnonymousMethod = Host.Iterator;
1381 + protected class GetEnumeratorStatement : Statement
1383 + IteratorHost host;
1387 + ExpressionStatement initializer;
1391 + public GetEnumeratorStatement (IteratorHost host, Expression type,
1396 + this.is_generic = is_generic;
1397 + loc = host.Location;
1400 + public override bool Resolve (EmitContext ec)
1402 + type = type.ResolveAsTypeTerminal (ec, false);
1403 + if ((type == null) || (type.Type == null))
1406 + initializer = host.GetEnumeratorInitializer (ec);
1407 + if (initializer == null)
1410 + cast = new ClassCast (initializer, type.Type);
1412 + ce = host.GetCompareExchange ();
1414 + ec.CurrentBranching.CurrentUsageVector.Return ();
1418 + protected override void DoEmit (EmitContext ec)
1420 + ILGenerator ig = ec.ig;
1421 + Label label_init = ig.DefineLabel ();
1423 + ig.Emit (OpCodes.Ldarg_0);
1424 + ig.Emit (OpCodes.Ldflda, host.PC.FieldBuilder);
1425 + ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Running);
1426 + ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Uninitialized);
1427 + ig.Emit (OpCodes.Call, ce);
1429 + ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Uninitialized);
1430 + ig.Emit (OpCodes.Bne_Un, label_init);
1432 + ig.Emit (OpCodes.Ldarg_0);
1433 + ig.Emit (OpCodes.Ret);
1435 + ig.MarkLabel (label_init);
1437 + initializer.EmitStatement (ec);
1439 + ig.Emit (OpCodes.Ret);
1444 + protected class DisposeMethod : Method
1446 + public IteratorHost Host;
1448 + public DisposeMethod (IteratorHost host)
1449 + : base (host, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
1450 + false, new MemberName ("Dispose", host.Location),
1451 + Parameters.EmptyReadOnlyParameters, null)
1455 + host.AddMethod (this);
1457 + Block = new ToplevelBlock (host.Iterator.Block, null, Location);
1458 + Block.AddStatement (new DisposeMethodStatement (Host.Iterator));
1460 + Report.Debug (64, "DISPOSE METHOD", host, Block);
1463 + public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1465 + EmitContext ec = new EmitContext (
1466 + this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
1468 + ec.CurrentAnonymousMethod = Host.Iterator;
1472 + protected class DisposeMethodStatement : Statement
1474 + Iterator iterator;
1476 + public DisposeMethodStatement (Iterator iterator)
1478 + this.iterator = iterator;
1479 + this.loc = iterator.Location;
1482 + public override bool Resolve (EmitContext ec)
1487 + protected override void DoEmit (EmitContext ec)
1489 + iterator.EmitDispose (ec);
1494 + protected ScopeInitializer GetEnumeratorInitializer (EmitContext ec)
1496 + ScopeInitializer init = new EnumeratorScopeInitializer (this);
1497 + if (init.Resolve (ec) == null)
1498 + throw new InternalErrorException ();
1502 + protected class EnumeratorScopeInitializer : IteratorHostInitializer
1504 + IteratorHost host;
1506 + public EnumeratorScopeInitializer (IteratorHost host)
1512 + protected override bool DoResolveInternal (EmitContext ec)
1514 + type = host.IsGeneric ? host.CurrentType : host.TypeBuilder;
1515 + return base.DoResolveInternal (ec);
1518 + protected override void DoEmit (EmitContext ec)
1520 + DoEmitInstance (ec);
1523 + protected override void EmitParameterReference (EmitContext ec,
1524 + CapturedParameter cp)
1526 + ec.ig.Emit (OpCodes.Ldarg_0);
1527 + ec.ig.Emit (OpCodes.Ldfld, cp.Field.FieldBuilder);
1531 + protected class CurrentBlock : Statement {
1532 + IteratorHost host;
1535 + public CurrentBlock (IteratorHost host, bool is_generic)
1538 + this.is_generic = is_generic;
1539 + loc = host.Location;
1542 + public override bool Resolve (EmitContext ec)
1544 + ec.CurrentBranching.CurrentUsageVector.Return ();
1548 + protected override void DoEmit (EmitContext ec)
1550 + ILGenerator ig = ec.ig;
1551 + Label label_ok = ig.DefineLabel ();
1553 + ig.Emit (OpCodes.Ldarg_0);
1554 + ig.Emit (OpCodes.Ldfld, host.PC.FieldBuilder);
1555 + ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Running);
1556 + ig.Emit (OpCodes.Bgt, label_ok);
1558 + ig.Emit (OpCodes.Newobj, host.GetInvalidOperationException ());
1559 + ig.Emit (OpCodes.Throw);
1561 + ig.MarkLabel (label_ok);
1562 + ig.Emit (OpCodes.Ldarg_0);
1563 + ig.Emit (OpCodes.Ldfld, host.CurrentField.FieldBuilder);
1565 + ig.Emit (OpCodes.Box, host.CurrentField.MemberType);
1566 + ig.Emit (OpCodes.Ret);
1571 + public class Iterator : AnonymousContainer {
1572 + protected readonly ToplevelBlock OriginalBlock;
1573 + protected readonly IMethodData OriginalMethod;
1574 + protected ToplevelBlock block;
1576 + public readonly bool IsEnumerable;
1577 public readonly bool IsStatic;
1581 // Context from the original method
1583 GenericMethod generic_method;
1584 - TypeContainer container;
1585 TypeExpr current_type;
1587 Parameters parameters;
1588 @@ -147,34 +593,33 @@
1589 IMethodData orig_method;
1591 MethodInfo dispose_method;
1592 - MoveNextMethod move_next_method;
1593 + Method move_next_method;
1595 - CaptureContext cc;
1597 Expression enumerator_type;
1598 Expression enumerable_type;
1599 Expression generic_enumerator_type;
1600 Expression generic_enumerable_type;
1601 TypeArguments generic_args;
1604 - protected enum State {
1605 + public readonly Type OriginalIteratorType;
1606 + public readonly IteratorHost IteratorHost;
1608 + public enum State {
1614 - static int proxy_count;
1616 public void EmitYieldBreak (ILGenerator ig)
1618 ig.Emit (OpCodes.Ldarg_0);
1619 IntConstant.EmitInt (ig, (int) State.After);
1620 - ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1621 + ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1622 ig.Emit (OpCodes.Br, move_next_error);
1625 - public void EmitMoveNext (EmitContext ec)
1626 + internal void EmitMoveNext (EmitContext ec, Block original_block)
1628 ILGenerator ig = ec.ig;
1631 resume_points.Add (entry_point);
1632 entry_point.Define (ig);
1634 - ec.EmitTopBlock (orig_method, original_block);
1635 + original_block.Emit (ec);
1637 EmitYieldBreak (ig);
1640 labels [i] = ((ResumePoint) resume_points [i]).Label;
1642 ig.Emit (OpCodes.Ldarg_0);
1643 - ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
1644 + ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
1645 ig.Emit (OpCodes.Switch, labels);
1647 Label end = ig.DefineLabel ();
1649 ig.BeginFaultBlock ();
1651 ig.Emit (OpCodes.Ldarg_0);
1652 - ig.Emit (OpCodes.Callvirt, dispose_method);
1653 + ig.Emit (OpCodes.Callvirt, IteratorHost.Dispose);
1655 ig.EndExceptionBlock ();
1657 @@ -264,12 +709,12 @@
1659 ig.MarkLabel (dispatcher);
1660 ig.Emit (OpCodes.Ldarg_0);
1661 - ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
1662 + ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
1663 ig.Emit (OpCodes.Switch, labels);
1665 ig.Emit (OpCodes.Ldarg_0);
1666 IntConstant.EmitInt (ig, (int) State.After);
1667 - ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1668 + ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1672 @@ -305,13 +750,13 @@
1673 // Store the new current
1674 ig.Emit (OpCodes.Ldarg_0);
1676 - ig.Emit (OpCodes.Stfld, current_field.FieldBuilder);
1677 + ig.Emit (OpCodes.Stfld, IteratorHost.CurrentField.FieldBuilder);
1681 ig.Emit (OpCodes.Ldarg_0);
1682 IntConstant.EmitInt (ig, pc);
1683 - ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1684 + ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1687 ig.Emit (OpCodes.Br, move_next_ok);
1688 @@ -329,728 +774,94 @@
1690 ig.Emit (OpCodes.Ldarg_0);
1691 IntConstant.EmitInt (ig, pc);
1692 - ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1693 + ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1695 ResumePoint point = new ResumePoint (finally_blocks);
1696 resume_points.Add (point);
1700 - private static MemberName MakeProxyName (string name, GenericMethod generic, Location loc)
1702 - int pos = name.LastIndexOf ('.');
1704 - name = name.Substring (pos + 1);
1705 + public override bool IsIterator {
1706 + get { return true; }
1709 - string proxy_name = "<" + name + ">__" + (proxy_count++);
1711 - if (generic != null) {
1712 - TypeArguments args = new TypeArguments (loc);
1713 - foreach (TypeParameter tparam in generic.CurrentTypeParameters)
1714 - args.Add (new SimpleName (tparam.Name, loc));
1715 - return new MemberName (proxy_name, args, loc);
1717 - return new MemberName (proxy_name, loc);
1718 + public override AnonymousMethodHost RootScope {
1719 + get { return IteratorHost; }
1725 - public Iterator (IMethodData m_container, DeclSpace parent, GenericMethod generic,
1727 - : base (parent.NamespaceEntry, parent,
1728 - MakeProxyName (m_container.MethodName.Name, generic, m_container.Location),
1729 - (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null)
1730 + public Iterator (IMethodData m_container, TypeContainer host, GenericMethod generic,
1731 + ToplevelBlock container, ToplevelBlock block, int modifiers,
1732 + Type iterator_type, bool is_enumerable)
1733 + : base (null, host, generic, m_container.ParameterInfo,
1734 + block, m_container.Block, TypeManager.bool_type, modifiers,
1735 + m_container.Location)
1737 - this.orig_method = m_container;
1738 + this.OriginalBlock = m_container.Block;
1739 + this.OriginalMethod = m_container;
1740 + this.OriginalIteratorType = iterator_type;
1741 + this.IsEnumerable = is_enumerable;
1743 - this.generic_method = generic;
1744 - this.container = ((TypeContainer) parent).PartialContainer;
1745 - this.original_parameters = m_container.ParameterInfo;
1746 - this.original_block = orig_method.Block;
1747 - this.block = new ToplevelBlock (orig_method.Block, parameters, orig_method.Location);
1748 + Report.Debug (64, "NEW ITERATOR", host, generic, OriginalBlock,
1749 + Container, Block, block);
1751 - if (generic != null) {
1752 - ArrayList constraints = new ArrayList ();
1753 - foreach (TypeParameter tparam in generic.TypeParameters)
1754 - constraints.Add (tparam.Constraints);
1755 + IteratorHost = new IteratorHost (this);
1756 + Block.CreateIteratorHost (IteratorHost);
1758 - SetParameterInfo (constraints);
1760 + OriginalBlock.ReParent (Container);
1762 - IsStatic = (modifiers & Modifiers.STATIC) != 0;
1764 + m_container.Block = block;
1766 - public AnonymousContainer Host {
1767 - get { return move_next_method; }
1768 + OriginalBlock.MakeIterator (this);
1771 - public bool DefineIterator ()
1772 + protected class TestStatement : Statement
1774 - ec = new EmitContext (this, this, Location, null, null, ModFlags);
1775 - ec.CurrentAnonymousMethod = move_next_method;
1776 - ec.InIterator = true;
1778 - if (!CheckType ()) {
1779 - Report.Error (1624, Location,
1780 - "The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",
1781 - orig_method.GetSignatureForError (), TypeManager.CSharpName (orig_method.ReturnType));
1783 + public override bool Resolve (EmitContext ec)
1788 - for (int i = 0; i < original_parameters.Count; i++){
1789 - Parameter.Modifier mod = original_parameters.ParameterModifier (i);
1790 - if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
1793 - "Iterators cannot have ref or out parameters");
1797 - if ((mod & Parameter.Modifier.ARGLIST) != 0) {
1798 - Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");
1802 - if (original_parameters.ParameterType (i).IsPointer) {
1803 - Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");
1806 + protected override void DoEmit (EmitContext ec)
1808 + ec.ig.Emit (OpCodes.Nop);
1809 + ec.ig.Emit (OpCodes.Neg);
1810 + ec.ig.Emit (OpCodes.Pop);
1811 + ec.ig.Emit (OpCodes.Ret);
1814 - if (container.CurrentType != null)
1815 - this_type = container.CurrentType;
1817 - this_type = container.TypeBuilder;
1819 - container.AddIterator (this);
1821 - orig_method.Block = block;
1825 - MethodInfo FetchMethodDispose ()
1826 + public override bool Resolve (EmitContext ec)
1828 - MemberList dispose_list;
1829 + Report.Debug (64, "RESOLVE ITERATOR", this, Container, Block);
1831 - dispose_list = FindMembers (
1832 - current_type.Type,
1833 - MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
1834 - Type.FilterName, "Dispose");
1836 - if (dispose_list.Count != 1)
1837 - throw new InternalErrorException ("Cannot find Dipose() method.");
1839 - return (MethodInfo) dispose_list [0];
1842 - protected override bool DoDefineMembers ()
1844 - ec.InIterator = true;
1845 - ec.CurrentAnonymousMethod = move_next_method;
1846 - ec.capture_context = cc;
1848 - if (!base.DoDefineMembers ())
1849 + if (!base.Resolve (ec))
1852 - dispose_method = FetchMethodDispose ();
1853 - if (dispose_method == null)
1855 + Report.Debug (64, "RESOLVE ITERATOR #1", this, method, method.Parent,
1861 - public override bool Define ()
1863 - if (!base.Define ())
1864 + if (!RootScope.DefineMembers ())
1867 - ec.InIterator = true;
1868 - ec.CurrentAnonymousMethod = move_next_method;
1869 - ec.capture_context = cc;
1870 + ExpressionStatement scope_init = RootScope.GetScopeInitializer (ec);
1871 + Container.AddStatement (new StatementExpression (scope_init));
1872 + Expression cast = new ClassCast (scope_init, OriginalMethod.ReturnType);
1873 + Container.AddStatement (new NoCheckReturn (cast));
1875 - ec.TypeContainer = ec.TypeContainer.Parent;
1877 - if (ec.TypeContainer.CurrentType != null)
1878 - ec.ContainerType = ec.TypeContainer.CurrentType;
1880 - ec.ContainerType = ec.TypeContainer.TypeBuilder;
1882 - ec.ig = move_next_method.method.MethodBuilder.GetILGenerator ();
1884 - if (!ctor.Define ())
1889 - if (!ec.ResolveTopBlock (null, original_block, parameters, orig_method, out unreachable))
1892 - if (!ec.ResolveTopBlock (null, block, parameters, orig_method, out unreachable))
1895 - original_block.CompleteContexts ();
1897 - cc.EmitAnonymousHelperClasses (ec);
1902 - TypeExpr InflateType (Type it)
1903 + protected override Method DoCreateMethodHost (EmitContext ec)
1905 - if (generic_method == null)
1906 - return new TypeExpression (it, Location);
1908 - if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
1909 - int pos = it.GenericParameterPosition;
1910 - it = CurrentTypeParameters [pos].Type;
1911 - } else if (it.IsGenericType) {
1912 - Type[] args = it.GetGenericArguments ();
1914 - TypeArguments inflated = new TypeArguments (Location);
1915 - foreach (Type t in args)
1916 - inflated.Add (InflateType (t));
1918 - return new ConstructedType (it, inflated, Location);
1919 - } else if (it.IsArray) {
1920 - TypeExpr et_expr = InflateType (it.GetElementType ());
1921 - int rank = it.GetArrayRank ();
1923 - Type et = et_expr.ResolveAsTypeTerminal (ec, false).Type;
1924 - it = et.MakeArrayType (rank);
1927 - return new TypeExpression (it, Location);
1928 + return new AnonymousMethodMethod (
1929 + this, null, TypeManager.system_boolean_expr,
1930 + Modifiers.PUBLIC, new MemberName ("MoveNext", Location),
1931 + Parameters.EmptyReadOnlyParameters);
1934 - Parameter InflateParameter (Parameter param)
1936 - TypeExpr te = InflateType (param.ParameterType);
1937 - return new Parameter (
1938 - te, param.Name, param.ModFlags, param.OptAttributes, param.Location);
1941 - Parameters InflateParameters (Parameters parameters, EmitContext ec)
1943 - int count = parameters.FixedParameters.Length;
1945 - return Parameters.EmptyReadOnlyParameters;
1946 - Parameter[] fixed_params = new Parameter [count];
1947 - for (int i = 0; i < count; i++)
1948 - fixed_params [i] = InflateParameter (parameters.FixedParameters [i]);
1950 - return new Parameters (fixed_params, parameters.HasArglist);
1953 - public override TypeExpr [] GetClassBases (out TypeExpr base_class)
1955 - iterator_type_expr = InflateType (original_iterator_type);
1957 - generic_args = new TypeArguments (Location);
1958 - generic_args.Add (iterator_type_expr);
1960 - ArrayList list = new ArrayList ();
1961 - if (is_enumerable) {
1962 - enumerable_type = new TypeExpression (
1963 - TypeManager.ienumerable_type, Location);
1964 - list.Add (enumerable_type);
1966 - generic_enumerable_type = new ConstructedType (
1967 - TypeManager.generic_ienumerable_type,
1968 - generic_args, Location);
1969 - list.Add (generic_enumerable_type);
1972 - enumerator_type = new TypeExpression (
1973 - TypeManager.ienumerator_type, Location);
1974 - list.Add (enumerator_type);
1976 - list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
1978 - generic_enumerator_type = new ConstructedType (
1979 - TypeManager.generic_ienumerator_type,
1980 - generic_args, Location);
1981 - list.Add (generic_enumerator_type);
1985 - return base.GetClassBases (out base_class);
1989 - // Returns the new block for the method, or null on failure
1991 - protected override bool DefineNestedTypes ()
1993 - if (CurrentType != null)
1994 - current_type = new TypeExpression (CurrentType, Location);
1996 - current_type = new TypeExpression (TypeBuilder, Location);
1999 - foreach (TypeParameter tparam in TypeParameters)
2000 - tparam.InflateConstraints (current_type.Type);
2003 - parameters = InflateParameters (original_parameters, ec);
2004 - if (!parameters.Resolve (ec)) {
2009 - Define_Current (false);
2010 - Define_Current (true);
2011 - Define_MoveNext ();
2013 - Define_Dispose ();
2015 - Define_Constructor ();
2019 - if (is_enumerable) {
2020 - Define_GetEnumerator (false);
2021 - Define_GetEnumerator (true);
2024 - return base.DefineNestedTypes ();
2028 - Field current_field;
2031 - void Create_Block ()
2033 - original_block.SetHaveAnonymousMethods (Location, move_next_method);
2034 - block.SetHaveAnonymousMethods (Location, move_next_method);
2036 - cc = original_block.CaptureContext;
2038 - int first = IsStatic ? 0 : 1;
2040 - ArrayList args = new ArrayList ();
2042 - Type t = this_type;
2043 - args.Add (new Argument (
2044 - new ThisParameterReference (t, Location)));
2045 - cc.CaptureThis (move_next_method);
2048 - args.Add (new Argument (new BoolLiteral (false, Location)));
2050 - for (int i = 0; i < parameters.Count; i++) {
2051 - Type t = original_parameters.ParameterType (i);
2052 - Type inflated = parameters.ParameterType (i);
2053 - string name = parameters.ParameterName (i);
2055 - args.Add (new Argument (
2056 - new SimpleParameterReference (t, first + i, Location)));
2058 - cc.AddParameterToContext (move_next_method, name, inflated, first + i);
2061 - TypeExpr proxy_type;
2062 - if (generic_method != null) {
2063 - TypeArguments new_args = new TypeArguments (Location);
2064 - if (Parent.IsGeneric) {
2065 - foreach (TypeParameter tparam in Parent.TypeParameters)
2066 - new_args.Add (new TypeParameterExpr (tparam, Location));
2068 - foreach (TypeParameter tparam in generic_method.TypeParameters)
2069 - new_args.Add (new TypeParameterExpr (tparam, Location));
2070 - ConstructedType ct = new ConstructedType (CurrentType, new_args, Location);
2071 - proxy_type = ct.ResolveAsTypeTerminal (ec, false);
2073 - proxy_type = current_type;
2075 - Expression new_expr = new New (proxy_type, args, Location);
2076 - block.AddStatement (new NoCheckReturn (new_expr, Location));
2079 - void Define_Fields ()
2081 - pc_field = new Field (
2082 - this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "$PC",
2084 - AddField (pc_field);
2086 - current_field = new Field (
2087 - this, iterator_type_expr, Modifiers.PRIVATE, "$current",
2089 - AddField (current_field);
2092 - void Define_Constructor ()
2094 - Parameters ctor_params;
2096 - ArrayList list = new ArrayList ();
2099 - list.Add (new Parameter (
2100 - new TypeExpression (this_type, Location),
2101 - "this", Parameter.Modifier.NONE,
2103 - list.Add (new Parameter (
2104 - TypeManager.bool_type, "initialized",
2105 - Parameter.Modifier.NONE, null, Location));
2107 - Parameter[] old_fixed = parameters.FixedParameters;
2108 - list.AddRange (old_fixed);
2110 - Parameter[] fixed_params = new Parameter [list.Count];
2111 - list.CopyTo (fixed_params);
2113 - ctor_params = new Parameters (fixed_params);
2115 - ctor = new Constructor (
2116 - this, MemberName.Name, Modifiers.PUBLIC, ctor_params,
2117 - new GeneratedBaseInitializer (Location),
2119 - AddConstructor (ctor);
2121 - ctor.Block = new ToplevelBlock (block, parameters, Location);
2123 - int first = IsStatic ? 2 : 3;
2125 - State initial = is_enumerable ? State.Uninitialized : State.Running;
2126 - ctor.Block.AddStatement (new SetState (this, initial, Location));
2128 - ctor.Block.AddStatement (new If (
2129 - new SimpleParameterReference (
2130 - TypeManager.bool_type, first - 1, Location),
2131 - new SetState (this, State.Running, Location),
2134 - ctor.Block.AddStatement (new InitScope (this, Location));
2137 - Statement Create_ThrowInvalidOperation ()
2139 - TypeExpr ex_type = new TypeExpression (
2140 - TypeManager.invalid_operation_exception_type, Location);
2142 - return new Throw (new New (ex_type, null, Location), Location);
2145 - Statement Create_ThrowNotSupported ()
2147 - TypeExpr ex_type = new TypeExpression (
2148 - TypeManager.not_supported_exception_type, Location);
2150 - return new Throw (new New (ex_type, null, Location), Location);
2153 - void Define_Current (bool is_generic)
2158 - left = new MemberName (
2159 - "System.Collections.Generic.IEnumerator",
2160 - generic_args, Location);
2161 - type = iterator_type_expr;
2163 - left = new MemberName ("System.Collections.IEnumerator", Location);
2164 - type = TypeManager.system_object_expr;
2167 - MemberName name = new MemberName (left, "Current", null, Location);
2169 - ToplevelBlock get_block = new ToplevelBlock (
2170 - block, parameters, Location);
2172 - get_block.AddStatement (new If (
2174 - Binary.Operator.LessThanOrEqual,
2175 - new FieldExpression (this, pc_field),
2176 - new IntLiteral ((int) State.Running, pc_field.Location)),
2177 - Create_ThrowInvalidOperation (),
2179 - new FieldExpression (this, current_field), Location),
2182 - Accessor getter = new Accessor (get_block, 0, null, Location);
2184 - Property current = new Property (
2185 - this, type, 0, false, name, null, getter, null);
2186 - AddProperty (current);
2189 - void Define_MoveNext ()
2191 - move_next_method = new MoveNextMethod (this, Location);
2193 - original_block.ReParent (block, move_next_method);
2195 - move_next_method.CreateMethod (ec);
2197 - AddMethod (move_next_method.method);
2200 - void Define_GetEnumerator (bool is_generic)
2205 - left = new MemberName (
2206 - "System.Collections.Generic.IEnumerable",
2207 - generic_args, Location);
2208 - type = generic_enumerator_type;
2210 - left = new MemberName ("System.Collections.IEnumerable", Location);
2211 - type = enumerator_type;
2214 - MemberName name = new MemberName (left, "GetEnumerator", Location);
2216 - Method get_enumerator = new Method (
2217 - this, null, type, 0, false, name,
2218 - Parameters.EmptyReadOnlyParameters, null);
2221 - // We call append instead of add, as we need to make sure that
2222 - // this method is resolved after the MoveNext method, as that one
2223 - // triggers the computation of the AnonymousMethod Scope, which is
2224 - // required during the code generation of the enumerator
2226 - AppendMethod (get_enumerator);
2228 - get_enumerator.Block = new ToplevelBlock (
2229 - block, parameters, Location);
2231 - get_enumerator.Block.SetHaveAnonymousMethods (Location, move_next_method);
2233 - Expression ce = new MemberAccess (
2234 - new SimpleName ("System.Threading.Interlocked", Location),
2235 - "CompareExchange");
2237 - Expression pc = new FieldExpression (this, pc_field);
2238 - Expression before = new IntLiteral ((int) State.Running, Location);
2239 - Expression uninitialized = new IntLiteral ((int) State.Uninitialized, Location);
2241 - ArrayList args = new ArrayList ();
2242 - args.Add (new Argument (pc, Argument.AType.Ref));
2243 - args.Add (new Argument (before, Argument.AType.Expression));
2244 - args.Add (new Argument (uninitialized, Argument.AType.Expression));
2246 - get_enumerator.Block.AddStatement (new If (
2248 - Binary.Operator.Equality,
2249 - new Invocation (ce, args),
2251 - new Return (new ThisParameterReference (type.Type, Location),
2255 - args = new ArrayList ();
2257 - args.Add (new Argument (new CapturedThisReference (this, Location)));
2260 - args.Add (new Argument (new BoolLiteral (true, Location)));
2262 - for (int i = 0; i < parameters.Count; i++) {
2263 - Expression cp = new CapturedParameterReference (
2264 - this, parameters.ParameterType (i),
2265 - parameters.ParameterName (i), Location);
2266 - args.Add (new Argument (cp));
2269 - Expression new_expr = new New (current_type, args, Location);
2270 - get_enumerator.Block.AddStatement (new Return (new_expr, Location));
2273 - protected class SimpleParameterReference : Expression
2277 - public SimpleParameterReference (Type type, int idx, Location loc)
2282 - eclass = ExprClass.Variable;
2285 - public override Expression DoResolve (EmitContext ec)
2290 - public override void Emit (EmitContext ec)
2295 - protected virtual void DoEmit (EmitContext ec)
2297 - ParameterReference.EmitLdArg (ec.ig, idx);
2301 - protected class ThisParameterReference : SimpleParameterReference, IMemoryLocation
2303 - public ThisParameterReference (Type type, Location loc)
2304 - : base (type, 0, loc)
2307 - protected override void DoEmit (EmitContext ec)
2310 - if (ec.TypeContainer is Struct)
2311 - ec.ig.Emit (OpCodes.Ldobj, type);
2314 - public void AddressOf (EmitContext ec, AddressOp mode)
2316 - if (ec.TypeContainer is Struct)
2317 - ec.ig.Emit (OpCodes.Ldarga, 0);
2319 - ec.ig.Emit (OpCodes.Ldarg, 0);
2323 - protected class CapturedParameterReference : Expression
2325 - Iterator iterator;
2328 - public CapturedParameterReference (Iterator iterator, Type type,
2329 - string name, Location loc)
2331 - this.iterator = iterator;
2335 - eclass = ExprClass.Variable;
2338 - public override Expression DoResolve (EmitContext ec)
2343 - public override void Emit (EmitContext ec)
2345 - ec.CurrentAnonymousMethod = iterator.move_next_method;
2347 - LocalTemporary dummy = null;
2349 - iterator.cc.EmitParameter (ec, name, false, false, ref dummy);
2353 - protected class CapturedThisReference : Expression
2355 - public CapturedThisReference (Iterator iterator, Location loc)
2358 - this.type = iterator.this_type;
2359 - eclass = ExprClass.Variable;
2362 - public override Expression DoResolve (EmitContext ec)
2367 - public override void Emit (EmitContext ec)
2369 - ec.EmitThis (false);
2373 - protected class FieldExpression : Expression
2375 - Iterator iterator;
2378 - public FieldExpression (Iterator iterator, Field field)
2380 - this.iterator = iterator;
2381 - this.field = field;
2382 - this.loc = iterator.Location;
2385 - public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
2387 - FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
2388 - fexpr.InstanceExpression = new ThisParameterReference (
2389 - iterator.this_type, loc);
2390 - return fexpr.ResolveLValue (ec, right_side, loc);
2393 - public override Expression DoResolve (EmitContext ec)
2395 - FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
2396 - fexpr.InstanceExpression = new ThisParameterReference (
2397 - iterator.this_type, loc);
2398 - return fexpr.Resolve (ec);
2401 - public override void Emit (EmitContext ec)
2403 - throw new InvalidOperationException ();
2407 - protected class MoveNextMethod : AnonymousContainer
2409 - Iterator iterator;
2411 - public MoveNextMethod (Iterator iterator, Location loc)
2412 - : base (iterator.parameters, iterator.original_block, loc)
2414 - this.iterator = iterator;
2417 - protected override bool CreateMethodHost (EmitContext ec)
2419 - method = new Method (
2420 - iterator, null, TypeManager.system_boolean_expr,
2421 - Modifiers.PUBLIC, false, new MemberName ("MoveNext", loc),
2422 - Parameters.EmptyReadOnlyParameters, null);
2424 - method.Block = Block;
2426 - MoveNextStatement inline = new MoveNextStatement (iterator, loc);
2427 - Block.AddStatement (inline);
2432 - public bool CreateMethod (EmitContext ec)
2434 - return CreateMethodHost (ec);
2437 - public override Iterator Iterator {
2438 - get { return iterator; }
2441 - public void ComputeHost ()
2443 - ComputeMethodHost ();
2446 - public override bool IsIterator {
2447 - get { return true; }
2450 - public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
2452 - scope.ScopeTypeBuilder = iterator.TypeBuilder;
2453 - scope.ScopeConstructor = iterator.ctor.ConstructorBuilder;
2456 - public override void Emit (EmitContext ec)
2458 - throw new InternalErrorException ();
2462 protected class MoveNextStatement : Statement {
2465 @@ -1062,147 +873,17 @@
2467 public override bool Resolve (EmitContext ec)
2470 + return iterator.OriginalBlock.Resolve (ec);
2473 protected override void DoEmit (EmitContext ec)
2475 - iterator.move_next_method.ComputeHost ();
2476 - ec.CurrentAnonymousMethod = iterator.move_next_method;
2477 - ec.InIterator = true;
2479 - iterator.EmitMoveNext (ec);
2480 + iterator.EmitMoveNext (ec, iterator.Block);
2484 - protected class DisposeMethod : Statement {
2485 - Iterator iterator;
2487 - public DisposeMethod (Iterator iterator, Location loc)
2490 - this.iterator = iterator;
2493 - public override bool Resolve (EmitContext ec)
2498 - protected override void DoEmit (EmitContext ec)
2500 - iterator.EmitDispose (ec);
2504 - protected class StatementList : Statement {
2505 - ArrayList statements;
2507 - public StatementList (Location loc)
2510 - statements = new ArrayList ();
2513 - public void Add (Statement statement)
2515 - statements.Add (statement);
2518 - public override bool Resolve (EmitContext ec)
2520 - foreach (Statement stmt in statements) {
2521 - if (!stmt.Resolve (ec))
2528 - protected override void DoEmit (EmitContext ec)
2530 - foreach (Statement stmt in statements)
2535 - protected class SetState : Statement
2537 - Iterator iterator;
2540 - public SetState (Iterator iterator, State state, Location loc)
2542 - this.iterator = iterator;
2543 - this.state = state;
2547 - public override bool Resolve (EmitContext ec)
2552 - protected override void DoEmit (EmitContext ec)
2554 - ec.ig.Emit (OpCodes.Ldarg_0);
2555 - IntConstant.EmitInt (ec.ig, (int) state);
2556 - ec.ig.Emit (OpCodes.Stfld, iterator.pc_field.FieldBuilder);
2560 - protected class InitScope : Statement
2562 - Iterator iterator;
2564 - public InitScope (Iterator iterator, Location loc)
2566 - this.iterator = iterator;
2570 - public override bool Resolve (EmitContext ec)
2575 - protected override void DoEmit (EmitContext ec)
2577 - iterator.cc.EmitInitScope (ec);
2581 - void Define_Reset ()
2583 - Method reset = new Method (
2584 - this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
2585 - false, new MemberName ("Reset", Location),
2586 - Parameters.EmptyReadOnlyParameters, null);
2587 - AddMethod (reset);
2589 - reset.Block = new ToplevelBlock (Location);
2590 - reset.Block = new ToplevelBlock (block, parameters, Location);
2591 - reset.Block.SetHaveAnonymousMethods (Location, move_next_method);
2593 - reset.Block.AddStatement (Create_ThrowNotSupported ());
2596 - void Define_Dispose ()
2598 - dispose = new Method (
2599 - this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
2600 - false, new MemberName ("Dispose", Location),
2601 - Parameters.EmptyReadOnlyParameters, null);
2602 - AddMethod (dispose);
2604 - dispose.Block = new ToplevelBlock (block, parameters, Location);
2605 - dispose.Block.SetHaveAnonymousMethods (Location, move_next_method);
2607 - dispose.Block.AddStatement (new DisposeMethod (this, Location));
2610 public Type IteratorType {
2611 - get { return iterator_type_expr.Type; }
2612 + get { return IteratorHost.IteratorType; }
2616 @@ -1212,10 +893,10 @@
2617 class NoCheckReturn : Statement {
2618 public Expression Expr;
2620 - public NoCheckReturn (Expression expr, Location l)
2621 + public NoCheckReturn (Expression expr)
2625 + loc = expr.Location;
2628 public override bool Resolve (EmitContext ec)
2629 @@ -1236,10 +917,49 @@
2634 + public static Iterator CreateIterator (IMethodData method, TypeContainer parent,
2635 + GenericMethod generic, int modifiers)
2637 - Type ret = orig_method.ReturnType;
2638 + bool is_enumerable;
2639 + Type iterator_type;
2641 + if (!CheckType (method.ReturnType, out iterator_type, out is_enumerable)) {
2642 + Report.Error (1624, method.Location,
2643 + "The body of `{0}' cannot be an iterator block " +
2644 + "because `{1}' is not an iterator interface type",
2645 + method.GetSignatureForError (),
2646 + TypeManager.CSharpName (method.ReturnType));
2650 + Report.Debug (64, "CREATE ITERATOR", parent, method, method.Block);
2652 + ToplevelBlock block = new ToplevelBlock (method.ParameterInfo, method.Location);
2654 + Iterator iterator = new Iterator (
2655 + method, parent, generic, null, block, modifiers,
2656 + iterator_type, is_enumerable);
2659 + if (!iterator.RootScope.Define ())
2661 + if (iterator.RootScope.DefineType () == null)
2663 + if (!iterator.RootScope.ResolveType ())
2667 + Report.Debug (64, "CREATE ITERATOR #1", iterator, iterator.RootScope,
2668 + iterator.RootScope.IsGeneric, iterator.RootScope.TypeBuilder);
2673 + static bool CheckType (Type ret, out Type original_iterator_type, out bool is_enumerable)
2675 + original_iterator_type = null;
2676 + is_enumerable = false;
2678 if (ret == TypeManager.ienumerable_type) {
2679 original_iterator_type = TypeManager.object_type;
2680 is_enumerable = true;
2681 Index: cs-parser.jay
2682 ===================================================================
2683 --- cs-parser.jay (revision 63019)
2684 +++ cs-parser.jay (working copy)
2686 TypeContainer current_container;
2687 TypeContainer current_class;
2689 - IIteratorContainer iterator_container;
2690 + IAnonymousHost anonymous_host;
2693 /// Current block is used to add statements as we find
2696 Delegate current_delegate;
2698 + GenericMethod current_generic_method;
2699 + AnonymousMethodExpression current_anonymous_method;
2702 /// This is used by the unary_expression code to resolve
2703 /// a name against a parameter.
2704 @@ -1064,7 +1067,7 @@
2708 - iterator_container = (IIteratorContainer) $1;
2709 + anonymous_host = (IAnonymousHost) $1;
2710 if (RootContext.Documentation != null)
2711 Lexer.doc_state = XmlCommentState.NotAllowed;
2713 @@ -1074,8 +1077,9 @@
2714 method.Block = (ToplevelBlock) $3;
2715 current_container.AddMethod (method);
2717 + anonymous_host = null;
2718 + current_generic_method = null;
2719 current_local_parameters = null;
2720 - iterator_container = null;
2722 if (RootContext.Documentation != null)
2723 Lexer.doc_state = XmlCommentState.Allowed;
2724 @@ -1132,7 +1136,9 @@
2725 method = new Method (current_class, generic, (Expression) $3, (int) $2, false,
2726 name, (Parameters) $6, (Attributes) $1);
2728 + anonymous_host = method;
2729 current_local_parameters = (Parameters) $6;
2730 + current_generic_method = generic;
2732 if (RootContext.Documentation != null)
2733 method.DocComment = Lexer.consume_doc_comment ();
2734 @@ -1168,7 +1174,9 @@
2735 method = new Method (current_class, generic, TypeManager.system_void_expr,
2736 (int) $2, false, name, (Parameters) $6, (Attributes) $1);
2738 + anonymous_host = method;
2739 current_local_parameters = (Parameters) $6;
2740 + current_generic_method = generic;
2742 if (RootContext.Documentation != null)
2743 method.DocComment = Lexer.consume_doc_comment ();
2744 @@ -1444,7 +1452,7 @@
2745 current_local_parameters = indexer_parameters;
2746 lexer.PropertyParsing = false;
2748 - iterator_container = SimpleIteratorContainer.GetSimple ();
2749 + anonymous_host = SimpleAnonymousHost.GetSimple ();
2753 @@ -1457,11 +1465,9 @@
2754 current_local_parameters = null;
2755 lexer.PropertyParsing = true;
2757 - if (SimpleIteratorContainer.Simple.Yields)
2758 - accessor.SetYields ();
2759 + SimpleAnonymousHost.Simple.Propagate (accessor);
2760 + anonymous_host = null;
2762 - iterator_container = null;
2764 if (RootContext.Documentation != null)
2765 if (Lexer.doc_state == XmlCommentState.Error)
2766 Lexer.doc_state = XmlCommentState.NotAllowed;
2767 @@ -1499,7 +1505,7 @@
2769 lexer.PropertyParsing = false;
2771 - iterator_container = SimpleIteratorContainer.GetSimple ();
2772 + anonymous_host = SimpleAnonymousHost.GetSimple ();
2776 @@ -1512,11 +1518,9 @@
2777 current_local_parameters = null;
2778 lexer.PropertyParsing = true;
2780 - if (SimpleIteratorContainer.Simple.Yields)
2781 - accessor.SetYields ();
2782 + SimpleAnonymousHost.Simple.Propagate (accessor);
2783 + anonymous_host = null;
2785 - iterator_container = null;
2787 if (RootContext.Documentation != null
2788 && Lexer.doc_state == XmlCommentState.Error)
2789 Lexer.doc_state = XmlCommentState.NotAllowed;
2790 @@ -1940,7 +1944,7 @@
2791 operator_declaration
2792 : opt_attributes opt_modifiers operator_declarator
2794 - iterator_container = SimpleIteratorContainer.GetSimple ();
2795 + anonymous_host = SimpleAnonymousHost.GetSimple ();
2799 @@ -1965,14 +1969,13 @@
2800 Lexer.doc_state = XmlCommentState.Allowed;
2803 - if (SimpleIteratorContainer.Simple.Yields)
2805 + SimpleAnonymousHost.Simple.Propagate (op);
2806 + anonymous_host = null;
2808 // Note again, checking is done in semantic analysis
2809 current_container.AddOperator (op);
2811 current_local_parameters = null;
2812 - iterator_container = null;
2816 @@ -2432,7 +2435,7 @@
2817 parsing_indexer = true;
2819 indexer_parameters = decl.param_list;
2820 - iterator_container = SimpleIteratorContainer.GetSimple ();
2821 + anonymous_host = SimpleAnonymousHost.GetSimple ();
2823 accessor_declarations
2825 @@ -3396,6 +3399,7 @@
2826 if (oob_stack == null)
2827 oob_stack = new Stack (6);
2829 + oob_stack.Push (current_anonymous_method);
2830 oob_stack.Push (current_local_parameters);
2831 current_local_parameters = (Parameters)$2;
2833 @@ -3403,7 +3407,12 @@
2834 oob_stack.Push (current_block);
2835 oob_stack.Push (top_current_block);
2836 current_block = null;
2839 + Location loc = (Location) $1;
2840 + current_anonymous_method = new AnonymousMethodExpression (
2841 + current_anonymous_method, current_generic_method, current_container,
2842 + (Parameters) $2, (ToplevelBlock) top_current_block, loc);
2846 Location loc = (Location) $1;
2847 @@ -3416,11 +3425,20 @@
2848 ToplevelBlock anon_block = (ToplevelBlock) $4;
2850 anon_block.Parent = current_block;
2851 - $$ = new AnonymousMethod (current_container, (Parameters) $2, (ToplevelBlock) top_current_block,
2854 + Report.Debug (64, "PARSER", anon_block, current_anonymous_method, anonymous_host,
2857 + current_anonymous_method.Block = anon_block;
2858 + if ((anonymous_host != null) && (current_anonymous_method.Parent == null))
2859 + anonymous_host.AddAnonymousMethod (current_anonymous_method);
2861 + $$ = current_anonymous_method;
2863 - current_local_parameters = (Parameters) oob_stack.Pop ();
2866 + current_local_parameters = (Parameters) oob_stack.Pop ();
2867 + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
2871 opt_anonymous_method_signature
2872 @@ -4000,7 +4018,8 @@
2875 if (current_block == null){
2876 - current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, (Location) $1);
2877 + current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters,
2878 + current_generic_method, (Location) $1);
2879 top_current_block = current_block;
2881 current_block = new Block (current_block, (Location) $1, Location.Null);
2882 @@ -4616,11 +4635,11 @@
2883 Report.FeatureIsNotStandardized (lt.Location, "yield statement");
2886 - if (iterator_container == null){
2887 + if (anonymous_host == null){
2888 Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
2891 - iterator_container.SetYields ();
2892 + anonymous_host.SetYields ();
2893 $$ = new Yield ((Expression) $3, lt.Location);
2896 @@ -4641,11 +4660,11 @@
2897 Report.FeatureIsNotStandardized (lt.Location, "yield statement");
2900 - if (iterator_container == null){
2901 + if (anonymous_host == null){
2902 Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
2905 - iterator_container.SetYields ();
2906 + anonymous_host.SetYields ();
2907 $$ = new YieldBreak (lt.Location);
2910 @@ -5006,22 +5025,41 @@
2914 -// We use this when we do not have an object in advance that is an IIteratorContainer
2915 +// We use this when we do not have an object in advance that is an IAnonymousHost
2917 -public class SimpleIteratorContainer : IIteratorContainer {
2918 - public bool Yields;
2919 +public class SimpleAnonymousHost : IAnonymousHost {
2920 + public static readonly SimpleAnonymousHost Simple = new SimpleAnonymousHost ();
2922 - public static SimpleIteratorContainer Simple = new SimpleIteratorContainer ();
2924 + ArrayList anonymous_methods;
2927 - // Reset and return
2929 - public static SimpleIteratorContainer GetSimple () {
2930 - Simple.Yields = false;
2931 + public static SimpleAnonymousHost GetSimple () {
2932 + Simple.yields = false;
2933 + Simple.anonymous_methods = null;
2937 - public void SetYields () { Yields = true; }
2938 + public void SetYields ()
2943 + public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
2945 + if (anonymous_methods == null)
2946 + anonymous_methods = new ArrayList ();
2947 + anonymous_methods.Add (anonymous);
2950 + public void Propagate (IAnonymousHost real_host)
2953 + real_host.SetYields ();
2954 + if (anonymous_methods != null) {
2955 + foreach (AnonymousMethodExpression ame in anonymous_methods)
2956 + real_host.AddAnonymousMethod (ame);
2963 ===================================================================
2964 --- convert.cs (revision 63019)
2965 +++ convert.cs (working copy)
2967 if (!TypeManager.IsDelegateType (target_type))
2970 - AnonymousMethod am = (AnonymousMethod) expr;
2971 - return am.ImplicitStandardConversionExists (target_type);
2972 + AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
2973 + return ame.ImplicitStandardConversionExists (target_type);
2977 @@ -1325,10 +1325,11 @@
2981 - AnonymousMethod am = (AnonymousMethod) expr;
2982 + AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
2984 int errors = Report.Errors;
2986 - Expression conv = am.Compatible (ec, target_type);
2987 + Expression conv = ame.Compatible (ec, target_type);
2992 ===================================================================
2993 --- anonymous.cs (revision 63019)
2994 +++ anonymous.cs (working copy)
2995 @@ -20,297 +20,742 @@
2997 namespace Mono.CSharp {
2999 - public abstract class AnonymousContainer : Expression
3000 + public abstract class CompilerGeneratedClass : Class
3002 - // Used to generate unique method names.
3003 - protected static int anonymous_method_count;
3005 - // An array list of AnonymousMethodParameter or null
3006 - public Parameters Parameters;
3009 - // The block that makes up the body for the anonymous mehtod
3011 - public ToplevelBlock Block;
3012 + GenericMethod generic_method;
3013 + static int next_index = 0;
3016 - // The container block for this anonymous method.
3018 - public Block ContainingBlock;
3019 + private static MemberName MakeProxyName (GenericMethod generic, Location loc)
3021 + string name = String.Format ("<>c__CompilerGenerated{0}", ++next_index);
3022 + if (generic != null) {
3023 + TypeArguments args = new TypeArguments (loc);
3024 + foreach (TypeParameter tparam in generic.CurrentTypeParameters)
3025 + args.Add (new SimpleName (tparam.Name, loc));
3026 + return new MemberName (name, args, loc);
3028 + return new MemberName (name, loc);
3032 - // The implicit method we create
3034 - public Method method;
3035 + protected string MakeName (string prefix)
3037 + return String.Format ("<>c__{0}{1}", prefix, ++next_index);
3040 - protected MethodInfo invoke_mb;
3042 - // The emit context for the anonymous method
3043 - public EmitContext aec;
3044 - public string[] TypeParameters;
3045 - public Type[] TypeArguments;
3046 - protected bool unreachable;
3047 + protected CompilerGeneratedClass (TypeContainer parent, GenericMethod generic,
3048 + int mod, Location loc)
3049 + : base (parent.NamespaceEntry, parent,
3050 + MakeProxyName (generic, loc), mod, null)
3052 + this.generic_method = generic;
3054 - // The method scope
3055 - ScopeInfo method_scope;
3056 - bool computed_method_scope = false;
3059 - // The modifiers applied to the method, we aggregate them
3061 - protected int method_modifiers = Modifiers.PRIVATE;
3064 - // Track the scopes that this method has used. At the
3065 - // end this is used to determine the ScopeInfo that will
3066 - // host the method
3068 - ArrayList scopes_used = new ArrayList ();
3071 - // Points to our container anonymous method if its present
3073 - public AnonymousContainer ContainerAnonymousMethod;
3074 + if (generic != null) {
3075 + ArrayList list = new ArrayList ();
3076 + foreach (TypeParameter tparam in generic.TypeParameters) {
3077 + if (tparam.Constraints != null)
3078 + list.Add (tparam.Constraints.Clone ());
3080 + SetParameterInfo (list);
3083 - protected AnonymousContainer (Parameters parameters, ToplevelBlock container,
3084 - ToplevelBlock block, Location l)
3085 + parent.AddCompilerGeneratedClass (this);
3088 + protected override bool DefineNestedTypes ()
3090 - Parameters = parameters;
3093 + RootContext.RegisterCompilerGeneratedType (TypeBuilder);
3094 + return base.DefineNestedTypes ();
3098 - // The order is important: this setups the CaptureContext tree hierarchy.
3100 - if (container == null) {
3102 + protected override bool DoDefineMembers ()
3104 + if (!PopulateType ())
3105 + throw new InternalErrorException ();
3107 + members_defined = true;
3109 + if (!base.DoDefineMembers ())
3112 + if (CompilerGenerated != null) {
3113 + foreach (CompilerGeneratedClass c in CompilerGenerated) {
3114 + if (!c.DefineMembers ())
3115 + throw new InternalErrorException ();
3118 - container.SetHaveAnonymousMethods (l, this);
3119 - block.SetHaveAnonymousMethods (l, this);
3124 - protected AnonymousContainer (Parameters parameters, ToplevelBlock container,
3126 - this (parameters, container, new ToplevelBlock (container, parameters, l), l)
3127 + protected override bool DoPopulateType ()
3129 + if (CompilerGenerated != null) {
3130 + foreach (CompilerGeneratedClass c in CompilerGenerated) {
3131 + if (!c.PopulateType ())
3139 - public override Expression DoResolve (EmitContext ec)
3140 + public GenericMethod GenericMethod {
3141 + get { return generic_method; }
3144 + protected TypeExpr InflateType (Type it)
3147 - // Set class type, set type
3149 + if (generic_method == null)
3150 + return new TypeExpression (it, Location);
3152 - eclass = ExprClass.Value;
3153 + if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
3154 + int pos = it.GenericParameterPosition;
3155 + it = CurrentTypeParameters [pos].Type;
3156 + } else if (it.IsGenericType) {
3157 + Type[] args = it.GetGenericArguments ();
3160 - // This hack means `The type is not accessible
3161 - // anywhere', we depend on special conversion
3164 - type = TypeManager.anonymous_method_type;
3165 + TypeArguments inflated = new TypeArguments (Location);
3166 + foreach (Type t in args)
3167 + inflated.Add (InflateType (t));
3170 + return new ConstructedType (it, inflated, Location);
3171 + } else if (it.IsArray) {
3172 + TypeExpr et_expr = InflateType (it.GetElementType ());
3173 + int rank = it.GetArrayRank ();
3175 + Type et = et_expr.ResolveAsTypeTerminal (this, false).Type;
3176 + it = et.MakeArrayType (rank);
3179 + return new TypeExpression (it, Location);
3182 - public void RegisterScope (ScopeInfo scope)
3183 + public Field CaptureVariable (string name, Type type)
3185 - if (scopes_used.Contains (scope))
3187 - scopes_used.Add (scope);
3188 + if (members_defined)
3189 + throw new InternalErrorException ("Helper class already defined!");
3191 + throw new ArgumentNullException ();
3193 + return new CapturedVariable (this, name, InflateType (type));
3196 - // Returns the deepest of two scopes
3197 - ScopeInfo Deepest (ScopeInfo a, ScopeInfo b)
3198 + bool members_defined;
3200 + internal void CheckMembersDefined ()
3203 + if (members_defined)
3204 + throw new InternalErrorException ("Helper class already defined!");
3213 + public override void EmitType ()
3215 + Report.Debug (64, "COMPILER GENERATED EMIT TYPE", this, CompilerGenerated);
3220 - // If they Scopes are on the same CaptureContext, we do the double
3221 - // checks just so if there is an invariant change in the future,
3222 - // we get the exception at the end
3224 - for (p = a; p != null; p = p.ParentScope)
3228 - for (p = b; p != null; p = p.ParentScope)
3231 + protected class CapturedVariable : Field
3233 + public CapturedVariable (CompilerGeneratedClass helper, string name,
3235 + : base (helper, type, Modifiers.INTERNAL, name, null, helper.Location)
3237 + helper.AddField (this);
3242 - CaptureContext ca = a.CaptureContext;
3243 - CaptureContext cb = b.CaptureContext;
3244 + public abstract class ScopeInfoBase : CompilerGeneratedClass
3246 + public Block ScopeBlock;
3248 - for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext)
3251 + protected ScopeInfoBase (TypeContainer parent, GenericMethod generic,
3252 + int mod, Location loc)
3253 + : base (parent, generic, mod, loc)
3256 - for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext)
3259 - throw new Exception ("Should never be reached");
3260 + TypeExpr scope_type;
3261 + protected Field scope_instance;
3262 + protected ScopeInitializerBase scope_initializer;
3264 + public abstract AnonymousMethodHost Host {
3269 - // Determines the proper host for a method considering the
3270 - // scopes it references
3272 - public void ComputeMethodHost ()
3273 + public Field ScopeInstance {
3274 + get { return scope_instance; }
3277 + public Type ScopeType {
3278 + get { return scope_type.Type; }
3281 + public void EmitScopeInstance (EmitContext ec)
3283 - if (computed_method_scope)
3286 - method_scope = null;
3287 - int top = scopes_used.Count;
3288 - computed_method_scope = true;
3289 + if (scope_initializer == null) {
3291 + // This is needed if someone overwrites the Emit method
3292 + // of Statement and manually calls Block.Emit without
3293 + // this snippet first:
3295 + // ec.EmitScopeInitFromBlock (The_Block);
3296 + // The_Block.Emit (ec);
3298 + throw new InternalErrorException ();
3302 + scope_initializer.Emit (ec);
3305 + public ExpressionStatement GetScopeInitializer (EmitContext ec)
3307 + Report.Debug (64, "GET SCOPE INITIALIZER",
3308 + this, GetType (), scope_initializer, ScopeBlock);
3310 + if (scope_initializer == null) {
3311 + scope_initializer = CreateScopeInitializer ();
3312 + if (scope_initializer.Resolve (ec) == null)
3313 + throw new InternalErrorException ();
3316 + return scope_initializer;
3319 + protected abstract ScopeInitializerBase CreateScopeInitializer ();
3321 + protected override bool DoPopulateType ()
3323 + Report.Debug (64, "SCOPE INFO RESOLVE TYPE", this, GetType (), IsGeneric,
3324 + Parent.IsGeneric, GenericMethod);
3327 + TypeArguments targs = new TypeArguments (Location);
3328 + if (Parent.IsGeneric)
3329 + foreach (TypeParameter t in Parent.TypeParameters)
3330 + targs.Add (new TypeParameterExpr (t, Location));
3331 + if (GenericMethod != null)
3332 + foreach (TypeParameter t in GenericMethod.TypeParameters)
3333 + targs.Add (new TypeParameterExpr (t, Location));
3335 + scope_type = new ConstructedType (TypeBuilder, targs, Location);
3336 + scope_type = scope_type.ResolveAsTypeTerminal (this, false);
3337 + if ((scope_type == null) || (scope_type.Type == null))
3340 + scope_type = new TypeExpression (TypeBuilder, Location);
3344 + scope_instance = Host.CaptureScope (this);
3346 + return base.DoPopulateType ();
3349 + protected abstract class ScopeInitializerBase : ExpressionStatement
3351 + ScopeInfoBase scope;
3352 + LocalBuilder scope_instance;
3353 + ConstructorInfo scope_ctor;
3357 + protected ScopeInitializerBase (ScopeInfoBase scope)
3359 + this.scope = scope;
3360 + this.loc = scope.Location;
3361 + eclass = ExprClass.Value;
3364 + public ScopeInfoBase Scope {
3365 + get { return scope; }
3368 + public override Expression DoResolve (EmitContext ec)
3370 + if (scope_ctor != null)
3373 + Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
3374 + ec, ec.CurrentBlock);
3376 + type = Scope.ScopeType;
3378 + if (!DoResolveInternal (ec))
3379 + throw new InternalErrorException ();
3384 + protected virtual bool DoResolveInternal (EmitContext ec)
3386 + MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookupFinal (
3387 + ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
3388 + AllBindingFlags | BindingFlags.DeclaredOnly, loc);
3390 + throw new InternalErrorException ();
3392 + scope_ctor = (ConstructorInfo) mg.Methods [0];
3394 + if (Scope.ScopeInstance == null)
3395 + scope_instance = ec.ig.DeclareLocal (type);
3400 + static int next_id;
3401 + int id = ++next_id;
3403 + protected virtual void DoEmit (EmitContext ec)
3405 + if (ec.CurrentBlock.Toplevel == Scope.ScopeBlock.Toplevel)
3406 + DoEmitInstance (ec);
3408 + ec.ig.Emit (OpCodes.Ldarg_0);
3411 + protected void DoEmitInstance (EmitContext ec)
3413 + ec.ig.Emit (OpCodes.Ldloc, scope_instance);
3416 + protected virtual void EmitScopeConstructor (EmitContext ec)
3418 + ec.ig.Emit (OpCodes.Newobj, scope_ctor);
3421 + public override void Emit (EmitContext ec)
3424 + throw new InternalErrorException (
3425 + "Scope {0} not initialized yet", scope);
3430 + public override void EmitStatement (EmitContext ec)
3435 + DoEmitStatement (ec);
3436 + initialized = true;
3439 + protected virtual void DoEmitStatement (EmitContext ec)
3441 + Report.Debug (64, "EMIT SCOPE INIT", this, id,
3442 + Scope, scope_instance, ec);
3444 + ec.ig.Emit (OpCodes.Nop);
3445 + ec.ig.Emit (OpCodes.Ldc_I4, id);
3446 + ec.ig.Emit (OpCodes.Pop);
3447 + ec.ig.Emit (OpCodes.Nop);
3449 + if (Scope != Scope.Host)
3450 + Scope.Host.EmitScopeInstance (ec);
3451 + else if (Scope.ScopeInstance != null)
3452 + ec.ig.Emit (OpCodes.Ldarg_0);
3453 + EmitScopeConstructor (ec);
3454 + if (Scope.ScopeInstance != null)
3455 + ec.ig.Emit (OpCodes.Stfld, Scope.ScopeInstance.FieldBuilder);
3457 + ec.ig.Emit (OpCodes.Stloc, scope_instance);
3462 + public class AnonymousMethodHost : ScopeInfo
3464 + public AnonymousMethodHost (ToplevelBlock toplevel, TypeContainer parent,
3465 + GenericMethod generic, Location loc)
3466 + : base (toplevel, parent, generic, loc)
3468 + scopes = new ArrayList ();
3472 + TypeExpr parent_type;
3473 + CapturedVariable parent_link;
3474 + CapturedVariable this_field;
3475 + Hashtable captured_params;
3477 + public override AnonymousMethodHost Host {
3478 + get { return this; }
3481 + public AnonymousMethodHost ParentHost {
3482 + get { return Parent as AnonymousMethodHost; }
3485 + public Type ParentType {
3486 + get { return parent_type.Type; }
3489 + public Field ParentLink {
3490 + get { return parent_link; }
3493 + public Field THIS {
3494 + get { return this_field; }
3497 + public bool HostsParameters {
3498 + get { return captured_params != null; }
3501 + public Field CaptureThis ()
3503 + if (ParentHost != null)
3504 + return ParentHost.CaptureThis ();
3506 + CheckMembersDefined ();
3507 + if (this_field == null)
3508 + this_field = new CapturedVariable (this, "<>THIS", parent_type);
3509 + return this_field;
3512 + public Field CaptureScope (ScopeInfoBase scope)
3514 + return CaptureVariable (MakeName ("scope"), scope.ScopeType);
3517 + public Variable GetCapturedParameter (Parameter par)
3519 + if (captured_params != null)
3520 + return (Variable) captured_params [par];
3525 + public bool IsParameterCaptured (string name)
3527 + if (captured_params != null)
3528 + return captured_params [name] != null;
3532 + public Variable AddParameter (Parameter par, int idx)
3534 + if (captured_params == null)
3535 + captured_params = new Hashtable ();
3537 + Variable var = (Variable) captured_params [par];
3538 + if (var == null) {
3539 + var = new CapturedParameter (this, par, idx);
3540 + captured_params.Add (par, var);
3541 + par.IsCaptured = true;
3547 + public void AddScope (ScopeInfo scope)
3549 + scopes.Add (scope);
3553 + public void LinkScopes ()
3558 - method_scope = (ScopeInfo) scopes_used [0];
3562 - for (int i = 1; i < top; i++)
3563 - method_scope = Deepest (method_scope, (ScopeInfo) scopes_used [i]);
3566 + if (ParentHost != null)
3567 + ParentHost.LinkScopes ();
3569 + foreach (ScopeInfo si in scopes) {
3570 + if (!si.Define ())
3571 + throw new InternalErrorException ();
3572 + if (si.DefineType () == null)
3573 + throw new InternalErrorException ();
3577 - public ScopeInfo Scope {
3579 - if (computed_method_scope)
3580 - return method_scope;
3581 + protected override ScopeInitializerBase CreateScopeInitializer ()
3583 + return new AnonymousMethodHostInitializer (this);
3586 + protected override bool DefineNestedTypes ()
3588 + Report.Debug (64, "ANONYMOUS METHOD HOST NESTED",
3589 + this, Name, Parent, Parent.Name, Parent.IsGeneric);
3591 + if (Parent.IsGeneric) {
3592 + parent_type = new ConstructedType (
3593 + Parent.TypeBuilder, Parent.TypeParameters, Location);
3594 + parent_type = parent_type.ResolveAsTypeTerminal (this, false);
3595 + if ((parent_type == null) || (parent_type.Type == null))
3598 + parent_type = new TypeExpression (Parent.TypeBuilder, Location);
3601 + CompilerGeneratedClass parent = Parent as CompilerGeneratedClass;
3602 + if (parent != null)
3603 + parent_link = new CapturedVariable (this, "<>parent", parent_type);
3605 + return base.DefineNestedTypes ();
3608 + protected override bool DoDefineMembers ()
3610 + Report.Debug (64, "ANONYMOUS METHOD HOST DEFINE MEMBERS",
3611 + this, Name, Parent, CompilerGenerated);
3613 + ArrayList args = new ArrayList ();
3614 + if (this is IteratorHost)
3615 + args.Add (new Parameter (
3616 + TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
3619 + Field pfield = Parent is CompilerGeneratedClass ? parent_link : this_field;
3620 + if (pfield != null)
3621 + args.Add (new Parameter (
3622 + pfield.MemberType, "parent", Parameter.Modifier.NONE,
3625 + if (HostsParameters) {
3626 + foreach (CapturedParameter cp in captured_params.Values) {
3627 + args.Add (new Parameter (
3628 + cp.Field.MemberType, cp.Field.Name,
3629 + Parameter.Modifier.NONE, null, Location));
3633 + Parameter[] ctor_params = new Parameter [args.Count];
3634 + args.CopyTo (ctor_params, 0);
3635 + Constructor ctor = new Constructor (
3636 + this, MemberName.Name, Modifiers.PUBLIC,
3637 + new Parameters (ctor_params),
3638 + new GeneratedBaseInitializer (Location),
3640 + AddConstructor (ctor);
3642 + ctor.Block = new ToplevelBlock (null, Location);
3643 + ctor.Block.AddStatement (new TheCtor (this));
3645 + return base.DoDefineMembers ();
3648 + protected virtual void EmitScopeConstructor (EmitContext ec)
3650 + int pos = (this is IteratorHost) ? 2 : 1;
3651 + Field pfield = Parent is CompilerGeneratedClass ? parent_link : this_field;
3652 + if (pfield != null) {
3653 + ec.ig.Emit (OpCodes.Ldarg_0);
3654 + ec.ig.Emit (OpCodes.Ldarg, pos);
3655 + ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
3659 + if (HostsParameters) {
3660 + foreach (CapturedParameter cp in captured_params.Values) {
3661 + ec.ig.Emit (OpCodes.Ldarg_0);
3662 + ParameterReference.EmitLdArg (ec.ig, pos++);
3663 + ec.ig.Emit (OpCodes.Stfld, cp.Field.FieldBuilder);
3668 + protected class TheCtor : Statement
3670 + AnonymousMethodHost host;
3672 + public TheCtor (AnonymousMethodHost host)
3677 + public override bool Resolve (EmitContext ec)
3682 + protected override void DoEmit (EmitContext ec)
3684 + host.EmitScopeConstructor (ec);
3688 + protected class AnonymousMethodHostInitializer : ScopeInitializer
3690 + AnonymousMethodHost host;
3692 + public AnonymousMethodHostInitializer (AnonymousMethodHost host)
3698 + public AnonymousMethodHost Host {
3699 + get { return host; }
3702 + protected override bool DoResolveInternal (EmitContext ec)
3704 + Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
3705 + this, Host, Host.ScopeType, Host.ParentType, loc);
3708 - // This means that ComputeMethodHost is not being called, most
3709 - // likely by someone who overwrote the CreateMethodHost method
3710 + // Copy the parameter values, if any
3712 - throw new Exception ("Internal error, AnonymousContainer.Scope is being used before its container is computed");
3713 + if (Host.HostsParameters) {
3714 + foreach (CapturedParameter cp in Host.captured_params.Values) {
3715 + FieldExpr fe = (FieldExpr) Expression.MemberLookup (
3716 + ec.ContainerType, type, cp.Field.Name, loc);
3718 + throw new InternalErrorException ();
3720 + fe.InstanceExpression = this;
3721 + cp.FieldInstance = fe;
3725 + return base.DoResolveInternal (ec);
3728 + protected override void EmitScopeConstructor (EmitContext ec)
3730 + if ((host.THIS != null) || (host.ParentLink != null))
3731 + ec.ig.Emit (OpCodes.Ldarg_0);
3733 + if (Host.HostsParameters) {
3734 + foreach (CapturedParameter cp in Host.captured_params.Values) {
3735 + EmitParameterReference (ec, cp);
3739 + base.EmitScopeConstructor (ec);
3744 - protected abstract bool CreateMethodHost (EmitContext ec);
3746 - public abstract void CreateScopeType (EmitContext ec, ScopeInfo scope);
3749 - public abstract Iterator Iterator {
3750 + public interface IAnonymousContainer
3752 + ToplevelBlock Container {
3756 - public abstract bool IsIterator {
3757 + GenericMethod GenericMethod {
3761 + AnonymousMethodHost RootScope {
3770 - public class AnonymousMethod : AnonymousContainer
3771 + public interface IAnonymousHost
3773 - TypeContainer host;
3775 + // Invoked if a yield statement is found in the body
3777 + void SetYields ();
3780 - // The value return by the Compatible call, this ensure that
3781 - // the code works even if invoked more than once (Resolve called
3782 - // more than once, due to the way Convert.ImplicitConversion works
3783 + // Invoked if an anonymous method is found in the body
3785 - Expression anonymous_delegate;
3786 + void AddAnonymousMethod (AnonymousMethodExpression anonymous);
3789 - public AnonymousMethod (TypeContainer host, Parameters parameters, ToplevelBlock container,
3790 - ToplevelBlock block, Location l)
3791 - : base (parameters, container, block, l)
3794 + public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
3796 + public readonly AnonymousMethodExpression Parent;
3797 + public readonly TypeContainer Host;
3798 + public readonly Parameters Parameters;
3800 + public ToplevelBlock Block;
3801 + protected AnonymousMethod anonymous;
3803 + protected readonly ToplevelBlock container;
3804 + protected readonly GenericMethod generic;
3806 + public ToplevelBlock Container {
3807 + get { return container; }
3810 - public override Iterator Iterator {
3811 - get { return null; }
3812 + public GenericMethod GenericMethod {
3813 + get { return generic; }
3816 - public override bool IsIterator {
3817 - get { return false; }
3818 + public AnonymousMethod AnonymousMethod {
3819 + get { return anonymous; }
3822 - public override void Emit (EmitContext ec)
3824 - // nothing, as we only exist to not do anything.
3825 + public AnonymousMethodHost RootScope {
3826 + get { return root_scope; }
3830 - // Creates the host for the anonymous method
3832 - protected override bool CreateMethodHost (EmitContext ec)
3833 + public AnonymousMethodExpression (AnonymousMethodExpression parent,
3834 + GenericMethod generic, TypeContainer host,
3835 + Parameters parameters, ToplevelBlock container,
3838 - ComputeMethodHost ();
3839 + this.Parent = parent;
3840 + this.generic = parent != null ? null : generic;
3842 + this.Parameters = parameters;
3843 + this.container = container;
3847 - // Crude hack follows: we replace the TypeBuilder during the
3848 - // definition to get the method hosted in the right class
3850 - TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
3851 - TypeBuilder type_host = (Scope == null ) ? current_type : Scope.ScopeTypeBuilder;
3852 + Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
3855 - if (current_type == null)
3856 - throw new Exception ("The current_type is null");
3858 - if (type_host == null)
3859 - throw new Exception (String.Format ("Type host is null, method_host is {0}", Scope == null ? "null" : "Not null"));
3860 + if (parent != null)
3861 + parent.AddAnonymousMethod (this);
3864 - if (current_type != type_host)
3865 - method_modifiers = Modifiers.INTERNAL;
3866 + ArrayList children;
3867 + AnonymousMethodHost root_scope;
3869 - if (current_type == type_host && ec.IsStatic){
3870 - method_modifiers |= Modifiers.STATIC;
3871 - current_type = null;
3873 + void IAnonymousHost.SetYields ()
3875 + throw new InvalidOperationException ();
3878 - string name = "<#AnonymousMethod>" + anonymous_method_count++;
3879 - MemberName member_name;
3880 + public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
3882 + if (children == null)
3883 + children = new ArrayList ();
3884 + children.Add (anonymous);
3887 - GenericMethod generic_method = null;
3888 - if (TypeParameters != null) {
3889 - TypeArguments args = new TypeArguments (loc);
3890 - foreach (string t in TypeParameters)
3891 - args.Add (new SimpleName (t, loc));
3892 + public bool CreateAnonymousHelpers ()
3894 + Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
3895 + this, Host, container, loc);
3897 - member_name = new MemberName (name, args, loc);
3898 + if (container != null)
3899 + root_scope = container.CreateAnonymousMethodHost (Host);
3901 - generic_method = new GenericMethod (
3902 - ec.DeclContainer.NamespaceEntry,
3903 - (TypeContainer) ec.TypeContainer, member_name,
3904 - new TypeExpression (invoke_mb.ReturnType, loc),
3906 + if (children != null) {
3907 + foreach (AnonymousMethodExpression child in children) {
3908 + if (!child.CreateAnonymousHelpers ())
3913 - generic_method.SetParameterInfo (null);
3915 - member_name = new MemberName (name, loc);
3919 - method = new Method (
3920 - (TypeContainer) ec.TypeContainer, generic_method,
3921 - new TypeExpression (invoke_mb.ReturnType, loc),
3922 - method_modifiers, false, member_name, Parameters, null);
3923 - method.Block = Block;
3926 - // Swap the TypeBuilder while we define the method, then restore
3928 - if (current_type != null)
3929 - ec.TypeContainer.TypeBuilder = type_host;
3930 - bool res = method.Define ();
3931 - if (current_type != null)
3932 - ec.TypeContainer.TypeBuilder = current_type;
3935 + public override string ExprClassName {
3937 + return "anonymous method";
3941 void Error_ParameterMismatch (Type t)
3943 Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
3944 - "{0}' since there is a parameter mismatch", TypeManager.CSharpName (t));
3945 + "{0}' since there is a parameter mismatch",
3946 + TypeManager.CSharpName (t));
3949 public bool ImplicitStandardConversionExists (Type delegate_type)
3951 if (Parameters == null)
3954 - MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (host.TypeBuilder, delegate_type, loc);
3955 - invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3956 + MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
3957 + Host.TypeBuilder, delegate_type, loc);
3958 + MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3959 ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
3961 if (Parameters.Count != invoke_pd.Count)
3962 @@ -338,31 +784,20 @@
3964 public Expression Compatible (EmitContext ec, Type delegate_type)
3966 - if (anonymous_delegate != null)
3967 - return anonymous_delegate;
3969 + if (anonymous != null)
3970 + return anonymous.AnonymousDelegate;
3973 // At this point its the first time we know the return type that is
3974 // needed for the anonymous method. We create the method here.
3977 - MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (ec.ContainerType, delegate_type, loc);
3978 - invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3979 + MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
3980 + ec.ContainerType, delegate_type, loc);
3981 + MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3982 ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
3984 - if (delegate_type.IsGenericType) {
3985 - Type def = delegate_type.GetGenericTypeDefinition ();
3987 - if (def != delegate_type) {
3988 - Type[] tparam = TypeManager.GetTypeArguments (def);
3990 - TypeArguments = TypeManager.GetTypeArguments (delegate_type);
3991 - TypeParameters = new string [tparam.Length];
3992 - for (int i = 0; i < tparam.Length; i++)
3993 - TypeParameters [i] = tparam [i].Name;
3997 + Parameters parameters;
3998 if (Parameters == null) {
4000 // We provide a set of inaccessible parameters
4002 "+" + i, invoke_pd.ParameterModifier (i), null, loc);
4005 - Parameters = new Parameters (fixedpars);
4006 + parameters = new Parameters (fixedpars);
4007 + if (!parameters.Resolve (ec))
4010 if (Parameters.Count != invoke_pd.Count) {
4011 Report.SymbolRelatedToPreviousError (delegate_type);
4012 @@ -407,8 +844,10 @@
4017 + parameters = Parameters;
4022 // Second: the return type of the delegate must be compatible with
4023 // the anonymous type. Instead of doing a pass to examine the block
4024 @@ -419,135 +858,309 @@
4025 //MethodBuilder builder = method_data.MethodBuilder;
4026 //ILGenerator ig = builder.GetILGenerator ();
4028 - aec = new EmitContext (ec.ResolveContext,
4029 - ec.TypeContainer, ec.DeclContainer, loc, null,
4030 - invoke_mb.ReturnType,
4031 - /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
4032 - (ec.InUnsafe ? Modifiers.UNSAFE : 0) |
4033 - (ec.IsStatic ? Modifiers.STATIC : 0),
4034 - /* No constructor */ false);
4035 + Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
4036 + Container, Block, invoke_mb.ReturnType, delegate_type,
4037 + delegate_type.IsGenericType, loc);
4039 - aec.CurrentAnonymousMethod = this;
4040 - ContainerAnonymousMethod = ec.CurrentAnonymousMethod;
4041 - ContainingBlock = ec.CurrentBlock;
4042 + anonymous = new AnonymousMethod (
4043 + Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
4044 + GenericMethod, parameters, Container, Block, invoke_mb.ReturnType,
4045 + delegate_type, loc);
4047 - if (aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable)){
4048 - anonymous_delegate = new AnonymousDelegate (
4049 - this, delegate_type, loc).Resolve (ec);
4050 - return anonymous_delegate;
4053 + if (!anonymous.Resolve (ec))
4056 + return anonymous.AnonymousDelegate;
4059 public override Expression DoResolve (EmitContext ec)
4061 - if (!ec.IsAnonymousMethodAllowed) {
4062 - Report.Error (1706, loc, "Anonymous methods are not allowed in the attribute declaration");
4066 + // Set class type, set type
4069 - if (Parameters != null && !Parameters.Resolve (ec)) {
4070 + eclass = ExprClass.Value;
4073 + // This hack means `The type is not accessible
4074 + // anywhere', we depend on special conversion
4077 + type = TypeManager.anonymous_method_type;
4079 + if ((Parameters != null) && !Parameters.Resolve (ec))
4083 - return base.DoResolve (ec);
4087 + public override void Emit (EmitContext ec)
4089 + // nothing, as we only exist to not do anything.
4092 - public override string ExprClassName {
4094 - return "anonymous method";
4096 + public bool IsIterator {
4097 + get { return false; }
4101 - public MethodInfo GetMethodBuilder ()
4102 + public abstract class AnonymousContainer : IAnonymousContainer
4104 + // Used to generate unique method names.
4105 + protected static int anonymous_method_count;
4107 + public readonly Location Location;
4109 + // An array list of AnonymousMethodParameter or null
4110 + public readonly Parameters Parameters;
4113 + // The block that makes up the body for the anonymous mehtod
4115 + public readonly ToplevelBlock Block;
4117 + public readonly Type ReturnType;
4118 + public readonly TypeContainer Host;
4121 + // The implicit method we create
4123 + protected Method method;
4124 + protected EmitContext aec;
4126 + // The emit context for the anonymous method
4127 + protected bool unreachable;
4128 + protected readonly Location loc;
4129 + protected readonly ToplevelBlock container;
4130 + protected readonly GenericMethod generic;
4133 + // Points to our container anonymous method if its present
4135 + public readonly AnonymousContainer ContainerAnonymousMethod;
4137 + protected AnonymousContainer (AnonymousContainer parent, TypeContainer host,
4138 + GenericMethod generic, Parameters parameters,
4139 + ToplevelBlock container, ToplevelBlock block,
4140 + Type return_type, int mod, Location loc)
4142 - MethodInfo builder = method.MethodBuilder;
4143 - if (TypeArguments != null)
4144 - return builder.MakeGenericMethod (TypeArguments);
4147 + this.ContainerAnonymousMethod = parent;
4148 + this.ReturnType = return_type;
4151 + this.container = container;
4152 + this.generic = parent != null ? null : generic;
4153 + this.Parameters = parameters;
4154 + this.Block = block;
4158 - public override string GetSignatureForError ()
4159 + public Method Method {
4160 + get { return method; }
4163 + public abstract AnonymousMethodHost RootScope {
4167 + public string GetSignatureForError ()
4169 - string s = TypeManager.CSharpSignature (invoke_mb);
4170 - return s.Substring (0, s.IndexOf (".Invoke("));
4171 + return RootScope.GetSignatureForError ();
4174 - public bool EmitMethod (EmitContext ec)
4176 + public virtual bool Resolve (EmitContext ec)
4178 - if (!CreateMethodHost (ec))
4179 + if (!ec.IsAnonymousMethodAllowed) {
4180 + Report.Error (1706, loc,
4181 + "Anonymous methods are not allowed in the " +
4182 + "attribute declaration");
4186 - MethodBuilder builder = method.MethodBuilder;
4187 - ILGenerator ig = builder.GetILGenerator ();
4189 + Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, loc, ec,
4190 + RootScope, Parameters, ec.IsStatic);
4192 - Parameters.ApplyAttributes (builder);
4193 + aec = new EmitContext (
4194 + ec.ResolveContext, ec.TypeContainer,
4195 + RootScope != null ? RootScope : Host, loc, null, ReturnType,
4196 + /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
4197 + (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
4200 - // Adjust based on the computed state of the
4201 - // method from CreateMethodHost
4203 - aec.MethodIsStatic = (method_modifiers & Modifiers.STATIC) != 0;
4205 - aec.EmitMeta (Block);
4206 - aec.EmitResolvedTopBlock (Block, unreachable);
4208 + aec.CurrentAnonymousMethod = this;
4210 + Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, loc, ec, aec,
4211 + RootScope, Parameters, Block);
4214 + if (!aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable))
4217 + Report.Debug (64, "RESOLVE ANONYMOUS METHOD #3", this, ec, aec, Block);
4219 + method = DoCreateMethodHost (ec);
4221 + if (RootScope == null)
4222 + return method.Define ();
4227 - public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
4229 - TypeBuilder container = ec.TypeContainer.TypeBuilder;
4230 - string name = String.Format ("<>AnonHelp<{0}>", scope.id);
4231 + protected abstract Method DoCreateMethodHost (EmitContext ec);
4233 - scope.ScopeTypeBuilder = container.DefineNestedType (name,
4234 - TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit | TypeAttributes.NestedPrivate,
4235 - TypeManager.object_type);
4236 + public ToplevelBlock Container {
4237 + get { return container; }
4240 - Type [] constructor_types = Type.EmptyTypes;
4241 - ConstructorBuilder ctor = scope.ScopeTypeBuilder.DefineConstructor (
4242 - MethodAttributes.Public | MethodAttributes.HideBySig |
4243 - MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
4244 - CallingConventions.HasThis, constructor_types);
4245 - TypeManager.RegisterMethod (ctor, Parameters.EmptyReadOnlyParameters);
4246 + public GenericMethod GenericMethod {
4247 + get { return generic; }
4250 - ILGenerator cig = ctor.GetILGenerator ();
4251 - cig.Emit (OpCodes.Ldarg_0);
4252 - cig.Emit (OpCodes.Call, TypeManager.object_ctor);
4253 - cig.Emit (OpCodes.Ret);
4254 + public abstract bool IsIterator {
4258 - if (ec.TypeContainer.IsGeneric) {
4259 - TypeParameter[] tparam = ec.TypeContainer.TypeParameters;
4260 - string[] names = new string [tparam.Length];
4261 - Type[] types = new Type [tparam.Length];
4263 + public override string ToString ()
4265 + return String.Format ("{0} ({1})", GetType (), Name);
4269 - for (int i = 0; i < names.Length; i++) {
4270 - names [i] = tparam [i].Name;
4271 - types [i] = tparam [i].Type;
4272 + protected class AnonymousMethodMethod : Method
4274 + public AnonymousContainer AnonymousMethod;
4276 + public AnonymousMethodMethod (AnonymousContainer am, GenericMethod generic,
4277 + TypeExpr return_type, int mod, MemberName name,
4278 + Parameters parameters)
4279 + : base (am.RootScope != null ? am.RootScope : am.Host,
4280 + generic, return_type, mod, false, name, parameters, null)
4282 + this.AnonymousMethod = am;
4284 + if (am.RootScope != null) {
4285 + am.RootScope.CheckMembersDefined ();
4286 + am.RootScope.AddMethod (this);
4288 + ModFlags |= Modifiers.STATIC;
4289 + am.Host.AddMethod (this);
4294 - scope.ScopeTypeBuilder.DefineGenericParameters (names);
4295 - scope.ScopeTypeBuilder.GetGenericTypeDefinition ();
4296 + public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
4298 + EmitContext aec = AnonymousMethod.aec;
4305 - scope.ScopeType = scope.ScopeTypeBuilder.MakeGenericType (types);
4306 + public class AnonymousMethod : AnonymousContainer
4308 + public readonly Type DelegateType;
4311 + // The value return by the Compatible call, this ensure that
4312 + // the code works even if invoked more than once (Resolve called
4313 + // more than once, due to the way Convert.ImplicitConversion works
4315 + Expression anonymous_delegate;
4316 + AnonymousMethodHost root_scope;
4318 + public AnonymousMethod (AnonymousMethod parent, AnonymousMethodHost root_scope,
4319 + TypeContainer host, GenericMethod generic,
4320 + Parameters parameters, ToplevelBlock container,
4321 + ToplevelBlock block, Type return_type, Type delegate_type,
4323 + : base (parent, host, generic, parameters, container, block,
4324 + return_type, 0, loc)
4326 + this.DelegateType = delegate_type;
4327 + this.root_scope = root_scope;
4330 + public override AnonymousMethodHost RootScope {
4331 + get { return root_scope; }
4334 + public override bool IsIterator {
4335 + get { return false; }
4338 + public Expression AnonymousDelegate {
4339 + get { return anonymous_delegate; }
4343 + // Creates the host for the anonymous method
4345 + protected override Method DoCreateMethodHost (EmitContext ec)
4347 + string name = "<>c__AnonymousMethod" + anonymous_method_count++;
4348 + MemberName member_name;
4350 + GenericMethod generic_method = null;
4351 + if (DelegateType.IsGenericType) {
4352 + TypeArguments args = new TypeArguments (loc);
4354 + Type[] tparam = TypeManager.GetTypeArguments (DelegateType);
4355 + for (int i = 0; i < tparam.Length; i++)
4356 + args.Add (new SimpleName (tparam [i].Name, loc));
4358 + member_name = new MemberName (name, args, loc);
4360 + generic_method = new GenericMethod (
4361 + RootScope.NamespaceEntry, RootScope, member_name,
4362 + new TypeExpression (ReturnType, loc), Parameters);
4364 + generic_method.SetParameterInfo (null);
4366 - scope.ScopeType = scope.ScopeTypeBuilder;
4367 + member_name = new MemberName (name, loc);
4369 + return new AnonymousMethodMethod (
4370 + this, generic_method, new TypeExpression (ReturnType, loc),
4371 + Modifiers.INTERNAL, member_name, Parameters);
4374 - if (ec.TypeContainer.IsGeneric)
4375 - scope.ScopeConstructor = TypeBuilder.GetConstructor (
4376 - scope.ScopeType, ctor);
4378 - scope.ScopeConstructor = ctor;
4379 + public override bool Resolve (EmitContext ec)
4381 + if (!base.Resolve (ec))
4384 + anonymous_delegate = new AnonymousDelegate (this, DelegateType, loc).Resolve (ec);
4385 + if (anonymous_delegate == null)
4391 + public MethodInfo GetMethodBuilder (EmitContext ec)
4393 + MethodInfo builder = method.MethodBuilder;
4394 + if ((RootScope != null) && RootScope.IsGeneric) {
4395 + MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
4396 + ec.ContainerType, RootScope.ScopeType, builder.Name, loc);
4399 + throw new InternalErrorException ();
4400 + builder = (MethodInfo) mg.Methods [0];
4403 + if (!DelegateType.IsGenericType)
4406 + Type[] targs = TypeManager.GetTypeArguments (DelegateType);
4407 + return builder.MakeGenericMethod (targs);
4410 public static void Error_AddressOfCapturedVar (string name, Location loc)
4412 Report.Error (1686, loc,
4413 - "Local variable `{0}' or its members cannot have their address taken and be used inside an anonymous method block",
4415 + "Local variable `{0}' or its members cannot have their " +
4416 + "address taken and be used inside an anonymous method block",
4421 @@ -573,138 +1186,84 @@
4423 public override void Emit (EmitContext ec)
4425 - if (!am.EmitMethod (ec))
4427 + Report.Debug (64, "ANONYMOUS DELEGATE", this, am, ec.ContainerType, type,
4431 // Now emit the delegate creation.
4433 - if ((am.method.ModFlags & Modifiers.STATIC) == 0)
4434 - delegate_instance_expression = new AnonymousInstance (am);
4436 + if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
4437 + delegate_instance_expression = am.RootScope.GetScopeInitializer (ec);
4439 + if (delegate_instance_expression == null)
4440 + throw new InternalErrorException ();
4443 Expression ml = Expression.MemberLookup (ec.ContainerType, type, ".ctor", loc);
4444 constructor_method = ((MethodGroupExpr) ml).Methods [0];
4445 - delegate_method = am.GetMethodBuilder ();
4446 + delegate_method = am.GetMethodBuilder (ec);
4447 + Report.Debug (64, "ANONYMOUS DELEGATE #1", constructor_method, delegate_method,
4448 + delegate_method, delegate_instance_expression);
4452 - class AnonymousInstance : Expression {
4453 - AnonymousMethod am;
4455 - public AnonymousInstance (AnonymousMethod am)
4458 - eclass = ExprClass.Value;
4461 - public override Expression DoResolve (EmitContext ec)
4466 - public override void Emit (EmitContext ec)
4468 - am.aec.EmitMethodHostInstance (ec, am);
4473 - class CapturedParameter {
4475 - public FieldBuilder FieldBuilder;
4478 - public CapturedParameter (Type type, int idx)
4486 // Here we cluster all the variables captured on a given scope, we also
4487 // keep some extra information that might be required on each scope.
4489 - public class ScopeInfo {
4490 - public CaptureContext CaptureContext;
4491 - public ScopeInfo ParentScope;
4492 - public Block ScopeBlock;
4493 - public bool NeedThis = false;
4494 - public bool HostsParameters = false;
4496 + public class ScopeInfo : ScopeInfoBase {
4497 + public readonly AnonymousMethodHost RootScope;
4499 // For tracking the number of scopes created.
4502 - bool inited = false;
4504 - ArrayList locals = new ArrayList ();
4505 - ArrayList children = new ArrayList ();
4506 + Hashtable locals = new Hashtable ();
4509 - // The types and fields generated
4511 - public TypeBuilder ScopeTypeBuilder;
4512 - public Type ScopeType;
4513 - public ConstructorInfo ScopeConstructor;
4514 - public FieldBuilder THIS;
4515 - public FieldBuilder ParentLink;
4518 - // Points to the object of type `ScopeTypeBuilder' that
4519 - // holds the data for the scope
4521 - LocalBuilder scope_instance;
4523 - public ScopeInfo (CaptureContext cc, Block b)
4524 + public ScopeInfo (AnonymousMethodHost root, Block block)
4525 + : base (root, null, Modifiers.PUBLIC, block.StartLocation)
4527 - CaptureContext = cc;
4529 + this.RootScope = root;
4530 + ScopeBlock = block;
4533 - cc.RegisterCaptureContext ();
4534 + Report.Debug (64, "NEW SCOPE", this);
4536 + root.AddScope (this);
4539 - public void AddLocal (LocalInfo li)
4540 + public ScopeInfo (ToplevelBlock toplevel, TypeContainer parent,
4541 + GenericMethod generic, Location loc)
4542 + : base (parent, generic, 0, loc)
4544 - if (locals.Contains (li))
4546 + RootScope = (AnonymousMethodHost) this;
4547 + ScopeBlock = toplevel;
4553 - public bool IsCaptured (LocalInfo li)
4555 - return locals.Contains (li);
4556 + Report.Debug (64, "NEW ROOT SCOPE", this);
4559 - internal void AddChild (ScopeInfo si)
4561 - if (children.Contains (si))
4565 - // If any of the current children should be a children of `si', move them there
4567 - ArrayList move_queue = null;
4568 - foreach (ScopeInfo child in children){
4569 - if (child.ScopeBlock.IsChildOf (si.ScopeBlock)){
4570 - if (move_queue == null)
4571 - move_queue = new ArrayList ();
4572 - move_queue.Add (child);
4573 - child.ParentScope = si;
4574 - si.AddChild (child);
4578 - children.Add (si);
4579 + public override AnonymousMethodHost Host {
4580 + get { return RootScope; }
4583 - if (move_queue != null){
4584 - foreach (ScopeInfo child in move_queue){
4585 - children.Remove (child);
4587 + public Variable AddLocal (LocalInfo local)
4589 + Variable var = (Variable) locals [local];
4590 + if (var == null) {
4591 + var = new CapturedLocal (this, local);
4592 + locals.Add (local, var);
4593 + local.IsCaptured = true;
4599 + public Variable GetCapturedVariable (LocalInfo local)
4601 + return (Variable) locals [local];
4604 static int indent = 0;
4607 @@ -719,204 +1278,28 @@
4609 Console.WriteLine ("START");
4612 - Console.WriteLine ("NeedThis=" + NeedThis);
4613 - foreach (LocalInfo li in locals){
4614 + foreach (LocalInfo li in locals.Values){
4616 Console.WriteLine ("var {0}", MakeFieldName (li.Name));
4619 - foreach (ScopeInfo si in children)
4623 Console.WriteLine ("END");
4626 - private string MakeFieldName (string local_name)
4627 + protected string MakeFieldName (string local_name)
4629 return "<" + id + ":" + local_name + ">";
4632 - public void EmitScopeType (EmitContext ec)
4633 + protected override ScopeInitializerBase CreateScopeInitializer ()
4637 - if (ScopeTypeBuilder != null)
4641 - if (ec.TypeContainer.CurrentType != null)
4642 - container = ec.TypeContainer.CurrentType;
4644 - container = ec.TypeContainer.TypeBuilder;
4646 - CaptureContext.Host.CreateScopeType (ec, this);
4649 - THIS = ScopeTypeBuilder.DefineField ("<>THIS", container, FieldAttributes.Assembly);
4651 - if (ParentScope != null){
4652 - if (ParentScope.ScopeTypeBuilder == null){
4653 - throw new Exception (String.Format ("My parent has not been initialized {0} and {1}", ParentScope, this));
4656 - if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder)
4657 - ParentLink = ScopeTypeBuilder.DefineField (
4658 - "<>parent", ParentScope.ScopeType, FieldAttributes.Assembly);
4661 - if (NeedThis && ParentScope != null)
4662 - throw new Exception ("I was not expecting THIS && having a parent");
4664 - foreach (LocalInfo info in locals)
4665 - info.FieldBuilder = ScopeTypeBuilder.DefineField (
4666 - MakeFieldName (info.Name), info.VariableType, FieldAttributes.Assembly);
4668 - if (HostsParameters){
4669 - Hashtable captured_parameters = CaptureContext.captured_parameters;
4671 - foreach (DictionaryEntry de in captured_parameters){
4672 - string name = (string) de.Key;
4673 - CapturedParameter cp = (CapturedParameter) de.Value;
4676 - fb = ScopeTypeBuilder.DefineField ("<p:" + name + ">", cp.Type, FieldAttributes.Assembly);
4677 - cp.FieldBuilder = fb;
4681 - foreach (ScopeInfo si in children){
4682 - si.EmitScopeType (ec);
4684 + return new ScopeInitializer (this);
4687 - public void CloseTypes ()
4689 - RootContext.RegisterCompilerGeneratedType (ScopeTypeBuilder);
4690 - foreach (ScopeInfo si in children)
4695 - // Emits the initialization code for the scope
4697 - public void EmitInitScope (EmitContext ec)
4699 - ILGenerator ig = ec.ig;
4704 - if (ScopeConstructor == null)
4705 - throw new Exception ("ScopeConstructor is null for" + this.ToString ());
4707 - if (!CaptureContext.Host.IsIterator) {
4708 - scope_instance = ig.DeclareLocal (ScopeType);
4709 - ig.Emit (OpCodes.Newobj, ScopeConstructor);
4710 - ig.Emit (OpCodes.Stloc, scope_instance);
4713 - if (THIS != null){
4714 - if (CaptureContext.Host.IsIterator) {
4715 - ig.Emit (OpCodes.Ldarg_0);
4716 - ig.Emit (OpCodes.Ldarg_1);
4718 - ig.Emit (OpCodes.Ldloc, scope_instance);
4719 - ig.Emit (OpCodes.Ldarg_0);
4721 - ig.Emit (OpCodes.Stfld, THIS);
4725 - // Copy the parameter values, if any
4727 - int extra = ec.IsStatic ? 0 : 1;
4728 - if (CaptureContext.Host.IsIterator)
4730 - if (HostsParameters){
4731 - Hashtable captured_parameters = CaptureContext.captured_parameters;
4733 - foreach (DictionaryEntry de in captured_parameters){
4734 - CapturedParameter cp = (CapturedParameter) de.Value;
4736 - EmitScopeInstance (ig);
4737 - ParameterReference.EmitLdArg (ig, cp.Idx + extra);
4738 - ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
4742 - if (ParentScope != null){
4743 - if (!ParentScope.inited)
4744 - ParentScope.EmitInitScope (ec);
4746 - if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder) {
4748 - // Only emit initialization in our capturecontext world
4750 - if (ParentScope.CaptureContext == CaptureContext){
4751 - EmitScopeInstance (ig);
4752 - ParentScope.EmitScopeInstance (ig);
4753 - ig.Emit (OpCodes.Stfld, ParentLink);
4755 - EmitScopeInstance (ig);
4756 - ig.Emit (OpCodes.Ldarg_0);
4757 - ig.Emit (OpCodes.Stfld, ParentLink);
4764 - public void EmitScopeInstance (ILGenerator ig)
4766 - if (CaptureContext.Host.IsIterator)
4767 - ig.Emit (OpCodes.Ldarg_0);
4769 - if (scope_instance == null){
4771 - // This is needed if someone overwrites the Emit method
4772 - // of Statement and manually calls Block.Emit without
4773 - // this snippet first:
4775 - // ec.EmitScopeInitFromBlock (The_Block);
4776 - // The_Block.Emit (ec);
4779 - Console.WriteLine (
4780 - "The scope_instance has not been emitted, this typically means\n" +
4781 - "that inside the compiler someone is calling Block.Emit without\n" +
4782 - "first calling EmitScopeInitFromBlock for the block. See compiler" +
4783 - "source code for an explanation");
4784 - throw new Exception ("Internal compiler error");
4787 - ig.Emit (OpCodes.Ldloc, scope_instance);
4791 - public static void CheckCycles (string msg, ScopeInfo s)
4793 - ArrayList l = new ArrayList ();
4796 - for (ScopeInfo p = s; p != null; p = p.ParentScope,n++){
4797 - if (l.Contains (p)){
4798 - Console.WriteLine ("Loop detected {0} in {1}", n, msg);
4799 - throw new Exception ();
4805 static void DoPath (StringBuilder sb, ScopeInfo start)
4807 - CheckCycles ("print", start);
4809 - if (start.ParentScope != null){
4810 - DoPath (sb, start.ParentScope);
4813 sb.Append ((start.id).ToString ());
4816 @@ -925,614 +1308,146 @@
4817 StringBuilder sb = new StringBuilder ();
4820 - if (CaptureContext != null){
4821 - sb.Append (CaptureContext.ToString ());
4828 return sb.ToString ();
4833 - // CaptureContext objects are created on demand if a method has
4834 - // anonymous methods and kept on the ToplevelBlock.
4836 - // If they exist, all ToplevelBlocks in the containing block are
4837 - // linked together (children pointing to their parents).
4839 - public class CaptureContext {
4840 - public static int count;
4842 - public Location loc;
4845 - // Points to the toplevel block that owns this CaptureContext
4847 - ToplevelBlock toplevel_owner;
4850 - // All the scopes we capture
4852 - Hashtable scopes = new Hashtable ();
4855 - // All the root scopes
4857 - ArrayList roots = new ArrayList ();
4859 - bool have_captured_vars = false;
4860 - bool referenced_this = false;
4863 - // Captured fields
4865 - Hashtable captured_fields = new Hashtable ();
4866 - Hashtable captured_variables = new Hashtable ();
4867 - public Hashtable captured_parameters = new Hashtable ();
4868 - public AnonymousContainer Host;
4870 - public CaptureContext (ToplevelBlock toplevel_owner, Location loc,
4871 - AnonymousContainer host)
4872 + protected abstract class CapturedLocalOrParameter : Variable
4875 - this.toplevel_owner = toplevel_owner;
4877 + public readonly ScopeInfo Scope;
4878 + public readonly Field Field;
4883 + public FieldExpr FieldInstance;
4885 - void DoPath (StringBuilder sb, CaptureContext cc)
4887 - if (cc.ParentCaptureContext != null){
4888 - DoPath (sb, cc.ParentCaptureContext);
4890 + protected CapturedLocalOrParameter (ScopeInfo scope, string name, Type type)
4892 + this.Scope = scope;
4893 + this.Field = scope.CaptureVariable (
4894 + scope.MakeFieldName (name), type);
4896 - sb.Append (cc.cc_id.ToString ());
4899 - public void ReParent (ToplevelBlock new_toplevel, AnonymousContainer new_host)
4901 - toplevel_owner = new_toplevel;
4904 - for (CaptureContext cc = ParentCaptureContext; cc != null;
4905 - cc = cc.ParentCaptureContext) {
4906 - cc.Host = new_host;
4907 + public override Type Type {
4908 + get { return Field.MemberType; }
4912 - public override string ToString ()
4914 - StringBuilder sb = new StringBuilder ();
4916 - DoPath (sb, this);
4918 - return sb.ToString ();
4921 - public ToplevelBlock ParentToplevel {
4923 - return toplevel_owner.Container;
4924 + public override bool HasInstance {
4925 + get { return true; }
4929 - public CaptureContext ParentCaptureContext {
4931 - ToplevelBlock parent = ParentToplevel;
4933 - return (parent == null) ? null : parent.CaptureContext;
4934 + public override bool NeedsTemporary {
4935 + get { return true; }
4939 - ScopeInfo GetScopeForBlock (Block block)
4941 - ScopeInfo si = (ScopeInfo) scopes [block.ID];
4944 - si = new ScopeInfo (this, block);
4945 - scopes [block.ID] = si;
4949 - public void AddLocal (AnonymousContainer am, LocalInfo li)
4951 - if (li.Block.Toplevel != toplevel_owner){
4952 - ParentCaptureContext.AddLocal (am, li);
4954 + protected FieldInfo GetField (EmitContext ec)
4956 + if (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)
4957 + return Field.FieldBuilder;
4959 + return FieldInstance.FieldInfo;
4961 - ScopeInfo scope = GetScopeForBlock (li.Block);
4964 - // Adjust the owner
4967 - Host.RegisterScope (scope);
4970 - // Adjust the user
4972 - am.RegisterScope (scope);
4974 - if (captured_variables [li] != null)
4977 - have_captured_vars = true;
4978 - captured_variables [li] = li;
4979 - scope.AddLocal (li);
4983 - // Retursn the CaptureContext for the block that defines the parameter `name'
4985 - static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
4987 - ToplevelBlock container = current.Container;
4988 - if (container != null){
4989 - CaptureContext cc = _ContextForParameter (container, name);
4992 + public override void EmitInstance (EmitContext ec)
4994 + ec.CurrentBlock.Toplevel.EmitScopeInstance (ec, Scope);
4996 - if (current.IsParameterReference (name))
4997 - return current.ToplevelBlockCaptureContext;
5001 - static CaptureContext ContextForParameter (ToplevelBlock current, string name)
5003 - CaptureContext cc = _ContextForParameter (current, name);
5005 - throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
5010 - // Records the captured parameter at the appropriate CaptureContext
5012 - public void AddParameter (EmitContext ec, AnonymousContainer am,
5013 - string name, Type t, int idx)
5015 - CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5017 - cc.AddParameterToContext (am, name, t, idx);
5021 - // Records the parameters in the context
5023 - public void AddParameterToContext (AnonymousContainer am, string name, Type t, int idx)
5025 - if (captured_parameters == null)
5026 - captured_parameters = new Hashtable ();
5027 - if (captured_parameters [name] == null)
5028 - captured_parameters [name] = new CapturedParameter (t, idx);
5030 - ScopeInfo scope = GetScopeForBlock (toplevel_owner);
5031 - scope.HostsParameters = true;
5032 - am.RegisterScope (scope);
5036 - // Captured fields are only recorded on the topmost CaptureContext, because that
5037 - // one is the one linked to the owner of instance fields
5039 - public void AddField (EmitContext ec, AnonymousContainer am, FieldExpr fe)
5041 - if (fe.FieldInfo.IsStatic)
5042 - throw new Exception ("Attempt to register a static field as a captured field");
5043 - CaptureContext parent = ParentCaptureContext;
5044 - if (parent != null) {
5045 - parent.AddField (ec, am, fe);
5047 + public override void Emit (EmitContext ec)
5049 + ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
5052 - ScopeInfo scope = GetScopeForBlock (toplevel_owner);
5053 - am.RegisterScope (scope);
5056 - public void CaptureThis (AnonymousContainer am)
5059 - throw new Exception ("Internal Compiler error: Capturethis called with a null method");
5060 - CaptureContext parent = ParentCaptureContext;
5061 - if (parent != null) {
5062 - parent.CaptureThis (am);
5064 + public override void EmitAssign (EmitContext ec)
5066 + ec.ig.Emit (OpCodes.Stfld, GetField (ec));
5068 - referenced_this = true;
5070 - ScopeInfo scope = GetScopeForBlock (toplevel_owner);
5071 - am.RegisterScope (scope);
5074 - public bool HaveCapturedVariables {
5076 - return have_captured_vars;
5077 + public override void EmitAddressOf (EmitContext ec)
5079 + ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
5083 - public bool HaveCapturedFields {
5085 - CaptureContext parent = ParentCaptureContext;
5086 - if (parent != null)
5087 - return parent.HaveCapturedFields;
5088 - return captured_fields.Count > 0;
5092 - public bool IsCaptured (LocalInfo local)
5094 - foreach (ScopeInfo si in scopes.Values){
5095 - if (si.IsCaptured (local))
5100 + protected class CapturedParameter : CapturedLocalOrParameter {
5101 + public readonly Parameter Parameter;
5102 + public readonly int Idx;
5105 - // Returns whether the parameter is captured
5107 - public bool IsParameterCaptured (string name)
5109 - if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
5112 - if (captured_parameters != null)
5113 - return captured_parameters [name] != null;
5117 - public void EmitAnonymousHelperClasses (EmitContext ec)
5119 - if (roots.Count != 0){
5120 - foreach (ScopeInfo root in roots){
5122 - // FIXME: We really should do this in a per-ScopeInfo
5123 - // basis, instead of having the NeedThis applied to
5124 - // all of the roots.
5126 - root.NeedThis = HaveCapturedFields || referenced_this;
5128 - root.EmitScopeType (ec);
5133 - public void CloseAnonymousHelperClasses ()
5135 - if (roots.Count != 0)
5136 - foreach (ScopeInfo root in roots)
5137 - root.CloseTypes ();
5140 - public void EmitInitScope (EmitContext ec)
5142 - EmitAnonymousHelperClasses (ec);
5143 - if (roots.Count != 0)
5144 - foreach (ScopeInfo root in roots)
5145 - root.EmitInitScope (ec); }
5148 - // This is called externally when we start emitting code for a block
5149 - // if the block has a ScopeInfo associated, emit the init code
5151 - public void EmitScopeInitFromBlock (EmitContext ec, Block b)
5153 - ScopeInfo si = (ScopeInfo) scopes [b.ID];
5157 - si.EmitInitScope (ec);
5161 - // Emits the opcodes necessary to load the instance of the captured
5162 - // variable in `li'
5164 - public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li,
5165 - AnonymousContainer am)
5167 - ILGenerator ig = ec.ig;
5170 - if (li.Block.Toplevel == toplevel_owner){
5171 - si = (ScopeInfo) scopes [li.Block.ID];
5172 - si.EmitScopeInstance (ig);
5174 + public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
5175 + : base (scope, par.Name, par.ParameterType)
5177 + this.Parameter = par;
5182 - ig.Emit (OpCodes.Ldarg_0);
5184 - if (am.IsIterator && (si.ScopeBlock.Toplevel == li.Block.Toplevel)) {
5188 - while (si.ScopeBlock.ID != li.Block.ID){
5189 - if (si.ParentLink != null)
5190 - ig.Emit (OpCodes.Ldfld, si.ParentLink);
5191 - si = si.ParentScope;
5194 - Console.WriteLine ("Target: {0} {1}", li.Block.ID, li.Name);
5195 - while (si.ScopeBlock.ID != li.Block.ID){
5196 - Console.WriteLine ("Trying: {0}", si.ScopeBlock.ID);
5197 - si = si.ParentScope;
5200 - throw new Exception (
5201 - String.Format ("Never found block {0} starting at {1} while looking up {2}",
5202 - li.Block.ID, am.Scope.ScopeBlock.ID, li.Name));
5205 + public override string ToString ()
5207 + return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
5208 + Parameter.Name, Idx);
5213 - // Internal routine that loads the instance to reach parameter `name'
5215 - void EmitParameterInstance (EmitContext ec, string name)
5217 - CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5219 - cc.EmitParameterInstance (ec, name);
5222 + protected class CapturedLocal : CapturedLocalOrParameter {
5223 + public readonly LocalInfo Local;
5225 - CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5226 - if (par_info != null){
5228 - // FIXME: implementing this.
5230 + public CapturedLocal (ScopeInfo scope, LocalInfo local)
5231 + : base (scope, local.Name, local.VariableType)
5233 + this.Local = local;
5235 - ILGenerator ig = ec.ig;
5239 - if (ec.CurrentBlock.Toplevel == toplevel_owner) {
5240 - si = (ScopeInfo) scopes [toplevel_owner.ID];
5241 - si.EmitScopeInstance (ig);
5243 - si = ec.CurrentAnonymousMethod.Scope;
5244 - ig.Emit (OpCodes.Ldarg_0);
5245 + public override string ToString ()
5247 + return String.Format ("{0} ({1}:{2})", GetType (), Field,
5252 - while (si.ParentLink != null) {
5253 - ig.Emit (OpCodes.Ldfld, si.ParentLink);
5254 - si = si.ParentScope;
5260 - // Emits the code necessary to load the parameter named `name' within
5261 - // an anonymous method.
5263 - public void EmitParameter (EmitContext ec, string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
5264 + protected class ScopeInitializer : ScopeInitializerBase
5266 - CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5268 - cc.EmitParameter (ec, name, leave_copy, prepared, ref temp);
5272 - EmitParameterInstance (ec, name);
5273 - CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5274 - if (par_info != null){
5276 - // FIXME: implementing this.
5279 - ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
5283 - ec.ig.Emit (OpCodes.Dup);
5284 - temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
5286 + public ScopeInitializer (ScopeInfo scope)
5289 + this.scope = scope;
5294 - // Implements the assignment of `source' to the paramenter named `name' within
5295 - // an anonymous method.
5297 - public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
5299 - CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5301 - cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load, ref temp);
5303 + new public ScopeInfo Scope {
5304 + get { return scope; }
5306 - ILGenerator ig = ec.ig;
5307 - CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5309 - EmitParameterInstance (ec, name);
5310 - if (prepare_for_load)
5311 - ig.Emit (OpCodes.Dup);
5314 - ig.Emit (OpCodes.Dup);
5315 - temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
5318 - ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
5322 + protected override bool DoResolveInternal (EmitContext ec)
5324 + Report.Debug (64, "RESOLVE SCOPE INITIALIZER", this, Scope,
5325 + Scope.ScopeType, ec,
5326 + ec.TypeContainer.Name, ec.DeclContainer,
5327 + ec.DeclContainer.Name, ec.DeclContainer.IsGeneric);
5330 - // Emits the address for the parameter named `name' within
5331 - // an anonymous method.
5333 - public void EmitAddressOfParameter (EmitContext ec, string name)
5335 - CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5337 - cc.EmitAddressOfParameter (ec, name);
5340 - EmitParameterInstance (ec, name);
5341 - CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5342 - ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder);
5344 + foreach (CapturedLocal local in Scope.locals.Values) {
5345 + FieldExpr fe = (FieldExpr) Expression.MemberLookup (
5346 + ec.ContainerType, type, local.Field.Name, loc);
5347 + Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
5348 + Scope, ec, ec.ContainerType, type,
5349 + local.Field, local.Field.Name, loc, fe);
5351 + throw new InternalErrorException ();
5354 - // The following methods are only invoked on the host for the
5355 - // anonymous method.
5357 - public void EmitMethodHostInstance (EmitContext target, AnonymousContainer am)
5359 - ILGenerator ig = target.ig;
5360 - ScopeInfo si = am.Scope;
5362 - AnonymousContainer container = am.ContainerAnonymousMethod;
5364 - if ((si == null) || ((container != null) && (si == container.Scope))) {
5365 - ig.Emit (OpCodes.Ldarg_0);
5369 - si.EmitInitScope (target);
5370 - si.EmitScopeInstance (ig);
5373 - public void RegisterCaptureContext ()
5375 - toplevel_owner.RegisterCaptureContext (this);
5379 - // Returs true if `probe' is an ancestor of `scope' in the
5382 - bool IsAncestor (ScopeInfo probe, ScopeInfo scope)
5384 - for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
5385 - if (probe.ScopeBlock == b)
5392 - // Returns an ArrayList of ScopeInfos that enumerates all the ancestors
5393 - // of `scope' found in `scope_list'.
5395 - // The value returned is either a ScopeInfo or an Arraylist of ScopeInfos
5397 - object GetAncestorScopes (ScopeInfo scope, ScopeInfo [] scope_list)
5399 - object ancestors = null;
5401 - for (int i = 0; i < scope_list.Length; i++){
5402 - // Ignore the same scope
5403 - if (scope_list [i] == scope)
5406 - if (IsAncestor (scope_list [i], scope)){
5407 - if (ancestors == null){
5408 - ancestors = scope_list [i];
5412 - if (ancestors is ScopeInfo){
5413 - object old = ancestors;
5414 - ancestors = new ArrayList (4);
5415 - ((ArrayList)ancestors).Add (old);
5418 - ((ArrayList)ancestors).Add (scope_list [i]);
5419 + fe.InstanceExpression = this;
5420 + local.FieldInstance = fe;
5427 - // Returns the immediate parent of `scope' from all the captured
5428 - // scopes found in `scope_list', or null if this is a toplevel scope.
5430 - ScopeInfo GetParentScope (ScopeInfo scope, ScopeInfo [] scope_list)
5432 - object ancestors = GetAncestorScopes (scope, scope_list);
5433 - if (ancestors == null)
5436 - // Single match, thats the parent.
5437 - if (ancestors is ScopeInfo)
5438 - return (ScopeInfo) ancestors;
5440 - ArrayList candidates = (ArrayList) ancestors;
5441 - ScopeInfo parent = (ScopeInfo) candidates [0];
5442 - for (int i = 1; i < candidates.Count; i++){
5443 - if (IsAncestor (parent, (ScopeInfo) candidates [i]))
5444 - parent = (ScopeInfo) candidates [i];
5445 + return base.DoResolveInternal (ec);
5451 - // Links all the scopes
5454 - public void LinkScopes ()
5460 - if (ParentCaptureContext != null)
5461 - ParentCaptureContext.LinkScopes ();
5463 - int scope_count = scopes.Keys.Count;
5464 - ScopeInfo [] scope_list = new ScopeInfo [scope_count];
5465 - scopes.Values.CopyTo (scope_list, 0);
5467 - for (int i = 0; i < scope_count; i++){
5468 - ScopeInfo parent = GetParentScope (scope_list [i], scope_list);
5470 - if (parent == null){
5471 - roots.Add (scope_list [i]);
5475 - scope_list [i].ParentScope = parent;
5476 - parent.AddChild (scope_list [i]);
5477 + protected virtual void EmitParameterReference (EmitContext ec,
5478 + CapturedParameter cp)
5480 + int extra = ec.IsStatic ? 0 : 1;
5481 + ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
5485 - // Link the roots to their parent containers if any.
5487 - if (ParentCaptureContext != null && roots.Count != 0){
5488 - ScopeInfo one_root = (ScopeInfo) roots [0];
5489 - bool found = false;
5491 - foreach (ScopeInfo a_parent_root in ParentCaptureContext.roots){
5492 - if (!IsAncestor (a_parent_root, one_root))
5497 - // Found, link all the roots to this root
5498 - foreach (ScopeInfo root in roots){
5499 - root.ParentScope = a_parent_root;
5500 - a_parent_root.AddChild (root);
5506 - // This is to catch a condition in which it is
5507 - // not possible to determine the containing ScopeInfo
5508 - // from an encapsulating CaptureContext
5510 - throw new Exception ("Internal compiler error: Did not find the parent for the root in the chain");
5516 Index: expression.cs
5517 ===================================================================
5518 --- expression.cs (revision 63019)
5519 +++ expression.cs (working copy)
5523 ParameterReference pr = Expr as ParameterReference;
5524 - if ((pr != null) && (ec.capture_context != null) &&
5525 - ec.capture_context.IsParameterCaptured (pr.Name)) {
5526 + if ((pr != null) && pr.Parameter.IsCaptured) {
5527 AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
5530 @@ -3309,6 +3308,7 @@
5533 LocalTemporary temp;
5534 + Variable variable;
5536 public LocalVariableReference (Block block, string name, Location l)
5538 @@ -3363,20 +3363,19 @@
5539 if (!VerifyAssigned (ec))
5542 - if (ec.CurrentAnonymousMethod != null){
5544 - // If we are referencing a variable from the external block
5545 - // flag it for capturing
5547 - if ((local_info.Block.Toplevel != ec.CurrentBlock.Toplevel) ||
5548 - ec.CurrentAnonymousMethod.IsIterator)
5550 - if (local_info.AddressTaken){
5551 - AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
5554 - ec.CaptureVariable (local_info);
5556 + // If we are referencing a variable from the external block
5557 + // flag it for capturing
5559 + if (ec.MustCaptureVariable (local_info)) {
5560 + if (local_info.AddressTaken){
5561 + AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
5565 + ScopeInfo scope = local_info.Block.CreateScopeInfo ();
5566 + variable = scope.AddLocal (local_info);
5567 + type = variable.Type;
5571 @@ -3439,90 +3438,57 @@
5572 return Name == lvr.Name && Block == lvr.Block;
5575 + public Variable Variable {
5576 + get { return variable != null ? variable : local_info.Variable; }
5579 public override void Emit (EmitContext ec)
5581 - ILGenerator ig = ec.ig;
5583 - if (local_info.FieldBuilder == null){
5585 - // A local variable on the local CLR stack
5587 - ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
5590 - // A local variable captured by anonymous methods.
5593 - ec.EmitCapturedVariableInstance (local_info);
5595 - ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
5597 + Report.Debug (64, "EMIT LOCAL VARIABLE REFERENCE", this, ec, Variable, loc);
5599 + Variable.EmitInstance (ec);
5600 + Variable.Emit (ec);
5603 public void Emit (EmitContext ec, bool leave_copy)
5608 ec.ig.Emit (OpCodes.Dup);
5609 - if (local_info.FieldBuilder != null){
5610 + if (Variable.NeedsTemporary) {
5611 temp = new LocalTemporary (Type);
5617 - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5619 + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
5620 + bool prepare_for_load)
5622 ILGenerator ig = ec.ig;
5623 prepared = prepare_for_load;
5625 - if (local_info.FieldBuilder == null){
5627 - // A local variable on the local CLR stack
5629 - if (local_info.LocalBuilder == null)
5630 - throw new Exception ("This should not happen: both Field and Local are null");
5634 - ec.ig.Emit (OpCodes.Dup);
5635 - ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
5638 - // A local variable captured by anonymous methods or itereators.
5640 - ec.EmitCapturedVariableInstance (local_info);
5642 - if (prepare_for_load)
5643 - ig.Emit (OpCodes.Dup);
5646 - ig.Emit (OpCodes.Dup);
5647 + Report.Debug (64, "LOCAL VAR REF EMIT ASSIGN", this, source, loc);
5648 + Variable.EmitInstance (ec);
5649 + if (prepare_for_load && Variable.HasInstance)
5650 + ig.Emit (OpCodes.Dup);
5653 + ig.Emit (OpCodes.Dup);
5654 + if (Variable.NeedsTemporary) {
5655 temp = new LocalTemporary (Type);
5658 - ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
5662 + Variable.EmitAssign (ec);
5667 public void AddressOf (EmitContext ec, AddressOp mode)
5669 - ILGenerator ig = ec.ig;
5671 - if (local_info.FieldBuilder == null){
5673 - // A local variable on the local CLR stack
5675 - ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
5678 - // A local variable captured by anonymous methods or iterators
5680 - ec.EmitCapturedVariableInstance (local_info);
5681 - ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
5683 + Variable.EmitInstance (ec);
5684 + Variable.EmitAddressOf (ec);
5687 public override string ToString ()
5688 @@ -3561,7 +3527,14 @@
5692 + public Parameter Parameter {
5698 LocalTemporary temp;
5699 + Variable variable;
5701 public ParameterReference (Parameter par, Block block, int idx, Location loc)
5703 @@ -3577,6 +3550,10 @@
5707 + public Variable Variable {
5708 + get { return variable != null ? variable : par.Variable; }
5711 public bool VerifyFixed ()
5713 // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
5714 @@ -3630,23 +3607,33 @@
5716 vi = block.ParameterMap [idx];
5718 - if (ec.CurrentAnonymousMethod != null){
5719 - if (is_ref && !block.Toplevel.IsLocalParameter (name)){
5720 - Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block",
5724 + AnonymousContainer am = ec.CurrentAnonymousMethod;
5729 - // If we are referencing the parameter from the external block
5730 - // flag it for capturing
5732 - //Console.WriteLine ("Is parameter `{0}' local? {1}", name, block.IsLocalParameter (name));
5733 - if (!block.Toplevel.IsLocalParameter (name)){
5734 - ec.CaptureParameter (name, type, idx);
5735 + if (is_ref && !block.Toplevel.IsLocalParameter (name)){
5736 + Report.Error (1628, Location,
5737 + "Cannot use ref or out parameter `{0}' inside an " +
5738 + "anonymous method block", par.Name);
5742 + if (!am.IsIterator && block.Toplevel.IsLocalParameter (name))
5745 + AnonymousMethodHost host = null;
5746 + ToplevelBlock toplevel = block.Toplevel;
5747 + while (toplevel != null) {
5748 + if (toplevel.IsLocalParameter (name)) {
5749 + host = toplevel.AnonymousMethodHost;
5753 + toplevel = toplevel.Container;
5756 + variable = host.AddParameter (par, idx);
5757 + type = variable.Type;
5761 @@ -3681,7 +3668,8 @@
5762 if (!DoResolveBase (ec))
5765 - if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
5766 + if (is_out && ec.DoFlowAnalysis &&
5767 + (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
5771 @@ -3731,7 +3719,7 @@
5772 // FIXME: Review for anonymous methods
5777 public override void Emit (EmitContext ec)
5780 @@ -3739,19 +3727,10 @@
5782 public void Emit (EmitContext ec, bool leave_copy)
5784 - ILGenerator ig = ec.ig;
5785 - int arg_idx = idx;
5787 + Variable.EmitInstance (ec);
5788 + Variable.Emit (ec);
5790 - if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
5791 - ec.EmitParameter (name, leave_copy, prepared, ref temp);
5795 - if (!ec.MethodIsStatic)
5798 - EmitLdArg (ig, arg_idx);
5802 ec.ig.Emit (OpCodes.Dup);
5803 @@ -3760,84 +3739,51 @@
5804 // If we are a reference, we loaded on the stack a pointer
5805 // Now lets load the real value
5807 - LoadFromPtr (ig, type);
5808 + LoadFromPtr (ec.ig, type);
5813 ec.ig.Emit (OpCodes.Dup);
5816 - temp = new LocalTemporary (type);
5818 + if (is_ref || Variable.NeedsTemporary) {
5819 + temp = new LocalTemporary (Type);
5825 - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5827 + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
5828 + bool prepare_for_load)
5830 + ILGenerator ig = ec.ig;
5831 prepared = prepare_for_load;
5832 - if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
5833 - ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp);
5837 - ILGenerator ig = ec.ig;
5838 - int arg_idx = idx;
5842 - if (!ec.MethodIsStatic)
5844 + Variable.EmitInstance (ec);
5845 + if (prepare_for_load && Variable.HasInstance)
5846 + ig.Emit (OpCodes.Dup);
5848 + Variable.Emit (ec);
5850 - if (is_ref && !prepared)
5851 - EmitLdArg (ig, arg_idx);
5856 - ec.ig.Emit (OpCodes.Dup);
5860 - temp = new LocalTemporary (type);
5862 + ig.Emit (OpCodes.Dup);
5863 + if (Variable.NeedsTemporary) {
5864 + temp = new LocalTemporary (Type);
5868 - StoreFromPtr (ig, type);
5873 - if (arg_idx <= 255)
5874 - ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
5876 - ig.Emit (OpCodes.Starg, arg_idx);
5879 + StoreFromPtr (ig, type);
5881 + Variable.EmitAssign (ec);
5887 public void AddressOf (EmitContext ec, AddressOp mode)
5889 - if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
5890 - ec.EmitAddressOfParameter (name);
5894 - int arg_idx = idx;
5896 - if (!ec.MethodIsStatic)
5900 - if (arg_idx <= 255)
5901 - ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
5903 - ec.ig.Emit (OpCodes.Ldarg, arg_idx);
5905 - if (arg_idx <= 255)
5906 - ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
5908 - ec.ig.Emit (OpCodes.Ldarga, arg_idx);
5910 + Variable.EmitInstance (ec);
5911 + Variable.EmitAddressOf (ec);
5914 public override string ToString ()
5915 @@ -6649,11 +6595,14 @@
5919 - if (block != null && block.Toplevel.ThisVariable != null)
5920 - variable_info = block.Toplevel.ThisVariable.VariableInfo;
5921 + if (block != null) {
5922 + if (block.Toplevel.ThisVariable != null)
5923 + variable_info = block.Toplevel.ThisVariable.VariableInfo;
5925 - if (ec.CurrentAnonymousMethod != null)
5926 - ec.CaptureThis ();
5927 + AnonymousMethodHost host = block.Toplevel.AnonymousMethodHost;
5929 + host.CaptureThis ();
5935 ===================================================================
5936 --- codegen.cs (revision 63019)
5937 +++ codegen.cs (working copy)
5942 - #define PRODUCTION
5943 +// #define PRODUCTION
5947 @@ -350,25 +350,13 @@
5949 public bool InEnumContext;
5952 - /// Anonymous methods can capture local variables and fields,
5953 - /// this object tracks it. It is copied from the TopLevelBlock
5956 - public CaptureContext capture_context;
5958 public readonly IResolveContext ResolveContext;
5961 /// The current iterator
5963 public Iterator CurrentIterator {
5965 - if (CurrentAnonymousMethod != null)
5966 - return CurrentAnonymousMethod.Iterator;
5970 + get { return CurrentAnonymousMethod as Iterator; }
5976 public override string ToString ()
5978 - return String.Format ("EmitContext ({0}:{1}:{2})", id,
5979 - CurrentIterator, capture_context, loc);
5980 + return String.Format ("EmitContext ({0}:{1})", id,
5981 + CurrentAnonymousMethod, loc);
5984 public EmitContext (IResolveContext rc, DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
5985 @@ -525,16 +513,6 @@
5986 get { return current_flow_branching; }
5989 - public bool HaveCaptureInfo {
5990 - get { return capture_context != null; }
5993 - public void EmitScopeInitFromBlock (Block b)
5995 - if (capture_context != null)
5996 - capture_context.EmitScopeInitFromBlock (this, b);
6000 // Starts a new code branching. This inherits the state of all local
6001 // variables and parameters from the current branching.
6002 @@ -618,84 +596,17 @@
6003 current_flow_branching = current_flow_branching.Parent;
6006 - public void CaptureVariable (LocalInfo li)
6007 + public bool MustCaptureVariable (LocalInfo local)
6009 - capture_context.AddLocal (CurrentAnonymousMethod, li);
6010 - li.IsCaptured = true;
6011 + if (CurrentAnonymousMethod == null)
6013 + if (CurrentAnonymousMethod.IsIterator)
6015 + return local.Block.Toplevel != CurrentBlock.Toplevel;
6018 - public void CaptureParameter (string name, Type t, int idx)
6020 - capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
6023 - public void CaptureThis ()
6025 - capture_context.CaptureThis (CurrentAnonymousMethod);
6030 - // Use to register a field as captured
6032 - public void CaptureField (FieldExpr fe)
6034 - capture_context.AddField (this, CurrentAnonymousMethod, fe);
6038 - // Whether anonymous methods have captured variables
6040 - public bool HaveCapturedVariables ()
6042 - if (capture_context != null)
6043 - return capture_context.HaveCapturedVariables;
6048 - // Whether anonymous methods have captured fields or this.
6050 - public bool HaveCapturedFields ()
6052 - if (capture_context != null)
6053 - return capture_context.HaveCapturedFields;
6058 - // Emits the instance pointer for the host method
6060 - public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
6062 - if (capture_context != null)
6063 - capture_context.EmitMethodHostInstance (target, am);
6064 - else if (IsStatic)
6065 - target.ig.Emit (OpCodes.Ldnull);
6067 - target.ig.Emit (OpCodes.Ldarg_0);
6071 - // Returns whether the `local' variable has been captured by an anonymous
6074 - public bool IsCaptured (LocalInfo local)
6076 - return capture_context.IsCaptured (local);
6079 - public bool IsParameterCaptured (string name)
6081 - if (capture_context != null)
6082 - return capture_context.IsParameterCaptured (name);
6086 public void EmitMeta (ToplevelBlock b)
6088 - if (capture_context != null)
6089 - capture_context.EmitAnonymousHelperClasses (this);
6097 - capture_context = block.CaptureContext;
6100 CurrentFile = loc.File;
6102 @@ -745,6 +654,11 @@
6103 if (!block.ResolveMeta (this, ip))
6106 + if ((md != null) && (md.Iterator != null)) {
6107 + if (!md.Iterator.Resolve (this))
6108 + throw new InternalErrorException ();
6111 using (this.With (EmitContext.Flags.DoFlowAnalysis, true)) {
6112 FlowBranchingToplevel top_level;
6113 if (anonymous_method_host != null)
6114 @@ -783,12 +697,14 @@
6116 } else if (!CurrentAnonymousMethod.IsIterator) {
6117 Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
6118 - CurrentAnonymousMethod.GetSignatureForError ());
6119 + CurrentAnonymousMethod.GetSignatureForError ());
6124 - block.CompleteContexts ();
6125 + if (!block.CompleteContexts (this))
6131 @@ -829,12 +745,6 @@
6132 ig.Emit (OpCodes.Ret);
6137 - // Close pending helper classes if we are the toplevel
6139 - if (capture_context != null && capture_context.ParentToplevel == null)
6140 - capture_context.CloseAnonymousHelperClasses ();
6144 @@ -1002,50 +912,24 @@
6145 public void EmitThis (bool need_address)
6147 ig.Emit (OpCodes.Ldarg_0);
6148 - if (capture_context != null && CurrentAnonymousMethod != null){
6149 - ScopeInfo si = CurrentAnonymousMethod.Scope;
6150 - while (si != null){
6151 - if (si.ParentLink != null)
6152 - ig.Emit (OpCodes.Ldfld, si.ParentLink);
6153 - if (si.THIS != null){
6154 - if (need_address && TypeManager.IsValueType (si.THIS.FieldType))
6155 - ig.Emit (OpCodes.Ldflda, si.THIS);
6157 - ig.Emit (OpCodes.Ldfld, si.THIS);
6160 - si = si.ParentScope;
6161 + if (CurrentAnonymousMethod == null)
6164 + AnonymousMethodHost host = CurrentAnonymousMethod.RootScope;
6165 + while (host != null) {
6166 + if (host.ParentLink != null)
6167 + ig.Emit (OpCodes.Ldfld, host.ParentLink.FieldBuilder);
6168 + if (host.THIS != null) {
6169 + if (need_address && TypeManager.IsValueType (host.THIS.MemberType))
6170 + ig.Emit (OpCodes.Ldflda, host.THIS.FieldBuilder);
6172 + ig.Emit (OpCodes.Ldfld, host.THIS.FieldBuilder);
6176 + host = host.ParentHost;
6181 - // Emits the code necessary to load the instance required
6182 - // to access the captured LocalInfo
6184 - public void EmitCapturedVariableInstance (LocalInfo li)
6186 - if (capture_context == null)
6187 - throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
6189 - capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
6192 - public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
6194 - capture_context.EmitParameter (this, name, leave_copy, prepared, ref temp);
6197 - public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
6199 - capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load, ref temp);
6202 - public void EmitAddressOfParameter (string name)
6204 - capture_context.EmitAddressOfParameter (this, name);
6207 public Expression GetThis (Location loc)
6211 ===================================================================
6212 --- statement.cs (revision 63019)
6213 +++ statement.cs (working copy)
6214 @@ -962,23 +962,35 @@
6218 + public abstract class Variable
6220 + public abstract Type Type {
6224 + public abstract bool HasInstance {
6228 + public abstract bool NeedsTemporary {
6232 + public abstract void EmitInstance (EmitContext ec);
6234 + public abstract void Emit (EmitContext ec);
6236 + public abstract void EmitAssign (EmitContext ec);
6238 + public abstract void EmitAddressOf (EmitContext ec);
6242 // The information about a user-perceived local variable
6244 public class LocalInfo {
6245 public Expression Type;
6248 - // Most of the time a variable will be stored in a LocalBuilder
6250 - // But sometimes, it will be stored in a field (variables that have been
6251 - // hoisted by iterators or by anonymous methods). The context of the field will
6252 - // be stored in the EmitContext
6255 - public LocalBuilder LocalBuilder;
6256 - public FieldBuilder FieldBuilder;
6258 public Type VariableType;
6259 public readonly string Name;
6260 public readonly Location Location;
6261 @@ -986,6 +998,11 @@
6263 public VariableInfo VariableInfo;
6266 + public Variable Variable {
6267 + get { return var; }
6273 @@ -1022,18 +1039,27 @@
6277 - public void DeclareLocal (ILGenerator ig)
6278 + public void ResolveVariable (EmitContext ec)
6282 - // This is needed to compile on both .NET 1.x and .NET 2.x
6283 - // the later introduced `DeclareLocal (Type t, bool pinned)'
6285 - LocalBuilder = TypeManager.DeclareLocalPinned (ig, VariableType);
6287 + Block theblock = Block;
6288 + while (theblock.Implicit)
6289 + theblock = theblock.Parent;
6290 + if (theblock.ScopeInfo != null)
6291 + var = theblock.ScopeInfo.GetCapturedVariable (this);
6293 + if (var == null) {
6294 + LocalBuilder builder;
6297 + // This is needed to compile on both .NET 1.x and .NET 2.x
6298 + // the later introduced `DeclareLocal (Type t, bool pinned)'
6300 + builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType);
6302 + builder = ec.ig.DeclareLocal (VariableType);
6304 + var = new LocalVariable (this, builder);
6306 - if (!IsThis && !IsConstant)
6307 - LocalBuilder = ig.DeclareLocal (VariableType);
6310 public bool IsThisAssigned (EmitContext ec, Location loc)
6311 @@ -1185,6 +1211,50 @@
6312 flags = value ? (flags | Flags.IsThis) : (flags & ~Flags.IsThis);
6316 + protected class LocalVariable : Variable
6318 + public readonly LocalInfo LocalInfo;
6319 + LocalBuilder builder;
6321 + public LocalVariable (LocalInfo local, LocalBuilder builder)
6323 + this.LocalInfo = local;
6324 + this.builder = builder;
6327 + public override Type Type {
6328 + get { return LocalInfo.VariableType; }
6331 + public override bool HasInstance {
6332 + get { return false; }
6335 + public override bool NeedsTemporary {
6336 + get { return false; }
6339 + public override void EmitInstance (EmitContext ec)
6344 + public override void Emit (EmitContext ec)
6346 + ec.ig.Emit (OpCodes.Ldloc, builder);
6349 + public override void EmitAssign (EmitContext ec)
6351 + ec.ig.Emit (OpCodes.Stloc, builder);
6354 + public override void EmitAddressOf (EmitContext ec)
6356 + ec.ig.Emit (OpCodes.Ldloca, builder);
6362 @@ -1239,7 +1309,7 @@
6364 // The statements in this block
6366 - ArrayList statements;
6367 + protected ArrayList statements;
6371 @@ -1275,6 +1345,8 @@
6375 + ExpressionStatement scope_init;
6377 protected static int id;
6380 @@ -1589,6 +1661,8 @@
6382 public LocalInfo AddTemporaryVariable (TypeExpr te, Location loc)
6384 + Report.Debug (64, "ADD TEMPORARY", this, Toplevel, loc);
6386 if (temporary_variables == null)
6387 temporary_variables = new ArrayList ();
6389 @@ -1679,6 +1753,19 @@
6393 + public ScopeInfo ScopeInfo;
6395 + public ScopeInfo CreateScopeInfo ()
6398 + return Parent.CreateScopeInfo ();
6400 + if (ScopeInfo == null)
6401 + ScopeInfo = new ScopeInfo (Toplevel.AnonymousMethodHost, this);
6407 /// Emits the variable declarations and labels.
6409 @@ -1688,6 +1775,8 @@
6411 public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, Parameters ip)
6413 + Report.Debug (64, "BLOCK RESOLVE META", this, Parent, toplevel);
6415 // If some parent block was unsafe, we remain unsafe even if this block
6416 // isn't explicitly marked as such.
6417 using (ec.With (EmitContext.Flags.InUnsafe, ec.InUnsafe | Unsafe)) {
6418 @@ -1791,39 +1880,23 @@
6420 // Emits the local variable declarations for a block
6422 - public void EmitMeta (EmitContext ec)
6423 + public virtual void EmitMeta (EmitContext ec)
6425 - ILGenerator ig = ec.ig;
6427 + Report.Debug (64, "BLOCK EMIT META", this, Toplevel, ScopeInfo, ec);
6428 + if (ScopeInfo != null) {
6429 + scope_init = ScopeInfo.GetScopeInitializer (ec);
6430 + Report.Debug (64, "BLOCK EMIT META #1", this, Toplevel, ScopeInfo,
6434 if (variables != null){
6435 - bool have_captured_vars = ec.HaveCapturedVariables ();
6437 - foreach (DictionaryEntry de in variables){
6438 - LocalInfo vi = (LocalInfo) de.Value;
6440 - if (have_captured_vars && ec.IsCaptured (vi))
6443 - vi.DeclareLocal (ig);
6445 + foreach (LocalInfo vi in variables.Values)
6446 + vi.ResolveVariable (ec);
6449 if (temporary_variables != null) {
6450 - AnonymousContainer am = ec.CurrentAnonymousMethod;
6451 - TypeBuilder scope = null;
6452 - if ((am != null) && am.IsIterator) {
6453 - scope = am.Scope.ScopeTypeBuilder;
6454 - if (scope == null)
6455 - throw new InternalErrorException ();
6457 - foreach (LocalInfo vi in temporary_variables) {
6458 - if (scope != null) {
6459 - if (vi.FieldBuilder == null)
6460 - vi.FieldBuilder = scope.DefineField (
6461 - vi.Name, vi.VariableType, FieldAttributes.Assembly);
6463 - vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
6465 + foreach (LocalInfo vi in temporary_variables)
6466 + vi.ResolveVariable (ec);
6469 if (children != null){
6470 @@ -2031,15 +2104,19 @@
6471 string name = (string) de.Key;
6472 LocalInfo vi = (LocalInfo) de.Value;
6475 if (vi.LocalBuilder == null)
6478 ec.DefineLocalVariable (name, vi.LocalBuilder);
6483 ec.Mark (StartLocation, true);
6484 - ec.EmitScopeInitFromBlock (this);
6485 + Report.Debug (64, "BLOCK EMIT", this, Toplevel, ec, scope_init);
6486 + if (scope_init != null)
6487 + scope_init.EmitStatement (ec);
6489 ec.Mark (EndLocation, true);
6491 @@ -2083,13 +2160,11 @@
6492 // Pointer to the host of this anonymous method, or null
6493 // if we are the topmost block
6495 - ToplevelBlock container;
6496 - CaptureContext capture_context;
6497 + GenericMethod generic;
6498 + ToplevelBlock container, child;
6499 FlowBranchingToplevel top_level_branching;
6500 + AnonymousMethodHost anonymous_method_host;
6502 - Hashtable capture_contexts;
6503 - ArrayList children;
6505 public bool HasVarargs {
6506 get { return (flags & Flags.HasVarargs) != 0; }
6507 set { flags |= Flags.HasVarargs; }
6508 @@ -2103,39 +2178,37 @@
6509 get { return parameters; }
6512 - public void RegisterCaptureContext (CaptureContext cc)
6513 + public bool CompleteContexts (EmitContext ec)
6515 - if (capture_contexts == null)
6516 - capture_contexts = new Hashtable ();
6517 - capture_contexts [cc] = cc;
6519 + Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS", this,
6520 + container, anonymous_method_host);
6522 - public void CompleteContexts ()
6524 - if (capture_contexts == null)
6526 + if (anonymous_method_host != null)
6527 + anonymous_method_host.LinkScopes ();
6529 - foreach (CaptureContext cc in capture_contexts.Keys){
6531 + if ((container == null) && (anonymous_method_host != null)) {
6532 + Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS #1", this,
6533 + anonymous_method_host);
6535 + if (anonymous_method_host.DefineType () == null)
6537 + if (!anonymous_method_host.ResolveType ())
6539 + if (!anonymous_method_host.DefineMembers ())
6546 - public CaptureContext ToplevelBlockCaptureContext {
6547 - get { return capture_context; }
6548 + public GenericMethod GenericMethod {
6549 + get { return generic; }
6552 public ToplevelBlock Container {
6553 get { return container; }
6556 - protected void AddChild (ToplevelBlock block)
6558 - if (children == null)
6559 - children = new ArrayList ();
6561 - children.Add (block);
6565 // Parent is only used by anonymous blocks to link back to their
6567 @@ -2144,6 +2217,13 @@
6568 this (container, (Flags) 0, parameters, start)
6572 + public ToplevelBlock (ToplevelBlock container, Parameters parameters, GenericMethod generic,
6574 + this (container, parameters, start)
6576 + this.generic = generic;
6579 public ToplevelBlock (Parameters parameters, Location start) :
6580 this (null, (Flags) 0, parameters, start)
6581 @@ -2160,25 +2240,69 @@
6583 this.parameters = parameters == null ? Parameters.EmptyReadOnlyParameters : parameters;
6584 this.container = container;
6586 - if (container != null)
6587 - container.AddChild (this);
6590 public ToplevelBlock (Location loc) : this (null, (Flags) 0, null, loc)
6594 - public void SetHaveAnonymousMethods (Location loc, AnonymousContainer host)
6595 + public AnonymousMethodHost CreateAnonymousMethodHost (TypeContainer host)
6597 - if (capture_context == null)
6598 - capture_context = new CaptureContext (this, loc, host);
6599 + if (anonymous_method_host != null)
6600 + return anonymous_method_host;
6602 + if (container != null)
6603 + anonymous_method_host = new AnonymousMethodHost (
6604 + this, container.anonymous_method_host, null, StartLocation);
6606 + anonymous_method_host = new AnonymousMethodHost (
6607 + this, host, generic, StartLocation);
6609 + ScopeInfo = anonymous_method_host;
6610 + return anonymous_method_host;
6613 - public CaptureContext CaptureContext {
6614 - get { return capture_context; }
6615 + public void CreateIteratorHost (AnonymousMethodHost root_scope)
6617 + Report.Debug (64, "CREATE ITERATOR HOST", this, root_scope,
6618 + container, anonymous_method_host);
6620 + if ((container != null) || (anonymous_method_host != null))
6621 + throw new InternalErrorException ();
6623 + ScopeInfo = anonymous_method_host = root_scope;
6626 + public AnonymousMethodHost AnonymousMethodHost {
6628 + if (anonymous_method_host != null)
6629 + return anonymous_method_host;
6630 + else if (container != null)
6631 + return container.AnonymousMethodHost;
6637 + public void EmitScopeInstance (EmitContext ec, ScopeInfo scope)
6639 + AnonymousMethodHost root_scope = AnonymousMethodHost;
6641 + root_scope.EmitScopeInstance (ec);
6642 + while (root_scope != scope.Host) {
6643 + ec.ig.Emit (OpCodes.Ldfld, root_scope.ParentLink.FieldBuilder);
6644 + root_scope = root_scope.ParentHost;
6646 + if (root_scope == null)
6647 + throw new InternalErrorException (
6648 + "Never found scope {0} starting at block {1}",
6649 + scope, ec.CurrentBlock.ID);
6652 + if (scope != scope.Host)
6653 + ec.ig.Emit (OpCodes.Ldfld, scope.ScopeInstance.FieldBuilder);
6656 public FlowBranchingToplevel TopLevelBranching {
6657 get { return top_level_branching; }
6659 @@ -2192,15 +2316,12 @@
6660 // null. Later on, when resolving the iterator, we need to move the
6661 // anonymous method into that iterator.
6663 - public void ReParent (ToplevelBlock new_parent, AnonymousContainer new_host)
6664 + public void ReParent (ToplevelBlock new_parent)
6666 - foreach (ToplevelBlock block in children) {
6667 - if (block.CaptureContext == null)
6670 - block.container = new_parent;
6671 - block.CaptureContext.ReParent (new_parent, new_host);
6673 + Report.Debug (64, "TOPLEVEL REPARENT", this, Parent, new_parent);
6674 + container = new_parent;
6675 + Parent = new_parent;
6676 + new_parent.child = this;
6680 @@ -2290,10 +2411,58 @@
6682 ResolveMeta (this, ec, ip);
6684 + if (child != null)
6685 + child.ResolveMeta (this, ec, ip);
6687 top_level_branching = ec.StartFlowBranching (this);
6689 return Report.Errors == errors;
6692 + public override void EmitMeta (EmitContext ec)
6694 + base.EmitMeta (ec);
6695 + parameters.ResolveVariable (this);
6698 + public void MakeIterator (Iterator iterator)
6700 + Report.Debug (64, "TOPLEVEL MAKE ITERATOR", this, statements);
6702 + Block block = new Block (this);
6703 + foreach (Statement stmt in statements)
6704 + block.AddStatement (stmt);
6705 + statements = new ArrayList ();
6706 + statements.Add (new MoveNextStatement (iterator, block));
6709 + protected class MoveNextStatement : Statement {
6710 + Iterator iterator;
6713 + public MoveNextStatement (Iterator iterator, Block block)
6715 + this.iterator = iterator;
6716 + this.block = block;
6717 + this.loc = iterator.Location;
6720 + public override bool Resolve (EmitContext ec)
6722 + return block.Resolve (ec);
6725 + protected override void DoEmit (EmitContext ec)
6727 + iterator.EmitMoveNext (ec, block);
6731 + public override string ToString ()
6733 + return String.Format ("{0} ({1}:{2}{3})", GetType (), ID, StartLocation,
6734 + anonymous_method_host);
6738 public class SwitchLabel {
6739 @@ -3299,7 +3468,7 @@
6742 public abstract void Emit (EmitContext ec);
6743 - public abstract void EmitExit (ILGenerator ig);
6744 + public abstract void EmitExit (EmitContext ec);
6747 class ExpressionEmitter : Emitter {
6748 @@ -3313,14 +3482,14 @@
6749 // Store pointer in pinned location
6751 converted.Emit (ec);
6752 - ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6753 + vi.Variable.EmitAssign (ec);
6756 - public override void EmitExit (ILGenerator ig)
6757 + public override void EmitExit (EmitContext ec)
6759 - ig.Emit (OpCodes.Ldc_I4_0);
6760 - ig.Emit (OpCodes.Conv_U);
6761 - ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6762 + ec.ig.Emit (OpCodes.Ldc_I4_0);
6763 + ec.ig.Emit (OpCodes.Conv_U);
6764 + vi.Variable.EmitAssign (ec);
6768 @@ -3350,13 +3519,13 @@
6771 converted.Emit (ec);
6772 - ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6773 + vi.Variable.EmitAssign (ec);
6776 - public override void EmitExit(ILGenerator ig)
6777 + public override void EmitExit (EmitContext ec)
6779 - ig.Emit (OpCodes.Ldnull);
6780 - ig.Emit (OpCodes.Stloc, pinned_string);
6781 + ec.ig.Emit (OpCodes.Ldnull);
6782 + ec.ig.Emit (OpCodes.Stloc, pinned_string);
6786 @@ -3554,13 +3723,11 @@
6790 - ILGenerator ig = ec.ig;
6793 // Clear the pinned variable
6795 for (int i = 0; i < data.Length; i++) {
6796 - data [i].EmitExit (ig);
6797 + data [i].EmitExit (ec);
6801 @@ -3772,22 +3939,24 @@
6803 ig.BeginCatchBlock (c.CatchType);
6806 if (c.VarBlock != null)
6807 ec.EmitScopeInitFromBlock (c.VarBlock);
6809 if (c.Name != null){
6810 vi = c.Block.GetLocalInfo (c.Name);
6812 throw new Exception ("Variable does not exist in this block");
6814 - if (vi.IsCaptured){
6815 + if (vi.Variable.NeedsTemporary) {
6816 LocalBuilder e = ig.DeclareLocal (vi.VariableType);
6817 ig.Emit (OpCodes.Stloc, e);
6819 - ec.EmitCapturedVariableInstance (vi);
6821 + vi.Variable.EmitInstance (ec);
6822 ig.Emit (OpCodes.Ldloc, e);
6823 - ig.Emit (OpCodes.Stfld, vi.FieldBuilder);
6824 + vi.Variable.EmitAssign (ec);
6826 - ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6827 + vi.Variable.EmitAssign (ec);
6829 ig.Emit (OpCodes.Pop);
6831 @@ -4164,7 +4333,7 @@
6833 Type var_type = texpr.Type;
6835 - if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethod) {
6836 + if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
6837 Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
6838 expr.ExprClassName);
6840 @@ -4220,7 +4389,7 @@
6843 ec.ig.Emit (OpCodes.Ldc_I4_0);
6844 - EmitStore (ec.ig);
6848 public void Increment (EmitContext ec)
6849 @@ -4229,7 +4398,7 @@
6851 ec.ig.Emit (OpCodes.Ldc_I4_1);
6852 ec.ig.Emit (OpCodes.Add);
6853 - EmitStore (ec.ig);
6858 @@ -4323,7 +4492,7 @@
6860 lengths [i].EmitThis (ec);
6861 ((ArrayAccess) access).EmitGetLength (ec, i);
6862 - lengths [i].EmitStore (ig);
6863 + lengths [i].EmitStore (ec);
6866 for (int i = 0; i < rank; i++) {