diff options
Diffstat (limited to 'src/test/java')
13 files changed, 444 insertions, 220 deletions
diff --git a/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/src/test/java/com/seaofnodes/simple/Chapter10Test.java index a5e3a9e0..0b8be64b 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter10Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter10Test.java @@ -1,10 +1,7 @@ package com.seaofnodes.simple; -import com.seaofnodes.simple.node.Node; -import com.seaofnodes.simple.node.StopNode; -import com.seaofnodes.simple.node.LoadNode; -import com.seaofnodes.simple.node.StoreNode; import com.seaofnodes.simple.evaluator.Evaluator; +import com.seaofnodes.simple.node.*; import java.util.BitSet; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -29,9 +26,7 @@ public class Chapter10Test { private static final String NULLABLE_POINT_SOURCE = """ struct Point { int x; }; Point?[] points = new Point?[2]; - Point point = new Point; - point.x = 42; - points[arg] = point; + points[arg] = new Point { x = 42; }; Point? p = points[1]; """; @@ -101,10 +96,10 @@ return p-r; struct Bar { int a; int b; -} +}; struct Foo { int x; -} +}; Foo? foo = null; Bar bar = new Bar; bar.a = 1; @@ -118,7 +113,7 @@ return bar.a; @Test public void testExample() { Parser parser = new Parser(""" -struct Vector2D { int x; int y; } +struct Vector2D { int x; int y; }; Vector2D v = new Vector2D; v.x = 1; if (arg) @@ -136,7 +131,7 @@ return v; Parser parser = new Parser(""" struct s0 { int v0; -} +}; s0? v1=null; int v3=v1.zAicm; """); @@ -147,7 +142,7 @@ int v3=v1.zAicm; @Test public void testBug2() { Parser parser = new Parser(""" -struct s0 { int v0; } +struct s0 { int v0; }; arg=0+new s0.0; """); try { parser.parse(); fail(); } @@ -157,7 +152,7 @@ arg=0+new s0.0; @Test public void testLoop() { Parser parser = new Parser(""" -struct Bar { int a; } +struct Bar { int a; }; Bar bar = new Bar; while (arg) { bar.a = bar.a + 2; @@ -166,13 +161,13 @@ while (arg) { return bar.a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop15,0,(Phi_a+2));", stop.toString()); + assertEquals("return Phi(Loop17,0,(Phi_a+2));", stop.toString()); } @Test public void testIf() { Parser parser = new Parser(""" -struct Bar { int a; } +struct Bar { int a; }; Bar bar = new Bar; if (arg) bar = null; bar.a = 1; @@ -185,7 +180,7 @@ return bar.a; @Test public void testIf2() { Parser parser = new Parser(""" -struct Bar { int a; } +struct Bar { int a; }; Bar? bar = null; if (arg) bar = new Bar; bar.a = 1; @@ -198,7 +193,7 @@ return bar.a; @Test public void testIf3() { Parser parser = new Parser(""" -struct Bar { int a; } +struct Bar { int a; }; Bar bar = null; if (arg) bar = null; bar.a = 1; @@ -211,21 +206,21 @@ return bar.a; @Test public void testIfOrNull() { Parser parser = new Parser(""" -struct Bar { int a; } +struct Bar { int a; }; Bar? bar = new Bar; if (arg) bar = null; if( bar ) bar.a = 1; return bar; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region36,(*void)Phi(Region22,null,Bar),null);", stop.toString()); + assertEquals("return Phi(Region38,(*void)Phi(Region24,null,Bar),null);", stop.toString()); } @Test public void testIfOrNull2() { Parser parser = new Parser( """ -struct Bar { int a; } +struct Bar { int a; }; Bar? bar = new Bar; if (arg) bar = null; int rez = 3; @@ -234,13 +229,13 @@ else bar.a = 1; return rez; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region42,4,3);", stop.toString()); + assertEquals("return Phi(Region44,4,3);", stop.toString()); } @Test public void testWhileWithNullInside() { Parser parser = new Parser(""" -struct s0 {int v0;} +struct s0 {int v0;}; s0? v0 = new s0; int ret = 0; while(arg) { @@ -260,7 +255,7 @@ return ret; Parser parser = new Parser(""" struct s0 { int v0; -} +}; s0? v1=new s0; s0? v1; v1=new s0; @@ -277,7 +272,7 @@ v1=new s0; struct Iter { int x; int len; -} +}; Iter i = new Iter; i.len = arg; int sum=0; @@ -288,16 +283,14 @@ while( i.x < i.len ) { return sum; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop19,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString()); + assertEquals("return Phi(Loop22,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString()); } - - @Test public void test1() { Parser parser = new Parser(""" -struct s0 {int v0;} +struct s0 {int v0;}; s0 ret = new s0; while(arg) { s0 v0 = new s0; @@ -309,13 +302,13 @@ while(arg) { return ret; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop15,s0,Phi(Region42,s0,Phi_ret));", stop.toString()); + assertEquals("return Phi(Loop17,s0,Phi(Region44,s0,Phi_ret));", stop.toString()); } @Test public void test2() { Parser parser = new Parser(""" -struct s0 {int v0;} +struct s0 {int v0;}; s0 ret = new s0; s0 v0 = new s0; while(arg) { @@ -327,14 +320,14 @@ while(arg) { return ret; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop21,s0,Phi(Region43,s0,Phi_ret));", stop.toString()); + assertEquals("return Phi(Loop23,s0,Phi(Region45,s0,Phi_ret));", stop.toString()); } @Test public void test3() { Parser parser = new Parser(""" -struct s0 {int v0;} +struct s0 {int v0;}; s0 ret = new s0; while(arg < 10) { s0 v0 = new s0; @@ -344,21 +337,19 @@ while(arg < 10) { return ret; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop15,s0,Phi(Region39,s0,Phi_ret));", stop.toString()); + assertEquals("return Phi(Loop17,s0,Phi(Region41,s0,Phi_ret));", stop.toString()); } @Test public void testBug3() { Parser parser = new Parser(""" -struct s0 { - int f0; -} -if(0>=0) return new s0; +struct s0 { int f0; }; return new s0; int v0=null.f0; """); - try { parser.parse(); fail(); } - catch( Exception e ) { assertEquals("Accessing unknown field 'f0' from 'null'", e.getMessage()); } + StopNode stop = parser.parse().iterate(); + assertEquals("return s0;", stop.toString()); + assertEquals("Obj<s0>{f0=0}", Evaluator.evaluate(stop, 0).toString()); } @Test @@ -382,7 +373,7 @@ if(0) { Parser parser = new Parser(""" struct s0 { int f0; -} +}; if(0) return 0; else return new s0; if(new s0.f0) return 0; @@ -409,7 +400,7 @@ return 0; @Test public void testBug7() { Parser parser = new Parser(""" -struct s0 { int f0; } +struct s0 { int f0; }; s0 v0 = new s0; while(v0.f0) {} s0 v1 = v0; @@ -464,7 +455,7 @@ return 0; @Test public void testReadBeforeStores() { var stop = new Parser(""" - struct S { int x; int y; } + struct S { int x; int y; }; S a = new S; S b = new S; a.x = 11; b.x = 22; S p = a; if (arg) p = b; @@ -478,7 +469,7 @@ return 0; } static final String NESTED_MEMORY = """ - struct S { int x; int y; int z; } + struct S { int x; int y; int z; }; S s = new S; s.x = 5; s.y = 7; s.z = 11; while (arg > 0) { @@ -509,7 +500,7 @@ return 0; @Test public void testMemoryAtEarlyReturns() { var stop = new Parser(""" - struct S { int x; int y; int z; } + struct S { int x; int y; int z; }; S s = new S; s.x = 3; s.y = 5; s.z = 7; if (arg) { s.x = 11; s.z = 13; return s; } @@ -525,7 +516,7 @@ return 0; @Test public void testKeepLoadsAtMerge() { StopNode stop = new Parser(""" - struct S { int x; } + struct S { int x; }; S a = new S; S b = new S; a.x = arg; b.x = arg+1; S p = a; S q = b; @@ -543,7 +534,7 @@ return 0; @Test public void testDropStores() { StopNode stop = new Parser(""" - struct S { int x; } + struct S { int x; }; S s = new S; if (arg) s.x=arg+1; else s.x=arg+2; return s; @@ -555,7 +546,7 @@ return 0; @Test public void testKeepReadsBeforeWrites() { StopNode stop = new Parser(""" - struct S { int x; int y; } + struct S { int x; int y; }; S a = new S; S b = new S; a.x=arg; b.x=arg+1; S p=a; S q=b; diff --git a/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/src/test/java/com/seaofnodes/simple/Chapter11Test.java index 5f92c9c1..e009c6b6 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter11Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter11Test.java @@ -8,7 +8,7 @@ import static org.junit.Assert.*; public class Chapter11Test { @Test public void testIndependentField() { var stop = new Parser(""" - struct S { int x; int y; } + struct S { int x; int y; }; S s = new S; s.x = 42; while (arg > 0) { s.y = s.y + arg; arg = arg - 1; } @@ -21,7 +21,7 @@ public class Chapter11Test { @Test public void testParallelMemoryPhis() { var stop = new Parser(""" - struct S { int x; int y; int z; } + struct S { int x; int y; int z; }; S a = new S; S b = new S; S p = a; if (arg) p = b; while (arg > 0) { diff --git a/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/src/test/java/com/seaofnodes/simple/Chapter12Test.java index e885deb3..22976058 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter12Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter12Test.java @@ -2,7 +2,6 @@ package com.seaofnodes.simple; import com.seaofnodes.simple.evaluator.Evaluator; import com.seaofnodes.simple.node.StopNode; -import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -23,7 +22,7 @@ return 3.14; public void testLinkedList0() { Parser parser = new Parser( """ -struct LLI { LLI? next; int i; } +struct LLI { LLI? next; int i; }; LLI? head = null; while( arg ) { LLI x = new LLI; @@ -42,7 +41,7 @@ return head.next.i; public void testLinkedList1() { Parser parser = new Parser( """ -struct LLI { LLI? next; int i; } +struct LLI { LLI? next; int i; }; LLI? head = null; while( arg ) { LLI x = new LLI; @@ -65,8 +64,8 @@ return next.i; public void testCoRecur() { Parser parser = new Parser( """ -struct int0 { int i; flt0? f; } -struct flt0 { flt f; int0? i; } +struct int0 { int i; flt0? f; }; +struct flt0 { flt f; int0? i; }; int0 i0 = new int0; i0.i = 17; flt0 f0 = new flt0; @@ -83,7 +82,7 @@ return f0.i.f.i.i; public void testNullRef0() { Parser parser = new Parser( """ -struct N { N next; int i; } +struct N { N? next; int i; }; N n = new N; return n.next; """); @@ -95,33 +94,33 @@ return n.next; public void testNullRef1() { Parser parser = new Parser( """ -struct N { N next; int i; } -N n = new N; -n.next = new N; +struct M { int m; }; +struct N { M next; int i; }; +N n = new N { next = new M; }; return n.next; """); StopNode stop = parser.parse().iterate(); - assertEquals("return N;", stop.toString()); + assertEquals("return M;", stop.toString()); } @Test public void testNullRef2() { Parser parser = new Parser( """ -struct N { N next; int i; } -N n = new N; -n.next = null; +struct M { int m; }; +struct N { M next; int i; }; +N n = new N { next = null; } return n.next; """); try { parser.parse().iterate(); fail(); } - catch( Exception e ) { assertEquals("Cannot store null into field *N next",e.getMessage()); } + catch( Exception e ) { assertEquals("Type null is not of declared type *M",e.getMessage()); } } @Test public void testNullRef3() { Parser parser = new Parser( """ -struct N { N next; int i; } +struct N { N? next; int i; }; N n = new N; n.i = 3.14; return n.i; @@ -158,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(); } @@ -169,8 +168,8 @@ return new S2; public void testForwardRef1() { Parser parser = new Parser( """ -struct S1 { S2? s; } -struct S2 { int x; } +struct S1 { S2? s; }; +struct S2 { int x; }; return new S1.s=new S2; """); StopNode stop = parser.parse().iterate(); @@ -181,8 +180,8 @@ return new S1.s=new S2; public void testcheckNull() { Parser parser = new Parser( """ -struct I {int i;} -struct P {I pi;} +struct I {int i;}; +struct P { I? pi; }; P p1 = new P; P p2 = new P; p2.pi = new I; diff --git a/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/src/test/java/com/seaofnodes/simple/Chapter13Test.java index 3373a1aa..c749aba6 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -293,7 +293,7 @@ else { } """); StopNode stop = parser.parse().iterate(); - assertEquals("Stop[ return 9; return 0; return 0; return 0; ]", stop.toString()); + assertEquals("Stop[ return 9; return 0; return 0; ]", stop.toString()); } @@ -338,7 +338,7 @@ return primeCount; public void testAntiDeps1() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v=new S; v.f = 2; int i=new S.f; @@ -356,7 +356,7 @@ return i; public void testAntiDeps2() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v = new S; v.f = arg; S t = new S; @@ -370,14 +370,14 @@ if (arg) { return i; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region46,.f,0);", stop.toString()); + assertEquals("return Phi(Region48,.f,0);", stop.toString()); } @Test public void testAntiDeps3() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v0 = new S; S? v1; if (arg) v1 = new S; @@ -397,7 +397,7 @@ return v0; public void testAntiDeps4() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v = new S; v.f = arg; S t = new S; @@ -414,7 +414,7 @@ return i; public void testAntiDeps5() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v = new S; while(1) { while(arg+1) { arg=arg-1; } @@ -431,7 +431,7 @@ return v; public void testAntiDeps6() { Parser parser = new Parser( """ -struct s { int v; } +struct s { int v; }; s ptr=new s; while( -arg ) ptr = new s; @@ -446,7 +446,7 @@ while(1) public void testAntiDeps7() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v = new S; S t = new S; int i = v.f; @@ -464,7 +464,7 @@ return i; public void testAntiDeps8() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v = new S; S t = new S; while(arg) { @@ -477,14 +477,14 @@ while(arg) { return arg; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop21,arg,Phi(Region48,.f,0));", stop.toString()); + assertEquals("return Phi(Loop23,arg,Phi(Region50,.f,0));", stop.toString()); } @Test public void testAntiDeps9() { Parser parser = new Parser( """ -struct S { int f; } +struct S { int f; }; S v = new S; S t = new S; if (arg) { @@ -501,8 +501,8 @@ return v; @Test public void testExample2() { Parser parser = new Parser( - """ -struct S { int f; } +""" +struct S { int f; }; S v = new S; int i = arg; while (arg > 0) { @@ -516,4 +516,39 @@ return v; StopNode stop = parser.parse().iterate(); //assertEquals("return new S;", stop.toString()); } + + @Test + public void testScheduleUse() { + Parser parser = new Parser( +""" +int v0=0; +while(0>=0) { + u1 v1=0; + v1=v0; + if(v1*0) + v0=-v1; +} +return 0; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + } + + @Test + public void testLoopCarriedDep() { + Parser parser = new Parser( +""" +u32 v0=0; +{ + int v1=0; + while(v1) { + v1=1>>>v0!=0; + v0=v1/0; + } +} +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + } + } diff --git a/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/src/test/java/com/seaofnodes/simple/Chapter14Test.java index d64423de..03a02795 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter14Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter14Test.java @@ -93,7 +93,7 @@ return b; public void testRefLoad() { Parser parser = new Parser( """ -struct Foo { u1 b; } +struct Foo { u1 b; }; Foo f = new Foo; f.b = 123; return f.b; @@ -166,6 +166,39 @@ return arg; } @Test + public void testCloneAnd() { + Parser parser = new Parser(""" +int v0=0; +u32 v1 = 1&(1<<arg)&(1<<arg); +while(arg) v1=-v0; +while(v1) break; +return v1; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return (Phi(Loop17,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testAndHigh() { + Parser parser = new Parser(""" +int v0=0; +if(0&0>>>0) { + while(0) { + u8 v1=0; + v0=0>>>0; + v1=arg; + while(v1+0) {} + } +} +return v0; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + } + + @Test public void testTypes() { Parser parser = new Parser( """ diff --git a/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/src/test/java/com/seaofnodes/simple/Chapter15Test.java index 8f9d2d14..643b45e7 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter15Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter15Test.java @@ -4,81 +4,15 @@ import com.seaofnodes.simple.evaluator.Evaluator; import com.seaofnodes.simple.node.StopNode; import org.junit.Test; import org.junit.Ignore; - -import java.nio.charset.StandardCharsets; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class Chapter15Test { - @Test public void testPartialAllocationMemory() { - StopNode stop = new Parser(""" - struct Other { int a; int b; int c; } - struct S { int x; flt y; S? next; } - Other other = new Other; - other.c = 7; - S a = new S; - a.x = arg; - a.y = 1.5; - S b = new S; - // S's aliases are global identities, not tuple or input positions. - // Bypass b's zeroing for a, preserving the unrelated Other slice. - return a.x + a.y + b.x + b.y + other.c; - """).parse().iterate(); - assertEquals(8.5, Evaluator.evaluate(stop,0)); - assertEquals(12.5, Evaluator.evaluate(stop,4)); - - stop = new Parser(""" - struct S { int x; flt y; S? next; } - S a = new S; S b = new S; - S p = a; if (arg) p = b; - // The memory result carries distinct int, float and pointer facts. - if (p.next != null) return 99; - return p.x + p.y; - """).parse().iterate(); - assertEquals("return 0.0;",stop.toString()); - assertEquals(0.0,Evaluator.evaluate(stop,1)); - } - - @Test public void testReadAcrossAllocation() { - StopNode stop = new Parser(""" - struct S { int x; } - S a = new S; S b = new S; - a.x = 11; b.x = 22; - S p = a; if (arg) p = b; - int before = p.x; - S c = new S; - a.x = 33; b.x = 44; - // The partial input to c must not hide the read/write ordering. - // p can alias either object, so node inequality cannot bypass New. - return before*100 + p.x + c.x; - """).parse().iterate(); - assertEquals(1133L,Evaluator.evaluate(stop,0)); - assertEquals(2244L,Evaluator.evaluate(stop,1)); - } - - @Test public void testAllocationInLoop() { - StopNode stop = new Parser(""" - struct S { int x; flt y; S? next; } - S old = new S; old.x = 7; - S last = old; - while (arg > 0) { - S fresh = new S; - fresh.x = last.x + 1; - fresh.next = last; - last = fresh; - arg = arg - 1; - } - return old.x*100 + last.x; - """).parse().iterate(); - assertEquals(707L,Evaluator.evaluate(stop,0)); - assertEquals(712L,Evaluator.evaluate(stop,5)); - } - @Test public void testJig() { - Parser parser = new Parser(""" + Parser parser = new Parser( +""" return 3.14; """); StopNode stop = parser.parse().iterate(); @@ -87,29 +21,10 @@ return 3.14; } @Test - public void testLifetime() { - Parser parser = new Parser(""" -u8[] b = new u8[5]; -if (arg) { - b[0] = b[0] + 1; -} else { - b[1] = b[1] * 2; -} -return b[0] + b[1]; -"""); - StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region72,1,0);", stop.toString()); - assertEquals(0L, Evaluator.evaluate(stop, 0)); - assertEquals(1L, Evaluator.evaluate(stop, 1)); - } - - @Test public void testCyclic() { Parser parser = new Parser( """ -struct C { - C? l; -} +struct C { C? l; }; C c = new C; c.l = c; return c; @@ -134,7 +49,7 @@ output[i] = 1; return output; """); StopNode stop = parser.parse().iterate(); - assertEquals("return u8[];", stop.toString()); + assertEquals("return [u8];", stop.toString()); assertEquals("\u0001", Evaluator.evaluate(stop, 0).toString()); } @@ -181,20 +96,20 @@ return a[0]; public void testBasic4() { Parser parser = new Parser( """ -struct A { int i; } +struct A { int i; }; A?[] a = new A?[2]; return a; """); StopNode stop = parser.parse().iterate(); - assertEquals("return *A?[];", stop.toString()); - assertEquals("Obj<*A?[]>{#=2,[]=[null,null]}", Evaluator.evaluate(stop, 0).toString()); + assertEquals("return [*A?];", stop.toString()); + assertEquals("Obj<[*A?]>{#=2,[]=[null,null]}", Evaluator.evaluate(stop, 0).toString()); } @Test public void testBasic5() { Parser parser = new Parser( """ -struct S { int x; flt y; } +struct S { int x; flt y; }; // A new S S s = new S; s.x=99; s.y = 3.14; @@ -215,8 +130,10 @@ else { return rez; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Region122,1.2,Phi(Region119,2.3,.y));", stop.toString()); + // Shared allocation memory prevents folding the field Store into New. + assertEquals("return Phi(Region121,1.2,Phi(Region118,2.3,.y));", stop.toString()); assertEquals(3.14, Evaluator.evaluate(stop, 0)); + assertEquals(1.2 , Evaluator.evaluate(stop, 1)); } @Ignore @@ -224,7 +141,7 @@ return rez; public void testBasic6() { Parser parser = new Parser( """ -struct S { int x; flt y; } +struct S { int x; flt y; }; // A new S S s = new S; s.x=99; s.y = 3.14; @@ -250,7 +167,7 @@ return rez; Parser parser = new Parser( """ // Can we define a forward-reference array? -struct Tree { Tree?[] _kids; } +struct Tree { Tree?[]? _kids; }; Tree root = new Tree; root._kids = new Tree?[2]; root._kids[0] = new Tree; @@ -258,17 +175,14 @@ return root; """); StopNode stop = parser.parse().iterate(); assertEquals("return Tree;", stop.toString()); - assertEquals("Obj<Tree>{_kids=Obj<*Tree?[]>{#=2,[]=[Obj<Tree>{_kids=null},null]}}", Evaluator.evaluate(stop, 0).toString()); + assertEquals("Obj<Tree>{_kids=Obj<[*Tree?]>{#=2,[]=[Obj<Tree>{_kids=null},null]}}", Evaluator.evaluate(stop, 0).toString()); } @Test public void testNestedStructAddMemProj() { Parser parser = new Parser( """ -struct S { - int a; - int[] b; -} +struct S { int a; int[] b; }; return 0; """); StopNode stop = parser.parse(); @@ -338,9 +252,9 @@ while( j < nprimes ) { return rez; """); StopNode stop = parser.parse().iterate(); - assertEquals("return int[];", stop.toString()); + assertEquals("return [int];", stop.toString()); Evaluator.Obj obj = (Evaluator.Obj)Evaluator.evaluate(stop, 20); - assertEquals("int[] {\n # :int;\n [] :int;\n}",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++ ) @@ -351,7 +265,7 @@ return rez; public void testNewNodeInit() { Parser parser = new Parser( """ -struct S {int i; flt f;} +struct S {int i; flt f;}; S s1 = new S; S s2 = new S; s2.i = 3; @@ -382,7 +296,7 @@ return new flt; int is = new int[2]; """); try { parser.parse().iterate(); fail(); } - catch( Exception e ) { assertEquals("Type *int[] is not of declared type int",e.getMessage()); } + catch( Exception e ) { assertEquals("Type *[int] is not of declared type int",e.getMessage()); } } @Test @@ -412,4 +326,67 @@ return is[1]; catch( NegativeArraySizeException e ) { assertEquals("-1",e.getMessage()); } } + @Test + public void testProgress() { + Parser parser = new Parser(""" +i8 v1=0&0; +u8 v2=0; +byte v4=0; +if(0) {} +while(v2<0) { + v4=0-v1; + break; +} +int v5=0&0; +while(v5+(0&0)) { + int v7=0&0; + while(v7) + v4=0>>>v5; + while(v1) + return 0; +} +return v1; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testSharpNot() { + Parser parser = new Parser( +""" +if(0>>0) {} +while(0) {} +u32 v7=0; +int v8=0; +while(0<--1>>>---(v7*0==v8)) {} +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + } + + + @Test + public void testProgress2() { + Parser parser = new Parser( +""" +if(1) {} +else { + while(arg>>>0&0>>>0) {} + byte v3=0>>>0; + while(0) {} + int v7=0>>>0; + while(v7<0>>>0) { + while(0+v7<=0) if(1) arg=-12; + if(arg) { + v3=arg+v3+0; + arg=0; + } + } +} +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + } } diff --git a/src/test/java/com/seaofnodes/simple/Chapter16Test.java b/src/test/java/com/seaofnodes/simple/Chapter16Test.java new file mode 100644 index 00000000..0f5a5a16 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/Chapter16Test.java @@ -0,0 +1,189 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.evaluator.Evaluator; +import com.seaofnodes.simple.node.StopNode; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class Chapter16Test { + + @Test + public void testRequiredReference() { + for( String fields : new String[] { "int[] x;" } ) { + String src = "struct Point { "+fields+" }; Point p = new Point; p.x=p.x+1; return p;"; + try { new Parser(src).parse().iterate(); fail(fields); } + catch( Exception e ) { assertEquals("'Point' is not fully initialized, field 'x' needs to be set in a constructor",e.getMessage()); } + } + } + + @Test + public void testJig() { + Parser parser = new Parser( +""" +return 3.14; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 3.14;", stop.toString()); + assertEquals(3.14, Evaluator.evaluate(stop, 0)); + } + + + @Test + public void testMulti0() { + Parser parser = new Parser( +""" +int x, y; +return x+y; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 0;", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + } + @Test + public void testMulti1() { + Parser parser = new Parser( +""" +int x=2, y=x+1; +return x+y; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 5;", stop.toString()); + assertEquals(5L, Evaluator.evaluate(stop, 0)); + } + + + + + + @Test + public void testConstruct0() { + Parser parser = new Parser(""" +struct X { int x=3; }; +X z = new X; +return z.x; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 3;", stop.toString()); + assertEquals(3L, Evaluator.evaluate(stop, 0)); + } + + + + @Test + public void testConstruct2() { + Parser parser = new Parser(""" +struct X { int x=3; }; +X z = new X { x = 4; }; +return z.x; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return 4;", stop.toString()); + assertEquals(4L, Evaluator.evaluate(stop, 0)); + } + + + + + // Same as the Chapter13 test with the same name, but using the new + // constructor syntax + @Test + public void testLinkedList1() { + Parser parser = new Parser( +""" +struct LLI { LLI? next; int i; }; +LLI? head = null; +while( arg ) { + head = new LLI { next=head; i=arg; }; + arg = arg-1; +} +if( !head ) return 0; +LLI? next = head.next; +if( !next ) return 1; +return next.i; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("Stop[ return 0; return 1; return .i; ]", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + assertEquals(1L, Evaluator.evaluate(stop, 1)); + assertEquals(2L, Evaluator.evaluate(stop, 3)); + } + + @Test + public void testLinkedList2() { + Parser parser = new Parser( +""" +struct LLI { LLI? next; int i; }; +LLI? head = null; +while( arg ) { + head = new LLI { + next=head; + // Any old code in the constructor + int tmp=arg; + while( arg > 10 ) { + tmp = tmp + arg; + arg = arg - 1; + } + i=tmp; + }; + arg = arg-1; +} +if( !head ) return 0; +LLI? next = head.next; +if( !next ) return 1; +return next.i; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("Stop[ return 0; return 1; return .i; ]", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + assertEquals(1L, Evaluator.evaluate(stop, 1)); + assertEquals(2L, Evaluator.evaluate(stop, 11)); + } + + @Test + public void testSquare() { + Parser parser = new Parser( +""" +struct Square { + flt side = arg; + // 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; + while( 1 ) { + flt next = (side/diag + diag)/2; + if( next == diag ) break; + diag = next; + } +}; +return new Square; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return Square;", stop.toString()); + assertEquals("Obj<Square>{side=3.0,diag=1.7320508075688772}", Evaluator.evaluate(stop, 3).toString()); + assertEquals("Obj<Square>{side=4.0,diag=2.0}", Evaluator.evaluate(stop, 4).toString()); + } + static final String CONSTRUCTOR_MEMORY = """ + struct S { int x; int y; }; + struct T { int z=arg+40; }; + T t = new T; + S a = new S { x=11; y=7; }; + S b = new S { x=22; y=9; }; + S p=a; + if (arg) p=b; + int before=p.x; + S c = new S { + x=p.x+1; + { int i=0; while (i<2) { p.y=p.y+1; i=i+1; } } + y=p.y; + }; + p.x=33; + return before*10000+c.x*100+c.y+t.z; + """; + + @Test public void testConstructorMemory() { + StopNode stop = new Parser(CONSTRUCTOR_MEMORY).parse().iterate(); + assertEquals(111249L,Evaluator.evaluate(stop,0)); + assertEquals(222352L,Evaluator.evaluate(stop,1)); + } +} diff --git a/src/test/java/com/seaofnodes/simple/FuzzerWrap.java b/src/test/java/com/seaofnodes/simple/FuzzerWrap.java index 52c2a014..2c98f405 100644 --- a/src/test/java/com/seaofnodes/simple/FuzzerWrap.java +++ b/src/test/java/com/seaofnodes/simple/FuzzerWrap.java @@ -1,10 +1,9 @@ package com.seaofnodes.simple; import com.seaofnodes.simple.fuzzer.Fuzzer; -import org.junit.Test; +import java.util.Random; import org.junit.Ignore; - - +import org.junit.Test; import static org.junit.Assert.assertTrue; /** @@ -39,6 +38,15 @@ public class FuzzerWrap { } + @Test @Ignore + public void fuzzPeepsRandom() { + Random R = new Random(System.currentTimeMillis()); + var fuzzer = new Fuzzer(); + for (int i=0; i<100; i++) + fuzzer.fuzzPeeps(R.nextLong()); + assertTrue(fuzzer.noExceptions()); + } + @Test @Ignore public void fuzzPeepTiming() { diff --git a/src/test/java/com/seaofnodes/simple/SchedulerTest.java b/src/test/java/com/seaofnodes/simple/SchedulerTest.java index ad595822..4b692f51 100644 --- a/src/test/java/com/seaofnodes/simple/SchedulerTest.java +++ b/src/test/java/com/seaofnodes/simple/SchedulerTest.java @@ -40,7 +40,7 @@ return i; Parser parser = new Parser(""" struct S { int f; -} +}; S v0=new S; if(arg) v0.f=1; return v0; @@ -56,7 +56,7 @@ return v0; Parser parser = new Parser(""" struct S { int f; -} +}; S v=new S; v.f = 2; int i=new S.f; diff --git a/src/test/java/com/seaofnodes/simple/TypeTest.java b/src/test/java/com/seaofnodes/simple/TypeTest.java index cb45a0d7..6f7409cd 100644 --- a/src/test/java/com/seaofnodes/simple/TypeTest.java +++ b/src/test/java/com/seaofnodes/simple/TypeTest.java @@ -13,11 +13,11 @@ public class TypeTest { @Test public void testTypeAdHoc() { TypeStruct s1 = TypeStruct.make("s1", new Field[]{ - Field.make("a",-1, TypeInteger.BOT), - Field.make("b",-2, TypeInteger.BOT) }); + Field.make("a", TypeInteger.BOT,-1, false), + Field.make("b", TypeInteger.BOT,-2, false) }); TypeStruct s2 = TypeStruct.make("s2", new Field[]{ - Field.make("a",-3, TypeInteger.BOT), - Field.make("b",-4, TypeInteger.BOT) }); + Field.make("a", TypeInteger.BOT,-3, false), + Field.make("b", TypeInteger.BOT,-4, false) }); Assert.assertEquals(s1, s1.glb()); Assert.assertNotEquals(s1, s1.dual()); Assert.assertEquals(s1, s1.dual().glb()); diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java index 9eed23de..3eb406eb 100644 --- a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java +++ b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java @@ -100,7 +100,7 @@ public class Evaluator { } @Override public String toString() { - if (struct._name.equals("u8[]")) { + if (struct._name.equals("[u8]")) { var sb = new StringBuilder(); for (int i=struct._fields.length-1; i<fields.length; i++) { var v = fields[i]; @@ -192,28 +192,20 @@ public class Evaluator { if( n < 0 ) throw new NegativeArraySizeException(""+n); body = new Object[(int)n+1]; // Array body - var c = type._fields[type._fields.length-1]._type; - if (c instanceof TypeInteger) { - for (int i=0; i<n; i++) body[i+type._fields.length-1] = 0L; - } else if (c instanceof TypeFloat) { - for (int i = 0; i < n; i++) body[i+type._fields.length-1] = 0D; + var elem = type._fields[1]._type; + if (elem instanceof TypeInteger) { + for (int i=0; i<n; i++) body[i+1] = 0L; + } else if (elem instanceof TypeFloat) { + for (int i = 0; i < n; i++) body[i+1] = 0D; } else { - assert c instanceof TypeMemPtr; + assert elem instanceof TypeMemPtr; } - num = type._fields.length-1; + // Length value + body[0] = vall(alloc.in(3)); } else { - body = new Object[type._fields.length]; - num = type._fields.length; - } - for (int i=0; i<num; i++) { - var c = type._fields[i]._type; - if (c instanceof TypeInteger) { - body[i] = 0L; - } else if (c instanceof TypeFloat) { - body[i] = 0D; - } else { - assert c instanceof TypeMemPtr; - } + body = new Object[num = type._fields.length]; + for (int i=0; i<num; i++) + body[i] = val(alloc.in(3+i)); } return new Object[]{new Obj(type,body),MEMORY}; } diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java b/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java index 125f2f5e..afcc700f 100644 --- a/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java +++ b/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java @@ -557,7 +557,7 @@ public class Scheduler { blocks.put(first, switch(last) { case null -> new Block(arr, null, -1, new Block[0]); case IfNode i -> new Block(arr, i, -1, new Block[2]); - case RegionNode r -> new Block(arr, r, Utils.find(r._inputs, prev), new Block[1]); + case RegionNode r -> new Block(arr, r, r._inputs.find(prev), new Block[1]); case ReturnNode r -> new Block(arr, r, -1, new Block[0]); default -> throw new AssertionError("Unexpected block exit node"); }); diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java b/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java index 7cd854bf..d3cbb0ee 100644 --- a/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java +++ b/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java @@ -109,7 +109,7 @@ public class ScriptGenerator { static { new Parser("", TypeInteger.BOT); - for( var e : Parser.TYPES.entrySet() ) { + for( var e : Parser.defaultTypes().entrySet() ) { if( e.getValue() instanceof TypeInteger ) { INTTYPES.add(new TypeInt(e.getKey())); } |
