2009-08-12 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / iterators.cs
index 7cdb19d1a3c9d4959782bb30d8df3df4325aa33b..ddd316fa14cef277eb578f740bc398dbde7fef4f 100644 (file)
@@ -139,9 +139,9 @@ namespace Mono.CSharp {
        class IteratorStatement : Statement
        {
                Iterator iterator;
-               ExplicitBlock original_block;
+               Block original_block;
 
-               public IteratorStatement (Iterator iterator, ExplicitBlock original_block)
+               public IteratorStatement (Iterator iterator, Block original_block)
                {
                        this.iterator = iterator;
                        this.original_block = original_block;
@@ -183,11 +183,11 @@ namespace Mono.CSharp {
 
                        public IteratorMethod (IteratorStorey host, FullNamedExpression returnType, int mod, MemberName name)
                                : base (host, null, returnType, mod | Modifiers.DEBUGGER_HIDDEN | Modifiers.COMPILER_GENERATED,
-                                 name, Parameters.EmptyReadOnlyParameters, null)
+                                 name, ParametersCompiled.EmptyReadOnlyParameters, null)
                        {
                                this.host = host;
 
-                               Block = new ToplevelBlock (host.Iterator.Container.Toplevel, null, Location);
+                               Block = new ToplevelBlock (host.Iterator.Container.Toplevel, ParametersCompiled.EmptyReadOnlyParameters, Location);
                        }
 
                        public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
@@ -205,15 +205,15 @@ namespace Mono.CSharp {
                        sealed class GetEnumeratorStatement : Statement
                        {
                                IteratorStorey host;
-                               Expression type;
+                               IteratorMethod host_method;
 
                                Expression new_storey;
 
-                               public GetEnumeratorStatement (IteratorStorey host, Expression type)
+                               public GetEnumeratorStatement (IteratorStorey host, IteratorMethod host_method)
                                {
                                        this.host = host;
-                                       this.type = type;
-                                       loc = host.Location;
+                                       this.host_method = host_method;
+                                       loc = host_method.Location;
                                }
 
                                protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -223,10 +223,6 @@ namespace Mono.CSharp {
 
                                public override bool Resolve (EmitContext ec)
                                {
-                                       type = type.ResolveAsTypeTerminal (ec, false);
-                                       if ((type == null) || (type.Type == null))
-                                               return false;
-
                                        TypeExpression storey_type_expr = new TypeExpression (host.TypeBuilder, loc);
                                        ArrayList init = null;
                                        if (host.hoisted_this != null) {
@@ -253,15 +249,15 @@ namespace Mono.CSharp {
                                        }
 
                                        if (init != null) {
-                                               new_storey = new NewInitialize (storey_type_expr, new ArrayList (0),
+                                               new_storey = new NewInitialize (storey_type_expr, null,
                                                        new CollectionOrObjectInitializers (init, loc), loc);
                                        } else {
-                                               new_storey = new New (storey_type_expr, new ArrayList (0), loc);
+                                               new_storey = new New (storey_type_expr, null, loc);
                                        }
 
                                        new_storey = new_storey.Resolve (ec);
                                        if (new_storey != null)
-                                               new_storey = Convert.ImplicitConversionRequired (ec, new_storey, type.Type, loc);
+                                               new_storey = Convert.ImplicitConversionRequired (ec, new_storey, host_method.MemberType, loc);
 
                                        if (TypeManager.int_interlocked_compare_exchange == null) {
                                                Type t = TypeManager.CoreLookupType ("System.Threading", "Interlocked", Kind.Class, true);
@@ -308,7 +304,7 @@ namespace Mono.CSharp {
                        public GetEnumeratorMethod (IteratorStorey host, FullNamedExpression returnType, MemberName name)
                                : base (host, returnType, 0, name)
                        {
-                               Block.AddStatement (new GetEnumeratorStatement (host, type_name));
+                               Block.AddStatement (new GetEnumeratorStatement (host, this));
                        }
                }
 
@@ -350,7 +346,7 @@ namespace Mono.CSharp {
                        {
                                host.AddMethod (this);
 
-                               Block = new ToplevelBlock (host.Iterator.Container, null, Location);
+                               Block = new ToplevelBlock (host.Iterator.Container, ParametersCompiled.EmptyReadOnlyParameters, Location);
                                Block.AddStatement (new DisposeMethodStatement (host.Iterator));
                        }
                }
@@ -377,6 +373,25 @@ namespace Mono.CSharp {
                        }
                }
 
+               class DynamicFieldExpr : FieldExpr
+               {
+                       readonly Field field;
+
+                       public DynamicFieldExpr (Field field, Location loc)
+                               : base (loc)
+                       {
+                               this.field = field;
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               FieldInfo = field.FieldBuilder;
+                               type = TypeManager.TypeToCoreType (FieldInfo.FieldType);
+                               InstanceExpression = new CompilerGeneratedThis (type, Location);
+                               return base.DoResolve (ec);
+                       }
+               }
+
                public readonly Iterator Iterator;
 
                TypeExpr iterator_type_expr;
@@ -385,13 +400,9 @@ namespace Mono.CSharp {
 
                TypeExpr enumerator_type;
                TypeExpr enumerable_type;
-#if GMCS_SOURCE
                TypeArguments generic_args;
                TypeExpr generic_enumerator_type;
                TypeExpr generic_enumerable_type;
-#else
-               const TypeArguments generic_args = null;
-#endif
 
                ArrayList hoisted_params_copy;
                int local_name_idx;
@@ -401,7 +412,6 @@ namespace Mono.CSharp {
                          iterator.OriginalMethod as MemberBase, iterator.GenericMethod, "Iterator")
                {
                        this.Iterator = iterator;
-                       HasHoistedVariables = true;
                }
 
                public Field PC {
@@ -419,10 +429,7 @@ namespace Mono.CSharp {
                protected override TypeExpr [] ResolveBaseTypes (out TypeExpr base_class)
                {
                        iterator_type_expr = new TypeExpression (MutateType (Iterator.OriginalIteratorType), Location);
-
-#if GMCS_SOURCE
                        generic_args = new TypeArguments (iterator_type_expr);
-#endif
 
                        ArrayList list = new ArrayList ();
                        if (Iterator.IsEnumerable) {
@@ -430,12 +437,12 @@ namespace Mono.CSharp {
                                        TypeManager.ienumerable_type, Location);
                                list.Add (enumerable_type);
 
-#if GMCS_SOURCE
-                               generic_enumerable_type = new GenericTypeExpr (
-                                       TypeManager.generic_ienumerable_type,
-                                       generic_args, Location);
-                               list.Add (generic_enumerable_type);
-#endif
+                               if (TypeManager.generic_ienumerable_type != null) {
+                                       generic_enumerable_type = new GenericTypeExpr (
+                                               TypeManager.generic_ienumerable_type,
+                                               generic_args, Location);
+                                       list.Add (generic_enumerable_type);
+                               }
                        }
 
                        enumerator_type = new TypeExpression (
@@ -444,12 +451,12 @@ namespace Mono.CSharp {
 
                        list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
 
-#if GMCS_SOURCE
-                       generic_enumerator_type = new GenericTypeExpr (
-                               TypeManager.generic_ienumerator_type,
-                               generic_args, Location);
-                       list.Add (generic_enumerator_type);
-#endif
+                       if (TypeManager.generic_ienumerator_type != null) {
+                               generic_enumerator_type = new GenericTypeExpr (
+                                       TypeManager.generic_ienumerator_type,
+                                       generic_args, Location);
+                               list.Add (generic_enumerator_type);
+                       }
 
                        type_bases = list;
 
@@ -480,35 +487,38 @@ namespace Mono.CSharp {
                                }
                        }
 
-#if GMCS_SOURCE
-                       Define_Current (true);
-#endif
+                       if (generic_enumerator_type != null)
+                               Define_Current (true);
+
                        Define_Current (false);
                        new DisposeMethod (this);
                        Define_Reset ();
 
                        if (Iterator.IsEnumerable) {
-                               MemberName name = new MemberName (
-                                       new MemberName ("System.Collections.IEnumerable", Location), "GetEnumerator", Location);
-
-#if GMCS_SOURCE
-                               Method get_enumerator = new IteratorMethod (this, enumerator_type, 0, name);
-
-                               name = new MemberName (
-                                       new MemberName ("System.Collections.Generic.IEnumerable", generic_args, Location), "GetEnumerator", Location);
-                               Method gget_enumerator = new GetEnumeratorMethod (this, generic_enumerator_type, name);
-
-                               //
-                               // Just call generic GetEnumerator implementation
-                               //
-                               get_enumerator.Block.AddStatement (
-                                       new Return (new Invocation (new DynamicMethodGroupExpr (gget_enumerator, Location), new ArrayList (0)), Location));
-
-                               AddMethod (get_enumerator);
-                               AddMethod (gget_enumerator);
-#else
-                               AddMethod (new GetEnumeratorMethod (this, enumerator_type, name));
-#endif
+                               MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location);
+                               name = new MemberName (name, "Collections", Location);
+                               name = new MemberName (name, "IEnumerable", Location);
+                               name = new MemberName (name, "GetEnumerator", Location);
+
+                               if (generic_enumerator_type != null) {
+                                       Method get_enumerator = new IteratorMethod (this, enumerator_type, 0, name);
+
+                                       name = new MemberName (name.Left.Left, "Generic", Location);
+                                       name = new MemberName (name, "IEnumerable", generic_args, Location);
+                                       name = new MemberName (name, "GetEnumerator", Location);
+                                       Method gget_enumerator = new GetEnumeratorMethod (this, generic_enumerator_type, name);
+
+                                       //
+                                       // Just call generic GetEnumerator implementation
+                                       //
+                                       get_enumerator.Block.AddStatement (
+                                               new Return (new Invocation (new DynamicMethodGroupExpr (gget_enumerator, Location), null), Location));
+
+                                       AddMethod (get_enumerator);
+                                       AddMethod (gget_enumerator);
+                               } else {
+                                       AddMethod (new GetEnumeratorMethod (this, enumerator_type, name));
+                               }
                        }
                }
 
@@ -520,24 +530,25 @@ namespace Mono.CSharp {
 
                void Define_Current (bool is_generic)
                {
-                       MemberName left;
                        TypeExpr type;
 
+                       MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location);
+                       name = new MemberName (name, "Collections", Location);
+
                        if (is_generic) {
-                               left = new MemberName (
-                                       "System.Collections.Generic.IEnumerator",
-                                       generic_args, Location);
+                               name = new MemberName (name, "Generic", Location);
+                               name = new MemberName (name, "IEnumerator", generic_args, Location);
                                type = iterator_type_expr;
                        } else {
-                               left = new MemberName ("System.Collections.IEnumerator", Location);
+                               name = new MemberName (name, "IEnumerator");
                                type = TypeManager.system_object_expr;
                        }
 
-                       MemberName name = new MemberName (left, "Current", null, Location);
+                       name = new MemberName (name, "Current", Location);
 
                        ToplevelBlock get_block = new ToplevelBlock (Location);
-                       get_block.AddStatement (new CurrentBlock (this, is_generic));
-
+                       get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location));
+                               
                        Accessor getter = new Accessor (get_block, 0, null, null, Location);
 
                        Property current = new Property (
@@ -551,58 +562,16 @@ namespace Mono.CSharp {
                                this, null, TypeManager.system_void_expr,
                                Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
                                new MemberName ("Reset", Location),
-                               Parameters.EmptyReadOnlyParameters, null);
+                               ParametersCompiled.EmptyReadOnlyParameters, null);
                        AddMethod (reset);
 
                        reset.Block = new ToplevelBlock (Location);
-                       reset.Block.AddStatement (Create_ThrowNotSupported ());
-               }
-
-               Statement Create_ThrowNotSupported ()
-               {
-                       TypeExpr ex_type = new TypeLookupExpression ("System.NotSupportedException");
-
-                       return new Throw (new New (ex_type, null, Location), Location);
-               }
-
-               protected class CurrentBlock : Statement {
-                       IteratorStorey host;
-                       bool is_generic;
-
-                       public CurrentBlock (IteratorStorey host, bool is_generic)
-                       {
-                               this.host = host;
-                               this.is_generic = is_generic;
-                               loc = host.Location;
-                       }
-
-                       protected override void CloneTo (CloneContext clonectx, Statement target)
-                       {
-                               throw new NotSupportedException ();
-                       }
-
-                       public override bool Resolve (EmitContext ec)
-                       {
-                               // We emit a 'ret', so prevent the enclosing TopLevelBlock from emitting one too
-                               ec.CurrentBranching.CurrentUsageVector.Goto ();
-                               return true;
-                       }
-
-                       protected override void DoEmit (EmitContext ec)
-                       {
-                               ILGenerator ig = ec.ig;
 
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ig.Emit (OpCodes.Ldfld, host.CurrentField.FieldBuilder);
-                               if (!is_generic)
-                                       ig.Emit (OpCodes.Box, host.CurrentField.MemberType);
-                               ig.Emit (OpCodes.Ret);
-                       }
+                       Type ex_type = TypeManager.CoreLookupType ("System", "NotSupportedException", Kind.Class, true);
+                       if (ex_type == null)
+                               return;
 
-                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-                       {
-                               throw new NotSupportedException ();
-                       }
+                       reset.Block.AddStatement (new Throw (new New (new TypeExpression (ex_type, Location), null, Location), Location));
                }
        }
 
@@ -648,11 +617,6 @@ namespace Mono.CSharp {
                        Start = 0
                }
 
-               public override void AddStoreyReference (AnonymousMethodStorey storey)
-               {
-                       // do nothing
-               }
-
                public void EmitYieldBreak (ILGenerator ig, bool unwind_protect)
                {
                        ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error);
@@ -850,7 +814,7 @@ namespace Mono.CSharp {
                //
                private Iterator (IMethodData method, TypeContainer host, Type iterator_type, bool is_enumerable)
                        : base (
-                               new ToplevelBlock (method.Block, Parameters.EmptyReadOnlyParameters, method.Block.StartLocation),
+                               new ToplevelBlock (method.Block, ParametersCompiled.EmptyReadOnlyParameters, method.Block.StartLocation),
                                TypeManager.bool_type,
                                method.Location)
                {
@@ -873,7 +837,7 @@ namespace Mono.CSharp {
                                this, Storey, null, TypeManager.system_boolean_expr,
                                Modifiers.PUBLIC, OriginalMethod.GetSignatureForError (),
                                new MemberName ("MoveNext", Location),
-                               Parameters.EmptyReadOnlyParameters);
+                               ParametersCompiled.EmptyReadOnlyParameters);
 
                        if (!Compatible (ec))
                                return null;
@@ -932,7 +896,7 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       Parameters parameters = method.ParameterInfo;
+                       ParametersCompiled parameters = method.ParameterInfo;
                        for (int i = 0; i < parameters.Count; i++) {
                                Parameter p = parameters [i];
                                Parameter.Modifier mod = p.ModFlags;
@@ -942,7 +906,7 @@ namespace Mono.CSharp {
                                        return;
                                }
 
-                               if ((mod & Parameter.Modifier.ARGLIST) != 0) {
+                               if (p is ArglistParameter) {
                                        Report.Error (1636, method.Location,
                                                "__arglist is not allowed in parameter list of iterators");
                                        return;
@@ -990,13 +954,13 @@ namespace Mono.CSharp {
 
                        Type gt = TypeManager.DropGenericTypeArguments (ret);
                        if (gt == TypeManager.generic_ienumerable_type) {
-                               original_iterator_type = args [0];
+                               original_iterator_type = TypeManager.TypeToCoreType (args [0]);
                                is_enumerable = true;
                                return true;
                        }
                        
                        if (gt == TypeManager.generic_ienumerator_type) {
-                               original_iterator_type = args [0];
+                               original_iterator_type = TypeManager.TypeToCoreType (args [0]);
                                is_enumerable = false;
                                return true;
                        }