[svn] r7586: nemerle/trunk/ncc: generation/Typer3.n testsuite/negative/base-calls.n testsuite/positive/bas...

divan svnadmin at nemerle.org
Tue Apr 10 07:58:27 CEST 2007


Log:
1) Add number of base()/this() calls check.
2) Improve default base() call generation. 
3) Fix 986.

Author: divan
Date: Tue Apr 10 07:58:20 2007
New Revision: 7586

Modified:
   nemerle/trunk/ncc/generation/Typer3.n
   nemerle/trunk/ncc/testsuite/negative/base-calls.n
   nemerle/trunk/ncc/testsuite/positive/base-calls.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	Tue Apr 10 07:58:20 2007
@@ -92,6 +92,8 @@
     // typer of our typer method or null for top-level methods
     parent : Typer3;
 
+    ptyper : Typer;
+    ptyper2 : Typer2;
     is_ctor : bool;
     
     // current method we're working on
@@ -129,14 +131,16 @@
 
     
     #region Entry points
-    public this (meth : MethodBuilder)
+    public this (meth : MethodBuilder, pt : Typer = null, pt2 : Typer2 = null)
     {
-      this (null, meth);
+      this (null, meth, pt, pt2);
     }
 
 
-    this (parent : Typer3, meth : MethodBuilder)
+    this (parent : Typer3, meth : MethodBuilder, pt : Typer = null, pt2 : Typer2 = null)
     {
+      ptyper = pt;
+      ptyper2 = pt2;
       the_method = meth;
       this (parent, meth.GetHeader ());
       local_function_type = meth.DeclaringType;
@@ -1111,6 +1115,44 @@
       | _ => false
     }
 
+    //Return min*max ctor calls in expr
+    CtorCalls (e : TExpr) : int*int 
+    {
+      def default = (0, 0);
+      def f (_) {
+        | TExpr.Call (e, _, _) when IsCtor (e) => Some ((1, 1))
+        | _ => None ()
+      }
+      and ctor_calls (e) {
+        SimpleFlow (e, f, default, seq, fork)
+      }
+      and acc (_) {
+        | [] => (0, 0)
+        | h :: rst => 
+          def (a, b) = acc (rst);
+          (a + h[0], b + h[1])
+      }
+      and seq (l) {
+        acc (List.Map (l, x => ctor_calls (x)))
+      }
+      and min (a, b) {
+        if (a < b) a else b
+      }
+      and max (a, b) {
+        if (a < b) b else a
+      }
+      and alt (_) {
+        | [] => (0, 0)
+        | [q] => q
+        | h :: rst => 
+          def (a, b) = alt (rst);
+          (min (a, h[0]), max (b, h[1])) 
+      }
+      and fork (l) {
+        alt (List.Map (l, x => seq (x)))
+      };
+      ctor_calls (e);
+    }
     /*
     Inject expressions before base ctor call, after this ctor call
     If expression is null then don't inject it.
@@ -1265,10 +1307,57 @@
     FixBaseCall (clo_ini : TExpr = null) : void
     {
       // put base () / this () call before storing 'this' in closure inside constructor
+      mutable e = null;
+      when (is_ctor)
+      {
+        e = match (current_local_fun.body) {
+          | FunBody.Typed (e) => e
+          | _ => Util.ice ("bad function body")
+        }
+        if (CurrentType.IsValueType) 
+        {
+          //Value types cannot call base ctor, so they can call several this()
+          def f (_) {
+            | TExpr.Call (e, _, _) as o when IsBaseCtor (e)
+             => Message.Error (o.loc, "Base constructor call in struct isn't allowed");
+                Some (false)
+            | _ => None ()
+          }
+          and check (e) {
+            SimpleFlow (e, f, false, seq, fork)
+          }
+          and seq (l) {
+            _ = List.Map (l, check);
+            true
+          }
+          and fork (l) {
+            _ = List.Map (l, seq);
+            true
+          }
+          _ = check (e);
+        }
+        else
+        {
+          match (CtorCalls (e)) {
+            | (0, 0) => 
+              def bc = ptyper.TypeExpr ( <[ base () ]> );
+              def bc = ptyper2.Walk (Typer2.Context.TopLevel, bc);
+              e = TExpr.Sequence (e.loc, e.ty, bc, e);
+            | (1, 1) => ()
+            | (0, _) => 
+              Message.Warning ("Base constructor call can be missed");
+            | (x, _) when x > 1 => 
+              Message.Error ($"Base constructor call happens at least $x times");
+            | (_, y) => 
+              Message.Warning ($"Base constructor call can happen $y times");
+          }
+        }
+      }
       when (is_ctor && !CurrentType.IsValueType)
       {
         def ini = null;
-        mutable e = match (current_local_fun.body) {
+        when (e == null)
+          e = match (current_local_fun.body) {
           | FunBody.Typed (e) => e
           | _ => Util.ice ("bad function body")
         }

Modified: nemerle/trunk/ncc/testsuite/negative/base-calls.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/base-calls.n	(original)
+++ nemerle/trunk/ncc/testsuite/negative/base-calls.n	Tue Apr 10 07:58:20 2007
@@ -31,3 +31,35 @@
     System.Console.WriteLine (A ().x)
   }
 }
\ No newline at end of file
+
+class B {
+  this (x : int) { // W: Base constructor call can be missed
+    when (x == 0)
+      base ();
+  }
+}
+      
+class C {
+  this () {}
+  this (x : int) { // W: Base constructor call can happen 2 times
+    when (x == 0)
+      base ();
+    this ();
+  }
+}
+
+class D {
+  this (x : int) { // E: Base constructor call happens at least 2 times
+    match (x) {
+      | 0 => base ()
+      | _ => base (); if (x == 1) base (); else base ();
+    }
+    base ();
+  } 
+}
+
+struct E {
+  this (_ : int) {
+    base (); // E: Base constructor call in struct isn't allowed
+  }
+}
\ No newline at end of file

Modified: nemerle/trunk/ncc/testsuite/positive/base-calls.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/base-calls.n	(original)
+++ nemerle/trunk/ncc/testsuite/positive/base-calls.n	Tue Apr 10 07:58:20 2007
@@ -49,7 +49,8 @@
     b.Prop += 3;
     def _ = Inherit(1);
     _ = Closurising (5);
-    System.Console.WriteLine (A976 ().x)
+    _ = A2 ();
+    _ = A3 ("");
   }
 }
 
@@ -82,21 +83,21 @@
     myfun ();    
   }
 }
-class A976 {
-  public mutable x : int;
-  static q () : void {}
-  static w (_ : void -> void) : void {}
-  public this (mutable y : int = 7) {
+class A2 : Base {
+  public this (y : int = 7) {
     if (y == 1) 
-      base (); 
+      base (3); 
     else 
-      base ();
-    q ();
-    --y;
-    this.x = 1;
-    def f() {++x};
-    f (); 
-    w (f);
+      base (4);
+  }
+}
+struct A3 {
+  public this (x : int) {
+    System.Console.WriteLine (x);
+  }
+  public this (_ : string) {
+    this (1);
+    this (2);
   }
 }
 /*
@@ -112,6 +113,8 @@
 fun 5 and aaa and no fld
 A()
 fun 5 and bbb and no fld
+A()
+1
 2
 END-OUTPUT
 */

