[svn] r6014: nemerle/trunk/ncc: generation/Typer3.n testsuite/positive/yield.n typing/Typer.n

malekith svnadmin at nemerle.org
Sun Dec 18 13:20:03 CET 2005


Log:
Implement IEnumerable as well as IEnumerator yield pattern.

Author: malekith
Date: Sun Dec 18 13:20:02 2005
New Revision: 6014

Modified:
   nemerle/trunk/ncc/generation/Typer3.n
   nemerle/trunk/ncc/testsuite/positive/yield.n
   nemerle/trunk/ncc/typing/Typer.n

Modified: nemerle/trunk/ncc/generation/Typer3.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer3.n	(original)
+++ nemerle/trunk/ncc/generation/Typer3.n	Sun Dec 18 13:20:02 2005
@@ -666,7 +666,8 @@
       <[ decl:
         class $(Macros.NewSymbol ("Enumerator") : name) :
           System.Collections.IEnumerator,
-          System.Collections.Generic.IEnumerator [$(yield_type : typed)]
+          System.Collections.Generic.IEnumerator [$(yield_type : typed)],
+          System.IDisposable
         {
           public Current : $(yield_type : typed)
           {
@@ -691,6 +692,66 @@
       ]>
     }
 
+    PrepareEnumerableObject (yield_type : TyVar) : Parsetree.ClassMember
+    {
+      def name = Macros.NewSymbol ("Enumerable");
+
+      def has_mutable_parm = current_local_fun.parms.Exists (fun (fp) { fp.decl.IsMutable });
+
+      def interlocked_stuff =
+        if (has_mutable_parm)
+          <[ true ]>
+        else
+          <[ System.Threading.Interlocked.CompareExchange 
+             (ref _N_this_used, 1, 0) != 0 ]>;
+           
+      <[ decl:
+        class $(name : name) :
+          System.Collections.IEnumerator,
+          System.Collections.Generic.IEnumerator [$(yield_type : typed)],
+          System.IDisposable,
+          System.Collections.Generic.IEnumerable [$(yield_type : typed)]
+        {
+          public Current : $(yield_type : typed)
+          {
+            get { this._N_current }
+          }
+
+          public Dispose () : void
+          {
+            foobar
+          }
+
+          public Reset () : void
+          {
+            throw System.NotSupportedException ();
+          }
+
+          public MoveNext () : bool
+          {
+            foobar
+          }
+
+          mutable _N_this_used : int;
+          
+          public GetEnumerator () : System.Collections.Generic.IEnumerator [$(yield_type : typed)]
+          {
+            if ($interlocked_stuff) {
+              def res = $(name : name) ();
+              res.CopyFrom (this);
+              res
+            } else
+              this
+          }
+
+          CopyFrom (other : $(name : name)) : void
+          {
+            _N_this_used = 1;
+          }
+        }
+      ]>
+    }
+
     static RewriteTryFinally (clo_type : TypeBuilder, fh : Fun_header) : void
     {
       mutable dispose_expr = Typer.VoidLiteral ();
@@ -749,7 +810,7 @@
     }
 
 
-    SetEnumeratorBody (clo_type : TypeBuilder, subst : Subst) : void
+    SetEnumeratorBody (clo_type : TypeBuilder, subst : Subst, parm_field_names : list [string]) : void
     {
       match (current_local_fun.body) {
         | FunBody.Typed (DefValIn (_, _, DefValIn (_, _, DefFunctionsIn ([fh], _)))) =>
@@ -769,6 +830,14 @@
           child.current_subst = subst;
           child.Run ();
 
+          unless (parm_field_names.IsEmpty) {
+            def meth = SingleMemberLookup (clo_type, "CopyFrom") :> MethodBuilder;
+            def assigns = meth.Body :: parm_field_names.Map (fun (name) {
+              <[ this . $(name : dyn) = other . $(name : dyn) ]>
+            });
+            meth.Body = <[ { .. $assigns } ]>;
+          }
+
           current_local_fun.body = FunBody.Typed (PlainRef (current_closure));
 
         | FunBody.Typed (t)
@@ -794,6 +863,14 @@
         }
 
         def uses_yield = current_local_fun.yield_type != null;
+        def is_enumerable =
+          if (uses_yield)
+            match (current_local_fun.ret_type.Fix ()) {
+              | Class (tc, _) =>
+                tc.Equals (InternalType.Generic_IEnumerable_tc)
+              | _ => Util.ice ()
+            }
+          else false;
 
         def clo_decl = 
           if (!uses_yield)
@@ -803,7 +880,11 @@
                 internal this () {}
               }
             ]>
