[svn] r6007: nemerle/trunk/ncc: generation/Typer3.n hierarchy/ClassMembers.n testsuite/negative/yield2.n t...

malekith svnadmin at nemerle.org
Thu Dec 15 13:13:41 CET 2005


Log:
Move most of yield-handling to T3.

Author: malekith
Date: Thu Dec 15 13:13:39 2005
New Revision: 6007

Modified:
   nemerle/trunk/ncc/generation/Typer3.n
   nemerle/trunk/ncc/hierarchy/ClassMembers.n
   nemerle/trunk/ncc/testsuite/negative/yield2.n
   nemerle/trunk/ncc/testsuite/positive/yield.n
   nemerle/trunk/ncc/typing/LocalValue.n
   nemerle/trunk/ncc/typing/Typer.n
   nemerle/trunk/ncc/typing/Typer2.n

Modified: nemerle/trunk/ncc/generation/Typer3.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer3.n	(original)
+++ nemerle/trunk/ncc/generation/Typer3.n	Thu Dec 15 13:13:39 2005
@@ -428,7 +428,11 @@
     /** Return code referencing closure of [hd].  */
     ClosureRef (hd : Fun_header) : TExpr
     {
-      if (hd.id == current_method.id) {
+      if (current_method.name == "_N_yielding_function") {
+        Util.cassert (hd.id == current_method.id ||
+                      current_method.decl.DefinedIn.id == hd.id);
+        TExpr.This (local_function_type.GetMemType ())
+      } else if (hd.id == current_method.id) {
         PlainRef (current_closure)
       } else if (hd.usage == FunctionUsage.UsedJustOnce) {
         ClosureRef (hd.decl.DefinedIn)
@@ -655,6 +659,57 @@
     }
 
     
+    PrepareEnumeratorObject () : Parsetree.ClassMember
+    {
+      def yield_type = Option.UnSome (the_method.yield_stuff) [0];
+
+      <[ decl:
+        class $(Macros.NewSymbol ("Enumerator") : name) :
+          System.Collections.IEnumerator,
+          System.Collections.Generic.IEnumerator [$yield_type]
+        {
+          public Current : $yield_type
+          {
+            get { this._N_current }
+          }
+
+          public Dispose () : void
+          {
+            this._N_state = -1;
+          }
+
+          public Reset () : void
+          {
+            throw System.NotSupportedException ();
+          }
+
+          public MoveNext () : bool
+          {
+          }
+        }
+      ]>
+    }
+
+
+    SetEnumeratorBody (clo_type : TypeInfo, subst : Subst) : void
+    {
+      match (current_local_fun.body) {
+        | FunBody.Typed (DefValIn (_, _, DefValIn (_, _, DefFunctionsIn ([fh], _)))) =>
+          def meth = SingleMemberLookup (clo_type, "MoveNext") :> MethodBuilder;
+          fh.used_closures = fh.GetParents ();
+          PrepareForEmission (meth, fh, subst);
+          def child = Typer3 (this, meth);
+          child.current_subst = subst;
+          child.Run ();
+
+          current_local_fun.body = FunBody.Typed (PlainRef (current_closure));
+
+        | FunBody.Typed (t)
+        | _ with t = null => Util.ice ($ "oops, t=$t")
+      }
+    }
+
+    
     PrepareClosure () : list [TExpr]
     {
       //Message.Debug ($"closure for $(current_local_fun.name) $(current_local_fun.closure_vars)");
@@ -671,12 +726,17 @@
             subst.Apply (t.DeepFix ())
         }
 
-        def clo_type = CurrentType.DefineNestedType (<[ decl:
+        def clo_decl = 
+          if (the_method.yield_stuff.IsNone)
+            <[ decl:
           private sealed class $(Macros.NewSymbol ("closure") : name)
           {
             internal this () {}
           }
-        ]>, do_fixup = false);
+            ]>
+          else PrepareEnumeratorObject ();
+
+        def clo_type = CurrentType.DefineNestedType (clo_decl, do_fixup = false);
         clo_type.forced_typarms = new_tp;
         clo_type.FixupDefinedClass ();
         
@@ -704,7 +764,10 @@
           });
         
         foreach (decl in vars) {
-          def name = Macros.NewSymbol (decl.Name);
+          def name =
+            if (decl.Name == "_N_current" || decl.Name == "_N_state")
+              Parsetree.Name (decl.Name)
+            else Macros.NewSymbol (decl.Name);
           //Message.Debug ($"clo field: $name $(fix_type (decl.Type)) tv=$new_tp");
           def ptdecl = <[ decl: 
             internal mutable 
@@ -722,6 +785,9 @@
         clo_type.HasBeenUsed = true;
         clo_type.Compile ();
 
+        when (the_method.yield_stuff.IsSome)
+          SetEnumeratorBody (clo_type, subst);
+
         [TExpr.DefValIn (InternalType.Void, closure_val, ctor_call, null)]
       }
     }

