summaryrefslogtreecommitdiff
path: root/chapter25/src/test/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-08-20 10:56:30 -0700
committerCliff Click <cliffc@acm.org>2026-08-20 10:56:30 -0700
commit3568f3deed586327f885ac98b73d07ae3ade6e57 (patch)
treefce7865468dc9e2beabeb68342f23bfea5bdae1a /chapter25/src/test/java/com/seaofnodes
parent1cb8279a64f4f79615ac8358927b11237df29bf2 (diff)
downloadSimple-3568f3deed586327f885ac98b73d07ae3ade6e57.tar.gz
Simple-3568f3deed586327f885ac98b73d07ae3ade6e57.zip
Squashed commit of the following:
commit c05d7df4f9c90984d2c04126772be3fee1d81fd1 Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 20 10:52:58 2026 -0700 Fix local frefs, deferred inlining, and sys FileIO support - Defer non-trivial inlining out of CallEnd idealization and run it from IterPeeps after normal peepholes reach a fixed point. - Keep forward refs local to their lexical scope, promote them outward on scope pop, and track created FRefNodes directly for dependency discovery. - Preserve loop scope shape when frefs are first seen inside loop bodies. - Treat frefs as final constants from creation and force lazy self lookups before implicit calls. - Reset imported pointer/struct types conservatively for post-parse Iter. - Pin Start-owned global machine value chains and clone global constants per function during GCM. - Improve late ASM printing before encoding and namespace constant-pool symbols. - Add optional regalloc function-local edge verifier and improve empty-mask splitting for multi-def/fixed-register LRGs. - Add sys array compare, safer array copy bounds, libc open/creat/close/unlink bindings, aryu8.str0, and higher-level sys.io file operations. - Add docs/examples/FileIO.smp and a Chapter25 FileIO test. - Update spill/code-size goldens after the allocator and scheduling changes. commit ef5316979732ac118612d310b75923c8f59ecdc1 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 16:29:56 2026 -0700 Dijkstra uses bitset. TestC.exec for repeated test runs with different stdins. Support &= and |= op-update forms. commit 728a527587f19bb49860f02ae5ac5968ab01ae33 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 12:13:28 2026 -0700 Fix live demo commit e4c069b9ef2cbfafe28d8edfcbff55396cde085e Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:52:24 2026 -0700 Update Dijkstra.smp commit b8015739b4056e3f7a715a030e846a441021a9f1 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:41:17 2026 -0700 Better looking Dijkstra commit 7cce587804c6169b24829e0b5bdc10be94357a31 Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:33:33 2026 -0700 Fix CmpMemX86 encoding Use sys.aryu8 for number printing commit 310b5d8c9978a3b09622a4b89dac97f0e5e6f3fb Author: Cliff Click <cliffc@acm.org> Date: Fri Aug 14 09:04:58 2026 -0700 Progress dijlstra Fix NotX86 encoding. Allow Not-sinking through Phis; the Nots both take Scalar and might take different types (ptr vs int). Better guard installing during && || opers. Drop the csv parse flavor in sys lib. commit 5917d5322521dd5e762c4698d34e5d7ac9b3a37f Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 14:44:12 2026 -0700 missed commit da35ad4d8a330559a21c04ae6326536e0fd62c48 Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 14:43:42 2026 -0700 Major cleanup of allocation All the graph-gen is moved to the <ctor> declaration and not at the alloc site. commit c4223216099ccbc526d282bb263972532d48c5b2 Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 13:26:01 2026 -0700 Some work from Dykstra (more coming) commit a03bc567f61dc7e4355e453ee4be16ac2528d1ab Author: Cliff Click <cliffc@acm.org> Date: Thu Aug 13 09:32:55 2026 -0700 Spill correctness and improvements Had the callee-save pick-risky backwards vs cloneables. commit 2d306e4430225f916cb7fb999f4926e52f6fb70a Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 19:40:04 2026 -0700 Tighter parser handling of missing fields Bug fix add libc.errno, read can return -1, sys.ary exists commit b7eeefda4cafa1e86153170dca6f13d45ef63f69 Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 16:22:48 2026 -0700 Printer improvements commit 8b9112226f1d2d1c843b080eecefe0d5ddc1f8cf Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 15:30:46 2026 -0700 Remove GLB commit ae566f5c610b9c30831906d3f024901d8930a227 Author: Cliff Click <cliffc@acm.org> Date: Wed Aug 12 14:38:51 2026 -0700 Add Capitalize example Rename Ary to ary. Fix bug || carrying state along. Fix bug load-array removing control. Add sys.char tolower/upper
Diffstat (limited to 'chapter25/src/test/java/com/seaofnodes')
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java2
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter10Test.java14
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter13Test.java4
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter15Test.java2
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter17Test.java14
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter18Test.java3
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter19Test.java2
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java41
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java14
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java14
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java30
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java6
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java147
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/Simple.java2
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/TestC.java36
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/TypeTest.java30
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m.smp2
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/a.smp1
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/b.smp4
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/ary.smp (renamed from chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/Ary.smp)0
-rw-r--r--chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp10
21 files changed, 221 insertions, 157 deletions
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
index 0ebee2c4..a42ebc24 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
@@ -61,7 +61,7 @@ val brain_fuck = { ->
""";
TestC.runC(src,"brain_fuck", brain_fuck, 40);
- EvalRisc5 R5 = TestRisc5.build( src, "brain_fuck", 0, 28, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "brain_fuck", 0, 25, false);
int trap = R5.step(100000);
assertEquals(0,trap);
int ptr = (int)R5.regs[com.seaofnodes.simple.node.cpus.riscv.riscv.A0];
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter10Test.java
index 6b237b18..0d40d871 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter10Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter10Test.java
@@ -65,7 +65,7 @@ else
return v;
""");
code.parse().opto();
- assertEquals("Stop[ return Test.Vector2D; return MEM[ 2:.x=0; 3:.y=0;]; ]", code.print());
+ assertEquals("Stop[ return Test.Vector2D; return MEM[ 2:.x=0; 3:.y=0;]; return Test.Vector2D; ]", code.print());
}
@Test
@@ -103,7 +103,7 @@ while (arg) {
return bar.a;
""");
code.parse().opto();
- assertEquals("Stop[ return Phi(Loop,0,(Phi_a+2)); return MEM[ 2:.a=0;]; ]", code.print());
+ assertEquals("Stop[ return Phi(Loop,0,(Phi_a+2)); return MEM[ 2:.a=0;]; return Test.Bar; ]", code.print());
}
@Test
@@ -225,7 +225,7 @@ while( i.x < i.len ) {
return sum;
""");
code.parse().opto();
- assertEquals("Stop[ return Phi(Loop,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum)); return MEM[ 2:.x=0; 3:.len=0;]; ]", code.print());
+ assertEquals("Stop[ return Phi(Loop,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum)); return MEM[ 2:.x=0; 3:.len=0;]; return Test.Iter; ]", code.print());
}
@@ -244,7 +244,7 @@ while(arg) {
return ret;
""");
code.parse().opto();
- assertEquals("Stop[ return Phi(Loop,Test.s0,Phi(Region,Test.s0,Phi_ret)); return MEM[ 2:.v0=0;]; ]", code.print());
+ assertEquals("Stop[ return Phi(Loop,Test.s0,Phi(Region,Test.s0,Phi_ret)); return MEM[ 2:.v0=0;]; return Test.s0; ]", code.print());
}
@Test
@@ -297,7 +297,7 @@ s0 b = new s0();
return a.x * 100 + b.x * 10 + cnt;
""");
code.parse().iter().opto();
- assertEquals("Stop[ return 112; return MEM[ 2:___ 3:.x=1;]; ]", code.print());
+ assertEquals("Stop[ return 112; return MEM[ 2:___ 3:.x=1;]; return Test.s0; ]", code.print());
}
@@ -340,7 +340,7 @@ else return new s0;
if(new s0.f0) return 0;
""");
code.parse().iter().opto().typeCheck();
- assertEquals("Stop[ return Test.s0; return MEM[ 2:.f0=0;]; ]", code.print());
+ assertEquals("Stop[ return Test.s0; return MEM[ 2:.f0=0;]; return Test.s0; ]", code.print());
}
@Test
@@ -368,7 +368,7 @@ s0 v1 = v0;
return v1;
""");
code.parse().opto();
- assertEquals("Stop[ return (const)Test.s0; return MEM[ 2:.f0=0;]; ]", code.print());
+ assertEquals("Stop[ return (const)Test.s0; return MEM[ 2:.f0=0;]; return Test.s0; ]", code.print());
}
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter13Test.java
index 8bbcf21c..fedd59ce 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter13Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter13Test.java
@@ -99,7 +99,7 @@ N n = new N(new M);
return n.next;
""");
code.parse().opto();
- assertEquals("Stop[ return (const)Test.M; return MEM[ 2:.m=0;]; return MEM[ 2:___ 3:___ 4:___ 5:.next=Parm_m(Test.N.N,*Test.M {i64 !m; }); 6:.i=0;]; return MEM[ 2:___ 3:___ 4:___ 5:___ 6:.i=0;]; ]", code.print());
+ assertEquals("Stop[ return (const)Test.M; return MEM[ 2:.m=0;]; return Test.M; return MEM[ 2:___ 3:___ 4:___ 5:___ 6:.next=Parm_m(Test.N.N,*Test.M {i64 !m; }); 7:.i=0;]; return MEM[ 2:___ 3:___ 4:___ 5:___ 6:___ 7:.i=0;]; return Test.N; ]", code.print());
}
@Test
@@ -173,7 +173,7 @@ struct _S2 { int x; };
return (new _S1).s=new _S2;
""");
code.parse().opto();
- assertEquals("return _S2;", code.print());
+ assertEquals("return Test._S2;", code.print());
}
@Test
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index d4790b3b..4d273aff 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -175,7 +175,7 @@ return root;
""");
code.parse().opto().typeCheck();
assertEquals("return Test._Tree;", code.print());
- assertEquals("Test._Tree{_kids=*Test._Tree {*[]*Test._Tree?? !_kids; }?[ Test._Tree{_kids=null},null]}", Eval2.eval(code, 0));
+ assertEquals("Test._Tree{_kids=*Test._Tree {*[]*Test._Tree?[mutable]? !_kids; }?[ Test._Tree{_kids=null},null]}", Eval2.eval(code, 0));
}
@Test
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter17Test.java
index 24daa164..faba6451 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter17Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter17Test.java
@@ -335,6 +335,18 @@ return arg ? 0 : arg;
}
@Test
+ public void testShortCircuitGuard() {
+ CodeGen code = new CodeGen("""
+struct S { int !x; };
+val get = { S s -> s.x; };
+S? !s = arg ? new S;
+if( !s || !arg ) return 0;
+return get(s);
+""");
+ code.parse().opto().typeCheck();
+ }
+
+ @Test
public void testTrinary2() {
CodeGen code = new CodeGen("""
struct _Bar { int x; };
@@ -395,7 +407,7 @@ struct S{};
return arg ? 7 : new S;
""");
try { code.parse().opto().typeCheck(); fail(); }
- catch( Exception e ) { assertEquals("No common type amongst 7 and *Test.S {}",e.getMessage()); }
+ catch( Exception e ) { assertEquals("Cannot return generic scalar",e.getMessage()); }
}
// ---------------------------------------------------------------
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index b65e101b..dc29dafa 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -146,7 +146,8 @@ return fcn(3);
CodeGen code = new CodeGen("val _fact = { int x -> x <= 1 ? 1 : x*_fact(x-1); }; return _fact(arg);");
code.parse().opto().typeCheck();
String ir = code.print();
- assertTrue(ir.equals("Stop[ return Phi(Region,1,(arg*#2)); return Phi(Region,1,(Parm_x(_fact,(arg-1),(x-1))*#2)); ]") ||
+ assertTrue(ir.equals("Stop[ return #2; return Phi(Region,1,(Parm_x(_fact,arg,(x-1))*#2)); ]") ||
+ ir.equals("Stop[ return Phi(Region,1,(arg*#2)); return Phi(Region,1,(Parm_x(_fact,(arg-1),(x-1))*#2)); ]") ||
ir.equals("Stop[ return Phi(Region,1,(arg*Phi(Region,1,((arg-1)*#2)))); return Phi(Region,1,(Parm_x(_fact,(Sub-1),(x-1))*#2)); ]"));
assertEquals( "1", Eval2.eval(code, 0));
assertEquals( "1", Eval2.eval(code, 1));
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter19Test.java
index eaf76041..10c4690e 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter19Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter19Test.java
@@ -58,7 +58,7 @@ val hashCode = { String self ->
hashCode(new String("Hello, World!"));
""";
CodeGen code = new CodeGen(src).driver(Phase.LocalSched);
- assertEquals("Stop[ return Phi(Region,123456789,(!=0)Phi(Loop,0,(.[]+((Phi_hash<<5)-Phi_hash)))); return MEM[ 2:___ 3:___ 4:.cs=Parm_s(Test.String.String,*[]u8); 5:._hashCode=0;]; return MEM[ 2:___ 3:___ 4:___ 5:._hashCode=0;]; return Phi(Region,0,1,0,1); return Phi(Region,(!=0)._hashCode,Phi(Region,123456789,(!=0)Phi(Loop,0,(((Phi_hash<<5)-Phi_hash)+.[])))); ]", code.print());
+ assertEquals("Stop[ return Phi(Region,123456789,(!=0)Phi(Loop,0,(.[]+((Phi_hash<<5)-Phi_hash)))); return MEM[ 2:___ 3:___ 4:.cs=Parm_s(Test.String.String,*[]u8[final]); 5:._hashCode=0;]; return MEM[ 2:___ 3:___ 4:___ 5:._hashCode=0;]; return Test.String; return Phi(Region,0,1,0,1); return Phi(Region,(!=0)._hashCode,Phi(Region,123456789,(!=0)Phi(Loop,0,(.[]+((Phi_hash<<5)-Phi_hash))))); ]", code.print());
assertEquals("4029215624828139541", Eval2.eval(code, 2));
}
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java
index 17b0fd0a..e8a3a875 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java
@@ -80,9 +80,34 @@ val _test_sqrt_noInline = { flt x ->
};
flt farg = arg; return _test_sqrt_noInline(farg) + _test_sqrt_noInline(farg+2.0);
""";
- testCPU(src,"x86_64_v2", "SystemV",65,null);
- testCPU(src,"riscv" , "SystemV",35,null);
- testCPU(src,"arm" , "SystemV",35,null);
+ testCPU(src,"x86_64_v2", "SystemV",48,null);
+ testCPU(src,"riscv" , "SystemV",17,null);
+ testCPU(src,"arm" , "SystemV",18,null);
+ }
+
+ @Test
+ public void testIterPrettyPrintIsLocalAndReadOnly() {
+ CodeGen code = new CodeGen("""
+ val f_noInline = { flt x -> while(1) { if(x) return x; } };
+ flt y=arg;
+ return f_noInline(y)+f_noInline(y+2.0);
+ """).driver(CodeGen.Phase.Iter);
+ assertNull(code._start._ltree);
+ int pre = code._start._pre;
+
+ String p0 = code.toString();
+ String p1 = code.toString();
+ assertEquals(p0,p1);
+ assertNull(code._start._ltree);
+ assertEquals(pre,code._start._pre);
+
+ int main0 = p0.indexOf("--- class:Test.<clinit>");
+ int main1 = p0.indexOf("--- class:Test.<clinit> ----------------------",main0);
+ int fun0 = p0.indexOf("--- f_noInline ",main1);
+ int fun1 = p0.indexOf("--- f_noInline ----------------------",fun0);
+ assertTrue(main0 < main1 && main1 < fun0 && fun0 < fun1);
+ assertTrue(p0.indexOf("ToFloat",main0) < p0.indexOf("Call",main0));
+ assertTrue(p0.indexOf("CallEnd",fun0) == -1 || p0.indexOf("CallEnd",fun0) > fun1);
}
@Test
@@ -108,7 +133,7 @@ for( int i=0; i<ary#-1; i++ )
ary[i+1] += ary[i];
return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6
""";
- testCPU(src,"x86_64_v2", "SystemV",-1,"return .[];");
+ testCPU(src,"x86_64_v2", "SystemV",-1,"return mov(.[]);");
testCPU(src,"riscv" , "SystemV", 7,"return (add,.[],(mul,.[],1000));");
testCPU(src,"arm" , "SystemV", 5,"return (add,.[],(mul,.[],1000));");
}
@@ -149,16 +174,16 @@ val _hashCodeString = { String self ->
};
""";
testCPU(src,"x86_64_v2", "SystemV",18,null);
- testCPU(src,"riscv" , "SystemV", 5,null);
- testCPU(src,"arm" , "SystemV", 4,null);
+ testCPU(src,"riscv" , "SystemV", 7,null);
+ testCPU(src,"arm" , "SystemV", 8,null);
}
@Test
public void testCast() {
String src = "struct Bar { int x; }; var b = arg ? new Bar; return b ? b.x++ + b.x++ : -1;";
testCPU(src,"x86_64_v2", "SystemV",3,null);
- testCPU(src,"riscv" , "SystemV",3,null);
- testCPU(src,"arm" , "SystemV",3,null);
+ testCPU(src,"riscv" , "SystemV",6,null);
+ testCPU(src,"arm" , "SystemV",6,null);
}
@Test
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java
index e4d49e7f..6eb9a698 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java
@@ -74,7 +74,7 @@ for( int i=0; i<ary#-1; i++ )
ary[i+1] += ary[i];
return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6
""";
- testCPU(src,"x86_64_v2", "SystemV",-1,"return .[];");
+ testCPU(src,"x86_64_v2", "SystemV",-1,"return mov(.[]);");
testCPU(src,"riscv" , "SystemV", 7,"return (add,.[],(mul,.[],1000));");
testCPU(src,"arm" , "SystemV", 5,"return (add,.[],(mul,.[],1000));");
}
@@ -94,9 +94,9 @@ if (v1) {
}
return v0;
""";
- testCPU(src,"x86_64_v2", "SystemV",10,"return mov(mov(Test._S));");
+ testCPU(src,"x86_64_v2", "SystemV", 9,"return mov(mov(Test._S));");
testCPU(src,"riscv" , "SystemV",10,"return mov(mov(Test._S));");
- testCPU(src,"arm" , "SystemV",10,"return mov(mov(Test._S));");
+ testCPU(src,"arm" , "SystemV",11,"return mov(mov(Test._S));");
}
@Test
@@ -134,8 +134,8 @@ val _hashCodeString = { String self ->
};
""";
testCPU(src,"x86_64_v2", "SystemV",18,null);
- testCPU(src,"riscv" , "SystemV", 5,null);
- testCPU(src,"arm" , "SystemV", 4,null);
+ testCPU(src,"riscv" , "SystemV", 7,null);
+ testCPU(src,"arm" , "SystemV", 8,null);
}
@Test public void testStringExport() throws IOException {
@@ -359,7 +359,7 @@ val fib = { int n ->
int p1 = ps+4*8+1*8;
// P2 = { age } // sizeof=8
int p2 = ps+4*8+2*8;
- EvalRisc5 R5 = TestRisc5.build( src, "fcn", ps, 0, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "fcn", ps, 2, false);
R5.regs[riscv.A1] = 1; // Index 1
R5.st8(ps,3); // Length
R5.st8(ps+1*8,p0);
@@ -375,7 +375,7 @@ val fib = { int n ->
assertEquals(17+1,R5.ld8(p1));
assertEquals(60+0,R5.ld8(p2));
- EvalArm64 A5 = TestArm64.build("fcn", src, ps, 0, false);
+ EvalArm64 A5 = TestArm64.build("fcn", src, ps, 2, false);
A5.regs[arm.X1] = 1; // Index 1
A5.st8(ps, 3);
A5.st8(ps+1*8,p0);
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java
index 91b8310d..68f94f12 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java
@@ -60,7 +60,7 @@ _Person !p = new _Person;
p.age = (arg<<17)>>17;
return 0;
""";
- assertEquals(83, testCPUSize(src, "x86_64_v2","win64", 3 ));
+ assertEquals(82, testCPUSize(src, "x86_64_v2","win64", 3 ));
assertEquals(96, testCPUSize(src, "riscv", "SystemV", 4 ));
assertEquals(96, testCPUSize(src, "arm" , "SystemV", 4 ));
@@ -88,11 +88,11 @@ return 0;
int trap = R5.step(100);
assertEquals(0,trap);
- EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away_2", src, 0, 4, false);
+ EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away_2", src, 0, 3, false);
int trap_arm = A5.step(100);
assertEquals(0,trap_arm);
- assertEquals(83, testCPUSize(src, "x86_64_v2","win64",3 ));
+ assertEquals(82, testCPUSize(src, "x86_64_v2","win64",3 ));
assertEquals(96, testCPUSize(src, "riscv", "SystemV",4 ));
assertEquals(96, testCPUSize(src, "arm", "SystemV",4 ));
@@ -116,9 +116,9 @@ return 0;
int trap_arm = A5.step(100);
assertEquals(0,trap_arm);
- assertEquals(71, testCPUSize(src, "x86_64_v2","win64",3 ));
+ assertEquals(72, testCPUSize(src, "x86_64_v2","win64",3 ));
assertEquals(92, testCPUSize(src, "riscv", "SystemV",5 ));
- assertEquals(92, testCPUSize(src, "arm", "SystemV",5 ));
+ assertEquals(92, testCPUSize(src, "arm", "SystemV",5));
// do assertEquals here
}
@@ -148,7 +148,7 @@ val fcn = { Person?[] ps, int x -> // exports a field with a constant fcn ptr; e
int p1 = ps+4*8+1*8;
// P2 = { age } // sizeof=8
int p2 = ps+4*8+2*8;
- EvalRisc5 R5 = TestRisc5.build( src, "fcn", ps, 0, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "fcn", ps, 2, false);
R5.regs[riscv.A1] = 1; // Index 1
R5.st8(ps,3); // Length
R5.st8(ps+1*8,p0);
@@ -164,7 +164,7 @@ val fcn = { Person?[] ps, int x -> // exports a field with a constant fcn ptr; e
assertEquals(17+1,R5.ld8(p1));
assertEquals(60+0,R5.ld8(p2));
- EvalArm64 A5 = TestArm64.build("fcn", src, ps, 0, false);
+ EvalArm64 A5 = TestArm64.build("fcn", src, ps, 2, false);
A5.regs[arm.X1] = 1; // Index 1
A5.st8(ps, 3);
A5.st8(ps+1*8,p0);
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java
index 08acfd32..3346aa51 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java
@@ -86,6 +86,26 @@ return a && b ? 0 : 1; // Expected answer 0
}
@Test
+ public void testLogicalValueSemantics() {
+ assertEquals("42", Eval2.eval(new CodeGen("return 7 && 42;").parse().opto(), 0));
+ assertEquals("0", Eval2.eval(new CodeGen("return 0 && 42;").parse().opto(), 0));
+ assertEquals("7", Eval2.eval(new CodeGen("return 7 || 42;").parse().opto(), 0));
+ assertEquals("42", Eval2.eval(new CodeGen("return 0 || 42;").parse().opto(), 0));
+ }
+
+ @Test
+ public void testMixedScalarNotPhiPredicate() {
+ CodeGen code = new CodeGen("""
+struct S {};
+S? s = arg ? new S;
+return !(!s || !arg) ? 1 : 0;
+""");
+ code.parse().opto().typeCheck();
+ assertEquals("0", Eval2.eval(code, 0));
+ assertEquals("1", Eval2.eval(code, 1));
+ }
+
+ @Test
public void testAndPtr() throws IOException {
// Todo: have one src here
String src = """
@@ -97,7 +117,7 @@ return ptr && ptr.fld ? "true" : "false";
assertEquals("true", Eval2.eval(code, 0));
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build( src, "class:Test.<clinit>", 1, 8, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "class:Test.<clinit>", 1, 12, false);
int trap = R5.step(100);
assertEquals(0,trap);
int adr = (int)R5.regs[riscv.A0]; // Returns a Simple *u8[~] string
@@ -105,7 +125,7 @@ return ptr && ptr.fld ? "true" : "false";
assertEquals(0x65757274,R5.ld4s(adr+4)); // "true"
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("class:Test.<clinit>", src, 1, 8, false);
+ EvalArm64 arm = TestArm64.build("class:Test.<clinit>", src, 1, 12, false);
trap = arm.step(100);
assertEquals(0,trap);
int adr2 = (int)arm.regs[0]; // Returns a Simple *u8[~] string
@@ -185,13 +205,13 @@ return (a && sq_noInline(0))
TestC.runSF( src, "and3", "", 2);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build( src, "and3", 0, 5, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "and3", 0, 2, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("and3", src, 0, 5, false);
+ EvalArm64 arm = TestArm64.build("and3", src, 0, 2, false);
trap = arm.step(100);
assertEquals(0,trap);
assertEquals(0,arm.regs[0]);
@@ -251,7 +271,7 @@ return s.skip().x;
try { new CodeGen(src).parse().opto().typeCheck(); fail(); }
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());
+ assertEquals("Argument #0 isa *Test._Scan {i64 x; *[]u8[final] buf; { *Test._Scan -> *Test._Scan {i64 !x; *[]u8 buf; {[ 5]} skip; } #[ 5]} skip; }, but must be a *Test._Scan {i64 !x; *[]u8[final] buf; { *Test._Scan -> *Test._Scan #[ 5]} skip; }",e.getMessage());
}
};
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java
index fe8aaf2e..eb89dbb3 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java
@@ -62,16 +62,16 @@ return (sq_noInline(2) <= score < sq_noInline(3))
? 0 // Expected
: 1; // Error
""";
- TestC.runSF( src, "stacked_r_3", "", 4);
+ TestC.runSF( src, "stacked_r_3", "", 2);
// Evaluate on RISC5 emulator
- EvalRisc5 R5 = TestRisc5.build( src, "stacked_r_3", 0, 5, false);
+ EvalRisc5 R5 = TestRisc5.build( src, "stacked_r_3", 0, 2, false);
int trap = R5.step(100);
assertEquals(0,trap);
assertEquals(0,R5.regs[riscv.A0]);
// Evaluate on ARM emulator
- EvalArm64 arm = TestArm64.build("stacked_r_3", src, 0, 5, false);
+ EvalArm64 arm = TestArm64.build("stacked_r_3", src, 0, 3, false);
int trap_1 = arm.step(100);
assertEquals(0,trap_1);
assertEquals(0,arm.regs[0]);
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java
index 8f1c7285..b21734b4 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java
@@ -18,9 +18,17 @@ import static org.junit.Assert.*;
public class Chapter25Test {
- private static final String SYS_MODDIR = "src/main/smp";
private static final String SYS_BLDDIR = "build/objs/lib_"+TestC.CPU_ABI;
- private static final String RELEASE_SYS_BLDDIR = TestC.RELEASE_SYS_DIR;
+ private static final File SYS_FILE = new File(SYS_BLDDIR+"/sys.o");
+
+ @Test
+ public void testForwardConstructor() {
+ CodeGen code = new CodeGen("src/test/java/com/seaofnodes/simple/test_smp/forward_ctor",
+ "build/objs/forward_ctor_parse",null,
+ "m",null,123L,TypeInteger.BOT);
+ code.driver(CodeGen.Phase.TypeCheck);
+ }
+
@Test
public void testPostfixFieldUpdate() {
@@ -163,56 +171,34 @@ public class Chapter25Test {
}
- private File buildTestSys(boolean clean) {
- if( clean )
- delELFiles(new File(SYS_BLDDIR));
- File sys_file = new File(SYS_BLDDIR+"/sys.o" );
- if( sys_file.exists() )
- return sys_file;
-
- // Compile SYS_MODDIR/sys.smp into SYS_BLDDIR/sys.o. Chapter25
- // compiler tests intentionally depend on this freshly built sys.o.
- CodeGen code1 = new CodeGen(SYS_MODDIR, SYS_BLDDIR,null,
- "sys",null,123L,TypeInteger.BOT);
- code1.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION,false,false,0);
- assertTrue( sys_file.exists() );
- return sys_file;
- }
-
@Test
public void testSys() {
- delELFiles(new File(SYS_BLDDIR));
-
- CodeGen code1 = new CodeGen(SYS_MODDIR, SYS_BLDDIR,null,
- "sys",null,123L,TypeInteger.BOT);
- code1.driver(CodeGen.Phase.Export,TestC.CPU_PORT,TestC.CALL_CONVENTION,false,false,0);
-
- // Verify produces sys.o, sys/io.o
- File sys_file = new File(SYS_BLDDIR+"/sys.o" );
- assertTrue( sys_file.exists() );
+ assertTrue("Missing "+SYS_FILE+"; run make tests_sys", SYS_FILE.exists());
// Can read the ELF files
- ElfReader sys_elf = ElfReader.load( sys_file, null);
- sys_elf.loadSimple(code1);
+ CodeGen code1 = new CodeGen("return 0;");
+ ElfReader sys_elf = ElfReader.load(SYS_FILE, null);
+ sys_elf.loadPublicTypes(code1);
// Elf files are sane
- // Sys depends on io, libc, aryi64, aryu8
- assertEquals(6,sys_elf._deps.length);
+ // Sys depends on io, libc, char, collections, and array utilities.
+ assertEquals(10,sys_elf._deps.length);
assertSame("sys/aryu8" ,sys_elf._deps[0]);
- assertSame("sys/io" ,sys_elf._deps[1]);
- assertSame("sys/aryi64",sys_elf._deps[2]);
- assertSame("sys/Ary" ,sys_elf._deps[3]);
- assertSame("sys/Scan" ,sys_elf._deps[4]);
- assertSame("sys/libc" ,sys_elf._deps[5]);
+ assertSame("sys/char" ,sys_elf._deps[1]);
+ assertSame("sys/io" ,sys_elf._deps[2]);
+ assertSame("sys/ary" ,sys_elf._deps[3]);
+ assertSame("sys/aryi64",sys_elf._deps[4]);
+ assertSame("sys/adt/bitset",sys_elf._deps[5]);
+ assertSame("sys", sys_elf._deps[6]);
+ assertSame("sys/scan" ,sys_elf._deps[7]);
+ assertSame("sys/adt" ,sys_elf._deps[8]);
+ assertSame("sys/libc" ,sys_elf._deps[9]);
assertSame("class:sys" ,sys_elf._clz._name);
}
@Test
public void testHelloWorld() throws IOException {
- File sys_file = buildTestSys(false);
- assertTrue("Missing "+sys_file+"; testHelloWorld depends on testSys building it", sys_file.exists());
-
String expected = "Hello, World!\n";
String prog = "return sys.io.p(\""+expected+"\") - "+expected.length()+";";
TestC.run(prog,"helloWorld",new Ary<>(new String[]{SYS_BLDDIR}),
@@ -221,23 +207,16 @@ public class Chapter25Test {
@Test
public void testHelloWorldDriver() throws Exception {
- File sys_file = new File(RELEASE_SYS_BLDDIR+"/sys.o");
- assertTrue("Missing "+sys_file+"; run make release or make tests_sys first", sys_file.exists());
- Simple.main(new String[]{"-L",RELEASE_SYS_BLDDIR,"--norun","docs/examples/A_helloWorld.smp"});
+ Simple.main(new String[]{"-L",SYS_BLDDIR,"--norun","docs/examples/A_helloWorld.smp"});
}
@Test
public void testHelloWorldDriverLibFile() throws Exception {
- File sys_file = new File(RELEASE_SYS_BLDDIR+"/sys.o");
- assertTrue("Missing "+sys_file+"; run make release or make tests_sys first", sys_file.exists());
- Simple.main(new String[]{"-L",sys_file.toString(),"docs/examples/A_helloWorld.smp"});
+ Simple.main(new String[]{"-L",SYS_FILE.toString(),"docs/examples/A_helloWorld.smp"});
}
@Test
public void testHelloWorldNoInline() throws Exception {
- File sys_file = buildTestSys(false);
- assertTrue("Missing "+sys_file+"; testHelloWorldNoInline depends on testSys building it", sys_file.exists());
-
String base = "helloWorldNoInline";
String expected = "Hello, World!\n";
String prog = "return sys.io.p_noInline(\""+expected+"\") - "+expected.length()+";";
@@ -250,7 +229,7 @@ public class Chapter25Test {
String syms = run(new String[]{"nm",obj});
assertTrue(syms, syms.contains(" U sys.io.p_noInline"));
- String out = run(new String[]{"gcc",obj,sys_file.toString(),TestC.runtimeObject(),"-lm","-g","-o",exe});
+ String out = run(new String[]{"gcc",obj,SYS_FILE.toString(),TestC.runtimeObject(),"-lm","-g","-o",exe});
assertEquals("",out);
String rez = run(new String[]{exe});
assertEquals(expected,rez);
@@ -267,8 +246,6 @@ public class Chapter25Test {
@Test
public void testRedirectedRead() throws IOException {
- File sys_file = buildTestSys(false);
- assertTrue("Missing "+sys_file+"; testRedirectedRead depends on testSys building it", sys_file.exists());
String src = """
u8[] buf = new u8[10];
i64 ptr = buf;
@@ -282,28 +259,58 @@ return rez < buf# ? 0 : sys.libc._exit(-2);
@Test
public void testBubbles() throws IOException {
- File sys_file = buildTestSys(false);
- assertTrue("Missing "+sys_file+"; testBubbles depends on testSys building it", sys_file.exists());
String src = Files.readString( Path.of("docs/examples/BubbleSort.smp"));
- TestC.runArgs(src,"BubbleSort",new Ary<>(new String[]{SYS_BLDDIR}),
- TestC.CALL_CONVENTION,"-17, 2, 3, 999\n",-1,
- "[3, 2,-17, 999 ]");
-
- String obj = "build/objs/BubbleSort.o";
- String exe = "build/objs/BubbleSort"+(TestC.OS.startsWith("Windows") ? ".exe" : "");
- Ary<String> libs = new Ary<>(new String[]{sys_file.toString()});
- assertEquals("1, 2, 3, 4, 4, 5\n",
- TestC.gcc(obj,null,null,null,libs,exe,"[4, 5, 3, 1, 4, 2]"));
- assertEquals("1, 2, 3, 4, 5\n",
- TestC.gcc(obj,null,null,null,libs,exe,"[1, 2, 3, 4, 5]"));
- assertEquals("1, 2, 3, 4, 5, 6, 7, 8, 9\n",
- TestC.gcc(obj,null,null,null,libs,exe,"[9, 8, 7, 6, 5, 4, 3, 2, 1]"));
+ String exe = TestC.compile(src,"BubbleSort",new Ary<>(new String[]{SYS_BLDDIR}),
+ TestC.CALL_CONVENTION,null,null,-1);
+ assertEquals("[-17, 2, 3, 999]\n",
+ TestC.exec(exe,"[3, 2,-17, 999 ]"));
+ assertEquals("[1, 2, 3, 4, 4, 5]\n",
+ TestC.exec(exe,"[4, 5, 3, 1, 4, 2]"));
+ assertEquals("[1, 2, 3, 4, 5]\n",
+ TestC.exec(exe,"[1, 2, 3, 4, 5]"));
+ assertEquals("[1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
+ TestC.exec(exe,"[9, 8, 7, 6, 5, 4, 3, 2, 1]"));
String usage = "Usage: please provide a list of at least two integers to sort in the format \"[1, 2, 3, 4, 5]\"\n";
- assertEquals(usage,TestC.gcc(obj,null,null,null,libs,exe));
- assertEquals(usage,TestC.gcc(obj,null,null,null,libs,exe,""));
- assertEquals(usage,TestC.gcc(obj,null,null,null,libs,exe,"[1]"));
- assertEquals(usage,TestC.gcc(obj,null,null,null,libs,exe,"[4 5 3]"));
+ assertEquals(usage,TestC.exec(exe));
+ assertEquals(usage,TestC.exec(exe,""));
+ assertEquals(usage,TestC.exec(exe,"[1]"));
+ assertEquals(usage,TestC.exec(exe,"[4 5 3]"));
}
+ @Test
+ public void testCapitalize() throws IOException {
+ String src = Files.readString(Path.of("docs/examples/Capitalize.smp"));
+ String exe = TestC.compile(src,"Capitalize",new Ary<>(new String[]{SYS_BLDDIR}),
+ TestC.CALL_CONVENTION,null,null,-1);
+ assertEquals("Hello world\n",TestC.exec(exe,"hello world"));
+ assertEquals("Hello World\n",TestC.exec(exe,"Hello World"));
+ assertEquals("123 apples\n",TestC.exec(exe,"123 apples"));
+ assertEquals("Usage: please provide a string\n",TestC.exec(exe));
+ assertEquals("Usage: please provide a string\n",TestC.exec(exe,""));
+ assertEquals("Use quotes around multiple strings.\n",TestC.exec(exe,"hello","world"));
+ }
+
+ @Test
+ public void testDijkstra() throws IOException {
+ String src = Files.readString(Path.of("docs/examples/Dijkstra.smp"));
+ String matrix = "[0, 2, 0, 6, 0, 2, 0, 3, 8, 5, 0, 3, 0, 0, 7, 6, 8, 0, 0, 9, 0, 5, 7, 9, 0]";
+ String exe = TestC.compile(src,"Dijkstra",new Ary<>(new String[]{SYS_BLDDIR}),
+ TestC.CALL_CONVENTION,null,null,-1);
+ assertEquals("2\n",TestC.exec(exe,matrix,"0","1"));
+ String usage = "Usage: please provide three inputs: a serialized matrix, a source node and a destination node\n";
+ assertEquals("7\n",TestC.exec(exe,matrix,"0","4"));
+ assertEquals(usage,TestC.exec(exe));
+ assertEquals(usage,TestC.exec(exe,"","",""));
+ assertEquals(usage,TestC.exec(exe,"[1, 0, 3, 0, 5, 1]","1","2"));
+ assertEquals(usage,TestC.exec(exe,"[0, 0, 0, 0]","0","1"));
+ }
+
+ @Test
+ public void testFileIO() throws IOException {
+ String src = Files.readString(Path.of("docs/examples/FileIO.smp"));
+ String exe = TestC.compile(src,"FileIO",new Ary<>(new String[]{SYS_BLDDIR}),
+ TestC.CALL_CONVENTION,null,null,-1);
+ assertEquals("File I/O succeeded\n",TestC.exec(exe));
+ }
}
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Simple.java b/chapter25/src/test/java/com/seaofnodes/simple/Simple.java
index 35b9b922..a5d104e7 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/Simple.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/Simple.java
@@ -247,7 +247,7 @@ Options:
if ( !TestC.CPU_PORT.equals( cpu ) || !TestC.CALL_CONVENTION.equals( abi ) )
throw bad("cannot run code on not native target");
String exe = TestC.OS.startsWith("Windows") ? outBase+".exe" : outBase;
- String result = TestC.gcc(outBase+".o", null, null, true, exe);
+ String result = TestC.gcc(outBase+".o", null, null, "", TestC.linkObjs(externPaths), exe);
System.out.print(result);
}
}
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java
index 2f737579..bd8a52cc 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java
@@ -98,6 +98,17 @@ public abstract class TestC {
private static void run0( String src, String base, Ary<String> externPaths, String simple_conv, String c_conv,
String cfile, String stdin, String expected, int spills, String[] programArgs ) throws IOException {
+ String exe = compile(src,base,externPaths,simple_conv,c_conv,cfile,spills);
+
+ String[] execArgs = new String[programArgs.length+1];
+ execArgs[0] = exe;
+ System.arraycopy(programArgs,0,execArgs,1,programArgs.length);
+ String result = execStdin(stdin, execArgs );
+ assertEquals(expected,result);
+ }
+
+ public static String compile( String src, String base, Ary<String> externPaths, String simple_conv, String c_conv,
+ String cfile, int spills ) throws IOException {
// Simple file base-name example:
// foo.smp ->
// build/objs/foo.o - object file
@@ -110,17 +121,14 @@ public abstract class TestC {
CodeGen code = new CodeGen(null,"build/objs",externPaths,base,src,126L,TypeInteger.BOT);
code.driver( CPU_PORT, simple_conv, false, cfile==null );
- String[] execArgs = new String[programArgs.length+1];
- execArgs[0] = exe;
- System.arraycopy(programArgs,0,execArgs,1,programArgs.length);
- String result = gcc(obj, c_conv, cfile, stdin, linkObjs(externPaths), execArgs );
- assertEquals(expected,result);
+ linkExe(obj, c_conv, cfile, linkObjs(externPaths), exe);
// Allocation quality not degraded
int delta = spills>>3;
if( delta==0 ) delta = 1;
if( spills != -1 && !CodeGen.iterSeedOverridden() )
assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta);
+ return exe;
}
// Link with gcc, and execute the resulting binary, returning stdout as a
@@ -146,7 +154,11 @@ public abstract class TestC {
}
public static String gcc( String obj, String c_conv, String cfile, String stdin, Ary<String> linkObjs, String... args ) throws IOException {
+ linkExe(obj,c_conv,cfile,linkObjs,args[0]);
+ return execStdin(stdin,args);
+ }
+ public static void linkExe( String obj, String c_conv, String cfile, Ary<String> linkObjs, String exe ) throws IOException {
// Compile the C program. Compiling code and constants in the low
// 2Gig. Pointers are 64b BUT since always in the low 2G all the
// high bits are zero - and Simple code can be emitted treating
@@ -165,7 +177,7 @@ public abstract class TestC {
"-lm", // Picks up 'sqrt' for newtonFloat tests to compare
"-g",
"-o",
- args[0],
+ exe,
});
// Calling convention for C calls, if any
if( cfile!=null ) {
@@ -190,6 +202,13 @@ public abstract class TestC {
assertEquals( 0, exit );
//assertTrue(result.isEmpty()); // No data in error stream
+ }
+
+ public static String exec( String... args ) throws IOException {
+ return execStdin(null,args);
+ }
+
+ private static String execStdin( String stdin, String... args ) throws IOException {
// Execute results
ProcessBuilder smp = new ProcessBuilder(args);
File stdinFile = null;
@@ -204,8 +223,9 @@ public abstract class TestC {
Process p = smp.start();
if( stdin==null )
p.getOutputStream().close();
+ int exit;
try { exit = (byte)p.waitFor(); } catch( InterruptedException e ) { throw new IOException("interrupted"); }
- result = Files.readString(stdoutFile.toPath());
+ String result = Files.readString(stdoutFile.toPath());
if( stdinFile != null )
stdinFile.delete();
stdoutFile.delete();
@@ -214,7 +234,7 @@ public abstract class TestC {
return result;
}
- private static Ary<String> linkObjs(Ary<String> externPaths) {
+ static Ary<String> linkObjs(Ary<String> externPaths) {
if( externPaths == null )
return null;
Ary<String> objs = new Ary<>(String.class);
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TypeTest.java b/chapter25/src/test/java/com/seaofnodes/simple/TypeTest.java
index e881a2bf..65635afe 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/TypeTest.java
+++ b/chapter25/src/test/java/com/seaofnodes/simple/TypeTest.java
@@ -7,7 +7,7 @@ import static org.junit.Assert.assertSame;
public class TypeTest {
- // Test basic properties and GLB
+ // Test basic type properties
@Test
public void testTypeAdHoc() {
Assert.assertEquals( TypeScalar.BOT, TypeInteger.TRUE.meet(TypeNil.NIL) );
@@ -19,13 +19,8 @@ public class TypeTest {
TypeStruct s2 = TypeStruct.make("s2",false,
Field.make("a", TypeInteger.BOT,-3, false),
Field.make("b", TypeInteger.BOT,-4, false) );
- TypeStruct x1ro = (TypeStruct)s1.makeRO();
TypeMemPtr p1 = TypeMemPtr.make(s1);
- // GLB no longer forces RO
- //Assert.assertEquals(x1ro, ((TypeMemPtr)p1.glb(false))._obj);
Assert.assertNotEquals(s1, s1.dual());
- TypeStruct s1dglb = ((TypeMemPtr)p1.dual().glb(false))._obj;
- Assert.assertTrue(x1ro.isa(s1dglb));
TypeMem m1 = TypeMem.make(2,TypeNil.NIL);
TypeMem m2 = TypeMem.make(3,TypeInteger.U16);
@@ -42,9 +37,7 @@ public class TypeTest {
Assert.assertEquals(TypeMem.make(1,TypeScalar.BOT), m1.meet(m3));
Assert.assertEquals(scalarMemBot, ((TypeMem)m3.meet(m4)).makeFrom( XInt.FULL, XInt.FULL));
- Assert.assertEquals(TypeMem.make(2,Type.BOTTOM), m1.glb(false));
Assert.assertEquals(TypeMem.make(2,Type.XNIL,true,true,true, XInt.FULL, XInt.FULL), m1.dual());
- Assert.assertEquals(m4.dual(), m4.glb(false).dual());
TypeMemPtr ptr1 = TypeMemPtr.make(s1);
Assert.assertEquals(s1, ptr1._obj);
@@ -59,18 +52,8 @@ public class TypeTest {
Assert.assertEquals(s2, ptr2nil._obj);
Assert.assertNotEquals(ptr1, ptr2);
- Type p1glb = ptr1.glb(false);
- // GLB no longer forces RO
- //Assert.assertNotEquals(ptr1, p1glb );
- Type p1nro = ptr1nil.makeRO();
- // GLB no longer forces RO
- //Assert.assertEquals(p1nro, p1glb);
-
Assert.assertEquals(ptr1, ptr1.dual().dual());
- Assert.assertTrue(p1glb.makeRO().isa( ptr1.dual().glb(false)));
Assert.assertEquals(TypeMemPtr.makeNullable(TypeStruct.BOT), ptr1.meet(ptr2nil));
- // GLB no longer forces RO
- //Assert.assertEquals(p1glb, ptr1.meet(TypeNil.NIL).makeRO());
TypeMemPtr TOP = TypeMemPtr.TOP;
TypeMemPtr BOT = TypeMemPtr.makeNullable(TypeStruct.BOT);
@@ -96,9 +79,6 @@ public class TypeTest {
Assert.assertTrue(s1ro.isFinal());
Assert.assertFalse(S1.isConstant());
- Type s1glb = S1.field("s2")._t.glb(false);
- Type s1glb2 = S1.field("s2")._t.glb(false);
- Assert.assertSame(s1glb,s1glb2);
}
// Test theoretical properties.
@@ -178,14 +158,6 @@ public class TypeTest {
}
@Test
- public void testGLB() {
- Type[] ts = Type.gather();
- for( Type t0 : ts )
- if( !(t0 instanceof Field || t0 instanceof TypeStruct || t0 instanceof TypeTuple || t0 instanceof TypeConAry ) )
- Assert.assertTrue(t0.isa(t0.glb(false)));
- }
-
- @Test
public void testList() {
TypeStruct list = TypeStruct.open("List");
TypeMemPtr plist = TypeMemPtr.makeNullable(list);
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m.smp
new file mode 100644
index 00000000..569f38be
--- /dev/null
+++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m.smp
@@ -0,0 +1,2 @@
+val a = a;
+val b = b;
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/a.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/a.smp
new file mode 100644
index 00000000..97113b71
--- /dev/null
+++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/a.smp
@@ -0,0 +1 @@
+val f = { -> new b(1); };
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/b.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/b.smp
new file mode 100644
index 00000000..43770b60
--- /dev/null
+++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/forward_ctor/m/b.smp
@@ -0,0 +1,4 @@
+struct b {
+ int x;
+ new b = { int y -> x = y; };
+};
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/Ary.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/ary.smp
index e3dd6140..e3dd6140 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/Ary.smp
+++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/ary.smp
diff --git a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp
index 112a0321..e6b708a4 100644
--- a/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp
+++ b/chapter25/src/test/java/com/seaofnodes/simple/test_smp/seed_repro/sys/aryu8.smp
@@ -9,7 +9,7 @@ struct aryu8 {
int newlen = buf# * 2;
while( len+len2 >= newlen ) newlen *= 2;
u8[] !buf2 = new u8[newlen];
- Ary.copy(buf2,0,buf,0,buf#);
+ ary.copy(buf2,0,buf,0,buf#);
buf = buf2;
self;
};
@@ -21,10 +21,10 @@ struct aryu8 {
self;
};
- val addAry = { u8[~] ary ->
- _grow(ary#);
- Ary.copy(buf,len,ary,0,ary#);
- len += ary#;
+ val addAry = { u8[~] xs ->
+ _grow(xs#);
+ ary.copy(buf,len,xs,0,xs#);
+ len += xs#;
self;
};