//
// TODO:
// Flow analysis for Yield.
-// Emit calls to parent object constructor.
+// Emit calls to base object constructor.
//
// Generics note:
// Current should be defined to return T, and IEnumerator.Current returns object
}
public class Yield : Statement {
- public Expression expr;
+ Expression expr;
ArrayList finally_blocks;
-
+
public Yield (Expression expr, Location l)
{
this.expr = expr;
public static bool CheckContext (EmitContext ec, Location loc)
{
- if (ec.CurrentBranching.InFinally (true)){
+ if (ec.InFinally) {
Report.Error (1625, loc, "Cannot yield in the body of a " +
"finally clause");
return false;
+ }
+
+ if (ec.InUnsafe) {
+ Report.Error (1629, loc, "Unsafe code may not appear in iterators");
+ return false;
}
- if (ec.CurrentBranching.InCatch ()){
- Report.Error (1631, loc, "Cannot yield in the body of a " +
- "catch clause");
+ if (ec.InCatch){
+ Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
return false;
}
- if (ec.CurrentAnonymousMethod != null){
- Report.Error (1621, loc, "yield statement can not appear inside an anonymoud method");
+
+ AnonymousContainer am = ec.CurrentAnonymousMethod;
+ if ((am != null) && !am.IsIterator){
+ Report.Error (1621, loc, "The yield statement cannot be used inside anonymous method blocks");
return false;
}
- //
- // FIXME: Missing check for Yield inside try block that contains catch clauses
- //
+ if (ec.CurrentBranching.InTryWithCatch ()) {
+ Report.Error (1626, loc, "Cannot yield a value in the body of a " +
+ "try block with a catch clause");
+ return false;
+ }
return true;
}
expr = expr.Resolve (ec);
if (expr == null)
return false;
+
if (!CheckContext (ec, loc))
return false;
Iterator iterator = ec.CurrentIterator;
+
if (expr.Type != iterator.IteratorType){
expr = Convert.ImplicitConversionRequired (
ec, expr, iterator.IteratorType, loc);
}
public class Iterator : Class {
- ToplevelBlock original_block;
- ToplevelBlock block;
- string original_name;
+ protected ToplevelBlock original_block;
+ protected ToplevelBlock block;
- Type iterator_type;
+ Type original_iterator_type;
TypeExpr iterator_type_expr;
bool is_enumerable;
- bool is_static;
-
- Hashtable fields;
+ public readonly bool IsStatic;
//
// The state as we generate the iterator
//
// Context from the original method
//
+ GenericMethod generic_method;
TypeContainer container;
TypeExpr current_type;
Type this_type;
- Type return_type;
- Type [] param_types;
InternalParameters parameters;
+ InternalParameters original_parameters;
+ IMethodData orig_method;
+
+ MethodInfo dispose_method;
+ MoveNextMethod move_next_method;
+ Constructor ctor;
+ CaptureContext cc;
Expression enumerator_type;
Expression enumerable_type;
resume_points.Add (entry_point);
entry_point.Define (ig);
- ec.EmitTopBlock (original_block, parameters, Location);
+ ec.EmitTopBlock (orig_method, original_block, parameters);
+
EmitYieldBreak (ig);
ig.MarkLabel (dispatcher);
ig.BeginFaultBlock ();
ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Callvirt, dispose.MethodBuilder);
+ ig.Emit (OpCodes.Callvirt, dispose_method);
ig.EndExceptionBlock ();
Label dispatcher = ig.DefineLabel ();
ig.Emit (OpCodes.Br, dispatcher);
- ec.RemapToProxy = true;
Label [] labels = new Label [resume_points.Count];
for (int i = 0; i < labels.Length; i++) {
ResumePoint point = (ResumePoint) resume_points [i];
ig.EndExceptionBlock ();
ig.Emit (OpCodes.Br, end);
}
- ec.RemapToProxy = false;
ig.MarkLabel (dispatcher);
ig.Emit (OpCodes.Ldarg_0);
}
}
- //
- // Invoked when a local variable declaration needs to be mapped to
- // a field in our proxy class
- //
- // Prefixes registered:
- // v_ for EmitContext.MapVariable
- // s_ for Storage
- //
- public FieldBuilder MapVariable (string pfx, string name, Type t)
- {
- string full_name = pfx + name;
- FieldBuilder fb = (FieldBuilder) fields [full_name];
- if (fb != null)
- return fb;
-
- fb = TypeBuilder.DefineField (full_name, t, FieldAttributes.Private);
- fields.Add (full_name, fb);
- return fb;
- }
-
//
// Called back from Yield
//
point.Define (ig);
}
- private static MemberName MakeProxyName (string name)
+ private static MemberName MakeProxyName (string name, GenericMethod generic, Location loc)
{
int pos = name.LastIndexOf ('.');
if (pos > 0)
name = name.Substring (pos + 1);
- return new MemberName ("<" + name + ">__" + (proxy_count++));
+ string proxy_name = "<" + name + ">__" + (proxy_count++);
+
+ if (generic != null) {
+ TypeArguments args = new TypeArguments (loc);
+ foreach (TypeParameter tparam in generic.CurrentTypeParameters)
+ args.Add (new SimpleName (tparam.Name, loc));
+ return new MemberName (proxy_name, args, loc);
+ } else
+ return new MemberName (proxy_name, loc);
}
//
// Our constructor
//
- public Iterator (TypeContainer container, string name, Type return_type,
- Type [] param_types, InternalParameters parameters,
- int modifiers, ToplevelBlock block, Location loc)
- : base (container.NamespaceEntry, container, MakeProxyName (name),
- Modifiers.PRIVATE, null, loc)
+ public Iterator (IMethodData m_container, TypeContainer container, GenericMethod generic,
+ InternalParameters parameters, int modifiers)
+ : base (container.NamespaceEntry, container,
+ MakeProxyName (m_container.MethodName.Name, generic, m_container.Location),
+ (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null)
{
+ this.orig_method = m_container;
+
+ this.generic_method = generic;
this.container = container;
- this.return_type = return_type;
- this.param_types = param_types;
- this.parameters = parameters;
- this.original_name = name;
- this.original_block = block;
- this.block = new ToplevelBlock (loc);
+ this.original_parameters = parameters;
+ this.original_block = orig_method.Block;
+ this.block = new ToplevelBlock (orig_method.Block, parameters.Parameters, orig_method.Location);
+
+ if (generic != null) {
+ ArrayList constraints = new ArrayList ();
+ foreach (TypeParameter tparam in generic.TypeParameters)
+ constraints.Add (tparam.Constraints);
- fields = new Hashtable ();
+ SetParameterInfo (constraints);
+ }
+
+ IsStatic = (modifiers & Modifiers.STATIC) != 0;
+ }
- is_static = (modifiers & Modifiers.STATIC) != 0;
+ public AnonymousContainer Host {
+ get { return move_next_method; }
}
public bool DefineIterator ()
{
- ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
-
- if (!CheckType (return_type)) {
- Report.Error (
- 1624, Location,
- "The body of `{0}' cannot be an iterator block " +
- "because '{1}' is not an iterator interface type",
- original_name, TypeManager.CSharpName (return_type));
+ ec = new EmitContext (this, Location, null, null, ModFlags);
+ ec.CurrentAnonymousMethod = move_next_method;
+ ec.InIterator = true;
+
+ if (!CheckType ()) {
+ Report.Error (1624, Location,
+ "The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",
+ orig_method.GetSignatureForError (), TypeManager.CSharpName (orig_method.ReturnType));
return false;
}
- for (int i = 0; i < parameters.Count; i++){
- Parameter.Modifier mod = parameters.ParameterModifier (i);
+ for (int i = 0; i < original_parameters.Count; i++){
+ Parameter.Modifier mod = original_parameters.ParameterModifier (i);
if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
Report.Error (
1623, Location,
"Iterators cannot have ref or out parameters");
return false;
}
+
+ if ((mod & Parameter.Modifier.ARGLIST) != 0) {
+ Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");
+ return false;
+ }
+
+ if (original_parameters.ParameterType (i).IsPointer) {
+ Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");
+ return false;
+ }
}
if (container.CurrentType != null)
else
this_type = container.TypeBuilder;
+ container.AddIterator (this);
+
+ orig_method.Block = block;
+ return true;
+ }
+
+ MethodInfo FetchMethodDispose ()
+ {
+ MemberList dispose_list;
+
+ dispose_list = FindMembers (
+ current_type.Type,
+ MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
+ Type.FilterName, "Dispose");
+
+ if (dispose_list.Count != 1)
+ throw new InternalErrorException ("Cannot find Dipose() method.");
+
+ return (MethodInfo) dispose_list [0];
+ }
+
+ protected override bool DoDefineMembers ()
+ {
+ ec.InIterator = true;
+ ec.CurrentAnonymousMethod = move_next_method;
+ ec.capture_context = cc;
+
+ if (!base.DoDefineMembers ())
+ return false;
+
+ dispose_method = FetchMethodDispose ();
+ if (dispose_method == null)
+ return false;
+
+ return true;
+ }
+
+ public override bool Define ()
+ {
+ if (!base.Define ())
+ return false;
+
+ ec.InIterator = true;
+ ec.CurrentAnonymousMethod = move_next_method;
+ ec.capture_context = cc;
+
+ ec.TypeContainer = ec.TypeContainer.Parent;
+
+ if (ec.TypeContainer.CurrentType != null)
+ ec.ContainerType = ec.TypeContainer.CurrentType;
+ else
+ ec.ContainerType = ec.TypeContainer.TypeBuilder;
+
+ ec.ig = move_next_method.method.MethodBuilder.GetILGenerator ();
+
+ if (!ctor.Define ())
+ return false;
+
+ bool unreachable;
+
+ if (!ec.ResolveTopBlock (null, original_block, parameters, orig_method, out unreachable))
+ return false;
+
+ if (!ec.ResolveTopBlock (null, block, parameters, orig_method, out unreachable))
+ return false;
+
+ original_block.CompleteContexts ();
+
+ cc.EmitAnonymousHelperClasses (ec);
+
+ return true;
+ }
+
+ TypeExpr InflateType (Type it)
+ {
+ if (generic_method == null)
+ return new TypeExpression (it, Location);
+
+ if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
+ int pos = it.GenericParameterPosition;
+ it = CurrentTypeParameters [pos].Type;
+ } else if (it.IsGenericInstance) {
+ Type[] args = it.GetGenericArguments ();
+
+ TypeArguments inflated = new TypeArguments (Location);
+ foreach (Type t in args)
+ inflated.Add (InflateType (t));
+
+ return new ConstructedType (it, inflated, Location);
+ } else if (it.IsArray) {
+ TypeExpr et_expr = InflateType (it.GetElementType ());
+ int rank = it.GetArrayRank ();
+
+ Type et = et_expr.ResolveAsTypeTerminal (ec).Type;
+ it = et.MakeArrayType (rank);
+ }
+
+ return new TypeExpression (it, Location);
+ }
+
+ Parameter InflateParameter (Parameter param)
+ {
+ TypeExpr te = InflateType (param.ParameterType);
+ return new Parameter (
+ te, param.Name, param.ModFlags, param.OptAttributes, param.Location);
+ }
+
+ InternalParameters InflateParameters (Parameters parameters, EmitContext ec)
+ {
+ Parameter[] fixed_params = null;
+ if (parameters.FixedParameters != null) {
+ fixed_params = new Parameter [parameters.FixedParameters.Length];
+ for (int i = 0; i < fixed_params.Length; i++)
+ fixed_params [i] = InflateParameter (parameters.FixedParameters [i]);
+ }
+
+ Parameters new_params;
+ if (parameters.ArrayParameter != null) {
+ Parameter array_param = InflateParameter (parameters.ArrayParameter);
+ new_params = new Parameters (fixed_params, array_param);
+ } else
+ new_params = new Parameters (fixed_params, parameters.HasArglist);
+
+ Type [] types = new_params.GetParameterInfo (ec);
+ return new InternalParameters (types, new_params);
+ }
+
+ protected override TypeExpr [] GetClassBases (out TypeExpr base_class)
+ {
+ iterator_type_expr = InflateType (original_iterator_type);
+
generic_args = new TypeArguments (Location);
- generic_args.Add (new TypeExpression (iterator_type, Location));
+ generic_args.Add (iterator_type_expr);
ArrayList list = new ArrayList ();
if (is_enumerable) {
generic_args, Location);
list.Add (generic_enumerator_type);
- iterator_type_expr = new TypeExpression (iterator_type, Location);
-
- container.AddIterator (this);
-
Bases = list;
- return true;
+
+ return base.GetClassBases (out base_class);
}
//
else
current_type = new TypeExpression (TypeBuilder, Location);
+ parameters = InflateParameters (original_parameters.Parameters, ec);
+
Define_Fields ();
- Define_Constructor ();
Define_Current (false);
Define_Current (true);
Define_MoveNext ();
Define_Reset ();
Define_Dispose ();
+ Define_Constructor ();
+
+ Create_Block ();
+
if (is_enumerable) {
Define_GetEnumerator (false);
Define_GetEnumerator (true);
}
- Create_Block ();
-
return base.DefineNestedTypes ();
}
-
Field pc_field;
Field current_field;
Method dispose;
- public Field this_field;
- public Field[] parameter_fields;
-
void Create_Block ()
{
- int first = is_static ? 0 : 1;
+ original_block.SetHaveAnonymousMethods (Location, move_next_method);
+ block.SetHaveAnonymousMethods (Location, move_next_method);
+
+ cc = original_block.CaptureContext;
+
+ int first = IsStatic ? 0 : 1;
ArrayList args = new ArrayList ();
- if (!is_static) {
+ if (!IsStatic) {
Type t = this_type;
args.Add (new Argument (
- new ThisParameterReference (t, 0, Location)));
+ new ThisParameterReference (t, Location)));
+ cc.CaptureThis ();
}
args.Add (new Argument (new BoolLiteral (false)));
for (int i = 0; i < parameters.Count; i++) {
- Type t = parameters.ParameterType (i);
+ Type t = original_parameters.ParameterType (i);
+ Type inflated = parameters.ParameterType (i);
+ string name = parameters.ParameterName (i);
+
args.Add (new Argument (
new SimpleParameterReference (t, first + i, Location)));
- }
- Expression new_expr = new New (current_type, args, Location);
+ cc.AddParameterToContext (move_next_method, name, inflated, first + i);
+ }
+ TypeExpr proxy_type;
+ if (generic_method != null) {
+ TypeArguments new_args = new TypeArguments (Location);
+ if (Parent.IsGeneric) {
+ foreach (TypeParameter tparam in Parent.TypeParameters)
+ new_args.Add (new TypeParameterExpr (tparam, Location));
+ }
+ foreach (TypeParameter tparam in generic_method.TypeParameters)
+ new_args.Add (new TypeParameterExpr (tparam, Location));
+ ConstructedType ct = new ConstructedType (CurrentType, new_args, Location);
+ proxy_type = ct.ResolveAsTypeTerminal (ec);
+ } else
+ proxy_type = current_type;
+
+ Expression new_expr = new New (proxy_type, args, Location);
block.AddStatement (new NoCheckReturn (new_expr, Location));
}
void Define_Fields ()
{
- Location loc = Location.Null;
-
pc_field = new Field (
- this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "PC",
- null, null, loc);
+ this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "$PC",
+ null, null, Location);
AddField (pc_field);
current_field = new Field (
- this, iterator_type_expr, Modifiers.PRIVATE, "current",
- null, null, loc);
+ this, iterator_type_expr, Modifiers.PRIVATE, "$current",
+ null, null, Location);
AddField (current_field);
-
- if (!is_static) {
- this_field = new Field (
- this, new TypeExpression (this_type, loc),
- Modifiers.PRIVATE, "this", null, null, loc);
- AddField (this_field);
- }
-
- parameter_fields = new Field [parameters.Count];
- for (int i = 0; i < parameters.Count; i++) {
- string fname = String.Format (
- "field{0}_{1}", i, parameters.ParameterName (i));
-
- parameter_fields [i] = new Field (
- this,
- new TypeExpression (parameters.ParameterType (i), loc),
- Modifiers.PRIVATE, fname, null, null, loc);
- AddField (parameter_fields [i]);
- }
}
void Define_Constructor ()
ArrayList list = new ArrayList ();
- if (!is_static)
+ if (!IsStatic)
list.Add (new Parameter (
new TypeExpression (this_type, Location),
- "this", Parameter.Modifier.NONE, null));
+ "this", Parameter.Modifier.NONE,
+ null, Location));
list.Add (new Parameter (
TypeManager.system_boolean_expr, "initialized",
- Parameter.Modifier.NONE, null));
+ Parameter.Modifier.NONE, null, Location));
Parameter[] old_fixed = parameters.Parameters.FixedParameters;
if (old_fixed != null)
Parameter[] fixed_params = new Parameter [list.Count];
list.CopyTo (fixed_params);
- ctor_params = new Parameters (
- fixed_params, parameters.Parameters.ArrayParameter,
- Location);
+ ctor_params = new Parameters (fixed_params, parameters.Parameters.ArrayParameter);
- Constructor ctor = new Constructor (
- this, Name, Modifiers.PUBLIC, ctor_params,
- new ConstructorBaseInitializer (
- null, Parameters.EmptyReadOnlyParameters, Location),
+ ctor = new Constructor (
+ this, MemberName.Name, Modifiers.PUBLIC, ctor_params,
+ new ConstructorBaseInitializer (null, Location),
Location);
AddConstructor (ctor);
- ToplevelBlock block = ctor.Block = new ToplevelBlock (Location);
-
- if (!is_static) {
- Type t = this_type;
+ ctor.Block = new ToplevelBlock (block, parameters.Parameters, Location);
- Assign assign = new Assign (
- new FieldExpression (this_field),
- new SimpleParameterReference (t, 1, Location),
- Location);
-
- block.AddStatement (new StatementExpression (assign, Location));
- }
-
- int first = is_static ? 2 : 3;
-
- for (int i = 0; i < parameters.Count; i++) {
- Type t = parameters.ParameterType (i);
-
- Assign assign = new Assign (
- new FieldExpression (parameter_fields [i]),
- new SimpleParameterReference (t, first + i, Location),
- Location);
-
- block.AddStatement (new StatementExpression (assign, Location));
- }
+ int first = IsStatic ? 2 : 3;
State initial = is_enumerable ? State.Uninitialized : State.Running;
- block.AddStatement (new SetState (this, initial, Location));
+ ctor.Block.AddStatement (new SetState (this, initial, Location));
- block.AddStatement (new If (
+ ctor.Block.AddStatement (new If (
new SimpleParameterReference (
TypeManager.bool_type, first - 1, Location),
new SetState (this, State.Running, Location),
Location));
+
+ ctor.Block.AddStatement (new InitScope (this, Location));
}
Statement Create_ThrowInvalidOperation ()
if (is_generic) {
left = new MemberName (
"System.Collections.Generic.IEnumerator",
- generic_args);
+ generic_args, Location);
type = iterator_type_expr;
} else {
- left = new MemberName ("System.Collections.IEnumerator");
+ left = new MemberName ("System.Collections.IEnumerator", Location);
type = TypeManager.system_object_expr;
}
- MemberName name = new MemberName (left, "Current", null);
+ MemberName name = new MemberName (left, "Current", null, Location);
- ToplevelBlock get_block = new ToplevelBlock (Location);
+ ToplevelBlock get_block = new ToplevelBlock (
+ block, parameters.Parameters, Location);
get_block.AddStatement (new If (
new Binary (
Binary.Operator.LessThanOrEqual,
- new FieldExpression (pc_field),
- new IntLiteral ((int) State.Running), Location),
+ new FieldExpression (this, pc_field),
+ new IntLiteral ((int) State.Running)),
Create_ThrowInvalidOperation (),
new Return (
- new FieldExpression (current_field), Location),
+ new FieldExpression (this, current_field), Location),
Location));
Accessor getter = new Accessor (get_block, 0, null, Location);
Property current = new Property (
- this, type, 0, false, name, null, getter, null, Location);
+ this, type, 0, false, name, null, getter, null);
AddProperty (current);
}
void Define_MoveNext ()
{
- Method move_next = new Method (
- this, null, TypeManager.system_boolean_expr,
- Modifiers.PUBLIC, false, new MemberName ("MoveNext"),
- Parameters.EmptyReadOnlyParameters, null,
- Location.Null);
- AddMethod (move_next);
+ move_next_method = new MoveNextMethod (this, Location);
+
+ original_block.ReParent (block, move_next_method);
- ToplevelBlock block = move_next.Block = new ToplevelBlock (Location);
+ move_next_method.CreateMethod (ec);
- MoveNextMethod inline = new MoveNextMethod (this, Location);
- block.AddStatement (inline);
+ AddMethod (move_next_method.method);
}
void Define_GetEnumerator (bool is_generic)
if (is_generic) {
left = new MemberName (
"System.Collections.Generic.IEnumerable",
- generic_args);
+ generic_args, Location);
type = generic_enumerator_type;
} else {
- left = new MemberName ("System.Collections.IEnumerable");
+ left = new MemberName ("System.Collections.IEnumerable", Location);
type = enumerator_type;
}
- MemberName name = new MemberName (left, "GetEnumerator", null);
+ MemberName name = new MemberName (left, "GetEnumerator", Location);
Method get_enumerator = new Method (
this, null, type, 0, false, name,
- Parameters.EmptyReadOnlyParameters, null,
- Location.Null);
+ Parameters.EmptyReadOnlyParameters, null);
AddMethod (get_enumerator);
- get_enumerator.Block = new ToplevelBlock (Location);
+ get_enumerator.Block = new ToplevelBlock (
+ block, parameters.Parameters, Location);
+
+ get_enumerator.Block.SetHaveAnonymousMethods (Location, move_next_method);
Expression ce = new MemberAccess (
new SimpleName ("System.Threading.Interlocked", Location),
"CompareExchange", Location);
- Expression pc = new FieldExpression (pc_field);
+ Expression pc = new FieldExpression (this, pc_field);
Expression before = new IntLiteral ((int) State.Running);
Expression uninitialized = new IntLiteral ((int) State.Uninitialized);
get_enumerator.Block.AddStatement (new If (
new Binary (
Binary.Operator.Equality,
- new Invocation (ce, args, Location),
- uninitialized, Location),
- new Return (new This (block, Location), Location),
+ new Invocation (ce, args),
+ uninitialized),
+ new Return (new ThisParameterReference (type.Type, Location),
+ Location),
Location));
args = new ArrayList ();
- if (!is_static)
- args.Add (new Argument (new FieldExpression (this_field)));
+ if (!IsStatic) {
+ args.Add (new Argument (new CapturedThisReference (this, Location)));
+ }
args.Add (new Argument (new BoolLiteral (true)));
- for (int i = 0; i < parameters.Count; i++)
- args.Add (new Argument (
- new FieldExpression (parameter_fields [i])));
+ for (int i = 0; i < parameters.Count; i++) {
+ Expression cp = new CapturedParameterReference (
+ this, parameters.ParameterType (i),
+ parameters.ParameterName (i), Location);
+ args.Add (new Argument (cp));
+ }
Expression new_expr = new New (current_type, args, Location);
get_enumerator.Block.AddStatement (new Return (new_expr, Location));
}
}
- protected class ThisParameterReference : SimpleParameterReference
+ protected class ThisParameterReference : SimpleParameterReference, IMemoryLocation
{
- public ThisParameterReference (Type type, int idx, Location loc)
- : base (type, idx, loc)
+ public ThisParameterReference (Type type, Location loc)
+ : base (type, 0, loc)
{ }
protected override void DoEmit (EmitContext ec)
if (ec.TypeContainer is Struct)
ec.ig.Emit (OpCodes.Ldobj, type);
}
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ if (ec.TypeContainer is Struct)
+ ec.ig.Emit (OpCodes.Ldarga, 0);
+ else
+ ec.ig.Emit (OpCodes.Ldarg, 0);
+ }
+ }
+
+ protected class CapturedParameterReference : Expression
+ {
+ Iterator iterator;
+ string name;
+
+ public CapturedParameterReference (Iterator iterator, Type type,
+ string name, Location loc)
+ {
+ this.iterator = iterator;
+ this.loc = loc;
+ this.type = type;
+ this.name = name;
+ eclass = ExprClass.Variable;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.CurrentAnonymousMethod = iterator.move_next_method;
+
+ iterator.cc.EmitParameter (ec, name);
+ }
+ }
+
+ protected class CapturedThisReference : Expression
+ {
+ public CapturedThisReference (Iterator iterator, Location loc)
+ {
+ this.loc = loc;
+ this.type = iterator.this_type;
+ eclass = ExprClass.Variable;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.EmitThis ();
+ }
}
protected class FieldExpression : Expression
{
+ Iterator iterator;
Field field;
- public FieldExpression (Field field)
+ public FieldExpression (Iterator iterator, Field field)
{
+ this.iterator = iterator;
this.field = field;
+ this.loc = iterator.Location;
+ }
+
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
+ fexpr.InstanceExpression = new ThisParameterReference (
+ iterator.this_type, loc);
+ return fexpr.ResolveLValue (ec, right_side, loc);
}
public override Expression DoResolve (EmitContext ec)
{
FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
- fexpr.InstanceExpression = ec.GetThis (loc);
+ fexpr.InstanceExpression = new ThisParameterReference (
+ iterator.this_type, loc);
return fexpr.Resolve (ec);
}
}
}
- protected class MoveNextMethod : Statement {
+ protected class MoveNextMethod : AnonymousContainer
+ {
Iterator iterator;
public MoveNextMethod (Iterator iterator, Location loc)
+ : base (iterator.parameters.Parameters, iterator.original_block, loc)
+ {
+ this.iterator = iterator;
+ }
+
+ protected override bool CreateMethodHost (EmitContext ec)
+ {
+ method = new Method (
+ iterator, null, TypeManager.system_boolean_expr,
+ Modifiers.PUBLIC, false, new MemberName ("MoveNext", loc),
+ Parameters.EmptyReadOnlyParameters, null);
+
+ method.Block = Block;
+
+ MoveNextStatement inline = new MoveNextStatement (iterator, loc);
+ Block.AddStatement (inline);
+
+ return true;
+ }
+
+ public bool CreateMethod (EmitContext ec)
+ {
+ return CreateMethodHost (ec);
+ }
+
+ public override Iterator Iterator {
+ get { return iterator; }
+ }
+
+ public override bool IsIterator {
+ get { return true; }
+ }
+
+ public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
+ {
+ scope.ScopeTypeBuilder = iterator.TypeBuilder;
+ scope.ScopeConstructor = iterator.ctor.ConstructorBuilder;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new InternalErrorException ();
+ }
+ }
+
+ protected class MoveNextStatement : Statement {
+ Iterator iterator;
+
+ public MoveNextStatement (Iterator iterator, Location loc)
{
this.loc = loc;
this.iterator = iterator;
public override bool Resolve (EmitContext ec)
{
- ec.CurrentBranching.CurrentUsageVector.Return ();
return true;
}
protected override void DoEmit (EmitContext ec)
{
- int code_flags = Modifiers.METHOD_YIELDS;
- if (iterator.is_static)
- code_flags |= Modifiers.STATIC;
-
- EmitContext new_ec = new EmitContext (
- iterator.container, loc, ec.ig,
- TypeManager.int32_type, code_flags);
-
- new_ec.CurrentIterator = iterator;
+ ec.CurrentAnonymousMethod = iterator.move_next_method;
+ ec.InIterator = true;
- iterator.EmitMoveNext (new_ec);
+ iterator.EmitMoveNext (ec);
}
}
}
}
+ protected class InitScope : Statement
+ {
+ Iterator iterator;
+
+ public InitScope (Iterator iterator, Location loc)
+ {
+ this.iterator = iterator;
+ this.loc = loc;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ iterator.cc.EmitInitScope (ec);
+ }
+ }
+
void Define_Reset ()
{
Method reset = new Method (
this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
- false, new MemberName ("Reset"),
- Parameters.EmptyReadOnlyParameters, null, Location);
+ false, new MemberName ("Reset", Location),
+ Parameters.EmptyReadOnlyParameters, null);
AddMethod (reset);
reset.Block = new ToplevelBlock (Location);
+ reset.Block = new ToplevelBlock (block, parameters.Parameters, Location);
+ reset.Block.SetHaveAnonymousMethods (Location, move_next_method);
+
reset.Block.AddStatement (Create_ThrowNotSupported ());
}
{
dispose = new Method (
this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
- false, new MemberName ("Dispose"),
- Parameters.EmptyReadOnlyParameters, null, Location);
+ false, new MemberName ("Dispose", Location),
+ Parameters.EmptyReadOnlyParameters, null);
AddMethod (dispose);
- dispose.Block = new ToplevelBlock (Location);
- dispose.Block.AddStatement (new DisposeMethod (this, Location));
- }
+ dispose.Block = new ToplevelBlock (block, parameters.Parameters, Location);
+ dispose.Block.SetHaveAnonymousMethods (Location, move_next_method);
- public ToplevelBlock Block {
- get { return block; }
+ dispose.Block.AddStatement (new DisposeMethod (this, Location));
}
public Type IteratorType {
- get { return iterator_type; }
+ get { return iterator_type_expr.Type; }
}
//
// This return statement tricks return into not flagging an error for being
// used in a Yields method
//
- class NoCheckReturn : Return {
- public NoCheckReturn (Expression expr, Location loc) : base (expr, loc)
+ class NoCheckReturn : Statement {
+ public Expression Expr;
+
+ public NoCheckReturn (Expression expr, Location l)
{
+ Expr = expr;
+ loc = l;
}
public override bool Resolve (EmitContext ec)
{
- ec.InIterator = false;
- bool ret_val = base.Resolve (ec);
- ec.InIterator = true;
+ Expr = Expr.Resolve (ec);
+ if (Expr == null)
+ return false;
+
+ ec.CurrentBranching.CurrentUsageVector.Return ();
- return ret_val;
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ Expr.Emit (ec);
+ ec.ig.Emit (OpCodes.Ret);
}
}
- bool CheckType (Type t)
+ bool CheckType ()
{
- if (t == TypeManager.ienumerable_type) {
- iterator_type = TypeManager.object_type;
+ Type ret = orig_method.ReturnType;
+
+ if (ret == TypeManager.ienumerable_type) {
+ original_iterator_type = TypeManager.object_type;
is_enumerable = true;
return true;
- } else if (t == TypeManager.ienumerator_type) {
- iterator_type = TypeManager.object_type;
+ }
+ if (ret == TypeManager.ienumerator_type) {
+ original_iterator_type = TypeManager.object_type;
is_enumerable = false;
return true;
}
- if (!t.IsGenericInstance)
+ if (!ret.IsGenericInstance)
return false;
- Type[] args = TypeManager.GetTypeArguments (t);
+ Type[] args = TypeManager.GetTypeArguments (ret);
if (args.Length != 1)
return false;
- Type gt = t.GetGenericTypeDefinition ();
+ Type gt = ret.GetGenericTypeDefinition ();
if (gt == TypeManager.generic_ienumerable_type) {
- iterator_type = args [0];
+ original_iterator_type = args [0];
is_enumerable = true;
return true;
} else if (gt == TypeManager.generic_ienumerator_type) {
- iterator_type = args [0];
+ original_iterator_type = args [0];
is_enumerable = false;
return true;
}