📄 anonymous.cs
字号:
topmost = parent; } public void AddLocal (AnonymousContainer am, LocalInfo li) { if (li.Block.Toplevel != toplevel_owner){ ParentCaptureContext.AddLocal (am, li); return; } int block_id = li.Block.ID; ScopeInfo scope; if (scopes [block_id] == null){ scope = new ScopeInfo (this, li.Block); scopes [block_id] = scope; } else scope = (ScopeInfo) scopes [block_id]; if (topmost == null){ topmost = scope; } else { // Link to parent for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){ if (scopes [b.ID] != null){ LinkScope (scope, b.ID); break; } } if (scope.ParentScope == null && ParentCaptureContext != null){ CaptureContext pcc = ParentCaptureContext; for (Block b = am.ContainingBlock; b != null; b = b.Parent){ if (pcc.scopes [b.ID] != null){ pcc.LinkScope (scope, b.ID); break; } } } } // // Adjust the owner // if (Host != null) AdjustMethodScope (Host, topmost); // // Adjust the user // AdjustMethodScope (am, scope); if (captured_variables [li] != null) return; have_captured_vars = true; captured_variables [li] = li; scope.AddLocal (li); } // // Retursn the CaptureContext for the block that defines the parameter `name' // static CaptureContext _ContextForParameter (ToplevelBlock current, string name) { ToplevelBlock container = current.Container; if (container != null){ CaptureContext cc = _ContextForParameter (container, name); if (cc != null) return cc; } if (current.IsParameterReference (name)) return current.ToplevelBlockCaptureContext; return null; } static CaptureContext ContextForParameter (ToplevelBlock current, string name) { CaptureContext cc = _ContextForParameter (current, name); if (cc == null) throw new Exception (String.Format ("request for parameteter {0} failed: not found", name)); return cc; } // // Records the captured parameter at the appropriate CaptureContext // public void AddParameter (EmitContext ec, AnonymousContainer am, string name, Type t, int idx) { CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); cc.AddParameterToContext (am, name, t, idx); } // // Records the parameters in the context // public void AddParameterToContext (AnonymousContainer am, string name, Type t, int idx) { if (captured_parameters == null) captured_parameters = new Hashtable (); if (captured_parameters [name] == null) captured_parameters [name] = new CapturedParameter (t, idx); if (topmost == null){ // // Create one ScopeInfo, if there are none. // topmost = new ScopeInfo (this, toplevel_owner); scopes [toplevel_owner.ID] = topmost; } else { // // If the topmost ScopeInfo is not at the topblock level, insert // a new ScopeInfo there. // // FIXME: This code probably should be evolved to be like the code // in AddLocal // if (topmost.ScopeBlock != toplevel_owner){ ScopeInfo par_si = new ScopeInfo (this, toplevel_owner); ScopeInfo old_top = topmost; scopes [toplevel_owner.ID] = topmost; topmost.ParentScope = par_si; topmost = par_si; topmost.AddChild (old_top); } } topmost.HostsParameters = true; AdjustMethodScope (am, topmost); } // // Captured fields are only recorded on the topmost CaptureContext, because that // one is the one linked to the owner of instance fields // public void AddField (EmitContext ec, AnonymousContainer am, FieldExpr fe) { if (fe.FieldInfo.IsStatic) throw new Exception ("Attempt to register a static field as a captured field"); CaptureContext parent = ParentCaptureContext; if (parent != null) { parent.AddField (ec, am, fe); return; } if (topmost == null){ // // Create one ScopeInfo, if there are none. // topmost = new ScopeInfo (this, toplevel_owner); scopes [toplevel_owner.ID] = topmost; } AdjustMethodScope (am, topmost); } public void CaptureThis () { CaptureContext parent = ParentCaptureContext; if (parent != null) parent.CaptureThis (); referenced_this = true; } public bool HaveCapturedVariables { get { return have_captured_vars; } } public bool HaveCapturedFields { get { CaptureContext parent = ParentCaptureContext; if (parent != null) return parent.HaveCapturedFields; return captured_fields.Count > 0; } } public bool IsCaptured (LocalInfo local) { foreach (ScopeInfo si in scopes.Values){ if (si.IsCaptured (local)) return true; } return false; } // // Returns whether the parameter is captured // public bool IsParameterCaptured (string name) { if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name)) return true; if (captured_parameters != null) return captured_parameters [name] != null; return false; } public void EmitAnonymousHelperClasses (EmitContext ec) { if (topmost != null){ topmost.NeedThis = HaveCapturedFields || referenced_this; topmost.EmitScopeType (ec); } } public void CloseAnonymousHelperClasses () { if (topmost != null) topmost.CloseTypes (); } public void EmitInitScope (EmitContext ec) { EmitAnonymousHelperClasses (ec); if (topmost != null) topmost.EmitInitScope (ec); } ScopeInfo GetScopeFromBlock (EmitContext ec, Block b) { ScopeInfo si; si = (ScopeInfo) scopes [b.ID]; if (si == null) throw new Exception ("Si is null for block " + b.ID); si.EmitInitScope (ec); return si; } // // Emits the opcodes necessary to load the instance of the captured // variable in `li' // public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li, AnonymousContainer am) { ILGenerator ig = ec.ig; ScopeInfo si; if (li.Block.Toplevel == toplevel_owner){ si = GetScopeFromBlock (ec, li.Block); si.EmitScopeInstance (ig); return; } si = am.Scope; ig.Emit (OpCodes.Ldarg_0); if (si != null){ if (am.IsIterator && (si.ScopeBlock.Toplevel == li.Block.Toplevel)) { return; } while (si.ScopeBlock.ID != li.Block.ID){ if (si.ParentLink != null) ig.Emit (OpCodes.Ldfld, si.ParentLink); si = si.ParentScope; if (si == null) { si = am.Scope; Console.WriteLine ("Target: {0} {1}", li.Block.ID, li.Name); while (si.ScopeBlock.ID != li.Block.ID){ Console.WriteLine ("Trying: {0}", si.ScopeBlock.ID); si = si.ParentScope; } throw new Exception ( String.Format ("Never found block {0} starting at {1} while looking up {2}", li.Block.ID, am.Scope.ScopeBlock.ID, li.Name)); } } } } // // Internal routine that loads the instance to reach parameter `name' // void EmitParameterInstance (EmitContext ec, string name) { CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); if (cc != this){ cc.EmitParameterInstance (ec, name); return; } CapturedParameter par_info = (CapturedParameter) captured_parameters [name]; if (par_info != null){ // // FIXME: implementing this. // } ILGenerator ig = ec.ig; ScopeInfo si; if (ec.CurrentBlock.Toplevel == toplevel_owner) { si = GetScopeFromBlock (ec, toplevel_owner); si.EmitScopeInstance (ig); } else { si = ec.CurrentAnonymousMethod.Scope; ig.Emit (OpCodes.Ldarg_0); } if (si != null){ while (si.ParentLink != null) { ig.Emit (OpCodes.Ldfld, si.ParentLink); si = si.ParentScope; } } } // // Emits the code necessary to load the parameter named `name' within // an anonymous method. // public void EmitParameter (EmitContext ec, string name) { CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); if (cc != this){ cc.EmitParameter (ec, name); return; } EmitParameterInstance (ec, name); CapturedParameter par_info = (CapturedParameter) captured_parameters [name]; if (par_info != null){ // // FIXME: implementing this. // } ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder); } // // Implements the assignment of `source' to the paramenter named `name' within // an anonymous method. // public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load) { CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); if (cc != this){ cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load); return; } ILGenerator ig = ec.ig; CapturedParameter par_info = (CapturedParameter) captured_parameters [name]; EmitParameterInstance (ec, name); if (leave_copy) ig.Emit (OpCodes.Dup); source.Emit (ec); ig.Emit (OpCodes.Stfld, par_info.FieldBuilder); if (leave_copy){ ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder); } } // // Emits the address for the parameter named `name' within // an anonymous method. // public void EmitAddressOfParameter (EmitContext ec, string name) { CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); if (cc != this){ cc.EmitAddressOfParameter (ec, name); return; } EmitParameterInstance (ec, name); CapturedParameter par_info = (CapturedParameter) captured_parameters [name]; ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder); } // // The following methods are only invoked on the host for the // anonymous method. // public void EmitMethodHostInstance (EmitContext target, AnonymousContainer am) { ILGenerator ig = target.ig; ScopeInfo si = am.Scope; if (si == null){ ig.Emit (OpCodes.Ldarg_0); return; } si.EmitInitScope (target); si.EmitScopeInstance (ig); } ArrayList all_scopes = new ArrayList (); public void AddScope (ScopeInfo si) { all_scopes.Add (si); toplevel_owner.RegisterCaptureContext (this); } // // Links any scopes that were not linked previously // public void AdjustScopes () { foreach (ScopeInfo scope in all_scopes){ if (scope.ParentScope != null) continue; for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){ if (scopes [b.ID] != null){ LinkScope (scope, b.ID); break; } } if (scope.ParentScope == null && ParentCaptureContext != null){ CaptureContext pcc = ParentCaptureContext; for (Block b = Host.ContainingBlock; b != null; b = b.Parent){ if (pcc.scopes [b.ID] != null){ pcc.LinkScope (scope, b.ID); break; } } } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -