===================================================================
--- parameter.cs (revision 63019)
+++ parameter.cs (working copy)
-@@ -665,7 +665,7 @@
+@@ -212,6 +212,11 @@
+ protected Type parameter_type;
+ public readonly Location Location;
+
++ Variable var;
++ public Variable Variable {
++ get { return var; }
++ }
++
+ IResolveContext resolve_context;
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
+@@ -335,6 +340,15 @@
+ return true;
+ }
+
++ public void ResolveVariable (EmitContext ec, int idx)
++ {
++ Report.Debug (64, "PARAMETER RESOLVE VARIABLE", ParameterType, Name, Location);
++ var = ec.GetCapturedParameter (this);
++ Report.Debug (64, "PARAMETER RESOLVE VARIABLE #1", var);
++ if (var == null)
++ var = new ParameterVariable (this, idx);
++ }
++
+ public Type ExternalType ()
+ {
+ if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
+@@ -452,6 +466,74 @@
+ return attribute_targets;
+ }
+ }
++
++ protected class ParameterVariable : Variable
++ {
++ public readonly Parameter Parameter;
++ public readonly int Idx;
++ public readonly bool IsRef;
++
++ public ParameterVariable (Parameter par, int idx)
++ {
++ this.Parameter = par;
++ this.Idx = idx;
++ this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0;
++ }
++
++ public override Type Type {
++ get { return Parameter.ParameterType; }
++ }
++
++ public override bool NeedsTemporary {
++ get { return false; }
++ }
++
++ public override void EmitInstance (EmitContext ec)
++ {
++ }
++
++ public override void Emit (EmitContext ec)
++ {
++ int arg_idx = Idx;
++ if (!ec.MethodIsStatic)
++ arg_idx++;
++
++ ParameterReference.EmitLdArg (ec.ig, arg_idx);
++ }
++
++ public override void EmitAssign (EmitContext ec)
++ {
++ int arg_idx = Idx;
++ if (!ec.MethodIsStatic)
++ arg_idx++;
++
++ if (arg_idx <= 255)
++ ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
++ else
++ ec.ig.Emit (OpCodes.Starg, arg_idx);
++ }
++
++ public override void EmitAddressOf (EmitContext ec)
++ {
++ int arg_idx = Idx;
++
++ if (!ec.MethodIsStatic)
++ arg_idx++;
++
++ if (IsRef) {
++ if (arg_idx <= 255)
++ ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
++ else
++ ec.ig.Emit (OpCodes.Ldarg, arg_idx);
++ } else {
++ if (arg_idx <= 255)
++ ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
++ else
++ ec.ig.Emit (OpCodes.Ldarga, arg_idx);
++ }
++ }
++ }
++
+ }
+
+ /// <summary>
+@@ -607,6 +689,14 @@
+ return ok;
+ }
+
++ public void ResolveVariable (EmitContext ec)
++ {
++ for (int i = 0; i < FixedParameters.Length; ++i) {
++ Parameter p = FixedParameters [i];
++ p.ResolveVariable (ec, i);
++ }
++ }
++
+ public CallingConventions CallingConvention
+ {
+ get {
+@@ -665,7 +755,7 @@
}
}
}
//
-@@ -573,52 +888,112 @@
+@@ -573,52 +888,91 @@
public override void Emit (EmitContext ec)
{
- this.am = am;
- eclass = ExprClass.Value;
- }
-+ class CapturedParameter {
++ class CapturedParameter : Variable {
++ public readonly ScopeInfo Scope;
+ public readonly Parameter Parameter;
+ public readonly Field Field;
+ public readonly int Idx;
- {
- am.aec.EmitMethodHostInstance (ec, am);
- }
++ public FieldExpr FieldInstance;
++
+ public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
+ {
++ this.Scope = scope;
+ this.Parameter = par;
-+ Idx = idx;
++ this.Idx = idx;
+ Field = scope.HelperClass.CaptureVariable (
+ "<p:" + par.Name + ">", par.ParameterType);
}
- }
+- }
- class CapturedParameter {
- public Type Type;
- public FieldBuilder FieldBuilder;
- public int Idx;
-+ public class CapturedParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable
-+ {
-+ ScopeInfo scope;
-+ CapturedParameter cp;
-+ VariableInfo vi;
-+ bool prepared;
++ public override Type Type {
++ get { return Field.MemberType; }
++ }
- public CapturedParameter (Type type, int idx)
-+ internal CapturedParameterReference (ScopeInfo scope, CapturedParameter cp,
-+ Location loc)
++ public override bool NeedsTemporary {
++ get { return true; }
++ }
++
++ public override void EmitInstance (EmitContext ec)
{
- Type = type;
- Idx = idx;
-+ this.scope = scope;
-+ this.cp = cp;
-+ this.loc = loc;
-+
-+ type = cp.Field.MemberType;
-+ eclass = ExprClass.Variable;
++ ec.capture_context.EmitParameterInstance (ec, Parameter);
}
+
-+ public VariableInfo VariableInfo {
-+ get { return vi; }
-+ }
-+
-+ public override Expression DoResolve (EmitContext ec)
-+ {
-+ // We are born fully resolved.
-+ return this;
-+ }
-+
-+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
-+ {
-+ // We are born fully resolved.
-+ return this;
-+ }
-+
-+ LocalTemporary temp;
-+
+ public override void Emit (EmitContext ec)
+ {
-+ Emit (ec, false);
++ if (ec.capture_context == Scope.CaptureContext)
++ ec.ig.Emit (OpCodes.Ldfld, FieldInstance.FieldInfo);
++ else
++ ec.ig.Emit (OpCodes.Ldfld, Field.FieldBuilder);
+ }
+
-+ public void Emit (EmitContext ec, bool leave_copy)
++ public override void EmitAssign (EmitContext ec)
+ {
-+ scope.CaptureContext.EmitParameter (
-+ ec, cp.Parameter.Name, leave_copy, prepared, ref temp);
-+ }
-+
-+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
-+ bool prepare_for_load)
-+ {
-+ prepared = prepare_for_load;
-+ scope.CaptureContext.EmitAssignParameter (
-+ ec, cp.Parameter.Name, source, leave_copy, prepare_for_load, ref temp);
++ if (ec.capture_context == Scope.CaptureContext)
++ ec.ig.Emit (OpCodes.Stfld, FieldInstance.FieldInfo);
++ else
++ ec.ig.Emit (OpCodes.Stfld, Field.FieldBuilder);
+ }
+
-+ public void AddressOf (EmitContext ec, AddressOp mode)
++ public override void EmitAddressOf (EmitContext ec)
+ {
-+ scope.CaptureContext.EmitAddressOfParameter (ec, cp.Parameter.Name);
++ if (ec.capture_context == Scope.CaptureContext)
++ ec.ig.Emit (OpCodes.Ldflda, FieldInstance.FieldInfo);
++ else
++ ec.ig.Emit (OpCodes.Ldflda, Field.FieldBuilder);
+ }
+
-+ public bool VerifyFixed ()
++ public override string ToString ()
+ {
-+ // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
-+ return cp.Parameter.ModFlags == Parameter.Modifier.NONE;
++ return String.Format ("{0} ({1})", GetType (), Field);
+ }
}
//
-@@ -629,13 +1004,11 @@
+@@ -629,13 +983,11 @@
public CaptureContext CaptureContext;
public ScopeInfo ParentScope;
public Block ScopeBlock;
ArrayList locals = new ArrayList ();
ArrayList children = new ArrayList ();
-@@ -643,40 +1016,39 @@
+@@ -643,40 +995,39 @@
//
// The types and fields generated
//
internal void AddChild (ScopeInfo si)
{
if (children.Contains (si))
-@@ -719,8 +1091,6 @@
+@@ -719,8 +1070,6 @@
Pad ();
Console.WriteLine ("START");
indent++;
foreach (LocalInfo li in locals){
Pad ();
Console.WriteLine ("var {0}", MakeFieldName (li.Name));
-@@ -733,147 +1103,81 @@
+@@ -733,147 +1082,81 @@
Console.WriteLine ("END");
}
//
// This is needed if someone overwrites the Emit method
// of Statement and manually calls Block.Emit without
-@@ -882,16 +1186,9 @@
+@@ -882,16 +1165,9 @@
// ec.EmitScopeInitFromBlock (The_Block);
// The_Block.Emit (ec);
//
}
}
-@@ -935,6 +1232,303 @@
+@@ -935,6 +1211,268 @@
return sb.ToString ();
}
+
+ public override void EmitInstance (EmitContext ec)
+ {
-+ ec.EmitCapturedVariableInstance (Local);
++ ec.capture_context.EmitCapturedVariableInstance (
++ ec, Local.Block, ec.CurrentAnonymousMethod);
+ }
+
+ public override void Emit (EmitContext ec)
+ }
+ }
+
-+#if FIXME
-+ protected class CapturedLocalInstance : Variable
-+ {
-+ public readonly LocalInfo LocalInfo;
-+
-+ public CapturedLocalInstance (LocalInfo local)
-+ {
-+ this.LocalInfo = local;
-+ }
-+
-+ public override Type Type {
-+ get { return LocalInfo.TheField.Type; }
-+ }
-+
-+ public override bool NeedsTemporary {
-+ get { return true; }
-+ }
-+
-+ public override void EmitInstance (EmitContext ec)
-+ {
-+ ec.EmitCapturedVariableInstance (LocalInfo);
-+ }
-+
-+ public override void Emit (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldfld, LocalInfo.TheField.FieldInfo);
-+ }
-+
-+ public override void EmitAssign (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Stfld, LocalInfo.TheField.FieldInfo);
-+ }
-+
-+ public override void EmitAddressOf (EmitContext ec)
-+ {
-+ ec.ig.Emit (OpCodes.Ldflda, LocalInfo.TheField.FieldInfo);
-+ }
-+ }
-+#endif
-+
+ protected sealed class ScopeInitializer : ExpressionStatement
+ {
+ ScopeInfo scope;
+ throw new InternalErrorException ();
+
+ captured_params.Add (cp.Idx + extra, fe);
++
++ fe.InstanceExpression = this;
++ cp.FieldInstance = fe;
+ }
+ }
+
+ ec.ig.Emit (OpCodes.Neg);
+ ec.ig.Emit (OpCodes.Not);
+ ec.ig.Emit (OpCodes.Neg);
++ throw;
+ }
+ }
+ }
}
//
-@@ -965,7 +1559,6 @@
+@@ -965,25 +1503,24 @@
ArrayList roots = new ArrayList ();
bool have_captured_vars = false;
//
// Captured fields
-@@ -973,17 +1566,17 @@
+ //
Hashtable captured_fields = new Hashtable ();
Hashtable captured_variables = new Hashtable ();
- public Hashtable captured_parameters = new Hashtable ();
+- public Hashtable captured_parameters = new Hashtable ();
- public AnonymousContainer Host;
-
++ internal Hashtable captured_parameters = new Hashtable ();
+ public IAnonymousContainer Host;
+
public CaptureContext (ToplevelBlock toplevel_owner, Location loc,
}
void DoPath (StringBuilder sb, CaptureContext cc)
-@@ -1005,7 +1598,7 @@
+@@ -1005,7 +1542,7 @@
cc.Host = new_host;
}
}
public override string ToString ()
{
StringBuilder sb = new StringBuilder ();
-@@ -1029,41 +1622,67 @@
+@@ -1029,91 +1566,122 @@
}
}
}
//
-@@ -1093,27 +1712,32 @@
+ // Retursn the CaptureContext for the block that defines the parameter `name'
+ //
+- static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
++ static CaptureContext _ContextForParameter (ToplevelBlock current, Parameter par)
+ {
+ ToplevelBlock container = current.Container;
+ if (container != null){
+- CaptureContext cc = _ContextForParameter (container, name);
++ CaptureContext cc = _ContextForParameter (container, par);
+ if (cc != null)
+ return cc;
+ }
+- if (current.IsParameterReference (name))
++ if (current.IsParameterReference (par.Name))
+ return current.ToplevelBlockCaptureContext;
+ return null;
+ }
+
+- static CaptureContext ContextForParameter (ToplevelBlock current, string name)
++ static CaptureContext ContextForParameter (ToplevelBlock current, Parameter par)
+ {
+- CaptureContext cc = _ContextForParameter (current, name);
++ CaptureContext cc = _ContextForParameter (current, par);
+ if (cc == null)
+- throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
++ throw new InternalErrorException (
++ "Request for parameteter {0} failed: not found", par.Name);
+ return cc;
+ }
+
//
// Records the captured parameter at the appropriate CaptureContext
//
- public void AddParameter (EmitContext ec, AnonymousContainer am,
- string name, Type t, int idx)
-+ public Expression AddParameter (EmitContext ec, Parameter par, int idx, Location loc)
++ public Variable AddParameter (EmitContext ec, Parameter par, int idx)
{
- CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
-
- cc.AddParameterToContext (am, name, t, idx);
-+ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, par.Name);
-+ return cc.AddParameterToContext (ec.CurrentAnonymousMethod, par, idx, loc);
++ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, par);
++ return cc.AddParameterToContext (ec.CurrentAnonymousMethod, par, idx);
}
//
// Records the parameters in the context
//
- public void AddParameterToContext (AnonymousContainer am, string name, Type t, int idx)
-+ public Expression AddParameterToContext (AnonymousContainer am, Parameter par,
-+ int idx, Location loc)
++ public Variable AddParameterToContext (AnonymousContainer am, Parameter par, int idx)
{
if (captured_parameters == null)
captured_parameters = new Hashtable ();
scope.HostsParameters = true;
am.RegisterScope (scope);
+
-+ CapturedParameter cp = (CapturedParameter) captured_parameters [par.Name];
++ CapturedParameter cp = (CapturedParameter) captured_parameters [par];
+ if (cp == null) {
+ cp = new CapturedParameter (scope, par, idx);
-+ captured_parameters.Add (par.Name, cp);
++ captured_parameters.Add (par, cp);
+ }
+
-+ return new CapturedParameterReference (scope, cp, loc);
++ return cp;
}
//
-@@ -1137,16 +1761,15 @@
+@@ -1137,16 +1705,15 @@
public void CaptureThis (AnonymousContainer am)
{
if (am == null)
}
public bool HaveCapturedVariables {
-@@ -1164,13 +1787,9 @@
+@@ -1164,21 +1731,23 @@
}
}
+ return (Variable) captured_variables [local];
}
++ public Variable GetCapturedParameter (Parameter par)
++ {
++ return (Variable) captured_parameters [par];
++ }
++
//
-@@ -1188,45 +1807,23 @@
+ // Returns whether the parameter is captured
+ //
+ public bool IsParameterCaptured (string name)
+ {
+- if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
++ if ((ParentCaptureContext != null) &&
++ ParentCaptureContext.IsParameterCaptured (name))
+ return true;
+
+ if (captured_parameters != null)
+@@ -1188,86 +1757,65 @@
public void EmitAnonymousHelperClasses (EmitContext ec)
{
}
//
-@@ -1239,12 +1836,18 @@
+ // Emits the opcodes necessary to load the instance of the captured
+ // variable in `li'
+ //
+- public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li,
++ public void EmitCapturedVariableInstance (EmitContext ec, Block block,
+ AnonymousContainer am)
+ {
ILGenerator ig = ec.ig;
ScopeInfo si;
-+ Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE", this, li.Name,
-+ am, li.Block.Toplevel, toplevel_owner);
-+
- if (li.Block.Toplevel == toplevel_owner){
- si = (ScopeInfo) scopes [li.Block.ID];
+- if (li.Block.Toplevel == toplevel_owner){
+- si = (ScopeInfo) scopes [li.Block.ID];
- si.EmitScopeInstance (ig);
++ Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE", this,
++ am, block, block.Toplevel, toplevel_owner);
++
++ if (block.Toplevel == toplevel_owner){
++ si = (ScopeInfo) scopes [block.ID];
+ si.EmitScopeInstance (ec);
return;
}
-+ Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #1", this, li.Name,
-+ am, am.IsIterator, li.Block.Toplevel, toplevel_owner, am.Scope);
++ Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #1", this,
++ am, am.IsIterator, block.Toplevel, toplevel_owner, am.Scope);
+
si = am.Scope;
ig.Emit (OpCodes.Ldarg_0);
if (si != null){
-@@ -1252,15 +1855,19 @@
+- if (am.IsIterator && (si.ScopeBlock.Toplevel == li.Block.Toplevel)) {
++ if (am.IsIterator && (si.ScopeBlock.Toplevel == block.Toplevel)) {
return;
}
-+ Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #2", this, li.Name,
-+ si, si.ParentLink, si.ScopeBlock, li.Block);
+- while (si.ScopeBlock.ID != li.Block.ID){
++ Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #2", this,
++ si, si.ParentLink, si.ScopeBlock, block);
+
- while (si.ScopeBlock.ID != li.Block.ID){
++ while (si.ScopeBlock.ID != block.ID){
if (si.ParentLink != null)
- ig.Emit (OpCodes.Ldfld, si.ParentLink);
+ ig.Emit (OpCodes.Ldfld, si.ParentLink.FieldBuilder);
si = si.ParentScope;
- if (si == null) {
- si = am.Scope;
+- if (si == null) {
+- si = am.Scope;
- Console.WriteLine ("Target: {0} {1}", li.Block.ID, li.Name);
-+ Console.WriteLine ("Target: {0} {1}", li.Block, li.Name);
- while (si.ScopeBlock.ID != li.Block.ID){
+- while (si.ScopeBlock.ID != li.Block.ID){
- Console.WriteLine ("Trying: {0}", si.ScopeBlock.ID);
-+ Console.WriteLine ("Trying: {0} {1}",
-+ si, si.ScopeBlock);
- si = si.ParentScope;
- }
+- 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));
+- }
++ if (si == null)
++ throw new InternalErrorException (
++ "Never found block {0} starting at {1}",
++ block.ID, am.Scope.ScopeBlock.ID);
+ }
+ }
+ }
+@@ -1275,132 +1823,32 @@
+ //
+ // Internal routine that loads the instance to reach parameter `name'
+ //
+- void EmitParameterInstance (EmitContext ec, string name)
++ public void EmitParameterInstance (EmitContext ec, Parameter par)
+ {
+- CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
++ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, par);
+ if (cc != this){
+- cc.EmitParameterInstance (ec, name);
++ cc.EmitParameterInstance (ec, par);
+ return;
+ }
-@@ -1295,7 +1902,7 @@
+- 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 = (ScopeInfo) scopes [toplevel_owner.ID];
+ si.EmitScopeInstance (ec);
} else {
si = ec.CurrentAnonymousMethod.Scope;
- ig.Emit (OpCodes.Ldarg_0);
-@@ -1303,7 +1910,7 @@
+- ig.Emit (OpCodes.Ldarg_0);
++ ec.ig.Emit (OpCodes.Ldarg_0);
+ }
- if (si != null){
+- if (si != null){
++ if (si != null) {
while (si.ParentLink != null) {
- ig.Emit (OpCodes.Ldfld, si.ParentLink);
-+ ig.Emit (OpCodes.Ldfld, si.ParentLink.FieldBuilder);
++ ec.ig.Emit (OpCodes.Ldfld, si.ParentLink.FieldBuilder);
si = si.ParentScope;
}
}
-@@ -1328,11 +1935,11 @@
- // FIXME: implementing this.
- //
- }
-- ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
-+ ec.ig.Emit (OpCodes.Ldfld, par_info.Field.FieldBuilder);
+ }
- if (leave_copy){
- ec.ig.Emit (OpCodes.Dup);
+- //
+- // Emits the code necessary to load the parameter named `name' within
+- // an anonymous method.
+- //
+- public void EmitParameter (EmitContext ec, string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
+- {
+- CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+- if (cc != this){
+- cc.EmitParameter (ec, name, leave_copy, prepared, ref temp);
+- return;
+- }
+- if (!prepared)
+- EmitParameterInstance (ec, name);
+- CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+- if (par_info != null){
+- //
+- // FIXME: implementing this.
+- //
+- }
+- ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
+-
+- if (leave_copy){
+- ec.ig.Emit (OpCodes.Dup);
- temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
-+ temp = new LocalTemporary (par_info.Field.MemberType);
- temp.Store (ec);
- }
- }
-@@ -1357,10 +1964,10 @@
- source.Emit (ec);
- if (leave_copy){
- ig.Emit (OpCodes.Dup);
+- temp.Store (ec);
+- }
+- }
+-
+- //
+- // Implements the assignment of `source' to the paramenter named `name' within
+- // an anonymous method.
+- //
+- public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
+- {
+- CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+- if (cc != this){
+- cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load, ref temp);
+- return;
+- }
+- ILGenerator ig = ec.ig;
+- CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+-
+- EmitParameterInstance (ec, name);
+- if (prepare_for_load)
+- ig.Emit (OpCodes.Dup);
+- source.Emit (ec);
+- if (leave_copy){
+- ig.Emit (OpCodes.Dup);
- temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
-+ temp = new LocalTemporary (par_info.Field.MemberType);
- temp.Store (ec);
- }
+- temp.Store (ec);
+- }
- ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
-+ ig.Emit (OpCodes.Stfld, par_info.Field.FieldBuilder);
- if (temp != null)
- temp.Emit (ec);
- }
-@@ -1378,29 +1985,9 @@
- }
- EmitParameterInstance (ec, name);
- CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+- if (temp != null)
+- temp.Emit (ec);
+- }
+-
+- //
+- // 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);
-+ ec.ig.Emit (OpCodes.Ldflda, par_info.Field.FieldBuilder);
- }
-
+- }
+-
- //
- // The following methods are only invoked on the host for the
- // anonymous method.
public void RegisterCaptureContext ()
{
toplevel_owner.RegisterCaptureContext (this);
-@@ -1474,7 +2061,7 @@
+@@ -1474,7 +1922,7 @@
}
return parent;
}
//
// Links all the scopes
//
-@@ -1483,7 +2070,9 @@
+@@ -1483,7 +1931,9 @@
{
if (linked)
return;
linked = true;
if (ParentCaptureContext != null)
ParentCaptureContext.LinkScopes ();
-@@ -1492,9 +2081,14 @@
+@@ -1492,9 +1942,14 @@
ScopeInfo [] scope_list = new ScopeInfo [scope_count];
scopes.Values.CopyTo (scope_list, 0);
if (parent == null){
roots.Add (scope_list [i]);
continue;
-@@ -1504,17 +2098,28 @@
+@@ -1504,17 +1959,28 @@
parent.AddChild (scope_list [i]);
}
}
public override string ToString ()
-@@ -3636,15 +3600,6 @@
+@@ -3562,6 +3526,7 @@
+ }
+
+ LocalTemporary temp;
++ Variable variable;
+
+ public ParameterReference (Parameter par, Block block, int idx, Location loc)
+ {
+@@ -3577,6 +3542,10 @@
+ get { return vi; }
+ }
+
++ public Variable Variable {
++ get { return variable != null ? variable : par.Variable; }
++ }
++
+ public bool VerifyFixed ()
+ {
+ // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
+@@ -3636,15 +3605,6 @@
par.Name);
return false;
}
}
return true;
-@@ -3684,6 +3639,9 @@
- if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
+@@ -3681,9 +3641,15 @@
+ if (!DoResolveBase (ec))
+ return null;
+
+- if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
++ if (is_out && ec.DoFlowAnalysis &&
++ (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
return null;
-+ if (ec.MustCaptureParameter (block, name))
-+ return ec.capture_context.AddParameter (ec, par, idx, loc);
++ if (ec.MustCaptureParameter (block, name)) {
++ variable = ec.CaptureParameter (par, idx);
++ type = variable.Type;
++ }
+
return this;
}
-@@ -3694,6 +3652,9 @@
+@@ -3694,6 +3660,11 @@
SetAssigned (ec);
-+ if (ec.MustCaptureParameter (block, name))
-+ return ec.capture_context.AddParameter (ec, par, idx, loc);
++ if (ec.MustCaptureParameter (block, name)) {
++ variable = ec.CaptureParameter (par, idx);
++ type = variable.Type;
++ }
+
return this;
}
-@@ -3742,8 +3703,11 @@
+@@ -3731,7 +3702,68 @@
+ // FIXME: Review for anonymous methods
+ //
+ }
++
++ public override void Emit (EmitContext ec)
++ {
++ Emit (ec, false);
++ }
+
++ public void Emit (EmitContext ec, bool leave_copy)
++ {
++ if (!prepared)
++ Variable.EmitInstance (ec);
++ Variable.Emit (ec);
++
++ if (is_ref) {
++ if (prepared)
++ ec.ig.Emit (OpCodes.Dup);
++
++ //
++ // If we are a reference, we loaded on the stack a pointer
++ // Now lets load the real value
++ //
++ LoadFromPtr (ec.ig, type);
++ }
++
++ if (leave_copy) {
++ ec.ig.Emit (OpCodes.Dup);
++
++ if (is_ref || Variable.NeedsTemporary) {
++ temp = new LocalTemporary (Type);
++ temp.Store (ec);
++ }
++ }
++ }
++
++ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
++ bool prepare_for_load)
++ {
++ ILGenerator ig = ec.ig;
++ prepared = prepare_for_load;
++
++ Variable.EmitInstance (ec);
++ if (prepare_for_load)
++ ig.Emit (OpCodes.Dup);
++ source.Emit (ec);
++ if (leave_copy) {
++ ig.Emit (OpCodes.Dup);
++ if (Variable.NeedsTemporary) {
++ temp = new LocalTemporary (Type);
++ temp.Store (ec);
++ }
++ }
++ Variable.EmitAssign (ec);
++ if (temp != null)
++ temp.Emit (ec);
++ }
++
++ public void AddressOf (EmitContext ec, AddressOp mode)
++ {
++ Variable.EmitInstance (ec);
++ Variable.EmitAddressOf (ec);
++ }
++
++#if FIXME
+ public override void Emit (EmitContext ec)
+ {
+ Emit (ec, false);
+@@ -3742,8 +3774,11 @@
ILGenerator ig = ec.ig;
int arg_idx = idx;
return;
}
-@@ -3777,15 +3741,14 @@
+@@ -3772,20 +3807,19 @@
+ }
+ }
+ }
+-
++
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
{
prepared = prepare_for_load;
if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
if (!ec.MethodIsStatic)
arg_idx++;
-@@ -3818,7 +3781,7 @@
+@@ -3818,7 +3852,7 @@
public void AddressOf (EmitContext ec, AddressOp mode)
{
if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
return;
}
+@@ -3839,6 +3873,7 @@
+ ec.ig.Emit (OpCodes.Ldarga, arg_idx);
+ }
+ }
++#endif
+
+ public override string ToString ()
+ {
Index: codegen.cs
===================================================================
--- codegen.cs (revision 63019)
// <summary>
// Starts a new code branching. This inherits the state of all local
// variables and parameters from the current branching.
-@@ -618,23 +611,17 @@
+@@ -618,23 +611,22 @@
current_flow_branching = current_flow_branching.Parent;
}
}
- public void CaptureParameter (string name, Type t, int idx)
-- {
++ public Variable CaptureParameter (Parameter par, int idx)
+ {
- capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
-- }
--
++ return capture_context.AddParameter (this, par, idx);
+ }
+
public void CaptureThis ()
{
capture_context.CaptureThis (CurrentAnonymousMethod);
//
// Use to register a field as captured
//
-@@ -664,25 +651,14 @@
+@@ -664,25 +656,21 @@
}
//
- // Emits the instance pointer for the host method
-- //
++ // Returns whether the `local' variable has been captured by an anonymous
++ // method
+ //
- public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
-- {
-- if (capture_context != null)
++ public Variable GetCapturedVariable (LocalInfo local)
+ {
+ if (capture_context != null)
- capture_context.EmitMethodHostInstance (target, am);
- else if (IsStatic)
- target.ig.Emit (OpCodes.Ldnull);
- else
- target.ig.Emit (OpCodes.Ldarg_0);
-- }
--
++ return capture_context.GetCapturedVariable (local);
++ return null;
+ }
+
+- //
+- // Returns whether the `local' variable has been captured by an anonymous
+- // method
- //
- // Returns whether the `local' variable has been captured by an anonymous
- // method
- //
- public bool IsCaptured (LocalInfo local)
-+ public Variable GetCapturedVariable (LocalInfo local)
++ public Variable GetCapturedParameter (Parameter par)
{
- return capture_context.IsCaptured (local);
+ if (capture_context != null)
-+ return capture_context.GetCapturedVariable (local);
++ return capture_context.GetCapturedParameter (par);
+ return null;
}
public bool IsParameterCaptured (string name)
-@@ -691,6 +667,25 @@
+@@ -691,6 +679,25 @@
return capture_context.IsParameterCaptured (name);
return false;
}
public void EmitMeta (ToplevelBlock b)
{
-@@ -783,12 +778,14 @@
+@@ -783,12 +790,14 @@
return false;
} else if (!CurrentAnonymousMethod.IsIterator) {
Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
resolved = true;
return true;
}
-@@ -829,12 +826,6 @@
+@@ -829,12 +838,6 @@
ig.Emit (OpCodes.Ret);
}
}
}
/// <summary>
-@@ -995,6 +986,8 @@
+@@ -995,6 +998,8 @@
HasReturnLabel = true;
}
//
// Emits the proper object to address fields on a remapped
// variable/parameter to field in anonymous-method/iterator proxy classes.
-@@ -1004,14 +997,22 @@
+@@ -1004,14 +1009,22 @@
ig.Emit (OpCodes.Ldarg_0);
if (capture_context != null && CurrentAnonymousMethod != null){
ScopeInfo si = CurrentAnonymousMethod.Scope;
break;
}
si = si.ParentScope;
-@@ -1030,21 +1031,6 @@
-
- capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
+@@ -1019,33 +1032,6 @@
+ }
}
+
+- //
+- // Emits the code necessary to load the instance required
+- // to access the captured LocalInfo
+- //
+- public void EmitCapturedVariableInstance (LocalInfo li)
+- {
+- if (capture_context == null)
+- throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
+-
+- capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
+- }
-
- public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
- {
- {
- capture_context.EmitAddressOfParameter (this, name);
- }
-
+-
public Expression GetThis (Location loc)
{
+ This my_this;
Index: statement.cs
===================================================================
--- statement.cs (revision 63019)
/// <summary>
/// Emits the variable declarations and labels.
/// </summary>
-@@ -1793,37 +1854,17 @@
+@@ -1791,39 +1852,19 @@
//
- public void EmitMeta (EmitContext ec)
+ // Emits the local variable declarations for a block
+ //
+- public void EmitMeta (EmitContext ec)
++ public virtual void EmitMeta (EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
if (capture_context == null)
capture_context = new CaptureContext (this, loc, host);
}
-@@ -3299,7 +3389,7 @@
+@@ -2294,6 +2384,12 @@
+
+ return Report.Errors == errors;
+ }
++
++ public override void EmitMeta (EmitContext ec)
++ {
++ base.EmitMeta (ec);
++ parameters.ResolveVariable (ec);
++ }
+ }
+
+ public class SwitchLabel {
+@@ -3299,7 +3395,7 @@
}
public abstract void Emit (EmitContext ec);
}
class ExpressionEmitter : Emitter {
-@@ -3313,14 +3403,14 @@
+@@ -3313,14 +3409,14 @@
// Store pointer in pinned location
//
converted.Emit (ec);
}
}
-@@ -3350,13 +3440,13 @@
+@@ -3350,13 +3446,13 @@
return;
converted.Emit (ec);
}
}
-@@ -3554,13 +3644,11 @@
+@@ -3554,13 +3650,11 @@
if (has_ret)
return;
}
}
}
-@@ -3772,22 +3860,24 @@
+@@ -3772,22 +3866,24 @@
ig.BeginCatchBlock (c.CatchType);
} else
ig.Emit (OpCodes.Pop);
-@@ -4164,7 +4254,7 @@
+@@ -4164,7 +4260,7 @@
Type var_type = texpr.Type;
Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
expr.ExprClassName);
return false;
-@@ -4220,7 +4310,7 @@
+@@ -4220,7 +4316,7 @@
{
EmitThis (ec);
ec.ig.Emit (OpCodes.Ldc_I4_0);
}
public void Increment (EmitContext ec)
-@@ -4229,7 +4319,7 @@
+@@ -4229,7 +4325,7 @@
Emit (ec);
ec.ig.Emit (OpCodes.Ldc_I4_1);
ec.ig.Emit (OpCodes.Add);
}
}
-@@ -4323,7 +4413,7 @@
+@@ -4323,7 +4419,7 @@
lengths [i].EmitThis (ec);
((ArrayAccess) access).EmitGetLength (ec, i);