summaryrefslogtreecommitdiff
path: root/src/test/java/com/seaofnodes/simple/Chapter23Test.java
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-08-10 11:11:18 -0700
committerCliff Click <cliffc@acm.org>2026-08-10 15:21:17 -0700
commit28209703c72fb7e9955961dbdb84e24a0f871acd (patch)
tree8e4df2c1a5e6811696b454bbc4d7cd1cc30e42e7 /src/test/java/com/seaofnodes/simple/Chapter23Test.java
parente57bdd315a7918a0d130e1c95648ca4a1b4f08ed (diff)
downloadSimple-linear-chapter25.tar.gz
Simple-linear-chapter25.zip
Chapter 25: Moduleslinear-chapter25
Diffstat (limited to 'src/test/java/com/seaofnodes/simple/Chapter23Test.java')
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter23Test.java288
1 files changed, 115 insertions, 173 deletions
diff --git a/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/src/test/java/com/seaofnodes/simple/Chapter23Test.java
index 94e13a87..08acfd32 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter23Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter23Test.java
@@ -2,7 +2,6 @@ package com.seaofnodes.simple;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.node.cpus.riscv.riscv;
-import com.seaofnodes.simple.type.TypeInteger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -12,11 +11,11 @@ import static org.junit.Assert.*;
public class Chapter23Test {
- @Test
+ @Test @Ignore
public void testJig() throws IOException {
//String src = Files.readString(Path.of("src/test/java/com/seaofnodes/simple/progs/jig.smp"));
String src = Files.readString(Path.of("docs/examples/BubbleSort.smp"));
- testCPU(src,"x86_64_v2", "Win64" ,-1,null);
+ testCPU(src,"x86_64_v2", "win64" ,-1,null);
testCPU(src,"riscv" , "SystemV",-1,null);
testCPU(src,"arm" , "SystemV",-1,null);
}
@@ -26,278 +25,218 @@ public class Chapter23Test {
CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os);
int delta = spills>>3;
if( delta==0 ) delta = 1;
- if( spills != -1 )
+ if( spills != -1 && !CodeGen.iterSeedOverridden() )
assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta);
if( stop != null )
- assertEquals(stop, code._stop.toString());
+ assertEquals(stop, code.print());
return code;
}
@Test
public void testOr() throws IOException {
- String src =
- """
- int a = 1;
- int b = 0;
-
- if(a++ || b++ ) {
- if(b == 0 && a == 2) {
- sys.io.p("Or");
- }
- } else{
- sys.io.p("And");
- }
- return 0;
- """;
-
- TestC.runSF("or1", src, null, "Or", 0);
+ String src = """
+int a = 1;
+int b = 0;
+int rez = 2;
+
+if( a++ || b++ ) {
+ if( b == 0 && a == 2 )
+ rez = 0; // Expected answer
+} else {
+ rez = 1;
+}
+return rez;
+""";
+
+ TestC.runSF( src, "or1", "", 0);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build("or1", src, 0, 2, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "or1", 0, 0, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
- assertEquals("Or",R5._stdout.toString());
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("or1", src,0, 2, false);
+ EvalArm64 arm = TestArm64.build("or1", src,0, 0, false);
trap = arm.step(100);
assertEquals(0,trap);
assertEquals(0,arm.regs[0]);
- assertEquals("Or",arm._stdout.toString());
}
@Test
public void testAnd() throws IOException {
- String src =
- """
- int a = 1;
- int b = 1;
-
- if(a && b) {
- sys.io.p("And");
- } else {
- sys.io.p("Or");
- }
- return 0;
- """;
- TestC.runSF("and1", src, null, "And", 0);
+ String src = """
+int a = 1;
+int b = 1;
+return a && b ? 0 : 1; // Expected answer 0
+""";
+ TestC.runSF( src, "and1", "", 0);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build("and1", src, 0, 2, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "and1", 0, 0, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
- assertEquals("And",R5._stdout.toString());
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("and1", src, 0, 2, false);
+ EvalArm64 arm = TestArm64.build("and1", src, 0, 0, false);
trap = arm.step(100);
assertEquals(0,trap);
assertEquals(0,arm.regs[0]);
- assertEquals("And",arm._stdout.toString());
}
@Test
public void testAndPtr() throws IOException {
// Todo: have one src here
- String src =
- """
- struct S { S? fld; };
- val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};};
- return ptr && ptr.fld ? "true" : "false";
- """;
- String src2 =
- """
- struct S { S? fld; };
-
- val ptr = arg == 1 ? null : new S{fld = arg==1 ? null : new S{fld = null;};};
- if( ptr && ptr.fld ) {
- sys.io.p("true");
- } else {
- sys.io.p("false");
- }
-
- return 0;
- """;
+ String src = """
+struct S { S? fld; new S = { S? f -> fld=f; }; };
+val ptr = arg == 1 ? null : new S(arg==1 ? null : new S(null));
+return ptr && ptr.fld ? "true" : "false";
+""";
CodeGen code = new CodeGen(src).parse().opto().typeCheck();
- assertEquals("[97-117][ 116,114,117,101]", Eval2.eval(code, 0));
+ assertEquals("true", Eval2.eval(code, 0));
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build("ptrand",src2, 1, 8, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "class:Test.<clinit>", 1, 8, false);
int trap = R5.step(100);
assertEquals(0,trap);
- assertEquals(0,R5.regs[riscv.A0]);
- assertEquals("false",R5._stdout.toString());
+ int adr = (int)R5.regs[riscv.A0]; // Returns a Simple *u8[~] string
+ assertEquals(4,R5.ld4s(adr)); // String length
+ assertEquals(0x65757274,R5.ld4s(adr+4)); // "true"
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("ptrand", src2, 1, 8, false);
+ EvalArm64 arm = TestArm64.build("class:Test.<clinit>", src, 1, 8, false);
trap = arm.step(100);
assertEquals(0,trap);
- assertEquals(0,arm.regs[0]);
- assertEquals("false",arm._stdout.toString());
+ int adr2 = (int)arm.regs[0]; // Returns a Simple *u8[~] string
+ assertEquals(4,arm.ld4s(adr2)); // String length
+ assertEquals(0x65757274,arm.ld4s(adr2+4)); // "true"
}
// conditional side effect
@Test
public void testCondSideEffAnd() throws IOException {
- String src =
- """
- int a = 1;
- int b = 1;
-
- int x=1;
- int y=1;
- int z=0;
-
- int g = x++ && y++ && z++;
-
- if(x == 2 && y == 2 && z == 1 && g == 0) {
- sys.io.p("Effected");
- } else {
- sys.io.p("Not effected");
- }
- return 0;
- """;
-
- TestC.runSF("and2", src, null, "Effected", 0);
+ String src = """
+int x=1;
+int y=1;
+int z=0;
+
+int g = x++ && y++ && z++;
+return x == 2 && y == 2 && z == 1 && g == 0
+ ? 0 // Effected, Expected
+ : 1; // Error, not effected
+""";
+
+ TestC.runSF( src, "and2", "", 0);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build("and2", src, 0, 2, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "and2", 0, 0, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
- assertEquals("Effected",R5._stdout.toString());
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("and2", src, 0, 2, false);
+ EvalArm64 arm = TestArm64.build("and2", src, 0, 0, false);
trap = arm.step(100);
assertEquals(0,trap);
assertEquals(0,arm.regs[0]);
- assertEquals("Effected",arm._stdout.toString());
}
@Test
public void testCondSideEffOr() throws IOException {
- String src =
- """
- int a = 1;
- int b = 1;
-
- int x = -1;
- int y=1;
- int z= -1;
-
- int g = x++ || y++ || z++;
-
- int switch = 0;
- if(x == 4 || y == 4 || z == 4) {
- switch = -1;
- } else {
- switch = 1;
- }
- int cd = 1;
- if((x == 0 && y == 1 && z==-1) && switch && g) {
- sys.io.p("Effected");
- } else {
- sys.io.p("Not effected");
- }
- return 0;
- """;
- TestC.runSF("or2", src, null, "Effected", 0);
+ String src = """
+int x = -1;
+int y = 1;
+int z = -1;
+int g = x++ || y++ || z++;
+int switch = (x == 4 || y == 4 || z == 4) ? -1 : 1;
+return (x == 0 && y == 1 && z==-1) && switch && g
+ ? 0 // Effected, expected
+ : 1; // Error
+""";
+ TestC.runSF( src, "or2", "", 0);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build("or2", src, 0, 2, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "or2", 0, 0, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
- assertEquals("Effected",R5._stdout.toString());
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("or2", src, 0, 2, false);
+ EvalArm64 arm = TestArm64.build("or2", src, 0, 0, false);
trap = arm.step(100);
assertEquals(0,trap);
assertEquals(0,arm.regs[0]);
- assertEquals("Effected",arm._stdout.toString());
}
// test it with function calls
@Test
public void testFuncCall() throws IOException {
- String src =
- """
- // -*- mode: java; -*-
- int a = 1;
- int b = 1;
-
- var sq = { int x ->
- x*x;
- };
-
- if(a && sq(0)) {
- sys.io.p("And");
- } else {
- sys.io.p("Or");
- }
- return 0;
- """;
- TestC.runSF("and3", src, null, "Or", 0);
+ String src = """
+int a = 1;
+int b = 1;
+var sq_noInline = { int x ->
+ x*x;
+};
+return (a && sq_noInline(0))
+ ? 1 // Error
+ : 0; // Expected
+""";
+ TestC.runSF( src, "and3", "", 2);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build("and3", src, 0, 2, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "and3", 0, 5, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
- assertEquals("Or",R5._stdout.toString());
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("and3", src, 0, 2, false);
+ EvalArm64 arm = TestArm64.build("and3", src, 0, 5, false);
trap = arm.step(100);
assertEquals(0,trap);
assertEquals(0,arm.regs[0]);
- assertEquals("Or",arm._stdout.toString());
}
@Test
public void testFRefFields() {
- String src =
-"""
+ String src = """
// A hypothetical scanner class
-struct Scan {
+struct _Scan {
int !x;
u8[~] buf;
+ new _Scan = { u8[~] b -> buf=b; };
// Skip whitespace
- val skip = { Scan s ->
- while( s.buf[s.x] <= ' ' )
- s.x++;
+ val skip = { ->
+ while( buf[x] <= ' ' )
+ x++;
};
// Peek a character; if matched consume it, else false.
- val peek = { Scan s, u8 c ->
- skip(s);
- if( s.buf[s.x] != c ) return false;
- s.x++;
+ val peek = { u8 c ->
+ skip();
+ if( buf[x] != c ) return false;
+ x++;
return true;
};
};
-Scan !s = new Scan{ buf = " q"; };
-return Scan.peek(s,'q');
- """;
+_Scan !_s = new _Scan(" q");
+return _s.peek('q');
+""";
CodeGen code = new CodeGen(src).parse().opto().typeCheck();
- assertEquals("return Phi(Region,0,1);", code._stop.toString());
+ assertEquals("return Phi(Region,0,1);", code.print());
assertEquals("1", Eval2.eval(code, 0));
- testCPU(src,"x86_64_v2", "Win64" ,17,null);
+ testCPU(src,"x86_64_v2", "win64",1,null);
};
@Test
public void testFRefFields2() {
- String src =
-"""
+ String src ="""
// A hypothetical scanner class
-struct Scan {
+struct _Scan {
int !x;
u8[~] buf;
+ new _Scan = { u8[~] b -> buf=b; };
// Skip whitespace
val skip = { ->
while( buf[x] <= ' ' )
@@ -305,23 +244,26 @@ struct Scan {
return self;
};
};
-val s = new Scan{ buf = " q"; };
+val s = new _Scan(" q");
return s.skip().x;
- """;
+""";
try { new CodeGen(src).parse().opto().typeCheck(); fail(); }
- catch( Exception e ) { assertEquals("Argument #0 isa *Scan {i64 x; *[]u8 buf; { *Scan -> *Scan {i64 !x; *[]u8 buf; {21} skip; } #21} skip; }, but must be a *Scan {i64 !x; *[]u8 buf; ... }",e.getMessage()); }
+ catch( Exception e ) {
+ // Bad error message, but basically requires a mutable 'x' field.
+ assertEquals("Argument #0 isa *Test._Scan {i64 x; *[]u8 buf; { *Test._Scan -> *Test._Scan {i64 !x; *[]u8 buf; {[ 5]} skip; } #[ 5]} skip; }, but must be a *Test._Scan {i64 !x; *[]u8 buf; { *Test._Scan -> *Test._Scan #[ 5]} skip; }",e.getMessage());
+ }
};
@Test
public void testMethod() {
- String src =
-"""
+ String src = """
// A hypothetical scanner class
-struct Scan {
+struct _Scan {
int !x;
u8[~] buf;
+ new _Scan = { u8[~] b -> buf=b; };
// Skip whitespace
val skip = { ->
while( buf[x] <= ' ' )
@@ -332,14 +274,14 @@ struct Scan {
buf[x++]==ch;
};
};
-Scan !s = new Scan{ buf = " [1,2]"; };
-return s.require('[');
- """;
+_Scan !_s = new _Scan(" [1,2]");
+return _s.require('[');
+""";
CodeGen code = new CodeGen(src).parse().opto().typeCheck();
- assertEquals("return (.[]==91);", code._stop.toString());
+ assertEquals("return (.[]==91);", code.print());
assertEquals("1", Eval2.eval(code, 0));
- testCPU(src,"x86_64_v2", "Win64" ,16,null);
+ testCPU(src,"x86_64_v2", "win64", 0, null);
};