diff options
Diffstat (limited to 'src/test')
20 files changed, 758 insertions, 209 deletions
diff --git a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index d5ffe835..88d79215 100644 --- a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -15,7 +15,7 @@ public class BrainFuckTest { @Test public void testBrainfuck() { var program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.".getBytes(StandardCharsets.UTF_8); - var encoded = new StringBuilder("u8[] program = new u8[").append(program.length).append("];"); + var encoded = new StringBuilder("u8[] !program = new u8[").append(program.length).append("];"); for (int i = 0; i < program.length; i++) { int value = program[i] & 0xFF; encoded.append("program[").append(i).append("] = ").append(value).append(";"); @@ -23,54 +23,46 @@ public class BrainFuckTest { Parser parser = new Parser( encoded + """ -int pc = 0; -int d = 0; -u8[] data = new u8[100]; -u8[] output = new u8[0]; +var d = 0; +u8[] !output = new u8[0]; +u8[] !data = new u8[100]; -while (pc < program#) { - int command = program[pc]; +for( int pc = 0; pc < program#; pc++ ) { + var command = program[pc]; if (command == 62) { - d = d + 1; + d++; } else if (command == 60) { - d = d - 1; + d--; } else if (command == 43) { - data[d] = data[d] + 1; + data[d]++; } else if (command == 45) { - data[d] = data[d] - 1; + data[d]--; } else if (command == 46) { - u8[] old = output; + // Output a byte; increase the output array size + var old = output; output = new u8[output# + 1]; - int i = 0; - while (i < old#) { + for( var i = 0; i < old#; i++ ) output[i] = old[i]; - i = i + 1; - } - output[i] = data[d]; + output[old#] = data[d]; // Add the extra byte on the end } else if (command == 44) { data[d] = 42; } else if (command == 91) { if (data[d] == 0) { - int d = 1; - while (d > 0) { - pc = pc + 1; - command = program[pc]; - if (command == 91) d = d + 1; - if (command == 93) d = d - 1; + for( var d = 1; d > 0; ) { + command = program[++pc]; + if (command == 91) d++; + if (command == 93) d--; } } } else if (command == 93) { - if (data[d] != 0) { - int d = 1; - while (d > 0) { - pc = pc - 1; - command = program[pc]; - if (command == 93) d = d + 1; - if (command == 91) d = d - 1; + if (data[d]) { + for( var d = 1; d > 0; ) { + command = program[--pc]; + if (command == 93) d++; + if (command == 91) d--; } } } - pc = pc + 1; } return output; """); diff --git a/src/test/java/com/seaofnodes/simple/Chapter01Test.java b/src/test/java/com/seaofnodes/simple/Chapter01Test.java index c10dc510..f7524c17 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter01Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter01Test.java @@ -58,7 +58,7 @@ public class Chapter01Test { @Test public void testNotBad3() { // this test used to fail in chapter 1 - assertEquals("return 12;", new Parser("return --12;").parse().print()); + assertEquals("return 12;", new Parser("return - -12;").parse().print()); } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/src/test/java/com/seaofnodes/simple/Chapter03Test.java index 64ff153e..2de0b46e 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter03Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter03Test.java @@ -31,7 +31,7 @@ public class Chapter03Test { @Test public void testVarScopeNoPeephole() { - Parser parser = new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b; } return c; "); + Parser parser = new Parser("int a=1; int b=2; int !c=0; { int b=3; c=a+b; } return c; "); Node._disablePeephole = true; StopNode ret = parser.parse(); Node._disablePeephole = false; @@ -68,7 +68,7 @@ public class Chapter03Test { @Test public void testBad1() { try { - new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b;").parse(); + new Parser("int a=1; int b=2; int !c=0; { int b=3; c=a+b;").parse(); fail(); } catch( RuntimeException e ) { assertEquals("Syntax error, expected }: ",e.getMessage()); diff --git a/src/test/java/com/seaofnodes/simple/Chapter04Test.java b/src/test/java/com/seaofnodes/simple/Chapter04Test.java index 80cdb3f2..0db3afde 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter04Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter04Test.java @@ -96,14 +96,14 @@ public class Chapter04Test { @Test public void testBug1() { - Parser parser = new Parser("int a=arg+1; int b=a; b=1; return a+2; "); + Parser parser = new Parser("int a=arg+1; int !b=a; b=1; return a+2; "); StopNode ret = parser.parse(); assertEquals("return (arg+3);", ret.print()); } @Test public void testBug2() { - Parser parser = new Parser("int a=arg+1; a=a; return a; "); + Parser parser = new Parser("int !a=arg+1; a=a; return a; "); StopNode ret = parser.parse(); assertEquals("return (arg+1);", ret.print()); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter05Test.java b/src/test/java/com/seaofnodes/simple/Chapter05Test.java index b5920125..9afb8f28 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter05Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter05Test.java @@ -17,12 +17,11 @@ if (arg == 1) a = arg+2; else { a = arg-3; - } - -return a;"""); +return a; +"""); StopNode ret = parser.parse().iterate(); - assertEquals("return Phi(Region23,(arg+2),(arg-3));", ret.toString()); + assertEquals("return Phi(Region,(arg+2),(arg-3));", ret.toString()); } @Test @@ -37,7 +36,7 @@ if (arg == 1) { } return c;""", TypeInteger.BOT); StopNode ret = parser.parse().iterate(); - assertEquals("return Phi(Region22,4,3);", ret.toString()); + assertEquals("return Phi(Region,4,3);", ret.toString()); } @Test @@ -65,7 +64,7 @@ else b=a+1; return a+b;"""); StopNode ret = parser.parse().iterate(); - assertEquals("return ((arg*2)+Phi(Region26,2,3));", ret.toString()); + assertEquals("return ((arg*2)+Phi(Region,2,3));", ret.toString()); } @Test @@ -80,7 +79,7 @@ else a=b+1; return a+b;"""); StopNode ret = parser.parse().iterate(); - assertEquals("return ((Phi(Region37,(arg*2),arg)+arg)+Phi(Region,4,5));", ret.toString()); + assertEquals("return ((Phi(Region,(arg*2),arg)+arg)+Phi(Region,4,5));", ret.toString()); } @Test @@ -100,7 +99,7 @@ else return a; """, TypeInteger.BOT); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region43,Phi(Region28,2,3),Phi(Region41,4,5));", stop.toString()); + assertEquals("return Phi(Region,Phi(Region,2,3),Phi(Region,4,5));", stop.toString()); } @Test @@ -116,7 +115,7 @@ if( arg==0 ) return arg+a+b; """, TypeInteger.BOT); StopNode stop = parser.parse(); - assertEquals("return ((arg+Phi(Region20,1,0))+Phi(Region37,2,0));", stop.toString()); + assertEquals("return ((arg+Phi(Region,1,0))+Phi(Region,2,0));", stop.toString()); } @Test @@ -130,7 +129,7 @@ if( arg==1 ) } return a;"""); StopNode ret = parser.parse().iterate(); - assertEquals("return (arg==Phi(Region22,3,2));", ret.toString()); + assertEquals("return (arg==Phi(Region,3,2));", ret.toString()); } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter06Test.java b/src/test/java/com/seaofnodes/simple/Chapter06Test.java index ff1f3251..50c0580d 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter06Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter06Test.java @@ -65,7 +65,7 @@ else b=5; return b;""", TypeInteger.BOT); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region43,42,5);", stop.toString()); + assertEquals("return Phi(Region,42,5);", stop.toString()); } @Test @@ -84,7 +84,7 @@ else b=5; return b;""", TypeInteger.BOT); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region38,2,5);", stop.toString()); + assertEquals("return Phi(Region,2,5);", stop.toString()); } @Test @@ -144,7 +144,7 @@ else return a; """, TypeInteger.BOT); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region48,3,Phi(Region46,4,5));", stop.toString()); + assertEquals("return Phi(Region,3,Phi(Region,4,5));", stop.toString()); } @Test @@ -200,7 +200,7 @@ if( arg ) { return a+b; """); StopNode ret = parser.parse().iterate(); - assertEquals("return Phi(Region35,4,1);", ret.toString()); + assertEquals("return Phi(Region,4,1);", ret.toString()); } @@ -251,7 +251,7 @@ if( arg ) { return a+b+c; """); StopNode ret = parser.parse().iterate(); - assertEquals("return (Phi(Region48,Phi(Region29,2,3),0)+Phi(Region,3,1));", ret.toString()); + assertEquals("return (Phi(Region,Phi(Region,2,3),0)+Phi(Region,3,1));", ret.toString()); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter07Test.java b/src/test/java/com/seaofnodes/simple/Chapter07Test.java index b54c24a3..355bbba4 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter07Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter07Test.java @@ -10,15 +10,15 @@ public class Chapter07Test { @Test public void testExample() { Parser parser = new Parser( - """ - while(arg < 10) { - arg = arg + 1; - } - return arg; - """); +""" +while(arg < 10) { + arg = arg + 1; +} +return arg; +"""); Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop10,arg,(Phi_arg+1));", stop.toString()); + assertEquals("return Phi(Loop,arg,(Phi_arg+1));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); Node._disablePeephole = false; } @@ -36,7 +36,7 @@ if(arg){}else{ return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region31,1,Phi(Loop18,1,(Phi_a+1)));", stop.toString()); + assertEquals("return Phi(Region,1,Phi(Loop,1,(Phi_a+1)));", stop.toString()); } @Test @@ -56,7 +56,7 @@ while(i < arg) { return sum; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop12,0,Phi(Loop26,Phi_sum,(Phi_sum+Phi(Loop,0,(Phi_j+1)))));", stop.toString()); + assertEquals("return Phi(Loop,0,Phi(Loop,Phi_sum,(Phi_sum+Phi(Loop,0,(Phi_j+1)))));", stop.toString()); } @Test @@ -73,7 +73,7 @@ return b; """); Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop12,2,Phi(Region34,Phi_b,4));", stop.toString()); + assertEquals("return Phi(Loop,2,Phi(Region,Phi_b,4));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); Node._disablePeephole = false; } @@ -93,7 +93,7 @@ while(a < 10) { return b; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop12,2,(Phi(Region34,Phi_b,4)+1));", stop.toString()); + assertEquals("return Phi(Loop,2,(Phi(Region,Phi_b,4)+1));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -111,7 +111,7 @@ return a; """); Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop11,1,((Phi_a+1)+2));", stop.toString()); + assertEquals("return Phi(Loop,1,((Phi_a+1)+2));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); Node._disablePeephole = false; } @@ -128,7 +128,7 @@ while(a < 10) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,1,(Phi_a+3));", stop.toString()); + assertEquals("return Phi(Loop,1,(Phi_a+3));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -142,7 +142,7 @@ return a; """); Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop11,1,2);", stop.toString()); + assertEquals("return Phi(Loop,1,2);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); Node._disablePeephole = false; } @@ -156,7 +156,7 @@ while(arg) a = 2; return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,1,2);", stop.toString()); + assertEquals("return Phi(Loop,1,2);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -173,7 +173,7 @@ return a; """); Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop11,1,((Phi_a+1)+2));", stop.toString()); + assertEquals("return Phi(Loop,1,((Phi_a+1)+2));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); Node._disablePeephole = false; } @@ -190,7 +190,7 @@ while(a < 10) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,1,(Phi_a+3));", stop.toString()); + assertEquals("return Phi(Loop,1,(Phi_a+3));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -208,7 +208,7 @@ return a; """); Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop12,1,((Phi_a+1)+2));", stop.toString()); + assertEquals("return Phi(Loop,1,((Phi_a+1)+2));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); Node._disablePeephole = false; } @@ -226,7 +226,7 @@ while(a < 10) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop12,1,(Phi_a+3));", stop.toString()); + assertEquals("return Phi(Loop,1,(Phi_a+3));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter08Test.java b/src/test/java/com/seaofnodes/simple/Chapter08Test.java index c199b78c..bb3bd674 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter08Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter08Test.java @@ -23,7 +23,7 @@ while(arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region45,Phi(Region32,Phi(Loop10,arg,(Phi_arg+1)),Add),Add);", stop.toString()); + assertEquals("return Phi(Region,Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add),Add);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof RegionNode); Assert.assertEquals(5L, Evaluator.evaluate(stop, 1)); Assert.assertEquals(10L, Evaluator.evaluate(stop, 6)); @@ -46,7 +46,7 @@ while(arg < 10) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,1,Phi(Region52,Phi_a,(Phi_a+1)));", stop.toString()); + assertEquals("return Phi(Loop,1,Phi(Region,Phi_a,(Phi_a+1)));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -65,7 +65,7 @@ while(arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region43,Phi(Loop10,arg,(Phi_arg+1)),Add);", stop.toString()); + assertEquals("return Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof RegionNode); } @@ -81,7 +81,7 @@ while(arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region32,Phi(Loop10,arg,(Phi_arg+1)),Add);", stop.toString()); + assertEquals("return Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof RegionNode); } @@ -100,7 +100,7 @@ while(arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop10,arg,(Phi_arg+1));", stop.toString()); + assertEquals("return Phi(Loop,arg,(Phi_arg+1));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -117,7 +117,7 @@ while(arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop10,arg,(Phi_arg+1));", stop.toString()); + assertEquals("return Phi(Loop,arg,(Phi_arg+1));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode); } @@ -138,7 +138,7 @@ return arg; @Test public void testRegress2() { - Parser parser = new Parser("if(1) return 0; else while(arg>--arg) arg=arg+1; return 0;"); + Parser parser = new Parser("if(1) return 0; else while(arg>- -arg) arg=arg+1; return 0;"); StopNode stop = parser.parse().iterate(); assertEquals("return 0;", stop.toString()); } @@ -185,7 +185,7 @@ while(arg < 10) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region35,Phi(Loop11,1,(Phi_a+1)),Add);", stop.toString()); + assertEquals("return Phi(Region,Phi(Loop,1,(Phi_a+1)),Add);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof RegionNode); } @@ -201,7 +201,7 @@ while(1) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return (Phi(Loop11,1,Add)+1);", stop.toString()); + assertEquals("return (Phi(Loop,1,Add)+1);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof CProjNode prj && prj._idx==1 ); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/src/test/java/com/seaofnodes/simple/Chapter09Test.java index b1d9d6e5..c31afcd6 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter09Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter09Test.java @@ -69,7 +69,7 @@ while (arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,arg,(Phi_arg+2));", stop.toString()); + assertEquals("return Phi(Loop,arg,(Phi_arg+2));", stop.toString()); Assert.assertEquals(11L, Evaluator.evaluate(stop, 1)); } @@ -86,7 +86,7 @@ while (arg < 10) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop12,arg,(Phi_arg+4));", stop.toString()); + assertEquals("return Phi(Loop,arg,(Phi_arg+4));", stop.toString()); Assert.assertEquals(13L, Evaluator.evaluate(stop, 1)); } @@ -115,7 +115,7 @@ while (arg) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop18,arg,(Phi_arg+1));", stop.toString()); + assertEquals("return 0;", stop.toString()); } @Test @@ -185,7 +185,7 @@ while(arg) { return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop13,0,(-(Phi_a+3)));", stop.toString()); + assertEquals("return Phi(Loop,0,(-(Phi_a+3)));", stop.toString()); } @Test @@ -283,7 +283,7 @@ return v1+v0; public void testFuzz8() { Parser parser = new Parser("while(arg) arg = arg - 1; return arg;"); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop10,arg,(Phi_arg-1));", stop.toString()); + assertEquals("return 0;", stop.toString()); } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/src/test/java/com/seaofnodes/simple/Chapter10Test.java index 2a33031d..d41c83d8 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter10Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter10Test.java @@ -44,7 +44,7 @@ struct Foo { int x; }; Foo? foo = null; -Bar bar = new Bar; +Bar !bar = new Bar; bar.a = 1; bar.a = 2; return bar.a; @@ -57,7 +57,7 @@ return bar.a; public void testExample() { Parser parser = new Parser(""" struct Vector2D { int x; int y; }; -Vector2D v = new Vector2D; +Vector2D !v = new Vector2D; v.x = 1; if (arg) v.y = 2; @@ -96,7 +96,7 @@ arg=0+new s0.0; public void testLoop() { Parser parser = new Parser(""" struct Bar { int a; }; -Bar bar = new Bar; +Bar !bar = new Bar; while (arg) { bar.a = bar.a + 2; arg = arg + 1; @@ -104,14 +104,14 @@ while (arg) { return bar.a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop16,0,(Phi_a+2));", stop.toString()); + assertEquals("return Phi(Loop,0,(Phi_a+2));", stop.toString()); } @Test public void testIf() { Parser parser = new Parser(""" struct Bar { int a; }; -Bar bar = new Bar; +Bar !bar = new Bar; if (arg) bar = null; bar.a = 1; return bar.a; @@ -124,7 +124,7 @@ return bar.a; public void testIf2() { Parser parser = new Parser(""" struct Bar { int a; }; -Bar? bar = null; +Bar? !bar = null; if (arg) bar = new Bar; bar.a = 1; return bar.a; @@ -150,13 +150,13 @@ return bar.a; public void testIfOrNull() { Parser parser = new Parser(""" struct Bar { int a; }; -Bar? bar = new Bar; +Bar? !bar = new Bar; if (arg) bar = null; if( bar ) bar.a = 1; return bar; """); StopNode stop = parser.parse(false).iterate(); - assertEquals("return Phi(Region38,(*void)Phi(Region24,null,Bar),null);", stop.toString()); + assertEquals("return Phi(Region,(*void)Phi(Region,null,Bar),null);", stop.toString()); } @Test @@ -164,7 +164,7 @@ return bar; Parser parser = new Parser( """ struct Bar { int a; }; -Bar? bar = new Bar; +Bar? !bar = new Bar; if (arg) bar = null; int rez = 3; if( !bar ) rez=4; @@ -172,14 +172,14 @@ else bar.a = 1; return rez; """); StopNode stop = parser.parse(false).iterate(); - assertEquals("return Phi(Region44,4,3);", stop.toString()); + assertEquals("return Phi(Region,4,3);", stop.toString()); } @Test public void testWhileWithNullInside() { Parser parser = new Parser(""" struct s0 {int v0;}; -s0? v0 = new s0; +s0? !v0 = new s0; int ret = 0; while(arg) { ret = v0.v0; @@ -216,7 +216,7 @@ struct Iter { int x; int len; }; -Iter i = new Iter; +Iter !i = new Iter; i.len = arg; int sum=0; while( i.x < i.len ) { @@ -226,7 +226,7 @@ while( i.x < i.len ) { return sum; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop21,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString()); + assertEquals("return Phi(Loop,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString()); } @@ -234,9 +234,9 @@ return sum; public void test1() { Parser parser = new Parser(""" struct s0 {int v0;}; -s0 ret = new s0; +s0 !ret = new s0; while(arg) { - s0 v0 = new s0; + s0 !v0 = new s0; v0.v0 = arg; arg = arg-1; if (arg==5) ret=v0; @@ -245,15 +245,15 @@ while(arg) { return ret; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop16,s0,Phi(Region43,s0,Phi_ret));", stop.toString()); + assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", stop.toString()); } @Test public void test2() { Parser parser = new Parser(""" struct s0 {int v0;}; -s0 ret = new s0; -s0 v0 = new s0; +s0 !ret = new s0; +s0 !v0 = new s0; while(arg) { v0.v0 = arg; arg = arg-1; @@ -263,7 +263,7 @@ while(arg) { return ret; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop20,s0,Phi(Region44,s0,Phi_ret));", stop.toString()); + assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", stop.toString()); } @@ -271,16 +271,16 @@ return ret; public void test3() { Parser parser = new Parser(""" struct s0 {int v0;}; -s0 ret = new s0; +s0 !ret = new s0; while(arg < 10) { - s0 v0 = new s0; + s0 !v0 = new s0; if (arg == 5) ret=v0; arg = arg + 1; } return ret; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop16,s0,Phi(Region41,s0,Phi_ret));", stop.toString()); + assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", stop.toString()); } @Test @@ -350,7 +350,7 @@ s0 v1 = v0; return v1; """); StopNode stop = parser.parse().iterate(); - assertEquals("return s0;", stop.toString()); + assertEquals("return (const)s0;", stop.toString()); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/src/test/java/com/seaofnodes/simple/Chapter11Test.java index d6b7bb00..613b979b 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter11Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter11Test.java @@ -14,7 +14,7 @@ public class Chapter11Test { public void testFuzzer() { Parser parser = new Parser( """ -while(-----arg) { +while(---- -arg) { while(-arg) { while(-----arg*---0) { int N=--false==false<--arg; @@ -103,7 +103,7 @@ while(-----arg) { int UX=arg; while(UX<-3*arg) { UX=UX+arg/-1; - arg=-3--(-UX--47<arg==--arg==arg)/arg--UX>=-arg; + arg=-3--(-UX- -47<arg==--arg==arg)/arg- -UX>=-arg; if(---12) while(-UX) break; break; } @@ -224,9 +224,9 @@ if(arg!=62==arg) { } } arg=-arg+arg; - arg=--47+-arg<1>arg*(-arg==-arg--0>3); + arg=--47+-arg<1>arg*(-arg==-arg- -0>3); arg=(----arg)!=arg+--59; - arg=--4+arg==-(arg)-arg; + arg=- -4+arg==-(arg)-arg; } else { while(--true-----true*-25+-18>arg>=-----(-arg)---13) { @@ -292,7 +292,7 @@ else { } """); StopNode stop = parser.parse().iterate(); - assertEquals("Stop[ return 9; return 0; return 0; ]", stop.toString()); + assertEquals("Stop[ return 9; return 0; return 0; return 0; return 0; ]", stop.toString()); } @@ -324,7 +324,7 @@ while( prime <= arg ) { return primeCount; """); StopNode stop = parser.parse().iterate(); - assertEquals("Stop[ return 0; return Phi(Loop23,1,Phi(Region100,Phi_primeCount,Phi(Region93,(Phi_primeCount+1),Phi_primeCount))); ]", stop.toString()); + assertEquals("Stop[ return 0; return Phi(Loop,1,Phi(Region,Phi_primeCount,Phi(Region,(Phi_primeCount+1),Phi_primeCount))); ]", stop.toString()); assertEquals(0L, Evaluator.evaluate(stop, 1)); // No primes 1 or below assertEquals(1L, Evaluator.evaluate(stop, 2)); // 2 assertEquals(2L, Evaluator.evaluate(stop, 3)); // 2, 3 @@ -338,7 +338,7 @@ return primeCount; Parser parser = new Parser( """ struct S { int f; }; -S v=new S; +S !v=new S; v.f = 2; int i=new S.f; i=v.f; @@ -356,9 +356,9 @@ return i; Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; v.f = arg; -S t = new S; +S !t = new S; int i = 0; if (arg) { if (arg+1) v = t; @@ -369,7 +369,7 @@ if (arg) { return i; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region45,.f,0);", stop.toString()); + assertEquals("return Phi(Region,.f,0);", stop.toString()); } @Test @@ -377,7 +377,7 @@ return i; Parser parser = new Parser( """ struct S { int f; }; -S v0 = new S; +S !v0 = new S; S? v1; if (arg) v1 = new S; if (v1) { @@ -397,7 +397,7 @@ return v0; Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; v.f = arg; S t = new S; int i = v.f; @@ -414,7 +414,7 @@ return i; Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; while(1) { while(arg+1) { arg=arg-1; } if (arg) break; @@ -431,14 +431,14 @@ return v; Parser parser = new Parser( """ struct s { int v; }; -s ptr=new s; +s !ptr=new s; while( -arg ) ptr = new s; while(1) arg = arg+ptr.v; """); StopNode stop = parser.parse().iterate(); - assertEquals("Stop[ return 0; return 0; ]", stop.toString()); + assertEquals("return 0;", stop.toString()); } @Test @@ -446,7 +446,7 @@ while(1) Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; S t = new S; int i = v.f; while (arg) { @@ -464,7 +464,7 @@ return i; Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; S t = new S; while(arg) { arg=arg-1; @@ -476,7 +476,7 @@ while(arg) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop20,arg,Phi(Region48,.f,0));", stop.toString()); + assertEquals("return 0;", stop.toString()); } @Test @@ -484,7 +484,7 @@ return arg; Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; S t = new S; if (arg) { v.f=2; @@ -502,7 +502,7 @@ return v; Parser parser = new Parser( """ struct S { int f; }; -S v = new S; +S !v = new S; int i = arg; while (arg > 0) { int j = i/3; diff --git a/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/src/test/java/com/seaofnodes/simple/Chapter12Test.java index c0f6266a..a70a5f33 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter12Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter12Test.java @@ -43,7 +43,7 @@ while( 1 ) { return guess; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,(flt)arg,(((ToFloat/Phi_guess)+Phi_guess)/2.0));", stop.toString()); + assertEquals("return Phi(Loop,(flt)arg,(((ToFloat/Phi_guess)+Phi_guess)/2.0));", stop.toString()); assertEquals(3.0, Evaluator.evaluate(stop, 9)); assertEquals(1.414213562373095, Evaluator.evaluate(stop, 2)); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/src/test/java/com/seaofnodes/simple/Chapter13Test.java index 73fff8fd..eeb28f1d 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -23,9 +23,9 @@ return 3.14; Parser parser = new Parser( """ struct LLI { LLI? next; int i; }; -LLI? head = null; +LLI? !head = null; while( arg ) { - LLI x = new LLI; + LLI !x = new LLI; x.next = head; x.i = arg; head = x; @@ -42,9 +42,9 @@ return head.next.i; Parser parser = new Parser( """ struct LLI { LLI? next; int i; }; -LLI? head = null; +LLI? !head = null; while( arg ) { - LLI x = new LLI; + LLI !x = new LLI; x.next = head; x.i = arg; head = x; @@ -66,9 +66,9 @@ return next.i; """ struct int0 { int i; flt0? f; }; struct flt0 { flt f; int0? i; }; -int0 i0 = new int0; +int0 !i0 = new int0; i0.i = 17; -flt0 f0 = new flt0; +flt0 !f0 = new flt0; f0.f = 3.14; i0.f = f0; f0.i = i0; @@ -100,7 +100,7 @@ N n = new N { next = new M; }; return n.next; """); StopNode stop = parser.parse().iterate(); - assertEquals("return M;", stop.toString()); + assertEquals("return (const)M;", stop.toString()); } @Test @@ -121,19 +121,19 @@ return n.next; Parser parser = new Parser( """ struct N { N? next; int i; }; -N n = new N; +N !n = new N; n.i = 3.14; return n.i; """); try { parser.parse().iterate(); fail(); } - catch( Exception e ) { assertEquals("Cannot store 3.14 into field int i",e.getMessage()); } + catch( Exception e ) { assertEquals("Type 3.14 is not of declared type int",e.getMessage()); } } @Test public void testNullRef4() { - Parser parser = new Parser("-null-5/null-5"); + Parser parser = new Parser("-null-5/null-5;"); try { parser.parse().iterate(); fail(); } - catch( Exception e ) { assertEquals("Expected an identifier, found 'null'",e.getMessage()); } + catch( Exception e ) { assertEquals("Cannot 'Add' null",e.getMessage()); } } @Test public void testNullRef5() { @@ -157,7 +157,7 @@ struct S{}; public void testForwardRef0() { Parser parser = new Parser( """ -struct S1 { S2 s; }; +struct S1 { S2? s; }; return new S2; """); try { parser.parse().iterate(); fail(); } @@ -182,7 +182,7 @@ return new S1.s=new S2; """ struct I {int i;}; struct P { I? pi; }; -P p1 = new P; +P !p1 = new P; P p2 = new P; p2.pi = new I; p2.pi.i = 2; diff --git a/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/src/test/java/com/seaofnodes/simple/Chapter14Test.java index 7d7bb25a..23c82358 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter14Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter14Test.java @@ -59,7 +59,7 @@ while( b ) b = b + 456;// Truncate return b; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop11,123,((Phi_b+456)&255));", stop.toString()); + assertEquals("return 0;", stop.toString()); } @Test @@ -94,7 +94,7 @@ return b; Parser parser = new Parser( """ struct Foo { u1 b; }; -Foo f = new Foo; +Foo !f = new Foo; f.b = 123; return f.b; """); @@ -175,7 +175,7 @@ while(v1) break; return v1; """); StopNode stop = parser.parse().iterate(); - assertEquals("return (Phi(Loop18,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", stop.toString()); + assertEquals("return (Phi(Loop,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", stop.toString()); assertEquals(1L, Evaluator.evaluate(stop, 0)); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/src/test/java/com/seaofnodes/simple/Chapter15Test.java index 8161862f..4e2682dc 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter15Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter15Test.java @@ -25,7 +25,7 @@ return 3.14; Parser parser = new Parser( """ struct C { C? l; }; -C c = new C; +C !c = new C; c.l = c; return c; """); @@ -39,7 +39,7 @@ return c; Parser parser = new Parser( """ u8[] old = new u8[0]; -u8[] output = new u8[1]; +u8[] !output = new u8[1]; int i = 0; while (i < old#) { output[i] = old[i]; @@ -82,7 +82,7 @@ return is[1]; public void testBasic3() { Parser parser = new Parser( """ -int[] a = new int[2]; +int[] !a = new int[2]; a[0] = 1; a[1] = 2; return a[0]; @@ -97,7 +97,7 @@ return a[0]; Parser parser = new Parser( """ struct A { int i; }; -A?[] a = new A?[2]; +A?[] !a = new A?[2]; return a; """); StopNode stop = parser.parse().iterate(); @@ -111,10 +111,10 @@ return a; """ struct S { int x; flt y; }; // A new S -S s = new S; s.x=99; s.y = 3.14; +S !s = new S; s.x=99; s.y = 3.14; // Double-d array of Ss. Fill in one row. -S?[]?[] iss = new S?[]?[2]; +S?[]?[] !iss = new S?[]?[2]; iss[0] = new S?[7]; iss[0][2] = s; @@ -130,19 +130,18 @@ else { return rez; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region117,1.2,Phi(Region114,2.3,3.14));", stop.toString()); + assertEquals("return Phi(Region,1.2,Phi(Region,2.3,3.14));", stop.toString()); assertEquals(3.14, Evaluator.evaluate(stop, 0)); assertEquals(1.2 , Evaluator.evaluate(stop, 1)); } - @Ignore @Test public void testBasic6() { Parser parser = new Parser( """ struct S { int x; flt y; }; // A new S -S s = new S; s.x=99; s.y = 3.14; +S !s = new S; s.x=99; s.y = 3.14; // Double-d array of Ss. Fill in one row. S?[]?[] iss = new S?[]?[2]; @@ -156,9 +155,8 @@ if( iss[arg] ) rez = iss[arg][2].y; return rez; """); - StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region122,Phi(Region118,.y,1.2),1.2);", stop.toString()); - assertEquals(3.14, Evaluator.evaluate(stop, 0)); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Might be null accessing 'y'",e.getMessage()); } } @Test @@ -167,8 +165,8 @@ return rez; """ // Can we define a forward-reference array? struct Tree { Tree?[]? _kids; }; -Tree root = new Tree; -root._kids = new Tree?[2]; +Tree !root = new Tree; +root._kids = new Tree?[2]; // NO BANG SO ARRAY IS OF IMMUTABLE TREES???? root._kids[0] = new Tree; return root; """); @@ -192,7 +190,7 @@ return 0; public void testRollingSum() { Parser parser = new Parser( """ -int[] ary = new int[arg]; +int[] !ary = new int[arg]; // Fill [0,1,2,3,4,...] int i=0; while( i < ary# ) { @@ -216,44 +214,42 @@ return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6 public void sieveOEratosthenes() { Parser parser = new Parser( """ -int[] ary = new int[arg]; -int[] primes = new int[arg]; -int nprimes = 0; -// Find primes -int j=2; -while( j*j < arg ) { - while( ary[j]==1 ) j = j + 1; - // j is now a prime - primes[nprimes] = j; nprimes = nprimes + 1; +int[] !ary = new int[arg], !primes = new int[arg]; +int nprimes = 0, p=2; +// Find primes while p^2 < arg +while( p*p < arg ) { + // skip marked non-primes + while( ary[p]==1 ) p = p + 1; + // p is now a prime + primes[nprimes] = p; nprimes = nprimes + 1; // Mark out the rest non-primes - int i = j + j; + int i = p + p; while( i < ary# ) { ary[i] = 1; - i = i + j; + i = i + p; } - j = j + 1; + p = p + 1; } -// Now just collect the remaining primes -while( j < arg ) { - if( ary[j] == 0 ) { - primes[nprimes] = j; nprimes = nprimes + 1; +// Now just collect the remaining primes, no more marking +while( p < arg ) { + if( ary[p] == 0 ) { + primes[nprimes] = p; nprimes = nprimes + 1; } - j = j + 1; + p = p + 1; } -// Shrink the result array to size -int[] rez = new int[nprimes]; -j = 0; +// Copy/shrink the result array +int[] !rez = new int[nprimes]; +int j = 0; while( j < nprimes ) { rez[j] = primes[j]; j = j + 1; } - return rez; """); StopNode stop = parser.parse().iterate(); assertEquals("return [int];", stop.toString()); Evaluator.Obj obj = (Evaluator.Obj)Evaluator.evaluate(stop, 20); - assertEquals("[int] { # :int; [] :int; }",obj.struct().toString()); + assertEquals("[int] {int #; int ![]; }",obj.struct().toString()); long nprimes = (Long)obj.fields()[0]; long[] primes = new long[]{2,3,5,7,11,13,17,19}; for( int i=0; i<nprimes; i++ ) @@ -265,8 +261,8 @@ return rez; Parser parser = new Parser( """ struct S {int i; flt f;}; -S s1 = new S; -S s2 = new S; +S !s1 = new S; +S !s2 = new S; s2.i = 3; s2.f = 2.0; if (arg) s1 = new S; diff --git a/src/test/java/com/seaofnodes/simple/Chapter16Test.java b/src/test/java/com/seaofnodes/simple/Chapter16Test.java index ad287e82..5450824a 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter16Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter16Test.java @@ -43,28 +43,28 @@ return x+y; assertEquals(5L, Evaluator.evaluate(stop, 0)); } - @Test - public void testFinal0() { - Parser parser = new Parser( -""" -int !x=2; -x=3; -return x; -"""); - try { parser.parse().iterate(); fail(); } - catch( Exception e ) { assertEquals("Cannot reassign final 'x'",e.getMessage()); } - } +// @Test +// public void testFinal0() { +// Parser parser = new Parser( +//""" +//int !x=2; +//x=3; +//return x; +//"""); +// try { parser.parse().iterate(); fail(); } +// catch( Exception e ) { assertEquals("Cannot reassign final 'x'",e.getMessage()); } +// } @Test public void testFinal1() { Parser parser = new Parser( """ -int !x=2, y=3; +int x=2, y=3; if( arg ) { int x = y; x = x*x; y=x; } // Shadow final x return y; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region21,9,3);", stop.toString()); + assertEquals("return Phi(Region,9,3);", stop.toString()); assertEquals(3L, Evaluator.evaluate(stop, 0)); assertEquals(9L, Evaluator.evaluate(stop, 1)); } @@ -107,17 +107,78 @@ return z.x; @Test - public void testStructFinal() { + public void testStructFinal0() { Parser parser = new Parser(""" struct Point { int !x, !y; }; Point p = new Point { x=3; y=4; }; return p; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Point;", stop.toString()); + assertEquals("return (const)Point;", stop.toString()); assertEquals("Obj<Point>{x=3,y=4}", Evaluator.evaluate(stop, 0).toString()); } + @Test + public void testStructFinal1() { + Parser parser = new Parser(""" +struct Point { int x=3, y=4; }; +Point p = new Point { x=5; y=6; }; +p.x++; +return p; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); } + } + + @Test + public void testStructFinal2() { + Parser parser = new Parser(""" +struct Point { int x=3, y=4; }; +Point p = new Point; +p.x++; +return p; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); } + } + + @Test + public void testStructFinal3() { + Parser parser = new Parser(""" +struct Point { var x; var y; }; +Point p = new Point; +p.x++; +return p; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("'Point' is not fully initialized, field 'x' needs to be set in a constructor",e.getMessage()); } + } + + @Test + public void testStructFinal4() { + Parser parser = new Parser(""" +struct Point { val x=3; val y=4; }; +Point p = new Point; +p.x++; +return p; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot reassign final 'x'",e.getMessage()); } + } + + @Test + public void testStructFinal5() { + Parser parser = new Parser(""" +struct Point { var x=3; var y=4; }; +Point !p = new Point; +p.x++; +return p; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Point;", stop.toString()); + assertEquals("Obj<Point>{x=4,y=4}", Evaluator.evaluate(stop, 0).toString()); + } + // Same as the Chapter13 test with the same name, but using the new // constructor syntax @Test @@ -125,7 +186,7 @@ return p; Parser parser = new Parser( """ struct LLI { LLI? next; int i; }; -LLI? head = null; +LLI? !head = null; while( arg ) { head = new LLI { next=head; i=arg; }; arg = arg-1; @@ -147,12 +208,12 @@ return next.i; Parser parser = new Parser( """ struct LLI { LLI? next; int i; }; -LLI? head = null; +LLI? !head = null; while( arg ) { head = new LLI { next=head; // Any old code in the constructor - int tmp=arg; + int !tmp=arg; while( arg > 10 ) { tmp = tmp + arg; arg = arg - 1; @@ -182,7 +243,7 @@ struct Square { // Newtons approximation to the square root, computed in a constructor. // The actual allocation will copy in this result as the initial // value for 'diag'. - flt diag = arg*arg/2; + flt !diag = arg*arg/2; while( 1 ) { flt next = (side/diag + diag)/2; if( next == diag ) break; diff --git a/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/src/test/java/com/seaofnodes/simple/Chapter17Test.java new file mode 100644 index 00000000..1ca9a515 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/Chapter17Test.java @@ -0,0 +1,500 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.evaluator.Evaluator; +import com.seaofnodes.simple.node.StopNode; +import org.junit.Test; +import org.junit.Ignore; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class Chapter17Test { + + @Test + public void testJig() { + Parser parser = new Parser("return 1;"); + StopNode stop = parser.parse().iterate(); + assertEquals("return 1;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + + // --------------------------------------------------------------- + @Test + public void testInc0() { + Parser parser = new Parser(""" +return arg++; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return arg;", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testInc1() { + Parser parser = new Parser(""" +return arg+++arg++; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return ((arg*2)+1);", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testInc2() { + Parser parser = new Parser(""" +// -(arg--)-(arg--) +return -arg---arg--; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return (-((arg*2)+-1));", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testInc3() { + Parser parser = new Parser(""" +int[] !xs = new int[arg]; +xs[0]++; +xs[1]++; +return xs[0]; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 1;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 2)); + } + + @Test + public void testInc4() { + Parser parser = new Parser(""" +u8[] !xs = new u8[1]; +xs[0]--; +return xs[0]; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 255;", stop.toString()); + assertEquals(255L, Evaluator.evaluate(stop, 2)); + } + + @Test + public void testInc5() { + Parser parser = new Parser(""" +struct S { u16 x; }; +S !s = new S; +s.x--; +return s.x; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 65535;", stop.toString()); + assertEquals(65535L, Evaluator.evaluate(stop, 2)); + } + + @Test + public void testInc6() { + Parser parser = new Parser("return --arg;"); + StopNode stop = parser.parse().iterate(); + assertEquals("return (arg+-1);", stop.toString()); + assertEquals(-1L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testInc7() { + Parser parser = new Parser("u8 x=0; return --x;"); + StopNode stop = parser.parse().iterate(); + assertEquals("return 255;", stop.toString()); + assertEquals(255L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testInc8() { + Parser parser = new Parser("int x; x+=2; return x+=3;"); + StopNode stop = parser.parse().iterate(); + assertEquals("return 5;", stop.toString()); + assertEquals(5L, Evaluator.evaluate(stop, 0)); + } + + // --------------------------------------------------------------- + @Test public void testVar0() { + Parser parser = new Parser("var d; return d;"); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Syntax error, expected =expression: ;",e.getMessage()); } + } + + @Test public void testVar1() { + Parser parser = new Parser("val d; return d;"); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Syntax error, expected =expression: ;",e.getMessage()); } + } + + @Test public void testVar2() { + Parser parser = new Parser("int x; x=3; x++; return x; // Ok, no initializer so x is mutable "); + StopNode stop = parser.parse().iterate(); + assertEquals("return 4;", stop.toString()); + assertEquals(4L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testVar3() { + Parser parser = new Parser("int x=3; x++; return x; // Ok, primitive so x is mutable despite initializer "); + StopNode stop = parser.parse().iterate(); + assertEquals("return 4;", stop.toString()); + assertEquals(4L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testVar4() { + Parser parser = new Parser("struct S{int x;}; S s; s=new S; s.x++; return s.x; // Ok, no initializer so x is mutable "); + StopNode stop = parser.parse().iterate(); + assertEquals("return 1;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testVar5() { + Parser parser = new Parser("struct S{int x;}; S s; s=new S{x=3;}; s.x++; return s.x; // Ok, no initializer so x is mutable "); + StopNode stop = parser.parse().iterate(); + assertEquals("return 4;", stop.toString()); + assertEquals(4L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testVar6() { + Parser parser = new Parser("struct S{int x;}; S s=new S; s.x++; return s.x; // Error initializer so x is immutable "); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); } + } + + @Test public void testVar7() { + Parser parser = new Parser("struct S{int x;}; S s=new S{x=3;}; s.x++; return s.x; // Error initializer so x is immutable "); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); } + } + + @Test public void testVar8() { + Parser parser = new Parser("struct S{int x;}; S !s=new S; s.x++; return s.x; // Ok, has '!' so s.x is mutable "); + StopNode stop = parser.parse().iterate(); + assertEquals("return 1;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testVar9() { + Parser parser = new Parser("struct S{int x;}; var s=new S; s.x++; return s.x; // Ok, has var so s.x is mutable "); + StopNode stop = parser.parse().iterate(); + assertEquals("return 1;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testVar10() { + Parser parser = new Parser("struct S{int x;}; val s=new S; s.x++; return s.x; // Error, has val so x is immutable "); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); } + } + + @Test public void testVar11() { + Parser parser = new Parser(""" +struct Bar { int x; }; +Bar !bar = new Bar; +bar.x = 3; // Ok, bar is mutable + +struct Foo { Bar? !bar; int y; }; +Foo !foo = new Foo { bar = bar; }; +foo.bar = bar; // Ok foo is mutable +foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable + +val xfoo = foo; // Throw away mutability +xfoo.bar.x++; // Error, cannot mutate through xfoo + """); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); } + } + + @Test public void testVar12() { + Parser parser = new Parser(""" +struct Bar { int x; }; +Bar !bar = new Bar; +bar.x = 3; // Ok, bar is mutable + +struct Foo { Bar? !bar; int y; }; +Foo !foo = new Foo; +foo.bar = bar; // Ok bar is mutable +foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable + +val xfoo = foo; // Throw away mutability +int x4 = xfoo.bar.x; // Ok to read through xfoo, gets 4 +foo.bar.x++; // Bumps to 5 +int x5 = xfoo.bar.x; // Ok to read through xfoo, gets 5 +return x4*10+x5; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 45;", stop.toString()); + assertEquals(45L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testVar13() { + Parser parser = new Parser(""" +int i,i++; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Redefining name 'i'",e.getMessage()); } + } + + + @Test + public void testVar14() { + Parser parser = new Parser(""" +struct B {}; +struct A { B b; }; +A x = new A { + return b; // read before init + b = new B; +}; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Cannot read uninitialized field 'b'",e.getMessage()); } + } + + @Test + public void testVar15() { + Parser parser = new Parser(""" +struct B {}; +struct A { B b; }; +return new A { + if (arg) b = new B; // Constructor ends with partial init of b +}.b; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("'A' is not fully initialized, field 'b' needs to be set in a constructor",e.getMessage()); } + } + + // --------------------------------------------------------------- + @Test + public void testTrinary0() { + Parser parser = new Parser(""" +return arg ? 1 : 2; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Region,1,2);", stop.toString()); + assertEquals(2L, Evaluator.evaluate(stop, 0)); + assertEquals(1L, Evaluator.evaluate(stop, 1)); + } + + @Test + public void testTrinary1() { + Parser parser = new Parser(""" +return arg ? 0 : arg; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testTrinary2() { + Parser parser = new Parser(""" +struct Bar { int x; }; +var b = arg ? new Bar : null; +return b ? b.x++ + b.x++ : -1; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Region,1,-1);", stop.toString()); + assertEquals(-1L, Evaluator.evaluate(stop, 0)); + assertEquals( 1L, Evaluator.evaluate(stop, 1)); + } + + @Test + public void testTrinary3() { + Parser parser = new Parser(""" +struct Bar { int x; }; +var b = arg ? new Bar; +return b ? b.x++ + b.x++ : -1; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Region,1,-1);", stop.toString()); + assertEquals(-1L, Evaluator.evaluate(stop, 0)); + assertEquals( 1L, Evaluator.evaluate(stop, 1)); + } + + @Test + public void testTrinary4() { + // This test case will benefit from an unzipping transformation + Parser parser = new Parser(""" +struct Bar { Bar? next; int x; }; +var b = arg ? new Bar { next = (arg==2) ? new Bar{x=2;}; x=1; }; +return b ? b.next ? b.next.x : b.x; // parses "b ? (b.next ? b.next.x : b.x) : 0" +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Region,Phi(Region,.x,.x),0);", stop.toString()); + assertEquals( 0L, Evaluator.evaluate(stop, 0)); + assertEquals( 1L, Evaluator.evaluate(stop, 1)); + assertEquals( 2L, Evaluator.evaluate(stop, 2)); + } + + @Test + public void testTrinary5() { + Parser parser = new Parser(""" +flt f=arg?1:1.2; +return f; // missing widening +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Region,1.0,1.2);", stop.toString()); + assertEquals(1.2, Evaluator.evaluate(stop, 0)); + } + + // --------------------------------------------------------------- + @Test + public void testFor0() { + Parser parser = new Parser(""" +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return sum; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", stop.toString()); + assertEquals(3L, Evaluator.evaluate(stop, 3)); + assertEquals(45L, Evaluator.evaluate(stop, 10)); + } + @Test + public void testFor1() { + Parser parser = new Parser(""" +int sum=0, i=0; +for( ; i<arg; i++ ) + sum += i; +return sum; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", stop.toString()); + assertEquals(3L, Evaluator.evaluate(stop, 3)); + assertEquals(45L, Evaluator.evaluate(stop, 10)); + } + @Test + public void testFor2() { + Parser parser = new Parser(""" +int sum=0; +for( int i=0; ; i++ ) { + if( i>=arg ) break; + sum += i; +} +return sum; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", stop.toString()); + assertEquals(3L, Evaluator.evaluate(stop, 3)); + assertEquals(45L, Evaluator.evaluate(stop, 10)); + } + @Test + public void testFor3() { + Parser parser = new Parser(""" +int sum=0; +for( int i=0; i<arg; ) + sum += i++; +return sum; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", stop.toString()); + assertEquals(3L, Evaluator.evaluate(stop, 3)); + assertEquals(45L, Evaluator.evaluate(stop, 10)); + } + @Test + public void testFor4() { + Parser parser = new Parser(""" +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return i; +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Undefined name 'i'",e.getMessage()); } + } + @Test + public void testFor5() { + Parser parser = new Parser(""" +for(;;arg++;) {} +"""); + try { parser.parse().iterate(); fail(); } + catch( Exception e ) { assertEquals("Syntax error, expected Unexpected code after expression: ;",e.getMessage()); } + } + + + + // --------------------------------------------------------------- + @Test + public void testForward0() { + Parser parser = new Parser(""" +struct A{ + B? f1; + B? f2; +}; +return new A; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return A;", stop.toString()); + assertEquals("Obj<A>{f1=null,f2=null}", Evaluator.evaluate(stop).toString()); + } + + @Test + public void testForward1() { + Parser parser = new Parser(""" +struct A{ + B?[]? nil_array_of_b; + B?[] not_array_of_b = new B?[0]; +}; +return new A.not_array_of_b; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return (const)[*B?];", stop.toString()); + assertEquals("Obj<[*B?]>{#=0,[]=[]}", Evaluator.evaluate(stop).toString()); + } + + // --------------------------------------------------------------- + @Test + public void testLinkedList2() { + Parser parser = new Parser(""" +struct LLI { LLI? next; int i; }; +LLI? !head = null; +while( arg-- ) + head = new LLI { next=head; i=arg; }; +int sum=0; +var ptr = head; // A read-only ptr, to be assigned from read-only next fields +for( ; ptr; ptr = ptr.next ) + sum += ptr.i; +return sum; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Phi(Loop,0,(Phi_sum+.i));", stop.toString()); + assertEquals(45L, Evaluator.evaluate(stop, 10)); + } + + @Test + public void sieveOfEratosthenes() { + Parser parser = new Parser( +""" +var ary = new bool[arg], primes = new int[arg]; +var nprimes=0, p=0; +// Find primes while p^2 < arg +for( p=2; p*p < arg; p++ ) { + // skip marked non-primes + while( ary[p] ) p++; + // p is now a prime + primes[nprimes++] = p; + // Mark out the rest non-primes + for( int i = p + p; i < ary#; i += p ) + ary[i] = true; +} +// Now just collect the remaining primes, no more marking +for( ; p < arg; p++ ) + if( !ary[p] ) + primes[nprimes++] = p; +// Copy/shrink the result array +var !rez = new int[nprimes]; +for( int j=0; j<nprimes; j++ ) + rez[j] = primes[j]; +return rez; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return [int];", stop.toString()); + Evaluator.Obj obj = (Evaluator.Obj)Evaluator.evaluate(stop, 20); + assertEquals("[int] {int #; int ![]; }",obj.struct().toString()); + long nprimes = (Long)obj.fields()[0]; + long[] primes = new long[]{2,3,5,7,11,13,17,19}; + for( int i=0; i<nprimes; i++ ) + assertEquals(primes[i],(long)(Long)obj.fields()[i+1]); + } + +} diff --git a/src/test/java/com/seaofnodes/simple/SchedulerTest.java b/src/test/java/com/seaofnodes/simple/SchedulerTest.java index 168e0ed7..c67217af 100644 --- a/src/test/java/com/seaofnodes/simple/SchedulerTest.java +++ b/src/test/java/com/seaofnodes/simple/SchedulerTest.java @@ -24,7 +24,7 @@ public class SchedulerTest { struct S { int f; } -S v=new S; +S !v=new S; v.f = 2; int i=v.f; if (arg) v.f=1; @@ -42,7 +42,7 @@ return i; struct S { int f; }; -S v0=new S; +S !v0=new S; if(arg) v0.f=1; return v0; """); @@ -58,7 +58,7 @@ return v0; struct S { int f; }; -S v=new S; +S !v=new S; v.f = 2; int i=new S.f; i=v.f; diff --git a/src/test/java/com/seaofnodes/simple/TypeTest.java b/src/test/java/com/seaofnodes/simple/TypeTest.java index 6f7409cd..1cb97cf6 100644 --- a/src/test/java/com/seaofnodes/simple/TypeTest.java +++ b/src/test/java/com/seaofnodes/simple/TypeTest.java @@ -20,7 +20,7 @@ public class TypeTest { Field.make("b", TypeInteger.BOT,-4, false) }); Assert.assertEquals(s1, s1.glb()); Assert.assertNotEquals(s1, s1.dual()); - Assert.assertEquals(s1, s1.dual().glb()); + Assert.assertEquals(s1.makeRO(), s1.dual().glb()); TypeMem m1 = TypeMem.make(1,TypeInteger.ZERO); TypeMem m2 = TypeMem.make(2,TypeInteger.U16); @@ -57,7 +57,7 @@ public class TypeTest { Assert.assertEquals(ptr1nil, ptr1.glb()); Assert.assertEquals(ptr1, ptr1.dual().dual()); - Assert.assertEquals(ptr1.glb(), ptr1.dual().glb()); + Assert.assertEquals(ptr1.glb().makeRO(), ptr1.dual().glb()); Assert.assertEquals(TypeMemPtr.make(TypeStruct.BOT,true), ptr1.meet(ptr2nil)); Assert.assertEquals(ptr1.glb(), ptr1.meet(TypeMemPtr.NULLPTR)); @@ -79,7 +79,7 @@ public class TypeTest { // Test theoretical properties. // This is a symmetric complete bounded (ranked) lattice. - // Also the meet is commutative and associative. + // Also, the meet is commutative and associative. // The lattice has a dual (symmetric), and join is ~(~x meet ~y). // See https://en.wikipedia.org/wiki/Lattice_(order). @Test diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java index c215de00..72f84fa2 100644 --- a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java +++ b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java @@ -36,7 +36,7 @@ public class Evaluator { sb.append("obj@").append(cid); return id; } - if (struct._name.equals("u8[]")) { + if (struct._name.equals("[u8]")) { sb.append('"'); for (int i=struct._fields.length-1; i<fields.length; i++) { var v = fields[i]; @@ -308,6 +308,7 @@ public class Evaluator { case CProjNode cproj -> ((Object[])val(cproj.ctrl()))[cproj._idx]; case ProjNode proj -> ((Object[])val( proj.in(0) ))[ proj._idx]; case ScopeMinNode mem -> null; + case ReadOnlyNode ro -> val(ro.in(1)); default -> throw new AssertionError("Unexpected node " + node); }; } |