Modified: nemerle/trunk/ncc/typing/LocalValue.n
==============================================================================
--- nemerle/trunk/ncc/typing/LocalValue.n	(original)
+++ nemerle/trunk/ncc/typing/LocalValue.n	Tue Apr 10 07:58:20 2007
@@ -38,7 +38,7 @@
     mutable is_registered : bool;
     mutable closure_field : IField;
 
-    kind : Kind;
+    internal kind : Kind;
     id   : int;
 
     [Accessor] name       : string;

Modified: nemerle/trunk/ncc/typing/Typer.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer.n	(original)
+++ nemerle/trunk/ncc/typing/Typer.n	Tue Apr 10 07:58:20 2007
@@ -134,8 +134,6 @@
         solver.InUse = true;
 
         Util.locate (m.Location, {
-          MaybeAddBaseCall (m);
-
           mutable typer_done = false;
           assert (messenger.IsTopLevel);
 
@@ -264,28 +262,6 @@
       current_method_builder
     }
 
-    MaybeAddBaseCall (m : MethodBuilder) : void
-    {
-      when (is_instance_ctor && !m.DeclaringType.IsValueType)
-        match (current_fun.body) {
-          | FunBody.Parsed (Sequence (exprs) as seq) =>
-            def exists_ctor_call (_) {
-              | [] => false 
-              | <[ base (.. $_) ]> :: _ 
-              | <[ this (.. $_) ]> :: _ => true
-              | _ :: xs => exists_ctor_call (xs)
-            }
-            if (exists_ctor_call (exprs))
-              ()
-            else
-              Util.locate (seq.loc,
-                current_fun.body = FunBody.Parsed (<[ { ..$(<[ base (); ]> :: exprs) } ]>)
-              )
-          | _ => ()
-        }
-    }
-
-
     MaybeDumpTypedTree () : void
     {
       when (Manager.Options.ShouldDump (current_fun)) {
@@ -366,7 +342,7 @@
       def t2 = Typer2 (current_type, meth);
       t2.Run ();
 
-      def t3 = Typer3 (meth);
+      def t3 = Typer3 (meth, this, t2);
       t3.Run ();
     }
     #endregion

Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n	(original)
+++ nemerle/trunk/ncc/typing/Typer2.n	Tue Apr 10 07:58:20 2007
@@ -47,7 +47,7 @@
     inside_yielding_function : bool;
 
     [System.Flags]
-    enum Context {
+    internal enum Context {
       | Clean              = 0x0000
       | IsTail             = 0x0001
       | NeedLValue         = 0x0002
@@ -114,7 +114,7 @@
     }
 
     
-    Walk (ctx : Context, expr : TExpr) : TExpr
+    internal Walk (ctx : Context, expr : TExpr) : TExpr
     {
       assert (expr != null);
       Util.locate (expr.loc, {



More information about the svn mailing list