[fix] #631810: Form.DialogResult needs to call its close events *before* closing.
[mono.git] / mcs / mcs / iterators.cs
index b25dff540fc03dbaa26a73ea14a188e70b2f2cc8..0cfccd0759e30e75ebce4eef3323a71557d7da67 100644 (file)
@@ -21,7 +21,7 @@ using System.Reflection.Emit;
 
 namespace Mono.CSharp {
 
-       class Yield : ResumableStatement {
+       public class Yield : ResumableStatement {
                Expression expr;
                bool unwind_protect;
                Iterator iterator;
@@ -35,10 +35,6 @@ namespace Mono.CSharp {
 
                public static bool CheckContext (ResolveContext ec, Location loc)
                {
-                       //
-                       // We can't use `ec.InUnsafe' here because it's allowed to have an iterator
-                       // inside an unsafe class.  See test-martin-29.cs for an example.
-                       //
                        if (!ec.CurrentAnonymousMethod.IsIterator) {
                                ec.Report.Error (1621, loc,
                                              "The yield statement cannot be used inside " +
@@ -119,66 +115,8 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // Wraps method block into iterator wrapper block
-       //
-       class IteratorStatement : Statement
-       {
-               Iterator iterator;
-               Block original_block;
-
-               public IteratorStatement (Iterator iterator, Block original_block)
-               {
-                       this.iterator = iterator;
-                       this.original_block = original_block;
-                       this.loc = iterator.Location;
-               }
-
-               protected override void CloneTo (CloneContext clonectx, Statement target)
-               {
-                       IteratorStatement t = (IteratorStatement) target;
-                       t.original_block = (ExplicitBlock) original_block.Clone (clonectx);
-                       t.iterator = (Iterator) iterator.Clone (clonectx);
-               }
-
-               public override bool Resolve (BlockContext ec)
-               {
-                       ec.StartFlowBranching (iterator);
-                       bool ok = original_block.Resolve (ec);
-                       ec.EndFlowBranching ();
-                       return ok;
-               }
-
-               protected override void DoEmit (EmitContext ec)
-               {
-                       iterator.EmitMoveNext (ec, original_block);
-               }
-       }
-
        public class IteratorStorey : AnonymousMethodStorey
        {
-               class IteratorMethod : Method
-               {
-                       readonly IteratorStorey host;
-
-                       public IteratorMethod (IteratorStorey host, FullNamedExpression returnType, Modifiers mod, MemberName name)
-                               : base (host, null, returnType, mod | Modifiers.DEBUGGER_HIDDEN | Modifiers.COMPILER_GENERATED,
-                                 name, ParametersCompiled.EmptyReadOnlyParameters, null)
-                       {
-                               this.host = host;
-
-                               Block = new ToplevelBlock (Compiler, host.Iterator.Container.Toplevel, ParametersCompiled.EmptyReadOnlyParameters, Location);
-                       }
-
-                       public override EmitContext CreateEmitContext (ILGenerator ig)
-                       {
-                               EmitContext ec = new EmitContext (this, ig, MemberType);
-
-                               ec.CurrentAnonymousMethod = host.Iterator;
-                               return ec;
-                       }
-               }
-
                class GetEnumeratorMethod : IteratorMethod
                {
                        sealed class GetEnumeratorStatement : Statement
@@ -241,7 +179,7 @@ namespace Mono.CSharp {
                                        if (TypeManager.int_interlocked_compare_exchange == null) {
                                                TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Interlocked", MemberKind.Class, true);
                                                if (t != null) {
-                                                       var p = ParametersCompiled.CreateFullyResolved (
+                                                       var p = new ParametersImported (
                                                                new[] {
                                                                        new ParameterData (null, Parameter.Modifier.REF),
                                                                        new ParameterData (null, Parameter.Modifier.NONE),
@@ -249,8 +187,8 @@ namespace Mono.CSharp {
                                                                },
                                                                new[] {
                                                                        TypeManager.int32_type, TypeManager.int32_type, TypeManager.int32_type
-                                                               }
-                                                               );
+                                                               },
+                                                               false);
                                                        var f = new MemberFilter ("CompareExchange", 0, MemberKind.Method, p, TypeManager.int32_type);
                                                        TypeManager.int_interlocked_compare_exchange = TypeManager.GetPredefinedMethod (t, f, loc);
                                                }
@@ -284,7 +222,7 @@ namespace Mono.CSharp {
                        }
 
                        public GetEnumeratorMethod (IteratorStorey host, FullNamedExpression returnType, MemberName name)
-                               : base (host, returnType, 0, name)
+                               : base (host, returnType, Modifiers.DEBUGGER_HIDDEN, name)
                        {
                                Block.AddStatement (new GetEnumeratorStatement (host, this));
                        }
@@ -319,11 +257,11 @@ namespace Mono.CSharp {
                        }
 
                        public DisposeMethod (IteratorStorey host)
-                               : base (host, TypeManager.system_void_expr, Modifiers.PUBLIC, new MemberName ("Dispose", host.Location))
+                               : base (host, new TypeExpression (TypeManager.void_type, host.Location), Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
+                                       new MemberName ("Dispose", host.Location))
                        {
                                host.AddMethod (this);
 
-                               Block = new ToplevelBlock (Compiler, host.Iterator.Container, ParametersCompiled.EmptyReadOnlyParameters, Location);
                                Block.AddStatement (new DisposeMethodStatement (host.Iterator));
                        }
                }
@@ -336,7 +274,7 @@ namespace Mono.CSharp {
                        readonly Method method;
 
                        public DynamicMethodGroupExpr (Method method, Location loc)
-                               : base (null, loc)
+                               : base ((IList<MemberSpec>) null, null, loc)
                        {
                                this.method = method;
                                eclass = ExprClass.Unresolved;
@@ -386,8 +324,8 @@ namespace Mono.CSharp {
                int local_name_idx;
 
                public IteratorStorey (Iterator iterator)
-                       : base (iterator.Container.Toplevel, iterator.Host,
-                         iterator.OriginalMethod as MemberBase, iterator.GenericMethod, "Iterator")
+                       : base (iterator.Container.ParametersBlock, iterator.Host,
+                         iterator.OriginalMethod as MemberBase, iterator.GenericMethod == null ? null : iterator.GenericMethod.CurrentTypeParameters, "Iterator")
                {
                        this.Iterator = iterator;
                }
@@ -445,7 +383,7 @@ namespace Mono.CSharp {
                        return base.ResolveBaseTypes (out base_class);
                }
 
-               protected override string GetVariableMangledName (LocalInfo local_info)
+               protected override string GetVariableMangledName (LocalVariable local_info)
                {
                        return "<" + local_info.Name + ">__" + local_name_idx++.ToString ();
                }
@@ -458,7 +396,7 @@ namespace Mono.CSharp {
 
                void DefineIteratorMembers ()
                {
-                       pc_field = AddCompilerGeneratedField ("$PC", TypeManager.system_int32_expr);
+                       pc_field = AddCompilerGeneratedField ("$PC", new TypeExpression (TypeManager.int32_type, Location));
                        current_field = AddCompilerGeneratedField ("$current", iterator_type_expr);
 
                        if (hoisted_params != null) {
@@ -529,7 +467,7 @@ namespace Mono.CSharp {
                                type = iterator_type_expr;
                        } else {
                                name = new MemberName (name, "IEnumerator");
-                               type = TypeManager.system_object_expr;
+                               type = new TypeExpression (TypeManager.object_type, Location);
                        }
 
                        name = new MemberName (name, "Current", Location);
@@ -537,17 +475,17 @@ namespace Mono.CSharp {
                        ToplevelBlock get_block = new ToplevelBlock (Compiler, Location);
                        get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location));
                                
-                       Accessor getter = new Accessor (get_block, 0, null, null, Location);
+                       Property current = new Property (this, type, Modifiers.DEBUGGER_HIDDEN, name, null);
+                       current.Get = new Property.GetMethod (current, 0, null, Location);
+                       current.Get.Block = get_block;
 
-                       Property current = new Property (
-                               this, type, Modifiers.DEBUGGER_HIDDEN, name, null, getter, null, false);
                        AddProperty (current);
                }
 
                void Define_Reset ()
                {
                        Method reset = new Method (
-                               this, null, TypeManager.system_void_expr,
+                               this, null, new TypeExpression (TypeManager.void_type, Location),
                                Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
                                new MemberName ("Reset", Location),
                                ParametersCompiled.EmptyReadOnlyParameters, null);
@@ -563,12 +501,60 @@ namespace Mono.CSharp {
                }
        }
 
+       class IteratorMethod : Method
+       {
+               readonly IteratorStorey host;
+
+               public IteratorMethod (IteratorStorey host, FullNamedExpression returnType, Modifiers mod, MemberName name)
+                       : base (host, null, returnType, mod | Modifiers.COMPILER_GENERATED,
+                         name, ParametersCompiled.EmptyReadOnlyParameters, null)
+               {
+                       this.host = host;
+
+                       Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
+               }
+
+               public override EmitContext CreateEmitContext (ILGenerator ig)
+               {
+                       EmitContext ec = new EmitContext (this, ig, MemberType);
+
+                       ec.CurrentAnonymousMethod = host.Iterator;
+                       return ec;
+               }
+       }
+
        //
        // Iterators are implemented as hidden anonymous block
        //
-       public class Iterator : AnonymousExpression {
+       public class Iterator : AnonymousExpression
+       {
+               sealed class MoveNextMethodStatement : Statement
+               {
+                       Iterator iterator;
+
+                       public MoveNextMethodStatement (Iterator iterator)
+                       {
+                               this.iterator = iterator;
+                               this.loc = iterator.Location;
+                       }
+
+                       protected override void CloneTo (CloneContext clonectx, Statement target)
+                       {
+                               throw new NotSupportedException ();
+                       }
+
+                       public override bool Resolve (BlockContext ec)
+                       {
+                               return true;
+                       }
+
+                       protected override void DoEmit (EmitContext ec)
+                       {
+                               iterator.EmitMoveNext (ec);
+                       }
+               }
+
                public readonly IMethodData OriginalMethod;
-               AnonymousMethodMethod method;
                public readonly TypeContainer Host;
                public readonly bool IsEnumerable;
                List<ResumableStatement> resume_points;
@@ -597,7 +583,7 @@ namespace Mono.CSharp {
 
                public readonly TypeSpec OriginalIteratorType;
 
-               readonly IteratorStorey IteratorHost;
+               IteratorStorey IteratorHost;
 
                public enum State {
                        Running = -3, // Used only in CurrentPC, never stored into $PC
@@ -632,13 +618,13 @@ namespace Mono.CSharp {
                        ec.Emit (OpCodes.Ret);
                }
 
-               internal void EmitMoveNext (EmitContext ec, Block original_block)
+               void EmitMoveNext (EmitContext ec)
                {
                        move_next_ok = ec.DefineLabel ();
                        move_next_error = ec.DefineLabel ();
 
                        if (resume_points == null) {
-                               EmitMoveNext_NoResumePoints (ec, original_block);
+                               EmitMoveNext_NoResumePoints (ec, block);
                                return;
                        }
 
@@ -678,7 +664,7 @@ namespace Mono.CSharp {
                        ec.MarkLabel (labels [0]);
 
                        SymbolWriter.StartIteratorBody (ec);
-                       original_block.Emit (ec);
+                       block.Emit (ec);
                        SymbolWriter.EndIteratorBody (ec);
 
                        SymbolWriter.StartIteratorDispatcher (ec);
@@ -777,34 +763,29 @@ namespace Mono.CSharp {
                        ec.MarkLabel (resume_point);
                }
 
-               public override string ContainerType {
-                       get { return "iterator"; }
-               }
-
-               public override bool IsIterator {
-                       get { return true; }
-               }
-
-               public override AnonymousMethodStorey Storey {
-                       get { return IteratorHost; }
-               }
-
                //
                // Our constructor
                //
-               private Iterator (CompilerContext ctx, IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable)
-                       : base (
-                               new ToplevelBlock (ctx, method.Block, ParametersCompiled.EmptyReadOnlyParameters, method.Block.StartLocation),
-                               TypeManager.bool_type,
-                               method.Location)
+               public Iterator (ParametersBlock block, IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable)
+                       : base (block, TypeManager.bool_type, block.StartLocation)
                {
                        this.OriginalMethod = method;
                        this.OriginalIteratorType = iterator_type;
                        this.IsEnumerable = is_enumerable;
                        this.Host = host;
                        this.type = method.ReturnType;
+               }
+
+               public override string ContainerType {
+                       get { return "iterator"; }
+               }
 
-                       IteratorHost = Block.ChangeToIterator (this, method.Block);
+               public override bool IsIterator {
+                       get { return true; }
+               }
+
+               public override AnonymousMethodStorey Storey {
+                       get { return IteratorHost; }
                }
 
                public override string GetSignatureForError ()
@@ -814,14 +795,19 @@ namespace Mono.CSharp {
 
                protected override Expression DoResolve (ResolveContext ec)
                {
-                       method = new AnonymousMethodMethod (Storey,
-                               this, Storey, null, TypeManager.system_boolean_expr,
-                               Modifiers.PUBLIC, OriginalMethod.GetSignatureForError (),
-                               new MemberName ("MoveNext", Location),
-                               ParametersCompiled.EmptyReadOnlyParameters);
+                       IteratorHost = (IteratorStorey) block.TopBlock.AnonymousMethodStorey;
+
+                       BlockContext ctx = new BlockContext (ec, block, ReturnType);
+                       ctx.CurrentAnonymousMethod = this;
 
-                       if (Compatible (ec) == null)
-                               return null;
+                       ctx.StartFlowBranching (this, ec.CurrentBranching);
+                       Block.Resolve (ctx);
+                       ctx.EndFlowBranching ();
+
+                       var move_next = new IteratorMethod (IteratorHost, new TypeExpression (TypeManager.bool_type, loc),
+                               Modifiers.PUBLIC, new MemberName ("MoveNext", Location));
+                       move_next.Block.AddStatement (new MoveNextMethodStatement (this));
+                       IteratorHost.AddMethod (move_next);
 
                        eclass = ExprClass.Value;
                        return this;
@@ -832,7 +818,7 @@ namespace Mono.CSharp {
                        //
                        // Load Iterator storey instance
                        //
-                       method.Storey.Instance.Emit (ec);
+                       IteratorHost.Instance.Emit (ec);
 
                        //
                        // Initialize iterator PC when it's unitialized
@@ -899,11 +885,9 @@ namespace Mono.CSharp {
 
                        if ((modifiers & Modifiers.UNSAFE) != 0) {
                                ctx.Report.Error (1629, method.Location, "Unsafe code may not appear in iterators");
-                               return;
                        }
 
-                       // TODO: Ugly leftover
-                       new Iterator (ctx, method, parent, iterator_type, is_enumerable);
+                       method.Block.WrapIntoIterator (method, parent, iterator_type, is_enumerable);
                }
 
                static bool CheckType (TypeSpec ret, out TypeSpec original_iterator_type, out bool is_enumerable)