X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fiterators.cs;h=85cd202458601957feeb19acffd112fa21a28714;hb=74c2eca79fe94d3b29d339703689fd2f2787e792;hp=998073f76543f371ae72ac03900262b42fef5fba;hpb=5a0f1833b9c8bd67f7415fd630b1b9345bbd1545;p=mono.git diff --git a/mcs/gmcs/iterators.cs b/mcs/gmcs/iterators.cs index 998073f7654..85cd2024586 100644 --- a/mcs/gmcs/iterators.cs +++ b/mcs/gmcs/iterators.cs @@ -8,7 +8,7 @@ // // 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 @@ -51,9 +51,8 @@ namespace Mono.CSharp { "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; } @@ -112,9 +111,9 @@ namespace Mono.CSharp { } public class Iterator : Class { + ToplevelBlock original_block; + ToplevelBlock block; string original_name; - Block original_block; - Block block; Type iterator_type; TypeExpr iterator_type_expr; @@ -134,10 +133,14 @@ namespace Mono.CSharp { // Context from the original method // TypeContainer container; + TypeExpr current_type; + Type this_type; Type return_type; Type [] param_types; InternalParameters parameters; + MethodInfo dispose_method; + Expression enumerator_type; Expression enumerable_type; Expression generic_enumerator_type; @@ -156,6 +159,7 @@ namespace Mono.CSharp { { ig.Emit (OpCodes.Ldarg_0); IntConstant.EmitInt (ig, (int) State.After); + ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder); ig.Emit (OpCodes.Br, move_next_error); } @@ -205,7 +209,7 @@ namespace Mono.CSharp { ig.BeginFaultBlock (); ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Callvirt, dispose.MethodBuilder); + ig.Emit (OpCodes.Callvirt, dispose_method); ig.EndExceptionBlock (); @@ -222,6 +226,7 @@ namespace Mono.CSharp { 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]; @@ -245,6 +250,7 @@ namespace Mono.CSharp { ig.EndExceptionBlock (); ig.Emit (OpCodes.Br, end); } + ec.RemapToProxy = false; ig.MarkLabel (dispatcher); ig.Emit (OpCodes.Ldarg_0); @@ -354,7 +360,7 @@ namespace Mono.CSharp { // 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) { @@ -364,7 +370,7 @@ namespace Mono.CSharp { this.parameters = parameters; this.original_name = name; this.original_block = block; - this.block = new Block (null); + this.block = new ToplevelBlock (loc); fields = new Hashtable (); @@ -373,6 +379,8 @@ namespace Mono.CSharp { public bool DefineIterator () { + ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags); + if (!CheckType (return_type)) { Report.Error ( 1624, Location, @@ -392,6 +400,11 @@ namespace Mono.CSharp { } } + if (container.CurrentType != null) + this_type = container.CurrentType; + else + this_type = container.TypeBuilder; + generic_args = new TypeArguments (Location); generic_args.Add (new TypeExpression (iterator_type, Location)); @@ -426,11 +439,43 @@ namespace Mono.CSharp { return true; } + MethodInfo FetchMethodDispose () + { + MemberList dispose_list; + + dispose_list = FindMembers ( + current_type.Type, + MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance, + Type.FilterName, "Dispose"); + + if (dispose_list.Count != 1) + throw new InternalErrorException ("Cannot find Dipose() method."); + + return (MethodInfo) dispose_list [0]; + } + + protected override bool DoDefineMembers () + { + if (!base.DoDefineMembers ()) + return false; + + dispose_method = FetchMethodDispose (); + if (dispose_method == null) + return false; + + return true; + } + // // Returns the new block for the method, or null on failure // protected override bool DefineNestedTypes () { + if (CurrentType != null) + current_type = new TypeExpression (CurrentType, Location); + else + current_type = new TypeExpression (TypeBuilder, Location); + Define_Fields (); Define_Constructor (); Define_Current (false); @@ -463,7 +508,7 @@ namespace Mono.CSharp { ArrayList args = new ArrayList (); if (!is_static) { - Type t = container.TypeBuilder; + Type t = this_type; args.Add (new Argument ( new ThisParameterReference (t, 0, Location))); } @@ -476,8 +521,7 @@ namespace Mono.CSharp { new SimpleParameterReference (t, first + i, Location))); } - Expression new_expr = new New ( - new TypeExpression (TypeBuilder, Location), args, Location); + Expression new_expr = new New (current_type, args, Location); block.AddStatement (new NoCheckReturn (new_expr, Location)); } @@ -498,8 +542,7 @@ namespace Mono.CSharp { if (!is_static) { this_field = new Field ( - this, - new TypeExpression (container.TypeBuilder, Location), + this, new TypeExpression (this_type, loc), Modifiers.PRIVATE, "this", null, null, loc); AddField (this_field); } @@ -525,7 +568,7 @@ namespace Mono.CSharp { if (!is_static) list.Add (new Parameter ( - new TypeExpression (container.TypeBuilder, Location), + new TypeExpression (this_type, Location), "this", Parameter.Modifier.NONE, null)); list.Add (new Parameter ( TypeManager.system_boolean_expr, "initialized", @@ -549,10 +592,10 @@ namespace Mono.CSharp { Location); AddConstructor (ctor); - Block block = ctor.Block = new Block (null); + ToplevelBlock block = ctor.Block = new ToplevelBlock (Location); if (!is_static) { - Type t = container.TypeBuilder; + Type t = this_type; Assign assign = new Assign ( new FieldExpression (this_field), @@ -617,7 +660,7 @@ namespace Mono.CSharp { MemberName name = new MemberName (left, "Current", null); - Block get_block = new Block (null); + ToplevelBlock get_block = new ToplevelBlock (Location); get_block.AddStatement (new If ( new Binary ( @@ -629,7 +672,7 @@ namespace Mono.CSharp { new FieldExpression (current_field), Location), Location)); - Accessor getter = new Accessor (get_block, null, Location); + Accessor getter = new Accessor (get_block, 0, null, Location); Property current = new Property ( this, type, 0, false, name, null, getter, null, Location); @@ -645,7 +688,7 @@ namespace Mono.CSharp { 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); @@ -673,7 +716,7 @@ namespace Mono.CSharp { 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), @@ -706,8 +749,7 @@ namespace Mono.CSharp { args.Add (new Argument ( new FieldExpression (parameter_fields [i]))); - Expression new_expr = new New ( - new TypeExpression (TypeBuilder, Location), args, Location); + Expression new_expr = new New (current_type, args, Location); get_enumerator.Block.AddStatement (new Return (new_expr, Location)); } @@ -890,7 +932,7 @@ namespace Mono.CSharp { Parameters.EmptyReadOnlyParameters, null, Location); AddMethod (reset); - reset.Block = new Block (null); + reset.Block = new ToplevelBlock (Location); reset.Block.AddStatement (Create_ThrowNotSupported ()); } @@ -902,11 +944,11 @@ namespace Mono.CSharp { 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; } }