Modified: nemerle/trunk/ncc/hierarchy/ClassMembers.n
==============================================================================
--- nemerle/trunk/ncc/hierarchy/ClassMembers.n	(original)
+++ nemerle/trunk/ncc/hierarchy/ClassMembers.n	Thu Dec 15 13:13:39 2005
@@ -598,7 +598,7 @@
 
   internal mutable overridden_method : IMethod;
 
-  internal yield_stuff : option [PT.PExpr * list [PT.Fun_parm]] = None ();
+  internal mutable yield_stuff : option [PT.PExpr * list [PT.Fun_parm]] = None ();
 
   is_var_args : bool;
 

Modified: nemerle/trunk/ncc/testsuite/negative/yield2.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/yield2.n	(original)
+++ nemerle/trunk/ncc/testsuite/negative/yield2.n	Thu Dec 15 13:13:39 2005
@@ -4,6 +4,6 @@
 {
   public GetEnumerator () : IEnumerator [int]
   {
-    yield "foo"; // E: expected int, got string in assigned value
+    yield "foo"; // E: expected int.*, got string in assigned value
   }
 }

Modified: nemerle/trunk/ncc/testsuite/positive/yield.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/yield.n	(original)
+++ nemerle/trunk/ncc/testsuite/positive/yield.n	Thu Dec 15 13:13:39 2005
@@ -26,7 +26,7 @@
 
   do_get (qux : int) : IEnumerator [string]
   {
-    // yield qux.ToString ();
+    yield qux.ToString ();
     yield ene;
     yield this.due;
     yield rabe;
@@ -55,9 +55,11 @@
 42
 13
 77
+4
 raz
 dwa
 trzy
+5
 raz
 dwa
 trzy

Modified: nemerle/trunk/ncc/typing/LocalValue.n
==============================================================================
--- nemerle/trunk/ncc/typing/LocalValue.n	(original)
+++ nemerle/trunk/ncc/typing/LocalValue.n	Thu Dec 15 13:13:39 2005
@@ -54,6 +54,9 @@
     mutable is_registered : bool;
     mutable closure_field : IField;
 
+    [Accessor (flags = WantSetter | Internal)]
+    mutable never_closurise : bool;
+
     [Nemerle.OverrideObjectEquals]
     public Equals (other : LocalValue) : bool {
       id == other.id

Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n	(original)
+++ nemerle/trunk/ncc/typing/Typer.n	Thu Dec 15 13:13:39 2005
@@ -80,6 +80,7 @@
       solver = Passes.Solver;
       current_type = m.DeclaringType;
       yield_stuff = m.yield_stuff;
+      m.yield_stuff = None ();
       parent_typer = None ();
       env = current_type.GlobalEnv;
       current_fun = m.GetHeader ();
@@ -87,10 +88,6 @@
       messenger = solver.CurrentMessenger;
       locals_stack = Stack ();
 
-      inside_yielding_function =
-        m.Name == "MoveNext" && 
-        current_type.LookupMember ("_N_current") is [_];
-
       local_context = LocalContext.Empty;
 
       assert (solver.IsTopLevel);
@@ -150,10 +147,12 @@
                 Util.ice ($"hidden errors compiling $m");
                 
             | _ is SwitchToYielding =>
+              m.yield_stuff = yield_stuff;
               def errcnt = Message.ErrorCount;
               // just in case
               put_in_error_mode ();
               m.Body = MakeEnumeratorClass (m.Body);
+              inside_yielding_function = true;
               when (errcnt == Message.ErrorCount)
                 RunTyper ();
               when (errcnt == Message.ErrorCount) {
@@ -201,6 +200,7 @@
       is_method = parent.is_method;
       is_instance_ctor = parent.is_instance_ctor;
       env = parent.env;
+      inside_yielding_function = parent.inside_yielding_function;
       messenger = parent.messenger;
       locals_stack = Stack ();
       
@@ -295,17 +295,18 @@
         | FunBody.Typed => 
           Util.ice ($"$(current_fun.body)")
       }
-    }
 
-
-    RunSecondPass (meth : MethodBuilder) : void
-    {
-      when (inside_yielding_function)
+      when (inside_yielding_function &&
+            current_fun.name == "_N_yielding_function")
         match (current_fun.body) {
           | FunBody.Typed (t) => AddYieldStateMachine (t)
           | _ => Util.ice ()
         }
+    }
 
+
+    RunSecondPass (meth : MethodBuilder) : void
+    {
       def t2 = Typer2 (current_type, meth);
       t2.Run ();
       def t3 = Typer3 (meth);
@@ -1409,9 +1410,7 @@
 
 
         | PT.PExpr.This =>
-          if (inside_yielding_function)
-            TypeExpr (<[ $(This () : typed)._N_this ]>, expected)
-          else if (is_method) {
+          if (is_method) {
             _ = Expect (expected, current_type.GetMemType (), "`this'");
             This ()
           } else
@@ -2366,20 +2365,15 @@
         match (expr) {
           // FIXME | PT.PExpr.ToComplete 
           | PT.PExpr.Ref (name) when is_method =>
-            def th () {
-              if (inside_yielding_function) TypeExpr (<[ this ]>)
-              else This ()
-            }
-            
             def res =
               try {
                 solver.PushState ();
-                Option.UnSome (TypeMember (th (), name.Id, expected));
+                Option.UnSome (TypeMember (This (), name.Id, expected));
               } finally {
                 solver.PopState ();
               }
             if (res.IsEmpty) []
-            else Option.UnSome (TypeMember (th (), name.Id, expected))
+            else Option.UnSome (TypeMember (This (), name.Id, expected))
           | _ => []
         };
 
@@ -3050,28 +3044,18 @@
     #region yield handling
     MakeEnumeratorClass (body : PT.PExpr) : PT.PExpr
     {
-      def (yield_type, parms) = GetYieldStuff ();
-      def this_type = Util.ExprOfQid (current_type.FullName);
-      def all_parms = <[ parameter: _N_this : $this_type ]> :: parms;
+      def (yield_type, _) = GetYieldStuff ();
 
-      def pt = <[ decl:
-        class $(Macros.NewSymbol ("Enumerator") : name) :
-          System.Collections.IEnumerator,
-          System.Collections.Generic.IEnumerator [$yield_type]
-        {
-          mutable _N_current : $yield_type;
-          mutable _N_state : int;
-
-          public Current : $yield_type
-          {
-            get { _N_current }
-          }
+      def new_body =
+        <[
+          mutable _N_current = Nemerle.Extensions.DefaultValue ($yield_type);
+          mutable _N_state = 0;
 
-          public MoveNext () : bool
+          def _N_yielding_function () : bool
           {
             _N_MoveNext_exit : {
-              // AddYieldStateMachine will add something here, and change -42 to _N_state
-              match (-42) {
+              // AddYieldStateMachine will add something here
+              match (_N_state) {
                 | 0 => {}
                 | _ => _N_MoveNext_exit (false)
               }
@@ -3082,43 +3066,11 @@
             }
           }
 
-          public Dispose () : void
-          {
-            _N_state = -1;
-          }
-
-          public Reset () : void
-          {
-            throw System.NotSupportedException ();
-          }
-
-          public this (.. $all_parms)
-          {
-          }
-        }
+          _ = _N_yielding_function;
+          null
       ]>;
 
-      def tb = current_type.DefineNestedType (pt);
-      
-      def ctor_assigns =
-        all_parms.Map (fun (fp) {
-          when (fp.ty is <[ ref $_ ]> || fp.ty is <[ out $_ ]>)
-            ReportError (messenger, 
-                         "ref/out parameters not allowed in functions "
-                         "using ``yield''");
-          tb.Define (<[ decl: mutable $(fp.name) : $(fp.ty) ]>);
-          <[ this . $(fp.name) = $(fp.name.GetName () : name) ]>
-        });
-        
-      def meth = Typer3.SingleMemberLookup (tb, ".ctor") :> MethodBuilder;
-      meth.Body = <[ { .. $ctor_assigns } ]>;
-
-      tb.Compile ();
-
-      def parm_refs = 
-        <[ this ]> :: parms.Map (fun (fp) { <[ $(fp.name.GetName () : name) ]> });
-
-      <[ $(Util.ExprOfQid (tb.FullName)) (.. $parm_refs) ]>
+      new_body
     }
 
 
@@ -3134,7 +3086,7 @@
                            $ "yield used in a function returning "
                              "$(current_fun.ret_type) (it "
                              "should be System.Collections.Generic."
-                             "IEnumerable[T])");
+                             "IEnumerator[T])");
               (<[ object ]>, [])
          }
       }
@@ -3151,8 +3103,8 @@
       
       TypeExpr (<[ 
         {
-          $(This () : typed) . _N_current = $expr;
-          $(This () : typed) . _N_state = $(state_no : int);
+          _N_current = $expr;
+          _N_state = $(state_no : int);
           _N_MoveNext_exit (true);
           $(label : typed)
         }
@@ -3170,9 +3122,7 @@
             def yes = TExpr.Literal (InternalType.Boolean, Literal.Bool (true));
             Match_case ([(cntpat, yes, [])], TExpr.Goto (m.Type, id, 1), false)
           });
-          def state =
-            TypeExpr (<[ $(This () : typed)._N_state ]>, InternalType.Int32);
-          s.e1 = TExpr.Match (m.Type, state, cases + m.cases)
+          s.e1 = TExpr.Match (m.Type, m.expr, cases + m.cases)
         | _ => Util.ice ($ "e = $e")
       }
     }

Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n	(original)
+++ nemerle/trunk/ncc/typing/Typer2.n	Thu Dec 15 13:13:39 2005
@@ -40,8 +40,10 @@
     top_level_fun : MethodBuilder;
     mutable this_ptr_decl : LocalValue;
     mutable current_fun : Fun_header;
