[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