summaryrefslogtreecommitdiff
path: root/src/test/java/com/seaofnodes/simple/Chapter18Test.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/seaofnodes/simple/Chapter18Test.java')
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter18Test.java43
1 files changed, 20 insertions, 23 deletions
diff --git a/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index 11bdfb9a..e5dd259b 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -157,7 +157,7 @@ return a;
{int -> int}? x2 = null; // null function ptr
return x2;
""");
- code.parse().iter().finalizeIR();
+ code.driver(CodeGen.Phase.FinalizeIR);
assertEquals("return null;", code._stop.toString());
assertEquals("null", Eval2.eval(code, 0 ) );
}
@@ -170,7 +170,7 @@ return x2;
x*x;
};
""");
- code.parse().iter().finalizeIR();
+ code.driver(CodeGen.Phase.FinalizeIR);
assertEquals("return (Parm_x(sq,i64)*x);", code._stop.toString());
//assertEquals("{ int -> int #1}", Eval2.eval(code, 3));
}
@@ -197,7 +197,7 @@ return sq(arg)+sq(3);
int cnt=1;
return { -> cnt; };
""");
- try { code.parse().iter().finalizeIR(); fail(); }
+ try { code.driver(CodeGen.Phase.FinalizeIR); fail(); }
catch( Exception e ) { assertEquals("Variable 'cnt' is out of function scope and must be a final constant",e.getMessage()); }
}
@@ -209,7 +209,7 @@ return { -> cnt; };
val cnt=2;
return { -> cnt; }();
""");
- code.parse().iter().finalizeIR();
+ code.driver(CodeGen.Phase.FinalizeIR);
assertEquals("return 2;", code._stop.toString());
assertEquals("2", Eval2.eval(code, 0));
}
@@ -222,8 +222,8 @@ return { -> cnt; }();
var fcn = arg ? { int x -> x*x; } : { int x -> x+x; };
return fcn(3);
""");
- code.parse().iter().finalizeIR();
- assertEquals("Stop[ return #2; return (Parm_x($fun21,i64,3)*x); return (Parm_x($fun22,i64,3)<<1); ]", code._stop.toString());
+ code.driver(CodeGen.Phase.FinalizeIR);
+ assertEquals("Stop[ return #2; return (Parm_x($fun21,i64)*x); return (Parm_x($fun22,i64)<<1); ]", code._stop.toString());
assertEquals("6", Eval2.eval(code, 0));
assertEquals("9", Eval2.eval(code, 1));
}
@@ -233,7 +233,7 @@ return fcn(3);
public void testFcn5() {
CodeGen code = new CodeGen("val fact = { int x -> x <= 1 ? 1 : x*fact(x-1); }; return fact(arg);");
code.driver(CodeGen.Phase.TypeCheck);
- assertEquals("Stop[ return #2; return Phi(Region,1,(Parm_x(fact,i64,arg,(x-1))*#2)); ]", code._stop.toString());
+ assertEquals("Stop[ return #2; return Phi(Region,1,(Parm_x(fact,i64)*#2)); ]", code._stop.toString());
assertEquals( "1", Eval2.eval(code, 0));
assertEquals( "1", Eval2.eval(code, 1));
assertEquals( "2", Eval2.eval(code, 2));
@@ -249,7 +249,7 @@ struct S { int i; };
val newS = { int x -> return new S { i=x; }; };
return newS(1).i;
""");
- code.driver(CodeGen.Phase.Schedule);
+ code.driver(CodeGen.Phase.TypeCheck);
assertEquals("return 1;", code._stop.toString());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -264,8 +264,8 @@ val f = {->1;};
val g = {->2;};
return 2;
""");
- code.driver(CodeGen.Phase.Schedule);
- assertEquals("Stop[ return 1; return 1; return 2; ]", code._stop.toString());
+ code.driver(CodeGen.Phase.TypeCheck);
+ assertEquals("return 1;", code._stop.toString());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -342,7 +342,7 @@ for(;;) {
}
return 1;
""");
- try { code.parse().iter().finalizeIR(); fail(); }
+ try { code.driver(CodeGen.Phase.FinalizeIR); fail(); }
catch( Exception e ) { assertEquals("No active loop for a break or continue",e.getMessage()); }
}
@@ -399,15 +399,16 @@ for(;;) {
val g = { ->
g();
};
-return 0;
+return g();
""");
try { code.driver(CodeGen.Phase.TypeCheck); fail(); }
catch( Exception e ) { assertEquals("No defined return type",e.getMessage()); }
}
- // Mutual recursion. Fails without SCCP to lift the recursive return types.
- @Ignore @Test
+ // Local SCCP cannot infer this recursive return type. The next chapter
+ // solves across calls and checks the same program's execution results.
+ @Test
public void testFcnMutRec() {
CodeGen code = new CodeGen(
"""
@@ -415,12 +416,8 @@ val is_even = { int x -> x ? is_odd (x-1) : true ; };
val is_odd = { int x -> x ? is_even(x-1) : false; };
return is_even(arg);
""");
- code.parse().iter().finalizeIR();
- assertEquals("Stop[ return is_even( arg); return Phi(Region,Phi(Region,is_even( ((Parm_x(is_even,int,arg,Sub)-1)-1)),0),1); ]", code._stop.toString());
- assertEquals("1", Eval2.eval(code, 0));
- assertEquals("0", Eval2.eval(code, 1));
- assertEquals("1", Eval2.eval(code, 2));
- assertEquals("0", Eval2.eval(code, 3));
+ try { code.driver(CodeGen.Phase.TypeCheck); fail(); }
+ catch( Parser.ParseException e ) { assertEquals("No defined return type",e.getMessage()); }
}
// Forward ref to 'x' means that
@@ -489,7 +486,7 @@ return p.coffee_count;
""";
@Test public void testCallMemory() {
- var code = new CodeGen(CALL_MEMORY).parse().iter().finalizeIR();
+ var code = new CodeGen(CALL_MEMORY).driver(CodeGen.Phase.FinalizeIR);
int[] calls={0};
code._stop.walk(n -> { if(n instanceof CallNode) calls[0]++; return null; });
assertEquals(2,calls[0]); // Keep real calls so this checks scheduling across them.
@@ -518,7 +515,7 @@ return p.coffee_count;
""";
@Test public void testRecursiveMemory() {
- var code = new CodeGen(RECURSIVE_MEMORY).parse().iter().finalizeIR();
+ var code = new CodeGen(RECURSIVE_MEMORY).driver(CodeGen.Phase.FinalizeIR);
for(int n=0; n<7; n++)
assertEquals(Long.toString((10L*(n+1)+n*(n+1)/2)*100+10+n),Eval2.eval(code,n));
}
@@ -536,7 +533,7 @@ return p.coffee_count;
""";
@Test public void testInlineAllocationMemory() {
- var code = new CodeGen(INLINE_MEMORY).parse().iter().finalizeIR();
+ var code = new CodeGen(INLINE_MEMORY).driver(CodeGen.Phase.FinalizeIR);
assertNull(code._stop.walk(n -> n instanceof CallNode ? n : null));
assertEquals("400944",Eval2.eval(code,0));
assertEquals("420946",Eval2.eval(code,2));