//
// 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
"catch clause");
return false;
}
- if (ec.InAnonymousMethod){
- Report.Error (1621, loc, "yield statement can not appear " +
- "inside an anonymoud method");
+ if (ec.CurrentAnonymousMethod != null){
+ Report.Error (1621, loc, "yield statement can not appear inside an anonymoud method");
return false;
}
}
public class Iterator : Class {
+ ToplevelBlock original_block;
+ ToplevelBlock block;
string original_name;
- Block original_block;
- Block block;
Type iterator_type;
TypeExpr iterator_type_expr;
// Context from the original method
//
TypeContainer container;
+ TypeExpr current_type;
+ Type this_type;
Type return_type;
Type [] param_types;
InternalParameters parameters;
+ MethodInfo dispose_method;
+
Expression enumerator_type;
Expression enumerable_type;
Expression generic_enumerator_type;
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);
//
public Iterator (TypeContainer container, string name, Type return_type,
Type [] param_types, InternalParameters parameters,
- int modifiers, Block block, Location loc)
+ int modifiers, ToplevelBlock block, Location loc)
: base (container.NamespaceEntry, container, MakeProxyName (name),
Modifiers.PRIVATE, null, loc)
{
this.parameters = parameters;
this.original_name = name;
this.original_block = block;
- this.block = new Block (null);
+ this.block = new ToplevelBlock (loc);
fields = new Hashtable ();
public bool DefineIterator ()
{
+ ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
+
if (!CheckType (return_type)) {
Report.Error (
1624, Location,
}
}
+ if (container.CurrentType != null)
+ this_type = container.CurrentType;
+ else
+ this_type = container.TypeBuilder;
+
generic_args = new TypeArguments (Location);
generic_args.Add (new TypeExpression (iterator_type, Location));
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 ()
+ {
+ if (!base.DoDefineMembers ())
+ return false;
+
+ dispose_method = FetchMethodDispose ();
+ if (dispose_method == null)
+ return false;
+
+ return true;
+ }
+
//
// Returns the new block for the method, or null on failure
//
protected override bool DefineNestedTypes ()
{
+ if (CurrentType != null)
+ current_type = new TypeExpression (CurrentType, Location);
+ else
+ current_type = new TypeExpression (TypeBuilder, Location);
+
Define_Fields ();
Define_Constructor ();
Define_Current (false);
ArrayList args = new ArrayList ();
if (!is_static) {
- Type t = container.TypeBuilder;
+ Type t = this_type;
args.Add (new Argument (
new ThisParameterReference (t, 0, Location)));
}
new SimpleParameterReference (t, first + i, Location)));
}
- Expression new_expr = new New (
- new TypeExpression (TypeBuilder, Location), args, Location);
+ Expression new_expr = new New (current_type, args, Location);
block.AddStatement (new NoCheckReturn (new_expr, Location));
}
if (!is_static) {
this_field = new Field (
- this,
- new TypeExpression (container.TypeBuilder, Location),
+ this, new TypeExpression (this_type, loc),
Modifiers.PRIVATE, "this", null, null, loc);
AddField (this_field);
}
if (!is_static)
list.Add (new Parameter (
- new TypeExpression (container.TypeBuilder, Location),
+ new TypeExpression (this_type, Location),
"this", Parameter.Modifier.NONE, null));
list.Add (new Parameter (
TypeManager.system_boolean_expr, "initialized",
Location);
AddConstructor (ctor);
- Block block = ctor.Block = new Block (null);
+ ToplevelBlock block = ctor.Block = new ToplevelBlock (Location);
if (!is_static) {
- Type t = container.TypeBuilder;
+ Type t = this_type;
Assign assign = new Assign (
new FieldExpression (this_field),
MemberName name = new MemberName (left, "Current", null);
- Block get_block = new Block (null);
+ ToplevelBlock get_block = new ToplevelBlock (Location);
get_block.AddStatement (new If (
new Binary (
new FieldExpression (current_field), Location),
Location));
- Accessor getter = new Accessor (get_block, null, Location);
+ Accessor getter = new Accessor (get_block, 0, null, Location);
Property current = new Property (
this, type, 0, false, name, null, getter, null, Location);
Location.Null);
AddMethod (move_next);
- Block block = move_next.Block = new Block (null);
+ ToplevelBlock block = move_next.Block = new ToplevelBlock (Location);
MoveNextMethod inline = new MoveNextMethod (this, Location);
block.AddStatement (inline);
Location.Null);
AddMethod (get_enumerator);
- get_enumerator.Block = new Block (null);
+ get_enumerator.Block = new ToplevelBlock (Location);
Expression ce = new MemberAccess (
new SimpleName ("System.Threading.Interlocked", Location),
args.Add (new Argument (
new FieldExpression (parameter_fields [i])));
- Expression new_expr = new New (
- new TypeExpression (TypeBuilder, Location), args, Location);
+ Expression new_expr = new New (current_type, args, Location);
get_enumerator.Block.AddStatement (new Return (new_expr, Location));
}
Parameters.EmptyReadOnlyParameters, null, Location);
AddMethod (reset);
- reset.Block = new Block (null);
+ reset.Block = new ToplevelBlock (Location);
reset.Block.AddStatement (Create_ThrowNotSupported ());
}
Parameters.EmptyReadOnlyParameters, null, Location);
AddMethod (dispose);
- dispose.Block = new Block (null);
+ dispose.Block = new ToplevelBlock (Location);
dispose.Block.AddStatement (new DisposeMethod (this, Location));
}
- public Block Block {
+ public ToplevelBlock Block {
get { return block; }
}