📄 anonymous.cs
字号:
} public override void Emit (EmitContext ec) { am.aec.EmitMethodHostInstance (ec, am); } } } class CapturedParameter { public Type Type; public FieldBuilder FieldBuilder; public int Idx; public CapturedParameter (Type type, int idx) { Type = type; Idx = idx; } } // // Here we cluster all the variables captured on a given scope, we also // keep some extra information that might be required on each scope. // public class ScopeInfo { public CaptureContext CaptureContext; public ScopeInfo ParentScope; public Block ScopeBlock; public bool NeedThis = false; public bool HostsParameters = false; // For tracking the number of scopes created. public int id; static int count; bool inited = false; ArrayList locals = new ArrayList (); ArrayList children = new ArrayList (); // // The types and fields generated // public TypeBuilder ScopeTypeBuilder; public ConstructorBuilder ScopeConstructor; public FieldBuilder THIS; public FieldBuilder ParentLink; // // Points to the object of type `ScopeTypeBuilder' that // holds the data for the scope // LocalBuilder scope_instance; public ScopeInfo (CaptureContext cc, Block b) { CaptureContext = cc; ScopeBlock = b; id = count++; cc.AddScope (this); } public void AddLocal (LocalInfo li) { if (locals.Contains (li)) return; locals.Add (li); } public bool IsCaptured (LocalInfo li) { return locals.Contains (li); } internal void AddChild (ScopeInfo si) { if (children.Contains (si)) return; // // If any of the current children should be a children of `si', move them there // ArrayList move_queue = null; foreach (ScopeInfo child in children){ if (child.ScopeBlock.IsChildOf (si.ScopeBlock)){ if (move_queue == null) move_queue = new ArrayList (); move_queue.Add (child); child.ParentScope = si; si.AddChild (child); } } children.Add (si); if (move_queue != null){ foreach (ScopeInfo child in move_queue){ children.Remove (child); } } } static int indent = 0; void Pad () { for (int i = 0; i < indent; i++) Console.Write (" "); } void EmitDebug () { //Console.WriteLine (Environment.StackTrace); Pad (); Console.WriteLine ("START"); indent++; Pad (); Console.WriteLine ("NeedThis=" + NeedThis); foreach (LocalInfo li in locals){ Pad (); Console.WriteLine ("var {0}", MakeFieldName (li.Name)); } foreach (ScopeInfo si in children) si.EmitDebug (); indent--; Pad (); Console.WriteLine ("END"); } public string MakeHelperName () { return String.Format ("<>AnonHelp<{0}>", id); } private string MakeFieldName (string local_name) { return "<" + id + ":" + local_name + ">"; } public void EmitScopeType (EmitContext ec) { // EmitDebug (); if (ScopeTypeBuilder != null) return; TypeBuilder container = ec.TypeContainer.TypeBuilder; CaptureContext.Host.CreateScopeType (ec, this); if (NeedThis) THIS = ScopeTypeBuilder.DefineField ("<>THIS", container, FieldAttributes.Assembly); if (ParentScope != null){ if (ParentScope.ScopeTypeBuilder == null){ throw new Exception (String.Format ("My parent has not been initialized {0} and {1}", ParentScope, this)); } if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder) ParentLink = ScopeTypeBuilder.DefineField ("<>parent", ParentScope.ScopeTypeBuilder, FieldAttributes.Assembly); } if (NeedThis && ParentScope != null) throw new Exception ("I was not expecting THIS && having a parent"); foreach (LocalInfo info in locals) info.FieldBuilder = ScopeTypeBuilder.DefineField ( MakeFieldName (info.Name), info.VariableType, FieldAttributes.Assembly); if (HostsParameters){ Hashtable captured_parameters = CaptureContext.captured_parameters; foreach (DictionaryEntry de in captured_parameters){ string name = (string) de.Key; CapturedParameter cp = (CapturedParameter) de.Value; FieldBuilder fb; fb = ScopeTypeBuilder.DefineField ("<p:" + name + ">", cp.Type, FieldAttributes.Assembly); cp.FieldBuilder = fb; } } foreach (ScopeInfo si in children){ si.EmitScopeType (ec); } } public void CloseTypes () { RootContext.RegisterCompilerGeneratedType (ScopeTypeBuilder); foreach (ScopeInfo si in children) si.CloseTypes (); } // // Emits the initialization code for the scope // public void EmitInitScope (EmitContext ec) { ILGenerator ig = ec.ig; if (inited) return; if (ScopeConstructor == null) throw new Exception ("ScopeConstructor is null for" + this.ToString ()); if (!CaptureContext.Host.IsIterator) { scope_instance = ig.DeclareLocal (ScopeTypeBuilder); ig.Emit (OpCodes.Newobj, (ConstructorInfo) ScopeConstructor); ig.Emit (OpCodes.Stloc, scope_instance); } if (THIS != null){ if (CaptureContext.Host.IsIterator) { ig.Emit (OpCodes.Ldarg_0); ig.Emit (OpCodes.Ldarg_1); } else { ig.Emit (OpCodes.Ldloc, scope_instance); ig.Emit (OpCodes.Ldarg_0); } ig.Emit (OpCodes.Stfld, THIS); } // // Copy the parameter values, if any // int extra = ec.IsStatic ? 0 : 1; if (CaptureContext.Host.IsIterator) extra++; if (HostsParameters){ Hashtable captured_parameters = CaptureContext.captured_parameters; foreach (DictionaryEntry de in captured_parameters){ CapturedParameter cp = (CapturedParameter) de.Value; EmitScopeInstance (ig); ParameterReference.EmitLdArg (ig, cp.Idx + extra); ig.Emit (OpCodes.Stfld, cp.FieldBuilder); } } if (ParentScope != null){ if (!ParentScope.inited) ParentScope.EmitInitScope (ec); if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder) { // // Only emit initialization in our capturecontext world // if (ParentScope.CaptureContext == CaptureContext){ EmitScopeInstance (ig); ParentScope.EmitScopeInstance (ig); ig.Emit (OpCodes.Stfld, ParentLink); } else { EmitScopeInstance (ig); ig.Emit (OpCodes.Ldarg_0); ig.Emit (OpCodes.Stfld, ParentLink); } } } inited = true; } public void EmitScopeInstance (ILGenerator ig) { if (CaptureContext.Host.IsIterator) ig.Emit (OpCodes.Ldarg_0); else ig.Emit (OpCodes.Ldloc, scope_instance); } static void DoPath (StringBuilder sb, ScopeInfo start) { if (start.ParentScope != null){ DoPath (sb, start.ParentScope); sb.Append (", "); } sb.Append ((start.id).ToString ()); } public override string ToString () { StringBuilder sb = new StringBuilder (); sb.Append ("{"); if (CaptureContext != null){ sb.Append (CaptureContext.ToString ()); sb.Append (":"); } DoPath (sb, this); sb.Append ("}"); return sb.ToString (); } } // // CaptureContext objects are created on demand if a method has // anonymous methods and kept on the ToplevelBlock. // // If they exist, all ToplevelBlocks in the containing block are // linked together (children pointing to their parents). // public class CaptureContext { public static int count; public int cc_id; public Location loc; // // Points to the toplevel block that owns this CaptureContext // ToplevelBlock toplevel_owner; Hashtable scopes = new Hashtable (); bool have_captured_vars = false; bool referenced_this = false; ScopeInfo topmost = null; // // Captured fields // Hashtable captured_fields = new Hashtable (); Hashtable captured_variables = new Hashtable (); public Hashtable captured_parameters = new Hashtable (); public AnonymousContainer Host; public CaptureContext (ToplevelBlock toplevel_owner, Location loc, AnonymousContainer host) { cc_id = count++; this.toplevel_owner = toplevel_owner; this.loc = loc; if (host != null) Host = host; } void DoPath (StringBuilder sb, CaptureContext cc) { if (cc.ParentCaptureContext != null){ DoPath (sb, cc.ParentCaptureContext); sb.Append ("."); } sb.Append (cc.cc_id.ToString ()); } public void ReParent (ToplevelBlock new_toplevel, AnonymousContainer new_host) { toplevel_owner = new_toplevel; Host = new_host; for (CaptureContext cc = ParentCaptureContext; cc != null; cc = cc.ParentCaptureContext) { cc.Host = new_host; } } public override string ToString () { StringBuilder sb = new StringBuilder (); sb.Append ("["); DoPath (sb, this); sb.Append ("]"); return sb.ToString (); } public ToplevelBlock ParentToplevel { get { return toplevel_owner.Container; } } public CaptureContext ParentCaptureContext { get { ToplevelBlock parent = ParentToplevel; return (parent == null) ? null : parent.CaptureContext; } } // Returns the deepest of two scopes public ScopeInfo Deepest (ScopeInfo a, ScopeInfo b) { ScopeInfo p; if (a == null) return b; if (b == null) return a; if (a == b) return a; // // If they Scopes are on the same CaptureContext, we do the double // checks just so if there is an invariant change in the future, // we get the exception at the end // for (p = a; p != null; p = p.ParentScope) if (p == b) return a; for (p = b; p != null; p = p.ParentScope) if (p == a) return b; CaptureContext ca = a.CaptureContext; CaptureContext cb = b.CaptureContext; for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext) if (c == cb) return a; for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext) if (c == ca) return b; throw new Exception ("Should never be reached"); } void AdjustMethodScope (AnonymousContainer am, ScopeInfo scope) { am.Scope = Deepest (am.Scope, scope); } void LinkScope (ScopeInfo scope, int id) { ScopeInfo parent = (ScopeInfo) scopes [id]; scope.ParentScope = parent; parent.AddChild (scope); if (scope == topmost)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -