Also update this
[mono.git] / mcs / gmcs / iterators.cs
index bed88521116a6d5cf44dcedd176a68678621175a..8beb54506631f158a0cc13a523cdd0e5ba3aad89 100644 (file)
@@ -40,11 +40,11 @@ namespace Mono.CSharp {
 
                public static bool CheckContext (EmitContext ec, Location loc)
                {
-                       if (ec.InFinally){
+                       if (ec.CurrentBranching.InFinally (true)){
                                Report.Error (-208, loc, "yield statement can not appear in finally clause");
                                return false;
                        }
-                       if (ec.InCatch){
+                       if (ec.CurrentBranching.InCatch ()){
                                Report.Error (-209, loc, "yield statement can not appear in the catch clause");
                                return false;
                        }
@@ -66,6 +66,7 @@ namespace Mono.CSharp {
                                return false;
                        if (!CheckContext (ec, loc))
                                return false;
+
                        
                        Type iterator_type = IteratorHandler.Current.IteratorType;
                        if (expr.Type != iterator_type){
@@ -76,11 +77,9 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        IteratorHandler.Current.MarkYield (ec, expr);
-                       
-                       return false;
                }
        }
 
@@ -96,15 +95,13 @@ namespace Mono.CSharp {
                        if (!Yield.CheckContext (ec, loc))
                                return false;
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        IteratorHandler.Current.EmitYieldBreak (ec.ig, true);
-                       return false;
                }
        }
 
@@ -255,9 +252,13 @@ namespace Mono.CSharp {
                // Invoked when a local variable declaration needs to be mapped to
                // a field in our proxy class
                //
-               public FieldBuilder MapVariable (string name, Type t)
+               // Prefixes registered:
+               //   v_   for EmitContext.MapVariable
+               //   s_   for Storage
+               //
+               public FieldBuilder MapVariable (string pfx, string name, Type t)
                {
-                       return enumerator_proxy_class.DefineField ("v" + name, t, FieldAttributes.Public);
+                       return enumerator_proxy_class.DefineField (pfx + name, t, FieldAttributes.Public);
                }
                
                void Create_Reset ()
@@ -397,7 +398,7 @@ namespace Mono.CSharp {
                                constructor_types [0] = container.TypeBuilder;
 
                                Parameter THIS = new Parameter (
-                                       new TypeExpr (container.TypeBuilder, loc), "this", Parameter.Modifier.NONE, null);
+                                       new TypeExpression (container.TypeBuilder, loc), "this", Parameter.Modifier.NONE, null);
                                pars [0] = THIS;
                                i++;
                        }
@@ -405,7 +406,7 @@ namespace Mono.CSharp {
                        for (int j = 0; j < parameters.Count; j++, i++){
                                Type partype = parameters.ParameterType (j);
                                
-                               pars [i] = new Parameter (new TypeExpr (partype, loc),
+                               pars [i] = new Parameter (new TypeExpression (partype, loc),
                                                          parameters.ParameterName (j),
                                                          Parameter.Modifier.NONE, null);
                                constructor_types [i] = partype;
@@ -417,9 +418,12 @@ namespace Mono.CSharp {
                //
                void MakeEnumeratorProxy ()
                {
-                       Type [] proxy_base_interfaces = new Type [2];
-                       proxy_base_interfaces [0] = TypeManager.ienumerator_type;
-                       proxy_base_interfaces [1] = TypeManager.idisposable_type;
+                       TypeExpr [] proxy_base_interfaces = new TypeExpr [2];
+                       proxy_base_interfaces [0] = new TypeExpression (TypeManager.ienumerator_type, loc);
+                       proxy_base_interfaces [1] = new TypeExpression (TypeManager.idisposable_type, loc);
+                       Type [] proxy_base_itypes = new Type [2];
+                       proxy_base_itypes [0] = TypeManager.ienumerator_type;
+                       proxy_base_itypes [1] = TypeManager.idisposable_type;
                        TypeBuilder container_builder = container.TypeBuilder;
 
                        //
@@ -427,7 +431,7 @@ namespace Mono.CSharp {
                        //
                        enumerator_proxy_class = container_builder.DefineNestedType (
                                MakeProxyName (), TypeAttributes.AutoLayout | TypeAttributes.Class |TypeAttributes.NestedPublic,
-                               TypeManager.object_type, proxy_base_interfaces);
+                               TypeManager.object_type, proxy_base_itypes);
 
                        TypeManager.RegisterBuilder (enumerator_proxy_class, proxy_base_interfaces);
 
@@ -560,7 +564,7 @@ namespace Mono.CSharp {
                        Create_Current ();
                        Create_Dispose ();
 
-                       if (return_type == TypeManager.ienumerable_type){
+                       if (IsIEnumerable (return_type)){
                                Create_GetEnumerator ();
                                RootContext.RegisterHelperClass (enumerable_proxy_class);
                        }
@@ -614,7 +618,7 @@ namespace Mono.CSharp {
                                // Create the proxy class type.
                                handler.MakeEnumeratorProxy ();
 
-                               if (handler.return_type == TypeManager.ienumerable_type)
+                               if (IsIEnumerable (handler.return_type))
                                        handler.MakeEnumerableProxy ();
 
                                type = handler.return_type;
@@ -630,7 +634,7 @@ namespace Mono.CSharp {
                        {
                                handler.LoadArgs (ec.ig);
                                
-                               if (handler.return_type == TypeManager.ienumerable_type)
+                               if (IsIEnumerable (handler.return_type))
                                        ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) handler.enumerable_proxy_constructor);
                                else 
                                        ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) handler.enumerator_proxy_constructor);
@@ -655,18 +659,27 @@ namespace Mono.CSharp {
                                return ret_val;
                        }
                }
+
+               static bool IsIEnumerable (Type t)
+               {
+                       return t == TypeManager.ienumerable_type || TypeManager.ImplementsInterface (t, TypeManager.ienumerable_type);
+               }
+
+               static bool IsIEnumerator (Type t)
+               {
+                       return t == TypeManager.ienumerator_type || TypeManager.ImplementsInterface (t, TypeManager.ienumerator_type);
+               }
                
                //
                // Returns the new block for the method, or null on failure
                //
                public Block Setup (Block block)
                {
-                       if (return_type != TypeManager.ienumerator_type &&
-                           return_type != TypeManager.ienumerable_type){
+                       if (!(IsIEnumerator (return_type) || IsIEnumerable (return_type))){
                                Report.Error (
                                        -205, loc, String.Format (
-                                               "The method `{0}' contains a yield statement, but has an invalid return type for an iterator",
-                                               name));
+                                               "The method `{0}' contains a yield statement, but has an invalid return type for an iterator `{1}'",
+                                               name, TypeManager.CSharpName (return_type)));
                                return null;
                        }