summaryrefslogtreecommitdiff
path: root/chapter28b
diff options
context:
space:
mode:
Diffstat (limited to 'chapter28b')
-rw-r--r--chapter28b/src/main/java/com/seaofnodes/simple/Parser.java6
-rw-r--r--chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java8
-rw-r--r--chapter28b/src/main/java/com/seaofnodes/simple/codegen/ParseAll.java10
-rw-r--r--chapter28b/src/test/java/com/seaofnodes/simple/IncrementalBuildTest.java15
-rw-r--r--chapter28b/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java16
5 files changed, 40 insertions, 15 deletions
diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java b/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java
index b9cd9658..8410bf5c 100644
--- a/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java
@@ -101,6 +101,9 @@ public class Parser {
ScopeNode _continueScope; // Merge all the while-continues here
ScopeNode _returnScope; // Merge all the function exits here
Ary<FRefNode> _frefs; // Forward refs created during this parse
+ // Layouts needed by field accesses in this source file. Resolve after
+ // parsing, since a later local struct declaration can satisfy the use.
+ public final LinkedHashSet<String> _requiredTypes = new LinkedHashSet<>();
TypeStruct _ctorOpenStruct; // Open struct being initialized by an allocation constructor block.
// Constructor exit types survive scope teardown until all fields are known.
// A null entry denotes a constructor with no returning path.
@@ -171,6 +174,7 @@ public class Parser {
assert _frefs == null;
_lexer = new Lexer(ref);
_frefs = new Ary<>(FRefNode.class);
+ _requiredTypes.clear();
// Starting Scope has control, memory, initial arguments
_scope = new ScopeNode();
_scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer);
@@ -2751,6 +2755,8 @@ public class Parser {
}
// Field offset for an unknown type
public Node fldoff( Node n, String name ) {
+ if( n._type instanceof TypeMemPtr ptr && ptr._obj._fref )
+ _requiredTypes.add(ptr._obj._name);
return new FldOffNode(n,name,loc()).peephole();
}
public Node peep( Node n ) {
diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
index c2cd657f..561fdece 100644
--- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
+++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
@@ -625,14 +625,6 @@ public class CodeGen {
// Last check for bad programs
public CodeGen typeCheck() { return phase(Phase.TypeCheck, _phase==Phase.FinalizeIR, () -> TypeCheck.run(this)); }
- public static TypeStruct requiredStruct(Node n) {
- // CNC: remove? cleanup?
- if( n instanceof NewNode alloc ) return alloc._ts;
- if( n instanceof ConFldOffNode off ) return off._ts;
- if( n instanceof FldOffNode off && off.in(0)._type instanceof TypeMemPtr ptr ) return ptr._obj;
- return null;
- }
-
// ---------------------------
// TypeCheck queued surviving CLInits during its existing error walk.
public CodeGen lower() {
diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ParseAll.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ParseAll.java
index 10b8fd9b..1d9731fc 100644
--- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ParseAll.java
+++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ParseAll.java
@@ -198,13 +198,9 @@ public abstract class ParseAll {
}
private static void addRequiredTypes(CodeGen code, CompUnit cunit) {
- LinkedHashSet<String> required = new LinkedHashSet<>();
- code._stop.walk(n -> {
- TypeStruct ts = CodeGen.requiredStruct(n);
- if( ts!=null && ts._fref ) required.add(ts._name);
- return null;
- });
- for( String typeName : required ) {
+ for( String typeName : code.P._requiredTypes ) {
+ // A forward use can have been resolved later in this source file.
+ if( Parser.TYPES.get(typeName) instanceof TypeStruct ts && !ts._fref ) continue;
try {
CompUnit xcunit = findRequiredType(code,cunit,typeName);
if( xcunit != null )
diff --git a/chapter28b/src/test/java/com/seaofnodes/simple/IncrementalBuildTest.java b/chapter28b/src/test/java/com/seaofnodes/simple/IncrementalBuildTest.java
index 3c53c004..d8f7ef34 100644
--- a/chapter28b/src/test/java/com/seaofnodes/simple/IncrementalBuildTest.java
+++ b/chapter28b/src/test/java/com/seaofnodes/simple/IncrementalBuildTest.java
@@ -10,6 +10,21 @@ import org.junit.Test;
import static org.junit.Assert.*;
public class IncrementalBuildTest {
+ @Test public void testRequiredTypesBelongToTheirSource() throws Exception {
+ Path base = Path.of("build/objs/incremental");
+ Files.createDirectories(base);
+ Path root = Files.createTempDirectory(base,"required-types-");
+ Path src = Files.createDirectory(root.resolve("src")), obj = Files.createDirectory(root.resolve("obj"));
+ write(src,"App","val marker = 0;",1000);
+ write(src,"App/Main","return A.x+C.y;",1000);
+ write(src,"App/A","int x = 0; val readB = { B b -> b.x; };",1000);
+ write(src,"App/B","int x = 0;",1000);
+ write(src,"App/C","int y = 0;",1000);
+ CodeGen code = new CodeGen(src.toString(),obj.toString(),null,"App/Main",null,123,true,TypeInteger.BOT)
+ .parse();
+ ParseAllTestSupport.checkRequiredTypes(code);
+ }
+
@Test public void testTransitiveSourceChange() throws Exception {
Path base=Path.of("build/objs/incremental");
Files.createDirectories(base);
diff --git a/chapter28b/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java b/chapter28b/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java
new file mode 100644
index 00000000..2ce97a8e
--- /dev/null
+++ b/chapter28b/src/test/java/com/seaofnodes/simple/codegen/ParseAllTestSupport.java
@@ -0,0 +1,16 @@
+package com.seaofnodes.simple.codegen;
+
+import static org.junit.Assert.*;
+
+public class ParseAllTestSupport {
+ public static void checkRequiredTypes(CodeGen code) {
+ CompUnit a = code._compunits.get("App/A");
+ CompUnit b = code._compunits.get("App/B");
+ CompUnit c = code._compunits.get("App/C");
+ assertNotNull(b);
+ assertTrue(a._deps.find(b)!=-1);
+ // C was parsed after A, while B's layout was still unresolved.
+ // Only A used that layout; C must not inherit A's build dependency.
+ assertNull(c._deps);
+ }
+}