diff options
Diffstat (limited to 'chapter18/src')
6 files changed, 40 insertions, 15 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index d888f17e..3f4484f5 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -765,13 +765,14 @@ public class Parser { int lexlen = _scope._lexSize.last(); int varlen = _scope._vars._len; StructNode s = new StructNode(); - Field[] fs = new Field[varlen-lexlen]; + Ary<Field> fs = new Ary<>(Field.class); for( int i=lexlen; i<varlen; i++ ) { s.addDef(_scope.in(i)); Var v = _scope._vars.at(i); - fs[i-lexlen] = Field.make(v._name,v.type(),ALIAS++,v._final); + if( !v.isFRef() ) // Promote to outer scope, not defined here + fs.push(Field.make(v._name,v.type(),ALIAS++,v._final)); } - TypeStruct ts = s._ts = TypeStruct.make(typeName, fs); + TypeStruct ts = s._ts = TypeStruct.make(typeName, fs.asAry()); TYPES.put(typeName, TypeMemPtr.make(ts)); INITS.put(typeName,s.peephole().keep()); // Done with struct/block scope diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Var.java b/chapter18/src/main/java/com/seaofnodes/simple/Var.java index 6a8fe86d..e71d7ef2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Var.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Var.java @@ -1,6 +1,5 @@ package com.seaofnodes.simple; -import com.seaofnodes.simple.node.FRefNode; import com.seaofnodes.simple.type.*; @@ -14,13 +13,18 @@ public class Var { private Type _type; // Declared type public boolean _final; // Final field public Parser.Lexer _loc; // Source location + public boolean _fref; // Forward ref - public Var(int idx, String name, Type type, boolean xfinal, Parser.Lexer loc) { + public Var(int idx, String name, Type type, boolean xfinal, Parser.Lexer loc ) { + this(idx,name,type,xfinal,loc,false); + } + public Var(int idx, String name, Type type, boolean xfinal, Parser.Lexer loc, boolean fref) { _idx = idx; _name = name; _type = type; _final = xfinal; _loc = loc; + _fref = fref; } public Type type() { if( !_type.isFRef() ) return _type; @@ -33,16 +37,16 @@ public class Var { return t instanceof TypeMemPtr ? t : t.glb(); } - // Forward reference variables (not types) can only be a bottom - // function pointer. - public boolean isFRef() { return type()== FRefNode.FREF_TYPE; } + // Forward reference variables (not types) must be BOTTOM and + // distinct from inferred variables + public boolean isFRef() { return _fref; } - public boolean defFRef( Type type, boolean xfinal, Parser.Lexer loc ) { + public void defFRef( Type type, boolean xfinal, Parser.Lexer loc ) { assert isFRef() && xfinal; _type = type; _final = true; _loc = loc; - return true; + _fref = false; } @Override public String toString() { diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java index cae6300e..34d695f4 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java @@ -26,7 +26,7 @@ public class NewNode extends Node implements MultiNode { assert nodes[1]._type instanceof TypeInteger || nodes[1]._type==Type.NIL; for( int i=0; i<_len; i++ ) { // Memory slices for all fields. - assert nodes[2+ i]._type.isa(TypeMem.BOT); + assert nodes[2+ i]._type.isa(TypeMem.BOT); // Value slices for all fields. assert nodes[2 + _len + i]._type != null; } @@ -59,7 +59,7 @@ public class NewNode extends Node implements MultiNode { ts[1] = _ptr; for( int i=0; i<fs.length; i++ ) { Type mt = in(i+2)._type; - TypeMem mem = mt==Type.TOP ? TypeMem.TOP : (TypeMem)in(i+2)._type; + TypeMem mem = mt==Type.TOP ? TypeMem.TOP : (TypeMem)mt; Type tfld = in(2+_len+i)._type.meet(mem._t); ts[i+2] = TypeMem.make(fs[i]._alias,tfld); } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index 408c8195..5620a2d2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -156,7 +156,7 @@ public class ScopeNode extends MemMergeNode { setDef(n._idx,fref.addDef(init)); // Set FRef to defined; tell parser also } } - Var v = new Var(nIns(),name,declaredType,xfinal,loc); + Var v = new Var(nIns(),name,declaredType,xfinal,loc,init==Parser.XCTRL); _vars.add(v); // Creating a forward reference if( init==Parser.XCTRL ) diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java index ccabadb4..ee6832ad 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -93,8 +93,8 @@ public class StoreNode extends MemOpNode { err()==null ) { nnn.setDef(nnn.findAlias(_alias),val()); // Must retype the NewNode - nnn ._type = nnn. compute(); - mem()._type = mem().compute(); + nnn .setType(nnn .compute()); + mem().setType(mem().compute()); return mem(); } diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 9e74ce6d..39edb352 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -225,6 +225,26 @@ return f(); catch( Exception e ) { assertEquals("Expecting 2 arguments, but found 0",e.getMessage()); } } + + @Test + public void testErr4() { + CodeGen code = new CodeGen( +""" +struct S { + {int} f = { -> x(); return 0; }; // Do not let fref x be a field +}; +val x = { -> return 1; }; +S? s = null; +for(;;) { + if (s) return s.x; +} +"""); + try { code.parse().opto().typeCheck(); fail(); } + catch( Exception e ) { assertEquals("Accessing unknown field 'x' from '*S'",e.getMessage()); } + } + + + // Mutual recursion. Fails without SCCP to lift the recursive return types. @Ignore @Test public void testFcnMutRec() { |
