diff options
Diffstat (limited to 'src/test')
27 files changed, 629 insertions, 173 deletions
diff --git a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java index 37ecde1c..8f09cb3d 100644 --- a/src/test/java/com/seaofnodes/simple/BrainFuckTest.java +++ b/src/test/java/com/seaofnodes/simple/BrainFuckTest.java @@ -63,7 +63,7 @@ for( int pc = 0; pc < program#; pc++ ) { } return output; """); - code.parse().opto().typeCheck().GCM(); + code.parse().opto().typeCheck()/*.instSelect("x86_64_v2", "SystemV")*/.GCM().localSched(); assertEquals("Hello World!\n", Eval2.eval(code, 0, 10000)); } } diff --git a/src/test/java/com/seaofnodes/simple/Chapter02Test.java b/src/test/java/com/seaofnodes/simple/Chapter02Test.java index 324ebf41..d8607c32 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter02Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter02Test.java @@ -11,8 +11,8 @@ public class Chapter02Test { @Test public void testParseGrammar() { CodeGen code = new CodeGen("return 1+2*3+-5;"); - code.parse(true); // Disable peepholes - assertEquals("return ((1+(2*3))+(-5));", code.print()); + code.parse(); // No more disable peepholes + assertEquals("return 2;", code.print()); } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/src/test/java/com/seaofnodes/simple/Chapter03Test.java index 825235cc..4f9b2490 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter03Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter03Test.java @@ -29,8 +29,8 @@ public class Chapter03Test { @Test public void testVarScopeNoPeephole() { CodeGen code = new CodeGen("int a=1; int b=2; int !c=0; { int b=3; c=a+b; } return c; "); - code.parse(true); - assertEquals("return (1+3);", code.print()); + code.parse(); // Peepholes always run now + assertEquals("return 4;", code.print()); } @Test @@ -53,7 +53,7 @@ public class Chapter03Test { @Test public void testRedeclareVar() { try { - new Parser("int a=1; int b=2; int c=0; int b=3; c=a+b;").parse(); + new CodeGen("int a=1; int b=2; int c=0; int b=3; c=a+b;").parse(); fail(); } catch( RuntimeException e ) { assertEquals("Redefining name 'b'",e.getMessage()); diff --git a/src/test/java/com/seaofnodes/simple/Chapter04Test.java b/src/test/java/com/seaofnodes/simple/Chapter04Test.java index afed67d1..d09b1748 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter04Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter04Test.java @@ -34,14 +34,14 @@ public class Chapter04Test { public void testAddAddMul() { CodeGen code = new CodeGen("return arg+0+arg;"); code.parse(); - assertEquals("return (arg*2);", code.print()); + assertEquals("return (arg<<1);", code.print()); } @Test public void testPeephole3() { CodeGen code = new CodeGen("return 1+arg+2+arg+3; "); code.parse(); - assertEquals("return ((arg*2)+6);", code.print()); + assertEquals("return ((arg<<1)+6);", code.print()); } @Test @@ -62,8 +62,7 @@ public class Chapter04Test { // Adding functions means `main` does not constant fold the incoming arg value @Ignore @Test public void testConstantArg() { - CodeGen code = new CodeGen("return arg; ", TypeInteger.constant(2)); - code.parse(); + CodeGen code = new CodeGen("return arg; ", TypeInteger.constant(2), 123L).parse(); assertEquals("return 2;", code.expr().in(1).toString()); } @@ -111,12 +110,8 @@ public class Chapter04Test { @Test public void testBug3() { - try { - new Parser("inta=1; return a;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Undefined name 'inta'",e.getMessage()); - } + try { new CodeGen("inta=1; return a;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Undefined name 'inta'",e.getMessage()); } } @Test @@ -128,8 +123,8 @@ public class Chapter04Test { @Test public void testBug5() { - Parser parser = new Parser("return arg--2;"); - StopNode ret = parser.parse(); - assertEquals("return (arg--2);", ret.print()); + CodeGen code = new CodeGen("return arg--2;"); + code.parse(); + assertEquals("return (arg--2);", code.print()); } } diff --git a/src/test/java/com/seaofnodes/simple/Chapter05Test.java b/src/test/java/com/seaofnodes/simple/Chapter05Test.java index f4db5624..86ec4136 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter05Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter05Test.java @@ -64,7 +64,7 @@ else b=a+1; return a+b;"""); code.parse().opto(); - assertEquals("return ((arg*2)+Phi(Region,2,3));", code.print()); + assertEquals("return ((arg<<1)+Phi(Region,2,3));", code.print()); } @Test @@ -79,7 +79,7 @@ else a=b+1; return a+b;"""); code.parse().opto(); - assertEquals("return ((Phi(Region,(arg*2),arg)+arg)+Phi(Region,4,5));", code.print()); + assertEquals("return ((Phi(Region,(arg<<1),arg)+arg)+Phi(Region,4,5));", code.print()); } @Test @@ -135,79 +135,51 @@ return a; @Test public void testTrue() { - StopNode stop = new Parser("return true;").parse(); - assertEquals("return 1;",stop.ret().print()); + CodeGen code = new CodeGen("return true;").parse(); + assertEquals("return 1;",code.print()); } @Test public void testHalfDef() { - try { - new CodeGen("if( arg==1 ) int b=2; return b;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Cannot define a 'b' on one arm of an if",e.getMessage()); - } + try { new CodeGen("if( arg==1 ) int b=2; return b;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Cannot define a 'b' on one arm of an if",e.getMessage()); } } @Test public void testHalfDef2() { - try { - new Parser("if( arg==1 ) { int b=2; } else { int b=3; } return b;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Undefined name 'b'",e.getMessage()); - } + try { new CodeGen("if( arg==1 ) { int b=2; } else { int b=3; } return b;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Undefined name 'b'",e.getMessage()); } } @Test public void testRegress1() { - try { - new CodeGen("if(arg==2) int a=1; else int b=2; return a;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Cannot define a 'a' on one arm of an if",e.getMessage()); - } + try { new CodeGen("if(arg==2) int a=1; else int b=2; return a;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Cannot define a 'a' on one arm of an if",e.getMessage()); } } @Test public void testBadNum() { - try { - new Parser("return 1-;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Syntax error, expected an identifier or expression: ;",e.getMessage()); - } + try { new CodeGen("return 1-;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Syntax error, expected an identifier or expression: ;",e.getMessage()); } } @Test public void testKeyword1() { - try { - new Parser("int true=0; return true;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Expected an identifier, found 'true'",e.getMessage()); - } + try { new CodeGen("int true=0; return true;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Expected an identifier, found 'true'",e.getMessage()); } } @Test public void testKeyword2() { - try { - new Parser("int else=arg; if(else) else=2; else else=1; return else;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Expected an identifier, found 'else'",e.getMessage()); - } + try { new CodeGen("int else=arg; if(else) else=2; else else=1; return else;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Expected an identifier, found 'else'",e.getMessage()); } } @Test public void testKeyword3() { - try { - new CodeGen("int a=1; ififif(arg);a=2;return a;").parse(); - fail(); - } catch( RuntimeException e ) { - assertEquals("Undefined name 'ififif'",e.getMessage()); - } + try { new CodeGen("int a=1; ififif(arg);a=2;return a;").parse(); fail(); } + catch( RuntimeException e ) { assertEquals("Undefined name 'ififif'",e.getMessage()); } } } diff --git a/src/test/java/com/seaofnodes/simple/Chapter06Test.java b/src/test/java/com/seaofnodes/simple/Chapter06Test.java index 2107cdb0..117531f0 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter06Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter06Test.java @@ -103,8 +103,7 @@ else if( arg==3 ) else a=5; return a; -""", TypeInteger.constant(2)); - code.parse().opto(); +""", TypeInteger.constant(2), 123L).parse().opto(); assertEquals("return 5;", code.print()); } @@ -124,8 +123,7 @@ else if( arg==3 ) else a=5; return a; -""", TypeInteger.constant(1)); - code.parse().opto(); +""", TypeInteger.constant(1), 123L).parse().opto(); assertEquals("return 3;", code.print()); } @@ -165,7 +163,7 @@ else if( arg==3 ) else a=5; return a; -""", TypeInteger.constant(1)); +""", TypeInteger.constant(1), 123L); code.parse().opto(); assertEquals("return 3;", code.print()); } @@ -186,7 +184,7 @@ else if( arg==3 ) else a=5; return a; -""", TypeInteger.constant(3)); +""", TypeInteger.constant(3), 123L); code.parse().opto(); assertEquals("return 4;", code.print()); } @@ -210,7 +208,8 @@ return a+b; @Test public void testDemo1True() { - CodeGen code = new CodeGen(""" + CodeGen code = new CodeGen( +""" arg=1; int a = 0; int b = 1; @@ -220,14 +219,15 @@ if( arg ) { else b = 3; } return a+b; -""", TypeInteger.constant(1)); +""", TypeInteger.constant(1), 123L); code.parse().opto(); assertEquals("return 4;", code.print()); } @Test public void testDemo1False() { - CodeGen code = new CodeGen(""" + CodeGen code = new CodeGen( +""" arg=0; int a = 0; int b = 1; @@ -237,7 +237,7 @@ if( arg ) { else b = 3; } return a+b; -""", TypeInteger.constant(0)); +""", TypeInteger.constant(0), 123L); code.parse().opto(); assertEquals("return 1;", code.print()); } @@ -263,7 +263,8 @@ return a+b+c; @Test public void testDemo2True() { - CodeGen code = new CodeGen(""" + CodeGen code = new CodeGen( +""" arg=1; int a = 0; int b = 1; @@ -275,14 +276,15 @@ if( arg ) { else b = 3; } return a+b+c; -""", TypeInteger.constant(1)); +""", TypeInteger.constant(1), 123L); code.parse().opto(); assertEquals("return 6;", code.print()); } @Test public void testDemo2arg2() { - CodeGen code = new CodeGen(""" + CodeGen code = new CodeGen( +""" arg=2; int a = 0; int b = 1; @@ -294,7 +296,7 @@ if( arg ) { else b = 3; } return a+b+c; -""", TypeInteger.constant(2)); +""", TypeInteger.constant(2), 123L); code.parse().opto(); assertEquals("return 5;", code.print()); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter07Test.java b/src/test/java/com/seaofnodes/simple/Chapter07Test.java index 7cef0d9c..6d6a3ce7 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter07Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter07Test.java @@ -16,11 +16,9 @@ while(arg < 10) { } return arg; """); - Node._disablePeephole = true; code.parse(); assertEquals("return Phi(Loop,arg,(Phi_arg+1));", code.print()); assertTrue(code.ctrl() instanceof CProjNode); - Node._disablePeephole = false; } @Test @@ -71,11 +69,9 @@ while(a < 10) { } return b; """); - Node._disablePeephole = true; code.parse(); assertEquals("return Phi(Loop,2,Phi(Region,Phi_b,4));", code.print()); assertTrue(code.ctrl() instanceof CProjNode); - Node._disablePeephole = false; } @Test @@ -109,11 +105,9 @@ while(a < 10) { } return a; """); - Node._disablePeephole = true; code.parse(); assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print()); assertTrue(code.ctrl() instanceof CProjNode); - Node._disablePeephole = false; } @Test @@ -140,11 +134,9 @@ int a = 1; while(arg) a = 2; return a; """); - Node._disablePeephole = true; code.parse(); assertEquals("return Phi(Loop,1,2);", code.print()); assertTrue(code.ctrl() instanceof CProjNode); - Node._disablePeephole = false; } @Test @@ -171,11 +163,9 @@ while(a < 10) { } return a; """); - Node._disablePeephole = true; code.parse(); assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print()); assertTrue(code.ctrl() instanceof CProjNode); - Node._disablePeephole = false; } @Test @@ -206,11 +196,9 @@ while(a < 10) { } return a; """); - Node._disablePeephole = true; code.parse(); assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print()); assertTrue(code.ctrl() instanceof CProjNode); - Node._disablePeephole = false; } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter08Test.java b/src/test/java/com/seaofnodes/simple/Chapter08Test.java index 03a2c50a..350df18b 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter08Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter08Test.java @@ -1,8 +1,6 @@ package com.seaofnodes.simple; -import com.seaofnodes.simple.evaluator.Evaluator; import com.seaofnodes.simple.node.*; -import com.seaofnodes.simple.type.TypeInteger; import org.junit.Assert; import org.junit.Test; @@ -147,7 +145,7 @@ return arg; @Test public void testBreakOutsideLoop() { try { - new Parser(""" + new CodeGen(""" if(arg <= 10) { break; arg = arg + 1; diff --git a/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/src/test/java/com/seaofnodes/simple/Chapter09Test.java index b210f7e9..10f4a78b 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter09Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter09Test.java @@ -41,7 +41,7 @@ else { return x; """); code.parse().opto(); - assertEquals("return Phi(Region,(arg*2),(Mul+1));", code.print()); + assertEquals("return Phi(Region,(arg<<1),(Shl+1));", code.print()); Assert.assertEquals( "2", Eval2.eval(code, 1)); Assert.assertEquals("23", Eval2.eval(code, 11)); } @@ -255,7 +255,7 @@ while(0==1) while(v0) v0=1+v0; """); code.parse().opto(); - assertEquals("return ~int;", code.print()); + assertEquals("return 0;", code.print()); } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/src/test/java/com/seaofnodes/simple/Chapter13Test.java index 6aa64bf9..d05fd7d8 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -168,7 +168,7 @@ return new S1.s=new S2; struct I {int i;}; struct P { I? pi; }; P !p1 = new P; -P p2 = new P; +P !p2 = new P; p2.pi = new I; p2.pi.i = 2; if (arg) p1 = new P; diff --git a/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/src/test/java/com/seaofnodes/simple/Chapter14Test.java index a3025001..17708c37 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter14Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter14Test.java @@ -174,7 +174,7 @@ while(v1) break; return v1; """); code.parse().opto(); - assertEquals("return (Phi(Loop,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", code.print()); + assertEquals("return Phi(Loop,(((1<<arg)&1)&Shl),0);", code.print()); assertEquals("1", Eval2.eval(code, 0)); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/src/test/java/com/seaofnodes/simple/Chapter15Test.java index 86f5007d..546eb0e9 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter15Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter15Test.java @@ -140,7 +140,7 @@ struct S { int x; flt y; }; 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; @@ -149,10 +149,12 @@ flt rez = 1.2; if( iss[arg] ) if( iss[arg][2] ) rez = iss[arg][2].y; -return rez; -"""); - try { code.parse().opto().typeCheck(); fail(); } - catch( Exception e ) { assertEquals("Might be null accessing 'y'",e.getMessage()); } +return rez;"""); + code.parse().opto().typeCheck(); + assertEquals("return Phi(Region,Phi(Region,.y,1.2),1.2);", code.print()); + assertEquals("3.14", Eval2.eval(code, 0)); + try { Eval2.eval(code, 10); fail(); } // Fails AIOOBE in Eval2, no range checks + catch( Exception e ) { assertEquals("Index 10 out of bounds for length 2",e.getMessage()); } } @Test diff --git a/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/src/test/java/com/seaofnodes/simple/Chapter17Test.java index 8ec95f33..a1d0f8b9 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter17Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter17Test.java @@ -37,7 +37,7 @@ return arg++; return arg+++arg++; """); code.parse().opto(); - assertEquals("return ((arg*2)+1);", code.print()); + assertEquals("return ((arg<<1)+1);", code.print()); assertEquals("1", Eval2.eval(code, 0)); } @@ -48,7 +48,7 @@ return arg+++arg++; return -arg---arg--; """); code.parse().opto(); - assertEquals("return (-((arg*2)+-1));", code.print()); + assertEquals("return (-((arg<<1)+-1));", code.print()); assertEquals("1", Eval2.eval(code, 0)); } @@ -342,7 +342,7 @@ var b = arg ? new Bar : null; return b ? b.x++ + b.x++ : -1; """); code.parse().opto(); - assertEquals("return Phi(Region,((.x*2)+1),-1);", code.print()); + assertEquals("return Phi(Region,((.x<<1)+1),-1);", code.print()); assertEquals("-1", Eval2.eval(code, 0)); assertEquals("1", Eval2.eval(code, 1)); } @@ -355,7 +355,7 @@ var b = arg ? new Bar; return b ? b.x++ + b.x++ : -1; """); code.parse().opto(); - assertEquals("return Phi(Region,((.x*2)+1),-1);", code.print()); + assertEquals("return Phi(Region,((.x<<1)+1),-1);", code.print()); assertEquals("-1", Eval2.eval(code, 0)); assertEquals("1", Eval2.eval(code, 1)); } diff --git a/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 60f9b847..db970f60 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -64,7 +64,7 @@ return sq; """); code.parse().opto(); assertEquals("Stop[ return { sq}; return (Parm_x(sq,int)*x); ]", code._stop.toString()); - assertEquals("{ sq}", Eval2.eval(code, 3)); + assertEquals("{ int -> int #1}", Eval2.eval(code, 3)); } @Test @@ -76,7 +76,7 @@ var sq = { int x -> }; return sq(arg)+sq(3); """); - code.parse().opto(); + code.parse().opto().typeCheck().GCM().localSched(); assertEquals("Stop[ return (sq( 3)+sq( arg)); return (Parm_x(sq,int,3,arg)*x); ]", code._stop.toString()); assertEquals("13", Eval2.eval(code, 2)); } @@ -115,7 +115,7 @@ var fcn = arg ? { int x -> x*x; } : { int x -> x+x; }; return fcn(3); """); code.parse().opto(); - assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int,3)*x); return (Parm_x($fun,int,3)*2); ]", code._stop.toString()); + assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int,3)*x); return (Parm_x($fun,int,3)<<1); ]", code._stop.toString()); assertEquals("6", Eval2.eval(code, 0)); assertEquals("9", Eval2.eval(code, 1)); } @@ -124,7 +124,7 @@ return fcn(3); @Test public void testFcn5() { CodeGen code = new CodeGen("val fact = { int x -> x <= 1 ? 1 : x*fact(x-1); }; return fact(arg);"); - code.parse().opto(); + code.parse().opto().typeCheck(); assertEquals("Stop[ return fact( arg); return Phi(Region,1,(Parm_x(fact,int,arg,(x-1))*fact( Sub))); ]", code._stop.toString()); assertEquals( "1", Eval2.eval(code, 0)); assertEquals( "1", Eval2.eval(code, 1)); @@ -179,7 +179,6 @@ for(;;) { assertEquals("3", Eval2.eval(code, 0)); } - @Test public void testFcn9() { CodeGen code = new CodeGen( @@ -196,6 +195,31 @@ for(;;) { assertEquals(null, Eval2.eval(code, 0)); } + + @Test + public void testFcn10() { + CodeGen code = new CodeGen( +""" +struct Person { + int age; +}; + +val fcn = { Person?[] ps, int x -> + val tmp = ps[x]; + if( ps[x] ) + ps[x].age++; +}; + +var ps = new Person?[2]; +ps[0] = new Person; +ps[1] = new Person; +fcn(ps,1); +"""); + code.parse().opto().typeCheck().GCM().localSched(); + assertEquals("return 0;", code._stop.toString()); + assertEquals("0", Eval2.eval(code, 0)); + } + // Function break @Test public void testErr1() { diff --git a/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/src/test/java/com/seaofnodes/simple/Chapter19Test.java new file mode 100644 index 00000000..a4857a01 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/Chapter19Test.java @@ -0,0 +1,398 @@ +package com.seaofnodes.simple; + +import org.junit.Test; +import static org.junit.Assert.*; +import static org.junit.Assert.fail; +import org.junit.Ignore; + +public class Chapter19Test { + + @Test + public void testJig() { + CodeGen code = new CodeGen(""" +return 0; +"""); + code.parse().opto().typeCheck(); + assertEquals("return 0;", code._stop.toString()); + assertEquals("0", Eval2.eval(code, 2)); + } + + + @Test + public void testString() { + CodeGen code = new CodeGen( +""" +struct String { + u8[] cs; + int _hashCode; +}; + +val equals = { String self, String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +val hashCode = { String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { String self -> + int hash=0; + if( self.cs ) { + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + } + if( !hash ) hash = 123456789; + return hash; +}; + +String !s = new String { cs = new u8[17]; }; +s.cs[0] = 67; // C +s.cs[1] = 108; // l +hashCode(s);"""); + code.parse().opto().typeCheck().GCM().localSched(); + assertEquals("Stop[ return Phi(Region,123456789,Phi(Loop,0,(.[]+((Phi_hash<<5)-Phi_hash)))); return Phi(Region,1,0,0,1); ]", code._stop.toString()); + assertEquals("-2449306563677080489", Eval2.eval(code, 2)); + } + + @Test + public void testBasic0() { + CodeGen code = new CodeGen("return 0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return 0;", code._stop.toString()); + } + + @Test + public void testBasic1() { + CodeGen code = new CodeGen("return arg+1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (inc,arg);", code._stop.toString()); + } + + @Test + public void testBasic2() { + CodeGen code = new CodeGen("return -17;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return -17;", code._stop.toString()); + } + + + @Test + public void testBasic3() { + CodeGen code = new CodeGen("return arg==1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (set==,(cmp,arg));", code._stop.toString()); + } + + @Test + public void testBasic4() { + CodeGen code = new CodeGen("return arg<<1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (shli,arg);", code._stop.toString()); + } + + @Test + public void testBasic5() { + CodeGen code = new CodeGen("return arg >> 1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (sari,arg);", code._stop.toString()); + } + + @Test + public void testBasic6() { + CodeGen code = new CodeGen("return arg >>> 1;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (shri,arg);", code._stop.toString()); + } + + @Test + public void testBasic7() { + CodeGen code = new CodeGen("return arg / 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (div,arg,2);", code._stop.toString()); + } + + @Test + public void testBasic8() { + CodeGen code = new CodeGen("return arg * 6;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (muli,arg);", code._stop.toString()); + } + + @Test + public void testBasic9() { + CodeGen code = new CodeGen("return arg & 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (andi,arg);", code._stop.toString()); + } + + @Test + public void testBasic10() { + CodeGen code = new CodeGen("return arg | 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (ori,arg);", code._stop.toString()); + } + + @Test + public void testBasic11() { + CodeGen code = new CodeGen("return arg ^ 2;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (xori,arg);", code._stop.toString()); + } + + @Test + public void testBasic12() { + CodeGen code = new CodeGen("return arg + 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (addf,(i2f8,arg),2.0f);", code._stop.toString()); + } + + @Test + public void testBasic13() { + CodeGen code = new CodeGen("return arg - 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (subf,(i2f8,arg),2.0f);", code._stop.toString()); + } + + @Test + public void testBasic14() { + CodeGen code = new CodeGen("return arg * 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (mulf,(i2f8,arg),2.0f);", code._stop.toString()); + } + + @Test + public void testBasic15() { + CodeGen code = new CodeGen("return arg / 2.0;").parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (divf,(i2f8,arg),2.0f);", code._stop.toString()); + } + + @Test + public void testBasic16() { + CodeGen code = new CodeGen( +""" +int arg1 = arg + 1; +return arg1 / arg;"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (div,(inc,arg),arg);", code._stop.toString()); + } + + @Test + public void testBasic17() { + CodeGen code = new CodeGen( +""" +int arg1 = arg + 1; +return arg1 * arg; +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (mul,(inc,arg),arg);", code._stop.toString()); + } + + @Test + public void testToFloat() { + CodeGen code = new CodeGen(""" + int a = arg; + return a + 2.0; + """ + ).parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (addf,(i2f8,arg),2.0f);", code._stop.toString()); + } + + @Test + public void testIfStmt() { + CodeGen code = new CodeGen( +""" +int a = 1; +if (arg == 1) + a = arg+2; +else { + a = arg-3; +} +return a;"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return Phi(Region,(addi,arg),(addi,arg));", code.print()); + } + + @Test + public void testIfMerge2() { + CodeGen code = new CodeGen( +""" +int a=arg+1; +int b=arg+2; +if( arg==1 ) + b=b+a; +else + a=b+1; +return a+b;"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (add,(add,Phi(Region,(shli,arg),arg),arg),Phi(Region,4,5));", code.print()); + } + + @Test + public void testLoop() { + CodeGen code = new CodeGen( +""" +int sum=0; +for( int i=0; i<arg; i++ ) + sum += i; +return sum;"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return Phi(Loop,0,(add,Phi_sum,Phi(Loop,0,(inc,Phi_i))));", code.print()); + } + + @Test + public void testAlloc1() { + CodeGen code = new CodeGen( +""" +struct S { int a; S? c; }; +return new S;"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return S;", code.print()); + } + + @Test + public void testLea1() { + CodeGen code = new CodeGen("int x = arg/3; return arg+x+7;"); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (lea,arg,(div,arg,3));", code.print()); + } + + @Test + public void testLea2() { + CodeGen code = new CodeGen("int x = arg/3; return arg+x*4+7;"); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (lea,arg,(div,arg,3));", code.print()); + } + + @Test + public void testLea3() { + CodeGen code = new CodeGen("int x = arg/3; return x*4+arg;"); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return (lea,arg,(div,arg,3));", code.print()); + } + + @Test + public void testAlloc2() { + CodeGen code = new CodeGen("int[] !xs = new int[3]; xs[arg]=1; return xs[arg&1];"); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return .[];", code.print()); + } + + @Test + public void testAlloc3() { + CodeGen code = new CodeGen("int[] !xs = new int[3]; xs[arg]=1; return xs[arg&1]+3;"); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return .[];", code.print()); + } + + @Test + public void testArray1() { + CodeGen code = new CodeGen( +""" +int[] !ary = new int[arg]; +// Fill [0,1,2,3,4,...] +for( int i=0; i<ary#; i++ ) + ary[i] = i; +// Fill [0,1,3,6,10,...] +for( int i=0; i<ary#-1; i++ ) + ary[i+1] += ary[i]; +return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6 +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return .[];", code.print()); + } + + @Test + public void testArray2() { + CodeGen code = new CodeGen( +""" +flt[] !A = new flt[arg], !B = new flt[arg]; +// Fill [0,1,2,3,4,...] +for( int i=0; i<A#; i++ ) + A[i] = i; +for( int i=0; i<A#; i++ ) + B[i] += A[i]; +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return 0;", code.print()); + } + + @Test + public void testArray3() { + CodeGen code = new CodeGen( +""" +byte[] !A = new byte[arg]; +for( int i=0; i<A#; i++ ) + A[i]++; +return A[1]; +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return .[];", code.print()); + } + + @Test + public void testNewton() { + CodeGen code = new CodeGen( +""" +// Newtons approximation to the square root +val sqrt = { flt x -> + flt guess = x; + while( 1 ) { + flt next = (x/guess + guess)/2; + if( next == guess ) return guess; + guess = next; + } +}; +flt farg = arg; +return sqrt(farg); +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return Phi(Loop,(i2f8,arg),(divf,(addf,(divf,i2f8,Phi_guess),Phi_guess),2.0f));", code.print()); + }; + + + @Test + public void sieveOfEratosthenes() { + CodeGen code = new CodeGen( +""" +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; +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("return [int];", code.print()); + //assertEquals("int[ 2,3,5,7,11,13,17,19]",Eval2.eval(code, 20)); + } + + + @Test + public void testFcn1() { + CodeGen code = new CodeGen( +""" +val fcn = arg ? { int x -> x*x; } : { int x -> x+x; }; +return fcn(2)*10 + fcn(3); +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("Stop[ return (add,Phi(Region,{ int -> int #1},{ int -> int #2})( 3),(muli,Phi_( 2))); return (mul,Parm_x($fun,int,3,2),x); return (shli,Parm_x($fun,int,3,2)); ]", code.print()); + } + + @Test + public void testFcn2() { + CodeGen code = new CodeGen( +""" +val sq = { int x -> x*x; }; +return sq(arg) + sq(3); +"""); + code.parse().opto().typeCheck().instSelect("x86_64_v2", "SystemV").GCM().localSched(); + assertEquals("Stop[ return (add,sq(),sq()); return (mul,Parm_x(sq,int,3,arg),x); ]", code.print()); + } +} diff --git a/src/test/java/com/seaofnodes/simple/Eval2.java b/src/test/java/com/seaofnodes/simple/Eval2.java index 2da834e5..6ae8427c 100644 --- a/src/test/java/com/seaofnodes/simple/Eval2.java +++ b/src/test/java/com/seaofnodes/simple/Eval2.java @@ -179,7 +179,7 @@ public abstract class Eval2 { int path = r._inputs.find( prior ); // Parameters read from prior frame, Phis from local frame Frame frame = (r instanceof FunNode ? F._prior : F); - boolean isMain = r instanceof FunNode fun && fun.sig().isa(TypeFunPtr.MAIN); + boolean isMain = r instanceof FunNode fun && fun.sig().isa(CodeGen.CODE._main); // Parallel assign Phis. First parallel read and cache int i; @@ -341,7 +341,7 @@ public abstract class Eval2 { int num = type._fields.length; Object[] ptr = new Object[num]; for( int i=0; i<num; i++ ) - ptr[i] = val(alloc.in(2+i+num)); + ptr[i] = con(type._fields[i]._type.makeZero()); return ptr; } @@ -357,6 +357,8 @@ public abstract class Eval2 { } private static Object store( StoreNode st ) { + if( st._name.equals("#") ) + return "$mem"; // Eval stores the length in the java object[], no need to set it now TypeMemPtr tmp = (TypeMemPtr)st.ptr()._type; Object[] fs = (Object[])val(st.ptr()); int idx = tmp._obj.isAry() diff --git a/src/test/java/com/seaofnodes/simple/Main.java b/src/test/java/com/seaofnodes/simple/Main.java new file mode 100644 index 00000000..523bd306 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/Main.java @@ -0,0 +1,17 @@ +package com.seaofnodes.simple; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class Main { + // Compile and run a simple program + public static void main( String[] args ) throws Exception { + // First arg is file, 2nd+ args are program args + String src = Files.readString(Path.of(args[0])); + int arg = Integer.valueOf(args[1]); + CodeGen code = new CodeGen(src); + code.parse().opto().typeCheck().GCM().localSched(); + System.out.println(code._stop); + System.out.println(Eval2.eval(code,arg,100000)); + } +} diff --git a/src/test/java/com/seaofnodes/simple/SchedulerTest.java b/src/test/java/com/seaofnodes/simple/SchedulerTest.java index e869e133..d50c302a 100644 --- a/src/test/java/com/seaofnodes/simple/SchedulerTest.java +++ b/src/test/java/com/seaofnodes/simple/SchedulerTest.java @@ -30,7 +30,6 @@ int i=v.f; if (arg) v.f=1; return i; """); - StopNode._disablePeephole = true; code.parse();//.opto(); var eval = new Evaluator(code._stop); assertEquals(2L, eval.evaluate(1, 10)); diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java index 92b424df..a3b87e90 100644 --- a/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java +++ b/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java @@ -202,8 +202,12 @@ public class Evaluator { body[0] = vall(alloc.in(2+2)); } else { body = new Object[num = type._fields.length]; - for (int i=0; i<num; i++) - body[i] = val(alloc.in(2+i+num)); + for( int i=0; i<num; i++ ) + body[i] = switch( alloc._ptr._obj._fields[i]._type ) { + case TypeInteger ti -> 0L; + case TypeFloat tf -> 0; + default -> null; + }; } Object[] mems = new Object[type._fields.length+2]; // mems[0] is control @@ -342,7 +346,7 @@ public class Evaluator { assert block != null; for (; i < block.nodes().length; i++) { if (!(block.nodes()[i] instanceof PhiNode phi)) break; - var val = region instanceof FunNode fun && "main".equals(fun.sig()._name) && ((ParmNode)phi)._idx==2 && exit==1 + var val = region instanceof FunNode fun && "main".equals(fun._name) && ((ParmNode)phi)._idx==2 && exit==1 ? parameter : val(phi.in(exit)); phiCache.add(val); diff --git a/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java b/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java index 52d8f3e3..4bfa7628 100644 --- a/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java +++ b/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java @@ -508,7 +508,7 @@ public class Scheduler { private static CFGNode findSingleCFGOut(Node node) { if (node instanceof StartNode) { for(var n:node._outputs) - if (n instanceof FunNode fun && "main".equals(fun.sig()._name) ) + if (n instanceof FunNode fun && "main".equals(fun._name) ) return fun; return null; } diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java b/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java index f57a0031..f7e0c4ad 100644 --- a/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java +++ b/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java @@ -82,10 +82,10 @@ public class Fuzzer { private static void runCheck(String script, boolean valid) { CodeGen code1; try { - code1 = FuzzerUtils.parse(script, false); + code1 = FuzzerUtils.parse(script, 123); } catch (RuntimeException e1) { try { - FuzzerUtils.parse(script, true); + FuzzerUtils.parse(script, 456); } catch (RuntimeException e2) { if (FuzzerUtils.isExceptionFromSameCause(e1, e2)) { if (!valid || e1.getClass() == Parser.ParseException.class) return; @@ -95,7 +95,7 @@ public class Fuzzer { } throw e1; } - CodeGen code2 = FuzzerUtils.parse(script, true); + CodeGen code2 = FuzzerUtils.parse(script, 456); checkGraphs(code1, code2, 0); checkGraphs(code1, code2, 1); checkGraphs(code1, code2, 10); @@ -126,17 +126,16 @@ public class Fuzzer { var code = new CodeGen(sb.toString()); code.parse(); - int parse_peeps= Node.ITER_CNT; - int parse_nops = Node.ITER_NOP_CNT; + int nids = code.UID(); + if( nids <= max_nids ) return max_nids; // Smaller, looking for trends as we grow + int parse_peeps= code._iter_cnt; + int parse_nops = code._iter_nop_cnt; double parse_nop_ratio = (double)parse_nops/parse_peeps; - int nids = Node.UID(); - if( nids <= max_nids ) return max_nids; - double parse_peeps_per_node = (double)parse_peeps/nids; code.opto(); - int iter_peeps= Node.ITER_CNT; - int iter_nops = Node.ITER_NOP_CNT; + int iter_peeps= code._iter_cnt; + int iter_nops = code._iter_nop_cnt; double iter_nop_ratio = (double)iter_nops/iter_peeps; double iter_peeps_per_node = (double)iter_peeps/nids; diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java b/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java index 62a149a8..0781ad67 100644 --- a/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java +++ b/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java @@ -4,6 +4,7 @@ import com.seaofnodes.simple.CodeGen; import com.seaofnodes.simple.IterPeeps; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.StopNode; +import com.seaofnodes.simple.type.TypeInteger; import java.io.OutputStream; import java.io.PrintStream; import java.lang.invoke.MethodHandle; @@ -47,31 +48,10 @@ class FuzzerUtils { } /** - * Copy of Node.WVISIST - * Used to clear as exceptions might happen in the walk and left this bitset not cleared - */ - private static final BitSet NodeWalkVisit; - - /** - * Write access to Iterate.MID_ASSERT - * Exception could happen mid assert and left this at true. Used to reset to false prior to parsing. - */ - private static final MethodHandle set_MID_ASSERT; - - /** * Some problems might trigger debug output. Suppress this output with a null print stream during fuzzing. */ public static final PrintStream NULL_PRINT_STREAM = new PrintStream(OutputStream.nullOutputStream()); - static { - try { - NodeWalkVisit = getFieldValue(Node.class, "WVISIT"); - set_MID_ASSERT = MethodHandles.lookup().unreflectSetter(getField( IterPeeps.class, "MID_ASSERT")); - } catch (Exception e) { - throw new ExceptionInInitializerError(e); - } - } - /** * Check that the messages are similar. */ @@ -114,21 +94,15 @@ class FuzzerUtils { /** * Parse script with peepholes enabled or disabled */ - public static CodeGen parse(String script, boolean runPeeps) { + public static CodeGen parse(String script, long workListSeed) { var err = System.err; var out = System.out; try { System.setErr(NULL_PRINT_STREAM); System.setOut(NULL_PRINT_STREAM); - try { - set_MID_ASSERT.invokeExact(false); - } catch (Throwable e) { - throw rethrow(e); - } - var code = new CodeGen(script); - return code.parse(!runPeeps).opto().typeCheck().GCM().localSched(); + var code = new CodeGen(script, TypeInteger.BOT, workListSeed); + return code.parse().opto().typeCheck().GCM().localSched(); } finally { - NodeWalkVisit.clear(); System.setErr(err); System.setOut(out); } diff --git a/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java b/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java index 86dbe66a..f119fa1a 100644 --- a/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java +++ b/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java @@ -3,12 +3,13 @@ package com.seaofnodes.simple.fuzzer; import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.node.ScopeNode; import com.seaofnodes.simple.type.TypeInteger; - import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Random; import java.util.function.Predicate; +import static com.seaofnodes.simple.Parser.KEYWORDS; + /** * Generate a pseudo random script. @@ -34,18 +35,6 @@ public class ScriptGenerator { * Valid characters for identifiers. The last 10 are not valid for the first character. */ private static final String VAR_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"; - /** - * List of keywords not valid for identifiers. - */ - private static final HashSet<String> KEYWORDS; - - static { - try { - KEYWORDS = FuzzerUtils.getFieldValue(new Parser(""), "KEYWORDS"); - } catch (Throwable e) { - throw new ExceptionInInitializerError(e); - } - } /** * Flag for a statement that it does not pass on control flow to the next statement. @@ -108,7 +97,6 @@ public class ScriptGenerator { private static final List<TypeInt> INTTYPES = new ArrayList<>(); static { - new Parser("", TypeInteger.BOT); for( var e : Parser.defaultTypes().entrySet() ) { if( e.getValue() instanceof TypeInteger ) { INTTYPES.add(new TypeInt(e.getKey())); diff --git a/src/test/java/com/seaofnodes/simple/progs/fcn.smp b/src/test/java/com/seaofnodes/simple/progs/fcn.smp new file mode 100644 index 00000000..188e0a9f --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/fcn.smp @@ -0,0 +1,15 @@ + +struct Person { + int age; +}; + +val fcn = { Person?[] ps, int x -> + val tmp = ps[x]; + if( ps[x] ) + ps[x].age++; +}; + +Person?[] !ps = new Person?[2]; +ps[0] = new Person; +ps[1] = new Person; +fcn(ps,1); diff --git a/src/test/java/com/seaofnodes/simple/progs/fcn2.smp b/src/test/java/com/seaofnodes/simple/progs/fcn2.smp new file mode 100644 index 00000000..049132d9 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/fcn2.smp @@ -0,0 +1,5 @@ + +val fcn = (arg&1) + ? { int x -> x*x; } + : { int x -> x+x; }; +fcn(arg); diff --git a/src/test/java/com/seaofnodes/simple/progs/fcn3.smp b/src/test/java/com/seaofnodes/simple/progs/fcn3.smp new file mode 100644 index 00000000..a64564f0 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/fcn3.smp @@ -0,0 +1,42 @@ + +//val fact = { int n -> n <= 1 ? 1 : fact(n-1)*n; } +struct LL { LL? next; int payload; }; + + +struct String { + + val _hashCodeString = { -> + int hash=0; + for( int i=0; i< cs#; i++ ) + hash = hash*31 + cs[i]; + if( !hash ) hash = 123456789; + return hash; + }; + + val equals = { String s -> + if( self == s ) return true; + if( cs# != s.cs# ) return false; + for( int i=0; i< #; i++ ) + if( [i] != s.cs[i] ) + return false; + return true; + }; + + int _hashCode = hash(); + u8[] cs; +}; + + + +val hashCode= { String self -> + int hash = self._hashCode + ? self._hashCode + : self._hashCode = _hashCodeString(self); + return hash; +}; + + +String s = new String { cs = new u8[17]; }; +s.cs[0] = 67; // C +s.cs[1] = 108; // l +hashCode(s); diff --git a/src/test/java/com/seaofnodes/simple/progs/sieve.smp b/src/test/java/com/seaofnodes/simple/progs/sieve.smp new file mode 100644 index 00000000..0788e6c5 --- /dev/null +++ b/src/test/java/com/seaofnodes/simple/progs/sieve.smp @@ -0,0 +1,32 @@ + +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 = p + p; + while( i < ary# ) { + ary[i] = 1; + i = i + p; + } + p = p + 1; +} +// Now just collect the remaining primes, no more marking +while( p < arg ) { + if( ary[p] == 0 ) { + primes[nprimes] = p; nprimes = nprimes + 1; + } + p = p + 1; +} +// 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; |
