In mcs:
[mono.git] / mcs / gmcs / iterators.cs
index d55efb9c3f1e9374525ac5a0cef12b28b2a5ec68..82250f6bb91c6a674bb7c893de85283e02c8d181 100644 (file)
@@ -39,7 +39,7 @@ namespace Mono.CSharp {
                        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 " +
@@ -51,10 +51,6 @@ namespace Mono.CSharp {
                                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){
@@ -62,9 +58,12 @@ namespace Mono.CSharp {
                                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;
@@ -76,7 +75,7 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       if (!CheckContext (ec, loc))
+                       if (!CheckContext (ec, loc, false))
                                return false;
 
                        Iterator iterator = ec.CurrentIterator;
@@ -107,7 +106,7 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       if (!Yield.CheckContext (ec, loc))
+                       if (!Yield.CheckContext (ec, loc, true))
                                return false;
 
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
@@ -143,8 +142,8 @@ namespace Mono.CSharp {
                TypeContainer container;
                TypeExpr current_type;
                Type this_type;
-               InternalParameters parameters;
-               InternalParameters original_parameters;
+               Parameters parameters;
+               Parameters original_parameters;
                IMethodData orig_method;
 
                MethodInfo dispose_method;
@@ -157,6 +156,7 @@ namespace Mono.CSharp {
                Expression generic_enumerator_type;
                Expression generic_enumerable_type;
                TypeArguments generic_args;
+               EmitContext ec;
 
                protected enum State {
                        Uninitialized   = -2,
@@ -192,7 +192,7 @@ namespace Mono.CSharp {
                        resume_points.Add (entry_point);
                        entry_point.Define (ig);
 
-                       ec.EmitTopBlock (orig_method, original_block, parameters);
+                       ec.EmitTopBlock (orig_method, original_block);
 
                        EmitYieldBreak (ig);
 
@@ -356,19 +356,19 @@ namespace Mono.CSharp {
                //
                // Our constructor
                //
-               public Iterator (IMethodData m_container, TypeContainer container, GenericMethod generic,
-                                InternalParameters parameters, int modifiers)
-                       : base (container.NamespaceEntry, container,
+               public Iterator (IMethodData m_container, DeclSpace parent, GenericMethod generic,
+                                int modifiers)
+                       : 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.original_parameters = parameters;
+                       this.container = parent.PartialContainer;
+                       this.original_parameters = m_container.ParameterInfo;
                        this.original_block = orig_method.Block;
-                       this.block = new ToplevelBlock (orig_method.Block, parameters.Parameters, orig_method.Location);
+                       this.block = new ToplevelBlock (orig_method.Block, parameters, orig_method.Location);
 
                        if (generic != null) {
                                ArrayList constraints = new ArrayList ();
@@ -387,7 +387,7 @@ namespace Mono.CSharp {
 
                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;
 
@@ -504,7 +504,7 @@ namespace Mono.CSharp {
                        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);
@@ -516,7 +516,7 @@ namespace Mono.CSharp {
                                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);
                        }
 
@@ -530,27 +530,19 @@ namespace Mono.CSharp {
                                te, param.Name, param.ModFlags, param.OptAttributes, param.Location);
                }
 
-               InternalParameters InflateParameters (Parameters parameters, EmitContext ec)
+               Parameters 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);
+                       int count = parameters.FixedParameters.Length;
+                       if (count == 0)
+                               return Parameters.EmptyReadOnlyParameters;
+                       Parameter[] fixed_params = new Parameter [count];
+                       for (int i = 0; i < count; i++)
+                               fixed_params [i] = InflateParameter (parameters.FixedParameters [i]);
+
+                       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);
 
@@ -595,7 +587,15 @@ namespace Mono.CSharp {
                        else
                                current_type = new TypeExpression (TypeBuilder, Location);
 
-                       parameters = InflateParameters (original_parameters.Parameters, ec);
+                       if (IsGeneric) {
+                               foreach (TypeParameter tparam in TypeParameters)
+                                       tparam.InflateConstraints (current_type.Type);
+                       }
+
+                       parameters = InflateParameters (original_parameters, ec);
+                       if (!parameters.Resolve (ec)) {
+                               // TODO:
+                       }
 
                        Define_Fields ();
                        Define_Current (false);
@@ -660,7 +660,7 @@ namespace Mono.CSharp {
                                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;
 
@@ -672,12 +672,12 @@ namespace Mono.CSharp {
                {
                        pc_field = new Field (
                                this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "$PC",
-                               null, null, Location);
+                               null, Location);
                        AddField (pc_field);
 
                        current_field = new Field (
                                this, iterator_type_expr, Modifiers.PRIVATE, "$current",
-                               null, null, Location);
+                               null, Location);
                        AddField (current_field);
                }
 
@@ -693,17 +693,16 @@ namespace Mono.CSharp {
                                        "this", Parameter.Modifier.NONE,
                                        null, Location));
                        list.Add (new Parameter (
-                               TypeManager.system_boolean_expr, "initialized",
+                               TypeManager.bool_type, "initialized",
                                Parameter.Modifier.NONE, null, Location));
 
-                       Parameter[] old_fixed = parameters.Parameters.FixedParameters;
-                       if (old_fixed != null)
-                               list.AddRange (old_fixed);
+                       Parameter[] old_fixed = parameters.FixedParameters;
+                       list.AddRange (old_fixed);
 
                        Parameter[] fixed_params = new Parameter [list.Count];
                        list.CopyTo (fixed_params);
 
-                       ctor_params = new Parameters (fixed_params, parameters.Parameters.ArrayParameter);
+                       ctor_params = new Parameters (fixed_params);
 
                        ctor = new Constructor (
                                this, MemberName.Name, Modifiers.PUBLIC, ctor_params,
@@ -711,7 +710,7 @@ namespace Mono.CSharp {
                                Location);
                        AddConstructor (ctor);
 
-                       ctor.Block = new ToplevelBlock (block, parameters.Parameters, Location);
+                       ctor.Block = new ToplevelBlock (block, parameters, Location);
 
                        int first = IsStatic ? 2 : 3;
 
@@ -760,7 +759,7 @@ namespace Mono.CSharp {
                        MemberName name = new MemberName (left, "Current", null, Location);
 
                        ToplevelBlock get_block = new ToplevelBlock (
-                               block, parameters.Parameters, Location);
+                               block, parameters, Location);
 
                        get_block.AddStatement (new If (
                                new Binary (
@@ -809,16 +808,23 @@ namespace Mono.CSharp {
                        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.Parameters, Location);
+                               block, parameters, Location);
 
                        get_enumerator.Block.SetHaveAnonymousMethods (Location, move_next_method);
 
                        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);
@@ -930,7 +936,9 @@ namespace Mono.CSharp {
                        {
                                ec.CurrentAnonymousMethod = iterator.move_next_method;
 
-                               iterator.cc.EmitParameter (ec, name);
+                               LocalTemporary dummy = null;
+                               
+                               iterator.cc.EmitParameter (ec, name, false, false, ref dummy);
                        }
                }
 
@@ -950,7 +958,7 @@ namespace Mono.CSharp {
 
                        public override void Emit (EmitContext ec)
                        {
-                               ec.EmitThis ();
+                               ec.EmitThis (false);
                        }
                }
 
@@ -993,7 +1001,7 @@ namespace Mono.CSharp {
                        Iterator iterator;
 
                        public MoveNextMethod (Iterator iterator, Location loc)
-                               : base (iterator.parameters.Parameters, iterator.original_block, loc)
+                               : base (iterator.parameters, iterator.original_block, loc)
                        {
                                this.iterator = iterator;
                        }
@@ -1022,6 +1030,11 @@ namespace Mono.CSharp {
                                get { return iterator; }
                        }
 
+                       public void ComputeHost ()
+                       {
+                               ComputeMethodHost ();
+                       }
+                       
                        public override bool IsIterator {
                                get { return true; }
                        }
@@ -1054,6 +1067,7 @@ namespace Mono.CSharp {
 
                        protected override void DoEmit (EmitContext ec)
                        {
+                               iterator.move_next_method.ComputeHost ();
                                ec.CurrentAnonymousMethod = iterator.move_next_method;
                                ec.InIterator = true;
 
@@ -1167,7 +1181,7 @@ namespace Mono.CSharp {
                        AddMethod (reset);
 
                        reset.Block = new ToplevelBlock (Location);
-                       reset.Block = new ToplevelBlock (block, parameters.Parameters, Location);
+                       reset.Block = new ToplevelBlock (block, parameters, Location);
                        reset.Block.SetHaveAnonymousMethods (Location, move_next_method);
 
                        reset.Block.AddStatement (Create_ThrowNotSupported ());
@@ -1181,7 +1195,7 @@ namespace Mono.CSharp {
                                Parameters.EmptyReadOnlyParameters, null);
                        AddMethod (dispose);
 
-                       dispose.Block = new ToplevelBlock (block, parameters.Parameters, Location);
+                       dispose.Block = new ToplevelBlock (block, parameters, Location);
                        dispose.Block.SetHaveAnonymousMethods (Location, move_next_method);
 
                        dispose.Block.AddStatement (new DisposeMethod (this, Location));
@@ -1237,7 +1251,7 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       if (!ret.IsGenericInstance)
+                       if (!ret.IsGenericType)
                                return false;
 
                        Type[] args = TypeManager.GetTypeArguments (ret);