summaryrefslogtreecommitdiff
path: root/chapter18/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-12-22 09:44:53 -0800
committerCliff Click <cliffc@acm.org>2025-01-15 15:07:30 -0800
commite58920741c38043f3f257ef088ca330893b7c84c (patch)
tree0e01a3252cec2e16c6734c78bcfc9a266a18c194 /chapter18/src/main/java/com/seaofnodes
parent8095c50f846699f7570bdea4c6517653c5795c2e (diff)
downloadSimple-e58920741c38043f3f257ef088ca330893b7c84c.tar.gz
Simple-e58920741c38043f3f257ef088ca330893b7c84c.zip
Clean up public API for nil/byte testing
Diffstat (limited to 'chapter18/src/main/java/com/seaofnodes')
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/Parser.java26
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/NotNode.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/Type.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java92
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java8
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java6
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java2
9 files changed, 63 insertions, 79 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
index f7b7d0e9..1105c2b7 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
@@ -617,7 +617,15 @@ public class Parser {
} else {
if( inferType && !_scope.inCon() )
throw errorSyntax("=expression");
- expr = t instanceof TypeMemPtr tn ? (tn._nil==3 ? NIL : con(Type.TOP)) : (t==Type.BOTTOM ? con(t) : ZERO);
+ // Initial value for uninitialized struct fields.
+ expr = t instanceof TypeMemPtr tn
+ // Nullable pointers get a NIL; not-null get a TOP which
+ // signals that they *must* be initialized in the constructor.
+ ? (tn.nullable() ? NIL : con(Type.TOP))
+ // Bottom signals type inference: they must be initialized in
+ // the constructor and that's when we'll discover the type.
+ // Otherwise, its an Integer and use 0.
+ : (t==Type.BOTTOM ? con(t) : ZERO);
}
// Lift expression, based on type
@@ -664,7 +672,7 @@ public class Parser {
fs[i-lexlen] = Field.make(v._name,v.type(),ALIAS++,v._final);
}
TypeStruct ts = s._ts = TypeStruct.make(typeName, fs);
- TYPES.put(typeName, TypeMemPtr.make((byte)2,ts));
+ TYPES.put(typeName, TypeMemPtr.make(ts));
INITS.put(typeName,s.peephole().keep());
// Done with struct/block scope
require("}");
@@ -695,15 +703,15 @@ public class Parser {
if( t0 == null && KEYWORDS.contains(tname) )
return posT(old1);
if( t0 == Type.BOTTOM || t0 == Type.TOP ) return t0; // var/val type inference
- Type t1 = t0 == null ? TypeMemPtr.make((byte)2,TypeStruct.makeFRef(tname)) :t0; // Null: assume a forward ref type
+ Type t1 = t0 == null ? TypeMemPtr.make(TypeStruct.makeFRef(tname)) :t0; // Null: assume a forward ref type
// Nest arrays and '?' as needed
Type t2 = t1;
while( true ) {
if( match("?") ) {
if( !(t2 instanceof TypeMemPtr tmp) )
throw error("Type "+t0+" cannot be null");
- if( tmp._nil==3 ) throw error("Type "+t2+" already allows null");
- t2 = tmp.makeFrom((byte)3);
+ if( tmp.nullable() ) throw error("Type "+t2+" already allows null");
+ t2 = tmp.makeNullable();
} else if( match("[]") ) {
t2 = typeAry(t2);
} else
@@ -726,7 +734,7 @@ public class Parser {
// Make an array type of t
private TypeMemPtr typeAry( Type t ) {
- if( t instanceof TypeMemPtr tmp && (tmp._nil==1|| tmp._nil==2) )
+ if( t instanceof TypeMemPtr tmp && tmp.notNull() )
throw error("Arrays of reference types must always be nullable");
String tname = "["+t.str()+"]";
Type ta = TYPES.get(tname);
@@ -734,7 +742,7 @@ public class Parser {
// Need make an array type.
TypeStruct ts = TypeStruct.makeAry(TypeInteger.BOT,ALIAS++,t,ALIAS++);
assert ts.str().equals(tname);
- TypeMemPtr tary = TypeMemPtr.make((byte)2,ts);
+ TypeMemPtr tary = TypeMemPtr.make(ts);
TYPES.put(tname,tary);
return tary;
}
@@ -756,7 +764,7 @@ public class Parser {
if( ret==null ) return posT(old);
ts.set(0,ret);
if( !match("}") ) return posT(old); // Not a function
- return TypeFunPtr.make(TypeTuple.make(ts.asAry()),match("?"));
+ return TypeFunPtr.make(match("?"),TypeTuple.make(ts.asAry()));
}
Type t1 = type();
if( t1==null ) return posT(old); // Not a function
@@ -1059,7 +1067,7 @@ public class Parser {
// Initial values for every field
for( int i = 0; i < len; i++ )
ns[2+len+i] = init.get(i+idx);
- Node nnn = new NewNode(TypeMemPtr.make((byte)2,obj), ns).peephole();
+ Node nnn = new NewNode(TypeMemPtr.make(obj), ns).peephole();
for( int i = 0; i < len; i++ )
memAlias(fs[i]._alias, new ProjNode(nnn,i+2,memName(fs[i]._alias)).peephole());
return new ProjNode(nnn,1,obj._name).peephole();
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
index 818d6352..62323031 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
@@ -49,7 +49,7 @@ public abstract class MemOpNode extends Node {
// Already an error, but better error messages come from elsewhere
if( ptr == Type.BOTTOM ) return null;
// Better be a not-nil TMP
- if( ptr instanceof TypeMemPtr tmp && tmp._nil==2 )
+ if( ptr instanceof TypeMemPtr tmp && tmp.notNull() )
return null;
return "Might be null accessing '" + _name + "'";
}
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 54defe13..cae6300e 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/NewNode.java
@@ -17,7 +17,7 @@ public class NewNode extends Node implements MultiNode {
public NewNode(TypeMemPtr ptr, Node... nodes) {
super(nodes);
- assert ptr._nil!=3;
+ assert !ptr.nullable();
_ptr = ptr;
_len = ptr._obj._fields.length;
// Control in slot 0
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/NotNode.java
index d71e0fe6..b454de66 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -22,7 +22,7 @@ public class NotNode extends Node {
Type t0 = in(1)._type;
if( t0.isHigh() ) return TypeInteger.BOOL.dual();
if( t0 == Type.NIL || t0 == TypeInteger.ZERO ) return TypeInteger.TRUE;
- if( t0 instanceof TypeNil tn && tn._nil==2 ) return TypeInteger.FALSE;
+ if( t0 instanceof TypeNil tn && tn.notNull() ) return TypeInteger.FALSE;
if( t0 instanceof TypeInteger i && (i._min > 0 || i._max < 0) ) return TypeInteger.FALSE;
return TypeInteger.BOOL;
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java
index 5104f080..9f9f688a 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java
@@ -48,7 +48,7 @@ public class Type {
public final byte _type;
public boolean is_simple() { return _type < TSIMPLE; }
- private static final String[] STRS = new String[]{"Bot","Top","Ctrl","~Ctrl","nil","~nil"};
+ private static final String[] STRS = new String[]{"Bot","Top","Ctrl","~Ctrl","null","~nil"};
protected Type(byte type) { _type = type; }
public static final Type BOTTOM = new Type( TBOT ).intern(); // ALL
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java
index 9d4e5795..0c66c20c 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java
@@ -6,113 +6,83 @@ import java.util.ArrayList;
/**
* Represents a Pointer to a function.
- *
+ * <p></p>
* Functions have argument types and a return type, making a function
* signature. Within a signature there can be many instances of functions, and
* each function is labeled with a small integer constant. A TFP can represent
* a single signature and a set of functions; the set might contain only 1
* function or the zeroth function (the null ptr).
- *
+ * <p></p>
* Functions with different signatures cannot be mixed, and will result in a
* bottom function type, which can only be null-checked.
*/
-public class TypeFunPtr extends Type {
+public class TypeFunPtr extends TypeNil {
// A TypeFunPtr is Signature and a set of functions.
public final TypeTuple _sig;
// Cheesy easy implementation for a small set; 1 bit per unique function
// within the TypeTuple. Can be upgraded to a BitSet for larger classes of
// functions.
- private final long _fidxs; // 0 bit for null, and up to 63 unique functions per signature
+ private final long _fidxs; // 64 unique functions per signature
- private TypeFunPtr(TypeTuple sig, long fidxs) {
- super(TFUNPTR);
+ private TypeFunPtr(byte nil, TypeTuple sig, long fidxs) {
+ super(TFUNPTR,nil);
assert sig != null;
_sig = sig;
_fidxs = fidxs;
}
- public static TypeFunPtr make( TypeTuple sig, long fidxs ) { return new TypeFunPtr(sig,fidxs).intern(); }
- // Make a TFP with all functions
- public static TypeFunPtr make( TypeTuple sig, boolean nil ) { return new TypeFunPtr(sig,-2|(nil ? 1 : 0)).intern(); }
+ static TypeFunPtr make( byte nil, TypeTuple sig, long fidxs ) { return new TypeFunPtr(nil,sig,fidxs).intern(); }
+ public static TypeFunPtr make( boolean nil, TypeTuple sig ) { return make((byte)(nil ? 3 : 2),sig,-1); }
+ @Override TypeFunPtr makeFrom( byte nil ) { return nil==_nil ? this : make(nil,_sig,_fidxs); }
- public static TypeFunPtr BOT = make(TypeTuple.SIGBOT,-1);
- public static TypeFunPtr TOP = BOT.dual();
- public static TypeFunPtr TEST = make(TypeTuple.SIGTEST,2);
- public static TypeFunPtr TEST0 = make(TypeTuple.SIGTEST,3);
- public static TypeFunPtr NULLPTR = make(TypeTuple.SIGTOP,1);
- public static TypeFunPtr VOIDPTR = NULLPTR.dual();
- public static void gather(ArrayList<Type> ts) { ts.add(TEST); ts.add(TEST0); ts.add(NULLPTR); ts.add(BOT); }
+ public static TypeFunPtr BOT = make((byte)3,TypeTuple.SIGBOT,-1);
+ public static TypeFunPtr TEST = make((byte)2,TypeTuple.SIGTEST,1);
+ public static TypeFunPtr TEST0 = make((byte)3,TypeTuple.SIGTEST,3);
+ public static void gather(ArrayList<Type> ts) { ts.add(TEST); ts.add(TEST0); ts.add(BOT); }
@Override
Type xmeet(Type t) {
TypeFunPtr that = (TypeFunPtr) t;
- return TypeFunPtr.make((TypeTuple)_sig.meet(that._sig), _fidxs | that._fidxs);
+ return TypeFunPtr.make(xmeet0(that),(TypeTuple)_sig.meet(that._sig), _fidxs | that._fidxs);
}
@Override
- public TypeFunPtr dual() { return TypeFunPtr.make(_sig.dual(), ~_fidxs); }
+ public TypeFunPtr dual() { return TypeFunPtr.make(dual0(), _sig.dual(), ~_fidxs); }
+
+ // RHS is NIL
+ @Override public Type meet0() { return _nil==3 ? this : make((byte)3,_sig,_fidxs); }
@Override public TypeFunPtr glb() { throw Utils.TODO(); }
- // Is forward-reference
- @Override public boolean isFRef() { return false; }
- @Override public boolean isHigh() { return this==TOP; }
@Override public boolean isConstant() { return Long.bitCount(_fidxs)==1; }
- @Override public boolean isHighOrConst() { return Long.bitCount(_fidxs)<=1; }
@Override public int log_size() { return 2; } // (1<<2)==4-byte pointers
@Override
- int hash() { return Utils.fold(_sig.hashCode() ^ _fidxs); }
+ int hash() { return Utils.fold(_sig.hashCode() ^ _fidxs ^ super.hash()); }
@Override
boolean eq(Type t) {
TypeFunPtr ptr = (TypeFunPtr)t; // Invariant
- return _sig == ptr._sig && _fidxs == ptr._fidxs;
+ return _sig == ptr._sig && _fidxs == ptr._fidxs && super.eq(ptr);
}
- @Override public String str() {
- if( this== NULLPTR) return "null";
- if( this== VOIDPTR) return "*void";
- return print(new SB()).toString();
- }
-
- // [void,name,MANY]*[,?]
- @Override public SB print(SB sb) {
- if( this== NULLPTR) return sb.p("null");
- if( this== VOIDPTR) return sb.p("*void");
- sb.p("{ ");
- for( int i=1; i<_sig._types.length; i++ )
- _sig._types[i].print(sb).p(" ");
- _sig._types[0].print(sb.p("-> "));
- sb.p(" #");
- long fidxs = _fidxs&-2; // Strip off the null flag bit
- String fidx = fidxs==0 ? ""
- : Long.bitCount(fidxs) == 1 ? ""+Long.numberOfTrailingZeros(fidxs)
- : fidxs == -2 ? "ALL"
- : "b"+Long.toBinaryString(fidxs); // Just some function bits
- sb.p(fidx).p("}");
- if( (_fidxs&1)==1 ) sb.p("?");
- return sb;
- }
-
- @Override public SB gprint(SB sb) {
- if( this== NULLPTR) return sb.p("null");
- if( this== VOIDPTR) return sb.p("*void");
- sb.p("{ ");
+ @Override public String str() { return print(new SB()).toString(); }
+ @Override public SB print(SB sb) { return _print(sb,false); }
+ @Override public SB gprint(SB sb) { return _print(sb,true ); }
+ private static SB _print(SB sb, boolean g, Type t) { return g ? t.gprint(sb) : t.print(sb); }
+ private SB _print(SB sb, boolean g) {
+ sb.p(x()).p("{ ");
for( int i=1; i<_sig._types.length; i++ )
- _sig._types[i].gprint(sb).p(" ");
- _sig._types[0].gprint(sb.p("-> "));
- sb.p(" #");
- long fidxs = _fidxs&-2; // Strip off the null flag bit
+ _print(sb,g,_sig._types[i]).p(" ");
+ _print(sb.p("-> "),g,_sig._types[0]).p(" #");
+ long fidxs = isHigh() ? ~_fidxs : _fidxs;
String fidx = fidxs==0 ? ""
: Long.bitCount(fidxs) == 1 ? ""+Long.numberOfTrailingZeros(fidxs)
- : fidxs == -2 ? "ALL"
+ : fidxs == -1 ? "ALL"
: "b"+Long.toBinaryString(fidxs); // Just some function bits
- sb.p(fidx).p("}");
- if( (_fidxs&1)==1 ) sb.p("?");
- return sb;
+ return sb.p(fidx).p("}").p(q());
}
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
index d17cfd39..6dda9c39 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
@@ -31,10 +31,12 @@ public class TypeMemPtr extends TypeNil {
assert obj!=null;
_obj = obj;
}
- public static TypeMemPtr make(byte nil, TypeStruct obj) { return new TypeMemPtr(nil, obj).intern(); }
- public static TypeMemPtr make(TypeStruct obj) { return make((byte)3, obj); }
+ static TypeMemPtr make(byte nil, TypeStruct obj) { return new TypeMemPtr(nil, obj).intern(); }
+ public static TypeMemPtr makeNullable(TypeStruct obj) { return make((byte)3, obj); }
+ public static TypeMemPtr make(TypeStruct obj) { return new TypeMemPtr((byte)2, obj).intern(); }
public TypeMemPtr makeFrom(TypeStruct obj) { return obj==_obj ? this : make(_nil, obj); }
- @Override public TypeMemPtr makeFrom(byte nil) { return nil==_nil ? this : make(nil,_obj); }
+ public TypeMemPtr makeNullable() { return makeFrom((byte)3); }
+ @Override TypeMemPtr makeFrom(byte nil) { return nil==_nil ? this : make(nil,_obj); }
@Override public TypeMemPtr makeRO() { return makeFrom(_obj.makeRO()); }
@Override public boolean isFinal() { return _obj.isFinal(); }
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java
index d8003d50..03c67ce9 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java
@@ -12,7 +12,7 @@ public abstract class TypeNil extends Type {
// 1 = high-subclass no nil
// 2 = low -subclass no nil
// 3 = low -subclass also nil
- public final byte _nil;
+ final byte _nil;
TypeNil(byte t, byte nil ) { super(t); _nil = nil; }
@@ -48,6 +48,10 @@ public abstract class TypeNil extends Type {
@Override public boolean isConstant () { return false; }
@Override public boolean isHighOrConst() { return isHigh() || isConstant(); }
+
+ public boolean notNull() { return _nil==1 || _nil==2; }
+ public boolean nullable() { return _nil==3; }
+
final String q() { return _nil == 1 || _nil == 2 ? "" : "?"; }
final String x() { return isHigh() ? "~" : ""; }
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
index 35bbe36c..ee206579 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
@@ -49,7 +49,7 @@ public class TypeStruct extends Type {
// Array
public static TypeStruct makeAry(TypeInteger len, int lenAlias, Type body, int bodyAlias) {
- assert body instanceof TypeInteger || (body instanceof TypeNil tn && tn._nil==3);
+ assert body instanceof TypeInteger || (body instanceof TypeNil tn && tn.nullable());
return make("[" + body.str() + "]",
Field.make("#" ,len , lenAlias,true ),
Field.make("[]",body,bodyAlias,false));