+    top_fun : Fun_header;
     current_type : TypeBuilder;
     messenger : Messenger;
+    inside_yielding_function : bool;
 
     [System.Flags]
     enum Context {
@@ -63,11 +65,14 @@
     public this (ty : TypeBuilder, fn : MethodBuilder)
     {
       current_fun = fn.GetHeader ();
+      top_fun = current_fun;
       current_fun.usage = FunctionUsage.Used;
       top_level_fun = fn;
       current_type = ty;
 
       messenger = Passes.Solver.CurrentMessenger;
+
+      inside_yielding_function = fn.yield_stuff.IsSome;
     }
     
 
@@ -391,10 +396,12 @@
       }
       loop (current_fun.parms);
 
+      // move closure vars of loops to their parent function
       foreach (v in locals)
         match (v.ValKind) {
           | LocalValue.Kind.Function (h, _) =>
-            when (h.usage == FunctionUsage.UsedJustOnce)
+            when (h.usage == FunctionUsage.UsedJustOnce ||
+                  (inside_yielding_function && top_fun.id == current_fun.id))
               if (h.typarms is []) {
                 current_fun.closure_vars += h.closure_vars;
                 h.closure_vars = [];
@@ -405,7 +412,10 @@
         }
 
       foreach (v in locals) {
-        mutable in_clo = false;
+        // FIXME: this is wrong (performance problems) if we're inside
+        // some real local function in yielding function
+        mutable in_clo =
+          inside_yielding_function && !v.NeverClosurise;
 
         v.UsedIn.Iter (fun (h : Fun_header) {
           unless (in_clo) {
@@ -687,6 +697,7 @@
           LocalValue (current_fun, expr.jump_out.Name, 
                       expected, LocalValue.Kind.Plain (), 
                       is_mutable = true);
+        result.NeverClosurise = true;
         def label_id = Util.next_id ();
 
         def ret =



More information about the svn mailing list