-          else PrepareEnumeratorObject (fix_type (current_local_fun.yield_type));
+          else 
+            if (is_enumerable)
+              PrepareEnumerableObject (fix_type (current_local_fun.yield_type));
+            else 
+              PrepareEnumeratorObject (fix_type (current_local_fun.yield_type));
 
         def clo_type = CurrentType.DefineNestedType (clo_decl, do_fixup = false);
         clo_type.forced_typarms = new_tp;
@@ -832,6 +913,8 @@
             }
           });
         
+        mutable parm_field_names = [];
+
         foreach (decl in vars) {
           def name =
             if (decl.Name == "_N_current" || decl.Name == "_N_state")
@@ -845,6 +928,8 @@
           def fld = clo_type.DefineAndReturn (ptdecl);
           decl.ClosureField = fld :> IField;
           decl.ClosureField.HasBeenAssigned = true;
+          when (is_enumerable && decl.ValKind is FunParm (_))
+            parm_field_names ::= name.Id;
         }
         def ctor = SingleMemberLookup (clo_type, ".ctor");
         def ctor_ref = TExpr.StaticRef (ctor.GetMemType (), clo_mtype, ctor, []);
@@ -854,7 +939,8 @@
         clo_type.HasBeenUsed = true;
 
         when (uses_yield)
-          SetEnumeratorBody (clo_type, subst);
+          SetEnumeratorBody (clo_type, subst, parm_field_names);
+        
 
         clo_type.Compile ();
 

Modified: nemerle/trunk/ncc/testsuite/positive/yield.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/yield.n	(original)
+++ nemerle/trunk/ncc/testsuite/positive/yield.n	Sun Dec 18 13:20:02 2005
@@ -29,7 +29,12 @@
     yield qux.ToString ();
     yield ene;
     yield this.due;
+    try {
     yield rabe;
+    } catch {
+    | _ =>
+    yield rabe;
+    }
   }
 }
 
@@ -42,6 +47,22 @@
   }
 }
 
+class X {
+  public static FromTo (from : int, to : int) : IEnumerable [int]
+  {
+    for (mutable i = from; i <= to; ++i)
+      yield i;
+  }
+  
+  public static FromTo2 (mutable from : int, to : int) : IEnumerable [int]
+  {
+    while (from <= to) {
+      yield from;
+      from++;
+    }
+  }
+}
+
 foreach (e in C ())
   System.Console.WriteLine (e);
 
@@ -59,6 +80,23 @@
 foreach (e in E ())
   System.Console.WriteLine (e);
 
+def x = X.FromTo (42, 47);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+  System.Console.WriteLine (e);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+  System.Console.WriteLine (e);
+
+def x = X.FromTo2 (42, 47);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+  System.Console.WriteLine (e);
+System.Console.WriteLine ("------------");
+foreach (e in x)
+  System.Console.WriteLine (e);
+System.Console.WriteLine ("------------");
+
 /*
 BEGIN-OUTPUT
 42
@@ -79,5 +117,34 @@
 2
 3
 4
+------------
+42
+43
+44
+45
+46
+47
+------------
+42
+43
+44
+45
+46
+47
+------------
+42
+43
+44
+45
+46
+47
+------------
+42
+43
+44
+45
+46
+47
+------------
 END-OUTPUT
 */

Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n	(original)
+++ nemerle/trunk/ncc/typing/Typer.n	Sun Dec 18 13:20:02 2005
@@ -3086,12 +3086,14 @@
         | None =>
           match (current_fun.ret_type.Fix ()) {
             | Class (tc, [t])
-              when tc.Equals (InternalType.Generic_IEnumerator_tc) => t
+              when tc.Equals (InternalType.Generic_IEnumerator_tc) || 
+                   tc.Equals (InternalType.Generic_IEnumerable_tc) => t
             | t =>
               ReportError (messenger,
                            $ "yield used in a function returning "
                              "$t (it should be System.Collections.Generic."
-                             "IEnumerator[T])");
+                             "IEnumerator[T] or System.Collections.Generic."
+                             "IEnumerable[T])");
               InternalType.Object
          }
       }



More information about the svn mailing list