2 // anonymous.cs: Support for anonymous methods
5 // Miguel de Icaza (miguel@ximain.com)
7 // (C) 2003, 2004 Novell, Inc.
9 // TODO: Ideally, we should have the helper classes emited as a hierarchy to map
10 // their nesting, and have the visibility set to private, instead of NestedAssembly
17 using System.Collections;
18 using System.Reflection;
19 using System.Reflection.Emit;
21 namespace Mono.CSharp {
23 public class AnonymousMethod : Expression {
24 // Used to generate unique method names.
25 static int anonymous_method_count;
27 // An array list of AnonymousMethodParameter or null
28 public Parameters Parameters;
31 // The block that makes up the body for the anonymous mehtod
33 public ToplevelBlock Block;
36 // The container block for this anonymous method.
38 public Block ContainingBlock;
41 // The implicit method we create
47 // The emit context for the anonymous method
48 public EmitContext aec;
49 public InternalParameters amp;
53 // The modifiers applied to the method, we aggregate them
55 int method_modifiers = Modifiers.INTERNAL;
58 // During the resolve stage of the anonymous method body,
59 // we discover the actual scope where we are hosted, or
60 // null to host the method in the same class
62 public ScopeInfo Scope;
65 // Points to our container anonymous method if its present
67 public AnonymousMethod ContainerAnonymousMethod;
69 public AnonymousMethod (Parameters parameters, ToplevelBlock container, ToplevelBlock block, Location l)
71 Parameters = parameters;
76 // The order is important: this setups the CaptureContext tree hierarchy.
78 container.SetHaveAnonymousMethods (l, this);
79 block.SetHaveAnonymousMethods (l, this);
82 public override Expression DoResolve (EmitContext ec)
85 // Set class type, set type
88 eclass = ExprClass.Value;
91 // This hack means `The type is not accessible
92 // anywhere', we depend on special conversion
95 type = TypeManager.anonymous_method_type;
100 public override void Emit (EmitContext ec)
102 // nothing, as we only exist to not do anything.
106 // Creates the host for the anonymous method
108 bool CreateMethodHost (EmitContext ec, Type return_type)
111 // Crude hack follows: we replace the TypeBuilder during the
112 // definition to get the method hosted in the right class
115 TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
116 TypeBuilder type_host = Scope == null ? current_type : Scope.ScopeTypeBuilder;
118 if (current_type == null)
119 throw new Exception ("The current_type is null");
121 if (type_host == null)
122 throw new Exception ("Type host is null");
124 if (current_type == type_host && ec.IsStatic){
126 method_modifiers |= Modifiers.STATIC;
130 method = new Method (
131 (TypeContainer) ec.TypeContainer, null,
132 new TypeExpression (return_type, loc),
133 method_modifiers, false, new MemberName ("<#AnonymousMethod>" + anonymous_method_count++),
134 Parameters, null, loc);
135 method.Block = Block;
139 // Swap the TypeBuilder while we define the method, then restore
141 if (current_type != null)
142 ec.TypeContainer.TypeBuilder = type_host;
143 bool res = method.Define ();
144 if (current_type != null)
145 ec.TypeContainer.TypeBuilder = current_type;
149 void Error_ParameterMismatch (Type t)
151 Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
152 "{0}' since there is a parameter mismatch", t);
156 // Returns true if this anonymous method can be implicitly
157 // converted to the delegate type `delegate_type'
159 public Expression Compatible (EmitContext ec, Type delegate_type, bool probe)
162 // At this point its the first time we know the return type that is
163 // needed for the anonymous method. We create the method here.
166 MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (ec, delegate_type, loc);
167 invoke_mb = (MethodInfo) invoke_mg.Methods [0];
168 ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
171 // If implicit parameters are set, then we must check for out in the parameters
172 // and flag it accordingly.
174 bool out_invalid_check = false;
176 if (Parameters == null){
178 out_invalid_check = true;
181 // We provide a set of inaccessible parameters
184 for (i = 0; i < invoke_pd.Count; i++){
185 if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
188 int n = invoke_pd.Count - (params_idx != -1 ? 1 : 0);
189 Parameter [] fixedpars = new Parameter [n];
191 for (i = j = 0; i < invoke_pd.Count; i++){
192 if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
194 fixedpars [j] = new Parameter (
195 new TypeExpression (invoke_pd.ParameterType (i), loc),
196 "+" + j, invoke_pd.ParameterModifier (i), null);
200 Parameter variable = null;
201 if (params_idx != -1){
202 variable = new Parameter (
203 new TypeExpression (invoke_pd.ParameterType (params_idx), loc),
204 "+" + params_idx, invoke_pd.ParameterModifier (params_idx), null);
207 Parameters = new Parameters (fixedpars, variable, loc);
211 // First, parameter types of `delegate_type' must be compatible
212 // with the anonymous method.
214 amp = new InternalParameters (Parameters.GetParameterInfo (ec), Parameters);
216 if (amp.Count != invoke_pd.Count){
218 Report.Error (1593, loc,
219 "Anonymous method has {0} parameters, while delegate requires {1}",
220 amp.Count, invoke_pd.Count);
221 Error_ParameterMismatch (delegate_type);
226 for (int i = 0; i < amp.Count; i++){
227 Parameter.Modifier amp_mod = amp.ParameterModifier (i);
228 if (amp_mod != invoke_pd.ParameterModifier (i)){
230 Report.Error (1676, loc,
231 "Signature mismatch in parameter modifier for parameter #0", i + 1);
232 Error_ParameterMismatch (delegate_type);
237 if (amp.ParameterType (i) != invoke_pd.ParameterType (i)){
239 Report.Error (1678, loc,
240 "Signature mismatch in parameter {0}: need `{1}' got `{2}'", i + 1,
241 TypeManager.CSharpName (invoke_pd.ParameterType (i)),
242 TypeManager.CSharpName (amp.ParameterType (i)));
243 Error_ParameterMismatch (delegate_type);
248 if (out_invalid_check && (invoke_pd.ParameterModifier (i) & Parameter.Modifier.OUT) != 0){
250 Report.Error (1676, loc,"Parameter {0} must include the `out' modifier ", i+1);
251 Error_ParameterMismatch (delegate_type);
258 // If we are only probing, return ourselves
264 // Second: the return type of the delegate must be compatible with
265 // the anonymous type. Instead of doing a pass to examine the block
266 // we satisfy the rule by setting the return type on the EmitContext
267 // to be the delegate type return type.
270 //MethodBuilder builder = method_data.MethodBuilder;
271 //ILGenerator ig = builder.GetILGenerator ();
274 aec = new EmitContext (
275 ec.TypeContainer, ec.DeclSpace, loc, null,
276 invoke_mb.ReturnType,
277 /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
278 (ec.InUnsafe ? Modifiers.UNSAFE : 0),
279 /* No constructor */ false);
281 aec.CurrentAnonymousMethod = this;
282 ContainerAnonymousMethod = ec.CurrentAnonymousMethod;
283 ContainingBlock = ec.CurrentBlock;
285 if (aec.ResolveTopBlock (ec, Block, amp, loc, out unreachable))
286 return new AnonymousDelegate (this, delegate_type, loc).Resolve (ec);
291 public MethodBuilder GetMethodBuilder ()
293 return method.MethodData.MethodBuilder;
296 public bool EmitMethod (EmitContext ec)
298 if (!CreateMethodHost (ec, invoke_mb.ReturnType))
301 MethodBuilder builder = GetMethodBuilder ();
302 ILGenerator ig = builder.GetILGenerator ();
305 Parameters.LabelParameters (aec, builder, loc);
308 // Adjust based on the computed state of the
309 // method from CreateMethodHost
311 if ((method_modifiers & Modifiers.STATIC) != 0)
314 aec.EmitMeta (Block, amp);
315 aec.EmitResolvedTopBlock (Block, unreachable);
319 public static void Error_AddressOfCapturedVar (string name, Location loc)
321 Report.Error (1686, loc,
322 "Variable {0} is captured in an anonymous method and its address is also being taken: they are exclusive", name);
327 // This will emit the code for the delegate, as well delegate creation on the host
329 public class AnonymousDelegate : DelegateCreation {
332 public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
339 public override Expression DoResolve (EmitContext ec)
341 eclass = ExprClass.Value;
346 public override void Emit (EmitContext ec)
348 if (!am.EmitMethod (ec))
352 // Now emit the delegate creation.
354 if ((am.method.ModFlags & Modifiers.STATIC) == 0)
355 delegate_instance_expression = new AnonymousInstance (am);
357 Expression ml = Expression.MemberLookup (ec, type, ".ctor", loc);
358 constructor_method = ((MethodGroupExpr) ml).Methods [0];
359 delegate_method = am.GetMethodBuilder ();
363 class AnonymousInstance : Expression {
366 public AnonymousInstance (AnonymousMethod am)
369 eclass = ExprClass.Value;
372 public override Expression DoResolve (EmitContext ec)
377 public override void Emit (EmitContext ec)
379 am.aec.EmitMethodHostInstance (ec, am);
384 class CapturedParameter {
386 public FieldBuilder FieldBuilder;
389 public CapturedParameter (Type type, int idx)
397 // Here we cluster all the variables captured on a given scope, we also
398 // keep some extra information that might be required on each scope.
400 public class ScopeInfo {
401 public CaptureContext CaptureContext;
402 public ScopeInfo ParentScope;
403 public Block ScopeBlock;
404 public bool NeedThis = false;
405 public bool HostsParameters = false;
407 // For tracking the number of scopes created.
412 ArrayList locals = new ArrayList ();
413 ArrayList children = new ArrayList ();
416 // The types and fields generated
418 public TypeBuilder ScopeTypeBuilder;
419 public ConstructorBuilder ScopeConstructor;
420 public FieldBuilder THIS;
421 public FieldBuilder ParentLink;
424 // Points to the object of type `ScopeTypeBuilder' that
425 // holds the data for the scope
427 public LocalBuilder ScopeInstance;
430 public ScopeInfo (CaptureContext cc, Block b)
439 public void AddLocal (LocalInfo li)
441 if (locals.Contains (li))
447 public bool IsCaptured (LocalInfo li)
449 return locals.Contains (li);
452 public void AddChild (ScopeInfo si)
454 if (children.Contains (si))
459 static int indent = 0;
463 for (int i = 0; i < indent; i++)
469 //Console.WriteLine (Environment.StackTrace);
471 Console.WriteLine ("START");
474 Console.WriteLine ("NeedThis=" + NeedThis);
475 foreach (LocalInfo li in locals){
477 Console.WriteLine ("var {0}", li.Name);
480 foreach (ScopeInfo si in children)
484 Console.WriteLine ("END");
487 public string MakeHelperName ()
489 return String.Format ("<>AnonHelp<{0}>", id);
492 public void EmitScopeConstructor ()
494 Type [] constructor_types = TypeManager.NoTypes;
495 Parameters constructor_parameters = Parameters.EmptyReadOnlyParameters;
496 ScopeConstructor = ScopeTypeBuilder.DefineConstructor (
497 MethodAttributes.Public | MethodAttributes.HideBySig |
498 MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
499 CallingConventions.HasThis, constructor_types);
500 InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
501 TypeManager.RegisterMethod (ScopeConstructor, parameter_info, constructor_types);
503 ILGenerator cig = ScopeConstructor.GetILGenerator ();
504 cig.Emit (OpCodes.Ldarg_0);
505 cig.Emit (OpCodes.Call, TypeManager.object_ctor);
506 cig.Emit (OpCodes.Ret);
509 public void EmitScopeType (EmitContext ec)
513 if (ScopeTypeBuilder != null)
516 TypeBuilder container = ec.TypeContainer.TypeBuilder;
518 ScopeTypeBuilder = container.DefineNestedType (
519 MakeHelperName (), TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.NestedAssembly,
520 TypeManager.object_type, null);
523 THIS = ScopeTypeBuilder.DefineField ("<>THIS", container, FieldAttributes.Assembly);
525 if (ParentScope != null){
526 if (ParentScope.ScopeTypeBuilder == null){
527 throw new Exception (String.Format ("My parent has not been initialized {0} and {1}", ParentScope, this));
530 ParentLink = ScopeTypeBuilder.DefineField ("<>parent", ParentScope.ScopeTypeBuilder,
531 FieldAttributes.Assembly);
534 if (NeedThis && ParentScope != null)
535 throw new Exception ("I was not expecting THIS && having a parent");
537 foreach (LocalInfo info in locals){
538 info.FieldBuilder = ScopeTypeBuilder.DefineField (
539 info.Name, info.VariableType, FieldAttributes.Assembly);
542 if (HostsParameters){
543 Hashtable captured_parameters = CaptureContext.captured_parameters;
545 foreach (DictionaryEntry de in captured_parameters){
546 string name = (string) de.Key;
547 CapturedParameter cp = (CapturedParameter) de.Value;
550 fb = ScopeTypeBuilder.DefineField ("<p:" + name + ">", cp.Type, FieldAttributes.Assembly);
551 cp.FieldBuilder = fb;
555 EmitScopeConstructor ();
556 foreach (ScopeInfo si in children){
557 si.EmitScopeType (ec);
561 public void CloseTypes ()
563 RootContext.RegisterHelperClass (ScopeTypeBuilder);
564 foreach (ScopeInfo si in children)
569 // Emits the initialization code for the scope
571 public void EmitInitScope (EmitContext ec)
573 ILGenerator ig = ec.ig;
578 ig.Emit (OpCodes.Newobj, (ConstructorInfo) ScopeConstructor);
579 ScopeInstance = ig.DeclareLocal (ScopeTypeBuilder);
580 ig.Emit (OpCodes.Stloc, ScopeInstance);
583 ig.Emit (OpCodes.Ldloc, ScopeInstance);
584 ig.Emit (OpCodes.Ldarg_0);
585 ig.Emit (OpCodes.Stfld, THIS);
589 // Copy the parameter values, if any
591 int extra = ec.IsStatic ? 0 : 1;
592 if (HostsParameters){
593 Hashtable captured_parameters = CaptureContext.captured_parameters;
595 foreach (DictionaryEntry de in captured_parameters){
596 CapturedParameter cp = (CapturedParameter) de.Value;
598 ig.Emit (OpCodes.Ldloc, ScopeInstance);
599 ParameterReference.EmitLdArg (ig, cp.Idx + extra);
600 ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
604 if (ParentScope != null){
605 if (!ParentScope.inited)
606 ParentScope.EmitInitScope (ec);
609 // Only emit initialization in our capturecontext world
611 if (ParentScope.CaptureContext == CaptureContext){
612 ig.Emit (OpCodes.Ldloc, ScopeInstance);
613 ig.Emit (OpCodes.Ldloc, ParentScope.ScopeInstance);
614 ig.Emit (OpCodes.Stfld, ParentLink);
616 ig.Emit (OpCodes.Ldloc, ScopeInstance);
617 ig.Emit (OpCodes.Ldarg_0);
618 ig.Emit (OpCodes.Stfld, ParentLink);
624 static void DoPath (StringBuilder sb, ScopeInfo start)
626 if (start.ParentScope != null){
627 DoPath (sb, start.ParentScope);
630 sb.Append ((start.id).ToString ());
633 public override string ToString ()
635 StringBuilder sb = new StringBuilder ();
638 if (CaptureContext != null){
639 sb.Append (CaptureContext.ToString ());
646 return sb.ToString ();
651 // CaptureContext objects are created on demand if a method has
652 // anonymous methods and kept on the ToplevelBlock.
654 // If they exist, all ToplevelBlocks in the containing block are
655 // linked together (children pointing to their parents).
657 public class CaptureContext {
658 public static int count;
663 // Points to the toplevel block that owns this CaptureContext
665 ToplevelBlock toplevel_owner;
666 Hashtable scopes = new Hashtable ();
667 bool have_captured_vars = false;
668 ScopeInfo topmost = null;
673 Hashtable captured_fields = new Hashtable ();
674 Hashtable captured_variables = new Hashtable ();
675 public Hashtable captured_parameters = new Hashtable ();
676 public AnonymousMethod Host;
678 public CaptureContext (ToplevelBlock toplevel_owner, Location loc, AnonymousMethod host)
681 this.toplevel_owner = toplevel_owner;
688 void DoPath (StringBuilder sb, CaptureContext cc)
690 if (cc.ParentCaptureContext != null){
691 DoPath (sb, cc.ParentCaptureContext);
694 sb.Append (cc_id.ToString ());
697 public override string ToString ()
699 StringBuilder sb = new StringBuilder ();
703 return sb.ToString ();
706 public ToplevelBlock ParentToplevel {
708 return toplevel_owner.Container;
712 public CaptureContext ParentCaptureContext {
714 ToplevelBlock parent = ParentToplevel;
716 return (parent == null) ? null : parent.CaptureContext;
720 // Returns the deepest of two scopes
721 public ScopeInfo Deepest (ScopeInfo a, ScopeInfo b)
733 // If they Scopes are on the same CaptureContext, we do the double
734 // checks just so if there is an invariant change in the future,
735 // we get the exception at the end
737 for (p = a; p != null; p = p.ParentScope)
741 for (p = b; p != null; p = p.ParentScope)
745 CaptureContext ca = a.CaptureContext;
746 CaptureContext cb = b.CaptureContext;
748 for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext)
752 for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext)
755 throw new Exception ("Should never be reached");
758 void AdjustMethodScope (AnonymousMethod am, ScopeInfo scope)
760 am.Scope = Deepest (am.Scope, scope);
763 void LinkScope (ScopeInfo scope, int id)
765 ScopeInfo parent = (ScopeInfo) scopes [id];
766 scope.ParentScope = parent;
767 parent.AddChild (scope);
769 if (scope == topmost)
773 public void AddLocal (AnonymousMethod am, LocalInfo li)
775 if (li.Block.Toplevel != toplevel_owner){
776 ParentCaptureContext.AddLocal (am, li);
779 int block_id = li.Block.ID;
781 if (scopes [block_id] == null){
782 scope = new ScopeInfo (this, li.Block);
783 scopes [block_id] = scope;
785 scope = (ScopeInfo) scopes [block_id];
787 if (topmost == null){
791 for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
792 if (scopes [b.ID] != null){
793 LinkScope (scope, b.ID);
798 if (scope.ParentScope == null && ParentCaptureContext != null){
799 CaptureContext pcc = ParentCaptureContext;
801 for (Block b = am.ContainingBlock; b != null; b = b.Parent){
802 if (pcc.scopes [b.ID] != null){
803 pcc.LinkScope (scope, b.ID);
814 AdjustMethodScope (Host, topmost);
819 AdjustMethodScope (am, scope);
821 if (captured_variables [li] != null)
824 have_captured_vars = true;
825 captured_variables [li] = li;
830 // Retursn the CaptureContext for the block that defines the parameter `name'
832 static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
834 ToplevelBlock container = current.Container;
835 if (container != null){
836 CaptureContext cc = _ContextForParameter (container, name);
840 if (current.IsParameterReference (name))
841 return current.ToplevelBlockCaptureContext;
845 static CaptureContext ContextForParameter (ToplevelBlock current, string name)
847 CaptureContext cc = _ContextForParameter (current, name);
849 throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
854 // Records the captured parameter at the appropriate CaptureContext
856 public void AddParameter (EmitContext ec, AnonymousMethod am, string name, Type t, int idx)
858 CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
860 cc.AddParameterToContext (am, name, t, idx);
864 // Records the parameters in the context
866 void AddParameterToContext (AnonymousMethod am, string name, Type t, int idx)
868 if (captured_parameters == null)
869 captured_parameters = new Hashtable ();
870 if (captured_parameters [name] != null)
872 captured_parameters [name] = new CapturedParameter (t, idx);
874 if (topmost == null){
876 // Create one ScopeInfo, if there are none.
878 topmost = new ScopeInfo (this, toplevel_owner);
879 scopes [toplevel_owner.ID] = topmost;
882 // If the topmost ScopeInfo is not at the topblock level, insert
883 // a new ScopeInfo there.
885 if (topmost.ScopeBlock != toplevel_owner){
886 ScopeInfo par_si = new ScopeInfo (this, toplevel_owner);
887 scopes [toplevel_owner.ID] = topmost;
888 topmost.ParentScope = par_si;
893 topmost.HostsParameters = true;
894 AdjustMethodScope (am, topmost);
898 // Captured fields are only recorded on the topmost CaptureContext, because that
899 // one is the one linked to the owner of instance fields
901 public void AddField (FieldExpr fe)
903 if (fe.FieldInfo.IsStatic)
904 throw new Exception ("Attempt to register a static field as a captured field");
906 CaptureContext parent = ParentCaptureContext;
908 parent.AddField (fe);
910 captured_fields [fe] = fe;
914 public bool HaveCapturedVariables {
916 return have_captured_vars;
920 public bool HaveCapturedFields {
922 CaptureContext parent = ParentCaptureContext;
924 return parent.HaveCapturedFields;
925 return captured_fields.Count > 0;
929 public bool IsCaptured (LocalInfo local)
931 foreach (ScopeInfo si in scopes.Values){
932 if (si.IsCaptured (local))
939 // Returns whether the parameter is captured
941 public bool IsParameterCaptured (string name)
943 if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
946 if (captured_parameters != null)
947 return captured_parameters [name] != null;
951 public void EmitHelperClasses (EmitContext ec)
953 if (topmost != null){
954 topmost.NeedThis = HaveCapturedFields;
955 topmost.EmitScopeType (ec);
959 public void CloseHelperClasses ()
962 topmost.CloseTypes ();
965 ScopeInfo GetScopeFromBlock (EmitContext ec, Block b)
969 si = (ScopeInfo) scopes [b.ID];
971 throw new Exception ("Si is null for block " + b.ID);
972 si.EmitInitScope (ec);
978 // Emits the opcodes necessary to load the instance of the captured
981 public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li, AnonymousMethod am)
983 ILGenerator ig = ec.ig;
986 if (li.Block.Toplevel == toplevel_owner){
987 si = GetScopeFromBlock (ec, li.Block);
988 ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
993 ig.Emit (OpCodes.Ldarg_0);
995 while (si.ScopeBlock.ID != li.Block.ID){
996 if (si.ParentLink != null)
997 ig.Emit (OpCodes.Ldfld, si.ParentLink);
1000 throw new Exception (
1001 String.Format ("Never found block {0} starting at {1} while looking up {2}",
1002 li.Block.ID, am.Scope.ScopeBlock.ID, li.Name));
1008 // Internal routine that loads the instance to reach parameter `name'
1010 void EmitParameterInstance (EmitContext ec, string name)
1012 CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
1014 cc.EmitParameterInstance (ec, name);
1018 CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
1019 if (par_info != null){
1021 // FIXME: implementing this.
1024 ILGenerator ig = ec.ig;
1027 if (ec.CurrentBlock == toplevel_owner){
1028 si = GetScopeFromBlock (ec, toplevel_owner);
1029 ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
1033 si = ec.CurrentAnonymousMethod.Scope;
1034 ig.Emit (OpCodes.Ldarg_0);
1036 while (si.ParentLink != null) {
1037 ig.Emit (OpCodes.Ldfld, si.ParentLink);
1038 si = si.ParentScope;
1044 // Emits the code necessary to load the parameter named `name' within
1045 // an anonymous method.
1047 public void EmitParameter (EmitContext ec, string name)
1049 CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
1051 cc.EmitParameter (ec, name);
1054 EmitParameterInstance (ec, name);
1055 CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
1056 if (par_info != null){
1058 // FIXME: implementing this.
1061 ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
1065 // Implements the assignment of `source' to the paramenter named `name' within
1066 // an anonymous method.
1068 public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load)
1070 CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
1072 cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load);
1075 ILGenerator ig = ec.ig;
1076 CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
1078 EmitParameterInstance (ec, name);
1081 ig.Emit (OpCodes.Dup);
1082 ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
1086 // Emits the address for the parameter named `name' within
1087 // an anonymous method.
1089 public void EmitAddressOfParameter (EmitContext ec, string name)
1091 CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
1093 cc.EmitAddressOfParameter (ec, name);
1096 EmitParameterInstance (ec, name);
1097 CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
1098 ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder);
1102 // The following methods are only invoked on the host for the
1103 // anonymous method.
1105 public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
1107 ILGenerator ig = target.ig;
1108 ScopeInfo si = am.Scope;
1111 ig.Emit (OpCodes.Ldarg_0);
1115 si.EmitInitScope (target);
1116 ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
1119 ArrayList all_scopes = new ArrayList ();
1121 public void AddScope (ScopeInfo si)
1123 all_scopes.Add (si);
1124 toplevel_owner.RegisterCaptureContext (this);
1128 // Links any scopes that were not linked previously
1130 public void AdjustScopes ()
1132 foreach (ScopeInfo scope in all_scopes){
1133 if (scope.ParentScope != null)
1136 for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
1137 if (scopes [b.ID] != null){
1138 LinkScope (scope, b.ID);
1143 if (scope.ParentScope == null && ParentCaptureContext != null){
1144 CaptureContext pcc = ParentCaptureContext;
1146 for (Block b = Host.ContainingBlock; b != null; b = b.Parent){
1147 if (pcc.scopes [b.ID] != null){
1148 pcc.LinkScope (scope, b.ID);