loc = l;
}
- public static bool CheckContext (EmitContext ec, Location loc)
+ public static bool CheckContext (EmitContext ec, Location loc, bool isYieldBreak)
{
if (ec.InFinally) {
Report.Error (1625, loc, "Cannot yield in the body of a " +
Report.Error (1629, loc, "Unsafe code may not appear in iterators");
return false;
}
- if (ec.InCatch){
- Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
- return false;
- }
AnonymousContainer am = ec.CurrentAnonymousMethod;
if ((am != null) && !am.IsIterator){
return false;
}
- if (ec.CurrentBranching.InTryWithCatch ()) {
- Report.Error (1626, loc, "Cannot yield a value in the body of a " +
+ if (ec.CurrentBranching.InTryWithCatch () && (!isYieldBreak || !ec.InCatch)) {
+ if (!ec.InCatch)
+ Report.Error (1626, loc, "Cannot yield a value in the body of a " +
"try block with a catch clause");
+ else
+ Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
return false;
}
return true;
if (expr == null)
return false;
- if (!CheckContext (ec, loc))
+ if (!CheckContext (ec, loc, false))
return false;
Iterator iterator = ec.CurrentIterator;
public override bool Resolve (EmitContext ec)
{
- if (!Yield.CheckContext (ec, loc))
+ if (!Yield.CheckContext (ec, loc, true))
return false;
ec.CurrentBranching.CurrentUsageVector.Goto ();
Expression generic_enumerator_type;
Expression generic_enumerable_type;
TypeArguments generic_args;
+ EmitContext ec;
protected enum State {
Uninitialized = -2,
//
// Our constructor
//
- public Iterator (IMethodData m_container, TypeContainer container, GenericMethod generic,
+ public Iterator (IMethodData m_container, DeclSpace parent, GenericMethod generic,
int modifiers)
- : base (container.NamespaceEntry, container,
+ : base (parent.NamespaceEntry, parent,
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.container = parent.PartialContainer;
this.original_parameters = m_container.ParameterInfo;
this.original_block = orig_method.Block;
this.block = new ToplevelBlock (orig_method.Block, parameters, orig_method.Location);
public bool DefineIterator ()
{
- ec = new EmitContext (this, Location, null, null, ModFlags);
+ ec = new EmitContext (this, this, Location, null, null, ModFlags);
ec.CurrentAnonymousMethod = move_next_method;
ec.InIterator = true;
if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
int pos = it.GenericParameterPosition;
it = CurrentTypeParameters [pos].Type;
- } else if (it.IsGenericInstance) {
+ } else if (it.IsGenericType) {
Type[] args = it.GetGenericArguments ();
TypeArguments inflated = new TypeArguments (Location);
TypeExpr et_expr = InflateType (it.GetElementType ());
int rank = it.GetArrayRank ();
- Type et = et_expr.ResolveAsTypeTerminal (ec).Type;
+ Type et = et_expr.ResolveAsTypeTerminal (ec, false).Type;
it = et.MakeArrayType (rank);
}
return new Parameters (fixed_params, parameters.HasArglist);
}
- protected override TypeExpr [] GetClassBases (out TypeExpr base_class)
+ public override TypeExpr [] GetClassBases (out TypeExpr base_class)
{
iterator_type_expr = InflateType (original_iterator_type);
else
current_type = new TypeExpression (TypeBuilder, Location);
+ if (IsGeneric) {
+ foreach (TypeParameter tparam in TypeParameters)
+ tparam.InflateConstraints (current_type.Type);
+ }
+
parameters = InflateParameters (original_parameters, ec);
if (!parameters.Resolve (ec)) {
// TODO:
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);
+ proxy_type = ct.ResolveAsTypeTerminal (ec, false);
} else
proxy_type = current_type;
Method get_enumerator = new Method (
this, null, type, 0, false, name,
Parameters.EmptyReadOnlyParameters, null);
- AddMethod (get_enumerator);
+
+ //
+ // We call append instead of add, as we need to make sure that
+ // this method is resolved after the MoveNext method, as that one
+ // triggers the computation of the AnonymousMethod Scope, which is
+ // required during the code generation of the enumerator
+ //
+ AppendMethod (get_enumerator);
get_enumerator.Block = new ToplevelBlock (
block, parameters, Location);
Expression ce = new MemberAccess (
new SimpleName ("System.Threading.Interlocked", Location),
- "CompareExchange", Location);
+ "CompareExchange");
Expression pc = new FieldExpression (this, pc_field);
Expression before = new IntLiteral ((int) State.Running, Location);
public override void Emit (EmitContext ec)
{
- ec.EmitThis ();
+ ec.EmitThis (false);
}
}
get { return iterator; }
}
+ public void ComputeHost ()
+ {
+ ComputeMethodHost ();
+ }
+
public override bool IsIterator {
get { return true; }
}
protected override void DoEmit (EmitContext ec)
{
+ iterator.move_next_method.ComputeHost ();
ec.CurrentAnonymousMethod = iterator.move_next_method;
ec.InIterator = true;
return true;
}
- if (!ret.IsGenericInstance)
+ if (!ret.IsGenericType)
return false;
Type[] args = TypeManager.GetTypeArguments (ret);