summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-10-01 16:35:54 -0700
committerCliff Click <cliffc@acm.org>2024-10-06 08:56:22 -0700
commit5282ad9efea9b7f58ba293fb1e1d64a4815ceaac (patch)
treea6f8529a3b7ae8d998ddb2c5da2cdcce4b9f567f
parent240e150400eebcb86e55c56dab2c9fe4341352f2 (diff)
downloadSimple-5282ad9efea9b7f58ba293fb1e1d64a4815ceaac.tar.gz
Simple-5282ad9efea9b7f58ba293fb1e1d64a4815ceaac.zip
Switch array syntax again
`new u8[]?[4]` Always need a `?` since inner arrays can be null. Length given for the outermost array.
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/Parser.java80
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/type/TypeStruct.java5
2 files changed, 49 insertions, 36 deletions
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java
index e0077102..ab0fe427 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java
@@ -230,7 +230,8 @@ public class Parser {
if (_xScopes.size() > 1) throw errorSyntax("struct declarations can only appear in top level scope");
String typeName = requireId();
Type t = TYPES.get(typeName);
- if( t!=null && !(t instanceof TypeStruct ts && ts._fields==null) ) throw errorSyntax("struct '" + typeName + "' cannot be redefined");
+ if( t!=null && !(t instanceof TypeMemPtr tmp && tmp._obj._fields==null) )
+ throw errorSyntax("struct '" + typeName + "' cannot be redefined");
// Parse a collection of fields
ArrayList<Field> fields = new ArrayList<>();
require("{");
@@ -242,7 +243,7 @@ public class Parser {
require("}");
// Build and install the TypeStruct
TypeStruct ts = TypeStruct.make(typeName, fields.toArray(new Field[fields.size()]));
- TYPES.put(typeName, ts);
+ TYPES.put(typeName, TypeMemPtr.make(ts));
START.addMemProj(ts, _scope); // Insert memory edges
return parseStatement();
}
@@ -473,7 +474,7 @@ public class Parser {
// Auto-deepen forward ref types
Type e = expr._type;
if( e instanceof TypeMemPtr tmp && tmp._obj._fields==null )
- e = tmp.makeFrom((TypeStruct)TYPES.get(tmp._obj._name));
+ e = TYPES.get(tmp._obj._name);
// Type is sane
if( !e.isa(t) )
throw error("Type " + e.str() + " is not of declared type " + t.str());
@@ -490,15 +491,26 @@ public class Parser {
if( tname==null ) return null;
// Convert the type name to a type.
Type t0 = TYPES.get(tname);
- Type t1 = t0 == null ? TypeStruct.make(tname) : t0; // Null: assume a forward ref type
- // Nest arrays as needed
- while( match("[]") )
- t1 = typeAry(t1);
- // Handle trailing '?' for nullable
- Type t2 = t1 instanceof TypeStruct obj ? TypeMemPtr.make(obj,match("?")) : t1;
+ Type t1 = t0 == null ? TypeMemPtr.make(TypeStruct.make(tname)) : t0; // Null: assume a forward ref type
+ // Nest arrays and '?' as needed
+ while( true ) {
+ assert !(t1 instanceof TypeStruct);
+ if( match("?") ) {
+ if( !(t1 instanceof TypeMemPtr tmp) )
+ throw error("Type "+t0+" cannot be null");
+ if( tmp._nil ) throw error("Type "+t1+" already allows null");
+ t1 = TypeMemPtr.make(tmp._obj,true);
+ continue;
+ }
+ if( match("[]") ) {
+ t1 = typeAry(t1);
+ continue;
+ }
+ break;
+ }
// Check no forward ref
- if( t0 != null ) return t2;
+ if( t0 != null ) return t1;
// Check valid forward ref, after parsing all the type extra bits.
// Cannot check earlier, because cannot find required 'id' until after "[]?" syntax
int old2 = _lexer._position;
@@ -510,22 +522,22 @@ public class Parser {
}
// Yes a forward ref, so declare it
TYPES.put(tname,t1);
- return t2;
+ return t1;
}
// Make an array type of t
- private TypeStruct typeAry( Type t ) {
- assert !(t instanceof TypeMemPtr); // Arrays of references, not inlined structs
+ private TypeMemPtr typeAry( Type t ) {
+ if( t instanceof TypeMemPtr tmp && !tmp._nil )
+ throw error("Arrays of reference types must always be nullable");
String tname = t.str()+"[]";
Type ta = TYPES.get(tname);
- if( ta != null ) return (TypeStruct)ta;
- // Need make an array type. If the base type is a struct, wrap it.
- if( t instanceof TypeStruct obj )
- t = TypeMemPtr.make(obj,true);
+ if( ta != null ) return (TypeMemPtr)ta;
+ // Need make an array type.
TypeStruct ts = TypeStruct.makeAry(TypeInteger.BOT,ALIAS++,t,ALIAS++);
- TYPES.put(tname,ts);
+ TypeMemPtr tary = TypeMemPtr.make(ts);
+ TYPES.put(tname,tary);
START.addMemProj(ts, _scope); // Insert memory alias edges
- return ts;
+ return tary;
}
@@ -684,24 +696,25 @@ public class Parser {
if( matchx("false") ) return ZERO;
if( matchx("null" ) ) return new ConstantNode(TypeMemPtr.NULLPTR).peephole();
if( matchx("new") ) {
- String typeName = _lexer.matchId();
- if( typeName==null ) throw error("Expected a type");
- Type t = TYPES.get(typeName);
- if( t instanceof TypeStruct obj && obj._fields==null )
- throw error("Unknown struct type '" + typeName + "'");
- if( t!=null && match("[") ) {
+ Type t = type();
+ if( t==null ) throw error("Expected a type");
+ if( match("[") ) {
Node len = parseExpression().keep();
if( !(len._type instanceof TypeInteger) )
throw error("Cannot allocate an array with length "+len._type);
require("]");
- TypeStruct ary = typeAry(t);
- while( match("[]") )
- ary = typeAry(ary);
- return newArray(ary,len);
- } else if( t instanceof TypeStruct obj ) {
+ TypeMemPtr tmp = typeAry(t);
+ return newArray(tmp._obj,len);
+ }
+ if( t instanceof TypeMemPtr tmp ) {
+ TypeStruct obj = tmp._obj;
+ if( obj._fields==null )
+ throw error("Unknown struct type '" + obj._name + "'");
+ if( obj.isAry() )
+ throw Utils.TODO(); // Missing array length
return newStruct(obj,con(obj.offset(obj._fields.length)));
}
- throw error("Cannot allocate a "+typeName);
+ throw error("Cannot allocate a "+t.str());
}
String name = _lexer.matchId();
if( name == null) throw errorSyntax("an identifier or expression");
@@ -767,8 +780,9 @@ public class Parser {
if( ptr == TypeMemPtr.TOP ) throw error("Accessing field '" + name + "' from null");
if( ptr._obj == null ) throw error("Accessing unknown field '" + name + "' from '" + ptr.str() + "'");
// Sanity check field name for existing
- TypeStruct base = (TypeStruct)TYPES.get(ptr._obj._name);
- if( base == null ) throw error("Accessing unknown field '" + name + "' from '" + ptr.str() + "'");
+ TypeMemPtr tmp = (TypeMemPtr)TYPES.get(ptr._obj._name);
+ if( tmp == null ) throw error("Accessing unknown field '" + name + "' from '" + ptr.str() + "'");
+ TypeStruct base = tmp._obj;
int fidx = base.find(name);
if( fidx == -1 ) throw error("Accessing unknown field '" + name + "' from '" + ptr.str() + "'");
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter15/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
index b3a8f867..abfb8a67 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
@@ -40,9 +40,8 @@ public class TypeStruct extends Type {
// Array
public static TypeStruct makeAry(TypeInteger len, int lenAlias, Type body, int bodyAlias) {
- Type t = body;
- if( t instanceof TypeMemPtr tmp ) { assert tmp._nil; t = tmp._obj; }
- return make(t.str() + "[]",
+ assert !(body instanceof TypeMemPtr tmp && !tmp._nil);
+ return make(body.str() + "[]",
Field.make("#" , lenAlias,len ),
Field.make("[]",bodyAlias,body));
}