//
// 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
"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");
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;
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);
ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
point.Define (ig);
}
- private static string MakeProxyName (string name)
+ private static MemberName MakeProxyName (string name)
{
int pos = name.LastIndexOf ('.');
if (pos > 0)
name = name.Substring (pos + 1);
- return "<" + name + ">__" + (proxy_count++);
+ return new MemberName ("<" + name + ">__" + (proxy_count++));
}
//
//
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)
+ (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null, loc)
{
this.container = container;
this.return_type = return_type;
this.parameters = parameters;
this.original_name = name;
this.original_block = block;
- this.block = new Block (null);
+ this.block = new ToplevelBlock (loc);
fields = new Hashtable ();
is_static = (modifiers & Modifiers.STATIC) != 0;
}
- public bool Define ()
+ public bool DefineIterator ()
{
+ ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
+
if (!CheckType (return_type)) {
Report.Error (
1624, Location,
//
// Returns the new block for the method, or null on failure
//
- protected override bool DoDefineType ()
+ protected override bool DefineNestedTypes ()
{
Define_Fields ();
Define_Constructor ();
Create_Block ();
- return true;
+ return base.DefineNestedTypes ();
}
Field pc_field;
- Field this_field;
Field current_field;
Method dispose;
+ public Field this_field;
public Field[] parameter_fields;
void Create_Block ()
if (!is_static) {
Type t = container.TypeBuilder;
args.Add (new Argument (
- new SimpleParameterReference (t, 0, Location)));
+ new ThisParameterReference (t, 0, Location)));
}
args.Add (new Argument (new BoolLiteral (false)));
Location loc = Location.Null;
pc_field = new Field (
- TypeManager.system_int32_expr, Modifiers.PRIVATE, "PC",
+ this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "PC",
null, null, loc);
AddField (pc_field);
current_field = new Field (
- iterator_type_expr, Modifiers.PRIVATE, "current",
+ this, iterator_type_expr, Modifiers.PRIVATE, "current",
null, null, loc);
AddField (current_field);
if (!is_static) {
this_field = new Field (
+ this,
new TypeExpression (container.TypeBuilder, Location),
Modifiers.PRIVATE, "this", null, null, loc);
AddField (this_field);
"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]);
Location);
AddConstructor (ctor);
- Block block = ctor.Block = new Block (null);
+ ToplevelBlock block = ctor.Block = new ToplevelBlock (Location);
if (!is_static) {
Type t = container.TypeBuilder;
void Define_Current ()
{
- Block get_block = new Block (null);
+ ToplevelBlock get_block = new ToplevelBlock (Location);
+ MemberName left = new MemberName ("System.Collections.IEnumerator");
+ MemberName name = new MemberName (left, "Current");
get_block.AddStatement (new If (
new Binary (
new FieldExpression (current_field), Location),
Location));
- Accessor getter = new Accessor (get_block, null);
+ Accessor getter = new Accessor (get_block, 0, null, Location);
Property current = new Property (
- this, iterator_type_expr, Modifiers.PUBLIC,
- false, "Current", null, getter, null, Location);
+ this, iterator_type_expr, 0,
+ false, name, null, getter, null, Location);
AddProperty (current);
}
{
Method move_next = new Method (
this, TypeManager.system_boolean_expr,
- Modifiers.PUBLIC, false, "MoveNext",
+ Modifiers.PUBLIC, false, new MemberName ("MoveNext"),
Parameters.EmptyReadOnlyParameters, null,
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);
void Define_GetEnumerator ()
{
+ MemberName left = new MemberName ("System.Collections.IEnumerable");
+ MemberName name = new MemberName (left, "GetEnumerator");
+
Method get_enumerator = new Method (
this,
new TypeExpression (TypeManager.ienumerator_type, Location),
- Modifiers.PUBLIC, false, "GetEnumerator",
+ 0, false, name,
Parameters.EmptyReadOnlyParameters, null,
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),
}
public override void Emit (EmitContext ec)
+ {
+ DoEmit (ec);
+ }
+
+ protected virtual void DoEmit (EmitContext ec)
{
ParameterReference.EmitLdArg (ec.ig, idx);
}
}
+ protected class ThisParameterReference : SimpleParameterReference
+ {
+ public ThisParameterReference (Type type, int idx, Location loc)
+ : base (type, idx, loc)
+ { }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ base.DoEmit (ec);
+ if (ec.TypeContainer is Struct)
+ ec.ig.Emit (OpCodes.Ldobj, type);
+ }
+ }
+
protected class FieldExpression : Expression
{
Field field;
this.field = field;
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return DoResolve (ec);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
if (iterator.is_static)
code_flags |= Modifiers.STATIC;
+ code_flags |= iterator.ModFlags & Modifiers.UNSAFE;
+
EmitContext new_ec = new EmitContext (
iterator.container, loc, ec.ig,
TypeManager.int32_type, code_flags);
{
Method reset = new Method (
this, TypeManager.system_void_expr, Modifiers.PUBLIC,
- false, "Reset", Parameters.EmptyReadOnlyParameters,
- null, Location);
+ false, new MemberName ("Reset"),
+ Parameters.EmptyReadOnlyParameters, null, Location);
AddMethod (reset);
- reset.Block = new Block (null);
+ reset.Block = new ToplevelBlock (Location);
reset.Block.AddStatement (Create_ThrowNotSupported ());
}
{
dispose = new Method (
this, TypeManager.system_void_expr, Modifiers.PUBLIC,
- false, "Dispose", Parameters.EmptyReadOnlyParameters,
- null, Location);
+ false, new MemberName ("Dispose"),
+ 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; }
}