summaryrefslogtreecommitdiff
path: root/chapter28b/src/test/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-28 09:30:15 -0700
committerCliff Click <cliffc@acm.org>2026-10-28 09:30:15 -0700
commit696adef058d43695ac1c47a7223d9e7a8b8ab6ea (patch)
tree956dc21e7c2bdb1386da7b5451dd4f252d829456 /chapter28b/src/test/java/com/seaofnodes
parent76a7ee6eaf6963b044cb5d149c916c55ae4d24f7 (diff)
downloadSimple-696adef058d43695ac1c47a7223d9e7a8b8ab6ea.tar.gz
Simple-696adef058d43695ac1c47a7223d9e7a8b8ab6ea.zip
Another round of extra _phase changes removed
Also removes loading more code to resolve cyclic class dependencies, and instead rejects some of the more exciting cases
Diffstat (limited to 'chapter28b/src/test/java/com/seaofnodes')
-rw-r--r--chapter28b/src/test/java/com/seaofnodes/simple/ClassInitDependenciesTest.java15
-rw-r--r--chapter28b/src/test/java/com/seaofnodes/simple/SelectiveLoadingTest.java30
2 files changed, 25 insertions, 20 deletions
diff --git a/chapter28b/src/test/java/com/seaofnodes/simple/ClassInitDependenciesTest.java b/chapter28b/src/test/java/com/seaofnodes/simple/ClassInitDependenciesTest.java
index 08648187..38b4d8a2 100644
--- a/chapter28b/src/test/java/com/seaofnodes/simple/ClassInitDependenciesTest.java
+++ b/chapter28b/src/test/java/com/seaofnodes/simple/ClassInitDependenciesTest.java
@@ -248,25 +248,25 @@ public class ClassInitDependenciesTest {
Path dir=tempDir("import-"), stubs=tempDir("import-");
object(stubs,stubs,"A","int value=arg;");
object(stubs,stubs,"B","int value=arg;");
- // Each object is independently acyclic. Combining their real bodies
+ // Each object is independently acyclic. Combining their summaries
// must recheck the graph rather than trust either object's local order.
String asrc="int value=arg;\nvalue=B.value;";
CodeGen acode=module(dir,stubs,"A",Map.of("A",asrc));
String afile=acode._compunits.get("A").sourceFile();
module(dir,stubs,"B",Map.of("B","int value=arg; value=A.value;"));
for( String entry : new String[]{"A","B"} ) {
+ CodeGen code = new CodeGen(null,dir.toString(),new Ary<>(new String[]{dir.toString()}),
+ "Main","return "+entry+".value;",123,true,TypeInteger.BOT);
try {
- new CodeGen(null,dir.toString(),new Ary<>(new String[]{dir.toString()}),
- "Main","return "+entry+".value;",123,true,TypeInteger.BOT).driver(CodeGen.Phase.TypeCheck);
+ code.driver(CodeGen.Phase.TypeCheck);
fail("Expected imported initialization cycle");
} catch( Parser.ParseException ex ) {
assertCycle(ex.getMessage(),"A -> B -> A");
- assertTrue(ex.getMessage(),ex.getMessage().contains("value=B.value;\n -------^"));
- assertTrue(ex.getMessage(),ex.getMessage().contains("\n"+afile+":2:8: error: cyclic class initialization\n"));
+ assertNull(code.getElf(code._compunits.get("A")._obj)._nodes);
+ assertNull(code.getElf(code._compunits.get("B")._obj)._nodes);
}
}
- // The imported object must still report its saved path and offset
- // when the original source is no longer available.
+ // The summary reports the dependency chain even without source files.
Files.delete(Path.of(afile));
try {
new CodeGen(null,dir.toString(),new Ary<>(new String[]{dir.toString()}),
@@ -274,7 +274,6 @@ public class ClassInitDependenciesTest {
fail("Expected imported initialization cycle");
} catch( Parser.ParseException ex ) {
assertCycle(ex.getMessage(),"A -> B -> A");
- assertTrue(ex.getMessage(),ex.getMessage().contains("\n"+afile+": error: cyclic class initialization (source unavailable at byte offset "+asrc.indexOf('.')+")"));
}
}
diff --git a/chapter28b/src/test/java/com/seaofnodes/simple/SelectiveLoadingTest.java b/chapter28b/src/test/java/com/seaofnodes/simple/SelectiveLoadingTest.java
index d8fad3d5..d56d5c89 100644
--- a/chapter28b/src/test/java/com/seaofnodes/simple/SelectiveLoadingTest.java
+++ b/chapter28b/src/test/java/com/seaofnodes/simple/SelectiveLoadingTest.java
@@ -160,29 +160,35 @@ public class SelectiveLoadingTest {
}
}
- @Test public void testCycleRefinementLoadsConditionHelper() throws Exception {
+ @Test public void testPossibleCycleDoesNotLoadConditionHelper() throws Exception {
Path base = Path.of("build/objs/selective");
Files.createDirectories(base);
Path root = Files.createTempDirectory(base,"cycle-");
- Path stubs = Files.createDirectory(root.resolve("stubs"));
+ Path src = Files.createDirectory(root.resolve("src"));
Path lib = Files.createDirectory(root.resolve("lib"));
- object(stubs,null,"A","int value=arg;");
- object(stubs,null,"B","int value=arg;");
StringBuilder helper = new StringBuilder("val test={bool n -> ");
// Large parse, small final body: it will not request speculative loading.
for( int i = 0; i<80; i++ ) helper.append("val x").append(i).append("=n+0;");
helper.append("return n;};");
object(lib,null,"Predicate",helper.toString());
- Ary<String> inputs = new Ary<>(new String[]{stubs.toString(),lib.toString()});
- object(lib,inputs,"A","int value=1; if(Predicate.test(false)) value=B.value;");
- object(lib,inputs,"B","int value=A.value;");
- CodeGen code = new CodeGen(null,root.toString(),new Ary<>(new String[]{lib.toString()}),
- "Main","return A.value;",123,true,TypeInteger.BOT).driver(CodeGen.Phase.FinalizeIR);
+ // All sources and objects agree. The summary cannot express test(n)==n.
+ write(src,"Root","val entry=A;");
+ write(src,"Root/A","int value=1; if(Predicate.test(false)) value=B.value;");
+ write(src,"Root/B","int value=A.value;");
+ CodeGen code = new CodeGen(src.toString(),root.toString(),new Ary<>(new String[]{lib.toString()}),
+ "Root",null,123,true,TypeInteger.BOT).driver(CodeGen.Phase.FinalizeIR);
assertNotNull(function(code,"test").summary());
assertNotNull("Summaries alone report a potential cycle",new ClassInitDependencies(code).check());
- code.driver(CodeGen.Phase.TypeCheck);
- assertNull("The helper is outside A/B's apparent cycle",function(code,"test").summary());
- assertEquals("1",Eval2.eval(code,0));
+ try {
+ code.driver(CodeGen.Phase.TypeCheck);
+ fail("Reject the possible cycle without loading the condition helper");
+ } catch( Parser.ParseException ex ) {
+ assertTrue(ex.getMessage(),ex.getMessage().startsWith("Cyclic class initialization:"));
+ assertTrue(ex.getMessage(),ex.getMessage().contains("Root.A -> Root.B"));
+ assertTrue(ex.getMessage(),ex.getMessage().contains("Root.B -> Root.A"));
+ }
+ assertNotNull(function(code,"test").summary());
+ assertNull(code.getElf(code._compunits.get("Predicate")._obj)._nodes);
}
private static void object(Path dir, Ary<String> paths, String name, String source) {