2 // iterators.cs: Support for implementing iterators
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2003 Ximian, Inc.
10 // Flow analysis for Yield.
11 // Emit calls to base object constructor.
14 // Current should be defined to return T, and IEnumerator.Current returns object
18 using System
.Collections
;
19 using System
.Reflection
;
20 using System
.Reflection
.Emit
;
22 namespace Mono
.CSharp
{
24 public interface IIteratorContainer
{
27 // Invoked if a yield statement is found in the body
32 public class Yield
: Statement
{
34 ArrayList finally_blocks
;
36 public Yield (Expression expr
, Location l
)
42 public static bool CheckContext (EmitContext ec
, Location loc
)
45 Report
.Error (1625, loc
, "Cannot yield in the body of a " +
51 Report
.Error (1629, loc
, "Unsafe code may not appear in iterators");
55 Report
.Error (1631, loc
, "Cannot yield a value in the body of a catch clause");
59 AnonymousContainer am
= ec
.CurrentAnonymousMethod
;
60 if ((am
!= null) && !am
.IsIterator
){
61 Report
.Error (1621, loc
, "The yield statement cannot be used inside anonymous method blocks");
65 if (ec
.CurrentBranching
.InTryWithCatch ()) {
66 Report
.Error (1626, loc
, "Cannot yield a value in the body of a " +
67 "try block with a catch clause");
73 public override bool Resolve (EmitContext ec
)
75 expr
= expr
.Resolve (ec
);
79 if (!CheckContext (ec
, loc
))
82 Iterator iterator
= ec
.CurrentIterator
;
84 if (expr
.Type
!= iterator
.IteratorType
){
85 expr
= Convert
.ImplicitConversionRequired (
86 ec
, expr
, iterator
.IteratorType
, loc
);
91 ec
.CurrentBranching
.StealFinallyClauses (ref finally_blocks
);
95 protected override void DoEmit (EmitContext ec
)
97 ec
.CurrentIterator
.MarkYield (ec
, expr
, finally_blocks
);
101 public class YieldBreak
: Statement
{
103 public YieldBreak (Location l
)
108 public override bool Resolve (EmitContext ec
)
110 if (!Yield
.CheckContext (ec
, loc
))
113 ec
.CurrentBranching
.CurrentUsageVector
.Goto ();
117 protected override void DoEmit (EmitContext ec
)
119 ec
.CurrentIterator
.EmitYieldBreak (ec
.ig
);
123 public class Iterator
: Class
{
124 protected ToplevelBlock original_block
;
125 protected ToplevelBlock block
;
128 TypeExpr iterator_type_expr
;
130 public readonly bool IsStatic
;
133 // The state as we generate the iterator
135 Label move_next_ok
, move_next_error
;
136 ArrayList resume_points
= new ArrayList ();
140 // Context from the original method
142 TypeContainer container
;
144 Parameters parameters
;
145 IMethodData orig_method
;
147 MoveNextMethod move_next_method
;
151 protected enum State
{
157 static int proxy_count
;
159 public void EmitYieldBreak (ILGenerator ig
)
161 ig
.Emit (OpCodes
.Ldarg_0
);
162 IntConstant
.EmitInt (ig
, (int) State
.After
);
163 ig
.Emit (OpCodes
.Stfld
, pc_field
.FieldBuilder
);
164 ig
.Emit (OpCodes
.Br
, move_next_error
);
167 public void EmitMoveNext (EmitContext ec
)
169 ILGenerator ig
= ec
.ig
;
171 move_next_ok
= ig
.DefineLabel ();
172 move_next_error
= ig
.DefineLabel ();
174 LocalBuilder retval
= ec
.GetTemporaryLocal (TypeManager
.int32_type
);
176 ig
.BeginExceptionBlock ();
178 Label dispatcher
= ig
.DefineLabel ();
179 ig
.Emit (OpCodes
.Br
, dispatcher
);
181 ResumePoint entry_point
= new ResumePoint (null);
182 resume_points
.Add (entry_point
);
183 entry_point
.Define (ig
);
185 ec
.EmitTopBlock (orig_method
, original_block
);
189 ig
.MarkLabel (dispatcher
);
191 Label
[] labels
= new Label
[resume_points
.Count
];
192 for (int i
= 0; i
< labels
.Length
; i
++)
193 labels
[i
] = ((ResumePoint
) resume_points
[i
]).Label
;
195 ig
.Emit (OpCodes
.Ldarg_0
);
196 ig
.Emit (OpCodes
.Ldfld
, pc_field
.FieldBuilder
);
197 ig
.Emit (OpCodes
.Switch
, labels
);
199 Label end
= ig
.DefineLabel ();
201 ig
.MarkLabel (move_next_error
);
202 ig
.Emit (OpCodes
.Ldc_I4_0
);
203 ig
.Emit (OpCodes
.Stloc
, retval
);
204 ig
.Emit (OpCodes
.Leave
, end
);
206 ig
.MarkLabel (move_next_ok
);
207 ig
.Emit (OpCodes
.Ldc_I4_1
);
208 ig
.Emit (OpCodes
.Stloc
, retval
);
209 ig
.Emit (OpCodes
.Leave
, end
);
211 ig
.BeginFaultBlock ();
213 ig
.Emit (OpCodes
.Ldarg_0
);
214 ig
.Emit (OpCodes
.Callvirt
, dispose
.MethodBuilder
);
216 ig
.EndExceptionBlock ();
219 ig
.Emit (OpCodes
.Ldloc
, retval
);
220 ig
.Emit (OpCodes
.Ret
);
223 public void EmitDispose (EmitContext ec
)
225 ILGenerator ig
= ec
.ig
;
227 Label end
= ig
.DefineLabel ();
228 Label dispatcher
= ig
.DefineLabel ();
229 ig
.Emit (OpCodes
.Br
, dispatcher
);
231 Label
[] labels
= new Label
[resume_points
.Count
];
232 for (int i
= 0; i
< labels
.Length
; i
++) {
233 ResumePoint point
= (ResumePoint
) resume_points
[i
];
235 if (point
.FinallyBlocks
== null) {
240 labels
[i
] = ig
.DefineLabel ();
241 ig
.MarkLabel (labels
[i
]);
243 ig
.BeginExceptionBlock ();
244 ig
.BeginFinallyBlock ();
246 foreach (ExceptionStatement stmt
in point
.FinallyBlocks
) {
248 stmt
.EmitFinally (ec
);
251 ig
.EndExceptionBlock ();
252 ig
.Emit (OpCodes
.Br
, end
);
255 ig
.MarkLabel (dispatcher
);
256 ig
.Emit (OpCodes
.Ldarg_0
);
257 ig
.Emit (OpCodes
.Ldfld
, pc_field
.FieldBuilder
);
258 ig
.Emit (OpCodes
.Switch
, labels
);
260 ig
.Emit (OpCodes
.Ldarg_0
);
261 IntConstant
.EmitInt (ig
, (int) State
.After
);
262 ig
.Emit (OpCodes
.Stfld
, pc_field
.FieldBuilder
);
267 protected class ResumePoint
270 public readonly ExceptionStatement
[] FinallyBlocks
;
272 public ResumePoint (ArrayList list
)
275 FinallyBlocks
= new ExceptionStatement
[list
.Count
];
276 list
.CopyTo (FinallyBlocks
, 0);
280 public void Define (ILGenerator ig
)
282 Label
= ig
.DefineLabel ();
283 ig
.MarkLabel (Label
);
288 // Called back from Yield
290 public void MarkYield (EmitContext ec
, Expression expr
,
291 ArrayList finally_blocks
)
293 ILGenerator ig
= ec
.ig
;
295 // Store the new current
296 ig
.Emit (OpCodes
.Ldarg_0
);
298 ig
.Emit (OpCodes
.Stfld
, current_field
.FieldBuilder
);
302 ig
.Emit (OpCodes
.Ldarg_0
);
303 IntConstant
.EmitInt (ig
, pc
);
304 ig
.Emit (OpCodes
.Stfld
, pc_field
.FieldBuilder
);
307 ig
.Emit (OpCodes
.Br
, move_next_ok
);
309 ResumePoint point
= new ResumePoint (finally_blocks
);
310 resume_points
.Add (point
);
314 public void MarkFinally (EmitContext ec
, ArrayList finally_blocks
)
316 ILGenerator ig
= ec
.ig
;
320 ig
.Emit (OpCodes
.Ldarg_0
);
321 IntConstant
.EmitInt (ig
, pc
);
322 ig
.Emit (OpCodes
.Stfld
, pc_field
.FieldBuilder
);
324 ResumePoint point
= new ResumePoint (finally_blocks
);
325 resume_points
.Add (point
);
329 private static MemberName
MakeProxyName (string name
, Location loc
)
331 int pos
= name
.LastIndexOf ('.');
333 name
= name
.Substring (pos
+ 1);
335 return new MemberName ("<" + name
+ ">__" + (proxy_count
++), loc
);
341 public Iterator (IMethodData m_container
, TypeContainer container
,
343 : base (container
.NamespaceEntry
, container
, MakeProxyName (m_container
.MethodName
.Name
, m_container
.Location
),
344 (modifiers
& Modifiers
.UNSAFE
) | Modifiers
.PRIVATE
, null)
346 this.orig_method
= m_container
;
348 this.container
= container
;
349 this.parameters
= m_container
.ParameterInfo
;
350 this.original_block
= orig_method
.Block
;
351 this.block
= new ToplevelBlock (orig_method
.Block
, parameters
, orig_method
.Location
);
353 IsStatic
= (modifiers
& Modifiers
.STATIC
) != 0;
356 public AnonymousContainer Host
{
357 get { return move_next_method; }
360 public bool DefineIterator ()
362 ec
= new EmitContext (this, Mono
.CSharp
.Location
.Null
, null, null, ModFlags
);
363 ec
.CurrentAnonymousMethod
= move_next_method
;
364 ec
.CurrentIterator
= this;
365 ec
.InIterator
= true;
368 Report
.Error (1624, Location
,
369 "The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",
370 orig_method
.GetSignatureForError (), TypeManager
.CSharpName (orig_method
.ReturnType
));
374 for (int i
= 0; i
< parameters
.Count
; i
++){
375 Parameter
.Modifier mod
= parameters
.ParameterModifier (i
);
376 if ((mod
& (Parameter
.Modifier
.REF
| Parameter
.Modifier
.OUT
)) != 0){
379 "Iterators cannot have ref or out parameters");
383 if ((mod
& Parameter
.Modifier
.ARGLIST
) != 0) {
384 Report
.Error (1636, Location
, "__arglist is not allowed in parameter list of iterators");
388 if (parameters
.ParameterType (i
).IsPointer
) {
389 Report
.Error (1637, Location
, "Iterators cannot have unsafe parameters or yield types");
394 this_type
= container
.TypeBuilder
;
396 ArrayList list
= new ArrayList ();
398 list
.Add (new TypeExpression (
399 TypeManager
.ienumerable_type
, Location
));
400 list
.Add (new TypeExpression (TypeManager
.ienumerator_type
, Location
));
401 list
.Add (new TypeExpression (TypeManager
.idisposable_type
, Location
));
403 iterator_type_expr
= new TypeExpression (iterator_type
, Location
);
405 container
.AddIterator (this);
408 orig_method
.Block
= block
;
412 protected override bool DoDefineMembers ()
414 ec
.InIterator
= true;
415 ec
.CurrentIterator
= this;
416 ec
.CurrentAnonymousMethod
= move_next_method
;
417 ec
.capture_context
= cc
;
419 if (!base.DoDefineMembers ())
425 public override bool Define ()
430 ec
.InIterator
= true;
431 ec
.CurrentIterator
= this;
432 ec
.CurrentAnonymousMethod
= move_next_method
;
433 ec
.capture_context
= cc
;
434 ec
.TypeContainer
= ec
.TypeContainer
.Parent
;
436 ec
.ContainerType
= ec
.TypeContainer
.TypeBuilder
;
438 ec
.ig
= move_next_method
.method
.MethodBuilder
.GetILGenerator ();
445 if (!ec
.ResolveTopBlock (null, original_block
, parameters
, orig_method
, out unreachable
))
448 if (!ec
.ResolveTopBlock (null, block
, parameters
, orig_method
, out unreachable
))
451 original_block
.CompleteContexts ();
453 cc
.EmitAnonymousHelperClasses (ec
);
459 // Returns the new block for the method, or null on failure
461 protected override bool DefineNestedTypes ()
471 Define_Constructor ();
474 Define_GetEnumerator ();
476 return base.DefineNestedTypes ();
485 original_block
.SetHaveAnonymousMethods (Location
, move_next_method
);
486 block
.SetHaveAnonymousMethods (Location
, move_next_method
);
488 cc
= original_block
.CaptureContext
;
490 int first
= IsStatic
? 0 : 1;
492 ArrayList args
= new ArrayList ();
494 Type t
= container
.TypeBuilder
;
495 args
.Add (new Argument (
496 new ThisParameterReference (t
, Location
)));
497 cc
.CaptureThis (move_next_method
);
500 args
.Add (new Argument (new BoolLiteral (false, Location
)));
502 for (int i
= 0; i
< parameters
.Count
; i
++) {
503 Type t
= parameters
.ParameterType (i
);
504 string name
= parameters
.ParameterName (i
);
506 args
.Add (new Argument (
507 new SimpleParameterReference (t
, first
+ i
, Location
)));
509 cc
.AddParameterToContext (move_next_method
, name
, t
, first
+ i
);
512 Expression new_expr
= new New (
513 new TypeExpression (TypeBuilder
, Location
), args
, Location
);
515 block
.AddStatement (new NoCheckReturn (new_expr
, Location
));
518 void Define_Fields ()
520 pc_field
= new Field (
521 this, TypeManager
.system_int32_expr
, Modifiers
.PRIVATE
, "$PC",
525 current_field
= new Field (
526 this, iterator_type_expr
, Modifiers
.PRIVATE
, "$current",
528 AddField (current_field
);
531 void Define_Constructor ()
533 Parameters ctor_params
;
535 ArrayList list
= new ArrayList ();
538 list
.Add (new Parameter (
539 new TypeExpression (container
.TypeBuilder
, Location
),
540 "this", Parameter
.Modifier
.NONE
,
542 list
.Add (new Parameter (
543 TypeManager
.bool_type
, "initialized",
544 Parameter
.Modifier
.NONE
, null, Location
));
546 Parameter
[] old_fixed
= parameters
.FixedParameters
;
547 list
.AddRange (old_fixed
);
549 Parameter
[] fixed_params
= new Parameter
[list
.Count
];
550 list
.CopyTo (fixed_params
);
552 ctor_params
= new Parameters (fixed_params
);
554 ctor
= new Constructor (
555 this, Name
, Modifiers
.PUBLIC
, ctor_params
,
556 new GeneratedBaseInitializer (Location
),
558 AddConstructor (ctor
);
560 ctor
.Block
= new ToplevelBlock (block
, parameters
, Location
);
562 int first
= IsStatic
? 2 : 3;
564 State initial
= is_enumerable
? State
.Uninitialized
: State
.Running
;
565 ctor
.Block
.AddStatement (new SetState (this, initial
, Location
));
567 ctor
.Block
.AddStatement (new If (
568 new SimpleParameterReference (
569 TypeManager
.bool_type
, first
- 1, Location
),
570 new SetState (this, State
.Running
, Location
),
573 ctor
.Block
.AddStatement (new InitScope (this, Location
));
576 Statement
Create_ThrowInvalidOperation ()
578 TypeExpr ex_type
= new TypeExpression (
579 TypeManager
.invalid_operation_exception_type
, Location
);
581 return new Throw (new New (ex_type
, null, Location
), Location
);
584 Statement
Create_ThrowNotSupported ()
586 TypeExpr ex_type
= new TypeExpression (
587 TypeManager
.not_supported_exception_type
, Location
);
589 return new Throw (new New (ex_type
, null, Location
), Location
);
592 void Define_Current ()
594 ToplevelBlock get_block
= new ToplevelBlock (
595 block
, parameters
, Location
);
596 MemberName left
= new MemberName ("System.Collections.IEnumerator");
597 MemberName name
= new MemberName (left
, "Current", Location
);
599 get_block
.AddStatement (new If (
601 Binary
.Operator
.LessThanOrEqual
,
602 new FieldExpression (this, pc_field
),
603 new IntLiteral ((int) State
.Running
, pc_field
.Location
)),
604 Create_ThrowInvalidOperation (),
606 new FieldExpression (this, current_field
), Location
),
609 Accessor getter
= new Accessor (get_block
, 0, null, Location
);
611 Property current
= new Property (
612 this, iterator_type_expr
, 0,
613 false, name
, null, getter
, null);
614 AddProperty (current
);
617 void Define_MoveNext ()
619 move_next_method
= new MoveNextMethod (this, Location
);
621 original_block
.ReParent (block
, move_next_method
);
623 move_next_method
.CreateMethod (ec
);
625 AddMethod (move_next_method
.method
);
628 void Define_GetEnumerator ()
630 MemberName left
= new MemberName ("System.Collections.IEnumerable");
632 MemberName name
= new MemberName (left
, "GetEnumerator", Location
);
634 Method get_enumerator
= new Method (
636 new TypeExpression (TypeManager
.ienumerator_type
, Location
),
638 Parameters
.EmptyReadOnlyParameters
, null);
639 AddMethod (get_enumerator
);
641 get_enumerator
.Block
= new ToplevelBlock (
642 block
, parameters
, Location
);
644 get_enumerator
.Block
.SetHaveAnonymousMethods (Location
, move_next_method
);
646 Expression ce
= new MemberAccess (
647 new SimpleName ("System.Threading.Interlocked", Location
),
648 "CompareExchange", Location
);
650 Expression pc
= new FieldExpression (this, pc_field
);
651 Expression before
= new IntLiteral ((int) State
.Running
, Location
);
652 Expression uninitialized
= new IntLiteral ((int) State
.Uninitialized
, Location
);
654 ArrayList args
= new ArrayList ();
655 args
.Add (new Argument (pc
, Argument
.AType
.Ref
));
656 args
.Add (new Argument (before
, Argument
.AType
.Expression
));
657 args
.Add (new Argument (uninitialized
, Argument
.AType
.Expression
));
659 get_enumerator
.Block
.AddStatement (new If (
661 Binary
.Operator
.Equality
,
662 new Invocation (ce
, args
),
664 new Return (new ThisParameterReference (
665 TypeManager
.ienumerator_type
, Location
),
669 args
= new ArrayList ();
671 args
.Add (new Argument (new CapturedThisReference (this, Location
)));
674 args
.Add (new Argument (new BoolLiteral (true, Location
)));
676 for (int i
= 0; i
< parameters
.Count
; i
++) {
677 Expression cp
= new CapturedParameterReference (
678 this, parameters
.ParameterType (i
),
679 parameters
.ParameterName (i
), Location
);
680 args
.Add (new Argument (cp
));
683 Expression new_expr
= new New (
684 new TypeExpression (TypeBuilder
, Location
), args
, Location
);
685 get_enumerator
.Block
.AddStatement (new Return (new_expr
, Location
));
688 protected class SimpleParameterReference
: Expression
692 public SimpleParameterReference (Type type
, int idx
, Location loc
)
697 eclass
= ExprClass
.Variable
;
700 public override Expression
DoResolve (EmitContext ec
)
705 public override void Emit (EmitContext ec
)
710 protected virtual void DoEmit (EmitContext ec
)
712 ParameterReference
.EmitLdArg (ec
.ig
, idx
);
716 protected class ThisParameterReference
: SimpleParameterReference
, IMemoryLocation
718 public ThisParameterReference (Type type
, Location loc
)
719 : base (type
, 0, loc
)
722 protected override void DoEmit (EmitContext ec
)
725 if (ec
.TypeContainer
is Struct
)
726 ec
.ig
.Emit (OpCodes
.Ldobj
, type
);
729 public void AddressOf (EmitContext ec
, AddressOp mode
)
731 if (ec
.TypeContainer
is Struct
)
732 ec
.ig
.Emit (OpCodes
.Ldarga
, 0);
734 ec
.ig
.Emit (OpCodes
.Ldarg
, 0);
738 protected class CapturedParameterReference
: Expression
743 public CapturedParameterReference (Iterator iterator
, Type type
,
744 string name
, Location loc
)
746 this.iterator
= iterator
;
750 eclass
= ExprClass
.Variable
;
753 public override Expression
DoResolve (EmitContext ec
)
758 public override void Emit (EmitContext ec
)
760 ec
.CurrentAnonymousMethod
= iterator
.move_next_method
;
762 LocalTemporary dummy
= null;
764 iterator
.cc
.EmitParameter (ec
, name
, false, false, ref dummy
);
768 protected class CapturedThisReference
: Expression
770 public CapturedThisReference (Iterator iterator
, Location loc
)
773 this.type
= iterator
.this_type
;
774 eclass
= ExprClass
.Variable
;
777 public override Expression
DoResolve (EmitContext ec
)
782 public override void Emit (EmitContext ec
)
788 protected class FieldExpression
: Expression
793 public FieldExpression (Iterator iterator
, Field field
)
795 this.iterator
= iterator
;
797 this.loc
= iterator
.Location
;
800 public override Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
802 FieldExpr fexpr
= new FieldExpr (field
.FieldBuilder
, loc
);
803 fexpr
.InstanceExpression
= new ThisParameterReference (
804 iterator
.this_type
, loc
);
805 return fexpr
.ResolveLValue (ec
, right_side
, loc
);
808 public override Expression
DoResolve (EmitContext ec
)
810 FieldExpr fexpr
= new FieldExpr (field
.FieldBuilder
, loc
);
811 fexpr
.InstanceExpression
= new ThisParameterReference (
812 iterator
.this_type
, loc
);
813 return fexpr
.Resolve (ec
);
816 public override void Emit (EmitContext ec
)
818 throw new InvalidOperationException ();
822 protected class MoveNextMethod
: AnonymousContainer
826 public MoveNextMethod (Iterator iterator
, Location loc
)
827 : base (iterator
.parameters
, iterator
.original_block
, loc
)
829 this.iterator
= iterator
;
832 protected override bool CreateMethodHost (EmitContext ec
)
834 method
= new Method (
835 iterator
, TypeManager
.system_boolean_expr
,
836 Modifiers
.PUBLIC
, false, new MemberName ("MoveNext", loc
),
837 Parameters
.EmptyReadOnlyParameters
, null);
839 method
.Block
= Block
;
841 MoveNextStatement inline
= new MoveNextStatement (iterator
, loc
);
842 Block
.AddStatement (inline
);
847 public bool CreateMethod (EmitContext ec
)
849 return CreateMethodHost (ec
);
852 public override bool IsIterator
{
856 public override void CreateScopeType (EmitContext ec
, ScopeInfo scope
)
858 scope
.ScopeTypeBuilder
= iterator
.TypeBuilder
;
859 scope
.ScopeConstructor
= iterator
.ctor
.ConstructorBuilder
;
862 public override void Emit (EmitContext ec
)
864 throw new InternalErrorException ();
868 protected class MoveNextStatement
: Statement
{
871 public MoveNextStatement (Iterator iterator
, Location loc
)
874 this.iterator
= iterator
;
877 public override bool Resolve (EmitContext ec
)
882 protected override void DoEmit (EmitContext ec
)
884 ec
.CurrentIterator
= iterator
;
885 ec
.CurrentAnonymousMethod
= iterator
.move_next_method
;
886 ec
.InIterator
= true;
888 iterator
.EmitMoveNext (ec
);
892 protected class DisposeMethod
: Statement
{
895 public DisposeMethod (Iterator iterator
, Location loc
)
898 this.iterator
= iterator
;
901 public override bool Resolve (EmitContext ec
)
906 protected override void DoEmit (EmitContext ec
)
908 iterator
.EmitDispose (ec
);
912 protected class StatementList
: Statement
{
913 ArrayList statements
;
915 public StatementList (Location loc
)
918 statements
= new ArrayList ();
921 public void Add (Statement statement
)
923 statements
.Add (statement
);
926 public override bool Resolve (EmitContext ec
)
928 foreach (Statement stmt
in statements
) {
929 if (!stmt
.Resolve (ec
))
936 protected override void DoEmit (EmitContext ec
)
938 foreach (Statement stmt
in statements
)
943 protected class SetState
: Statement
948 public SetState (Iterator iterator
, State state
, Location loc
)
950 this.iterator
= iterator
;
955 public override bool Resolve (EmitContext ec
)
960 protected override void DoEmit (EmitContext ec
)
962 ec
.ig
.Emit (OpCodes
.Ldarg_0
);
963 IntConstant
.EmitInt (ec
.ig
, (int) state
);
964 ec
.ig
.Emit (OpCodes
.Stfld
, iterator
.pc_field
.FieldBuilder
);
968 protected class InitScope
: Statement
972 public InitScope (Iterator iterator
, Location loc
)
974 this.iterator
= iterator
;
978 public override bool Resolve (EmitContext ec
)
983 protected override void DoEmit (EmitContext ec
)
985 iterator
.cc
.EmitInitScope (ec
);
991 Method reset
= new Method (
992 this, TypeManager
.system_void_expr
, Modifiers
.PUBLIC
,
993 false, new MemberName ("Reset", Location
),
994 Parameters
.EmptyReadOnlyParameters
, null);
997 reset
.Block
= new ToplevelBlock (Location
);
998 reset
.Block
= new ToplevelBlock (block
, parameters
, Location
);
999 reset
.Block
.SetHaveAnonymousMethods (Location
, move_next_method
);
1001 reset
.Block
.AddStatement (Create_ThrowNotSupported ());
1004 void Define_Dispose ()
1006 dispose
= new Method (
1007 this, TypeManager
.system_void_expr
, Modifiers
.PUBLIC
,
1008 false, new MemberName ("Dispose", Location
),
1009 Parameters
.EmptyReadOnlyParameters
, null);
1010 AddMethod (dispose
);
1012 dispose
.Block
= new ToplevelBlock (block
, parameters
, Location
);
1013 dispose
.Block
.SetHaveAnonymousMethods (Location
, move_next_method
);
1015 dispose
.Block
.AddStatement (new DisposeMethod (this, Location
));
1018 public Type IteratorType
{
1019 get { return iterator_type; }
1023 // This return statement tricks return into not flagging an error for being
1024 // used in a Yields method
1026 class NoCheckReturn
: Statement
{
1027 public Expression Expr
;
1029 public NoCheckReturn (Expression expr
, Location l
)
1035 public override bool Resolve (EmitContext ec
)
1037 Expr
= Expr
.Resolve (ec
);
1041 ec
.CurrentBranching
.CurrentUsageVector
.Return ();
1046 protected override void DoEmit (EmitContext ec
)
1049 ec
.ig
.Emit (OpCodes
.Ret
);
1055 Type ret
= orig_method
.ReturnType
;
1057 if (ret
== TypeManager
.ienumerable_type
) {
1058 iterator_type
= TypeManager
.object_type
;
1059 is_enumerable
= true;
1062 if (ret
== TypeManager
.ienumerator_type
) {
1063 iterator_type
= TypeManager
.object_type
;
1064 is_enumerable
= false;