summaryrefslogtreecommitdiff
path: root/chapter17/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'chapter17/src/main/java')
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/Parser.java16
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/node/MinusNode.java5
2 files changed, 18 insertions, 3 deletions
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
index abd70f89..fac012a4 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
@@ -141,6 +141,8 @@ public class Parser {
put("u16" ,TypeInteger.U16);
put("u32" ,TypeInteger.U32);
put("u8" ,TypeInteger.U8 );
+ put("val" ,Type.TOP); // Marker type, indicates type inference
+ put("var" ,Type.BOTTOM); // Marker type, indicates type inference
}};
}
@@ -422,6 +424,8 @@ public class Parser {
? Type.TOP
// Else takes the default
: t.makeInit();
+ // "var" and "val" require an expression to infer
+ if( init == null ) throw errorSyntax("expression");
expr = con(init);
} else if( !match("=") ) { // Something else
@@ -453,6 +457,9 @@ public class Parser {
Type e = expr._type;
if( e instanceof TypeMemPtr tmp && tmp._obj._fields==null )
e = TYPES.get(tmp._obj._name);
+ // "var" and "val" use TOP and BOTTOM - but just take the expression type.
+ if( t==Type.TOP || t==Type.BOTTOM )
+ t = expr._type.glb();
// Type is sane
if( !e.isa(t) )
throw error("Type " + e.str() + " is not of declared type " + t.str());
@@ -468,7 +475,9 @@ public class Parser {
/** Parse final: [!]asgn
*/
private Node parseFinal(Type t) {
- boolean xfinal = t!=null && match("!");
+ // TOP is a "val" marker - uses type inference for a "value", i.e. a final.
+ // BOT is a "var" marker - uses type inference for a "variable", i.e. not final
+ boolean xfinal = t==Type.TOP || (t!=null && match("!"));
return parseAsgn(t,xfinal);
}
@@ -761,8 +770,11 @@ public class Parser {
// Expect an identifier now
ScopeMinNode.Var n = requireLookupId("an identifier or expression");
Node rvalue = _scope.in(n).keep();
- if( matchx("++") || matchx("--") )
+ if( matchx("++") || matchx("--") ) {
+ if( n._final )
+ throw error("Cannot reassign final '"+n._name+"'");
_scope.update(n,new AddNode(rvalue,con( _lexer.peek(-1)=='+' ? 1 : -1)).peephole());
+ }
return rvalue.unkeep();
}
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter17/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index 8a2c9406..760a4274 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -2,6 +2,7 @@ package com.seaofnodes.simple.node;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.Utils;
import java.util.BitSet;
@@ -22,7 +23,9 @@ public class MinusNode extends Node {
public Type compute() {
if( in(1)._type instanceof TypeInteger i0 ) {
if( i0.isHigh() ) return TypeInteger.TOP;
- return i0==TypeInteger.BOT ? TypeInteger.BOT : TypeInteger.make(-i0._max,-i0._min);
+ if( i0==TypeInteger.BOT || i0._min == Long.MIN_VALUE || i0._max == Long.MIN_VALUE )
+ return TypeInteger.BOT;
+ return TypeInteger.make(-i0._max,-i0._min);
}
return TypeInteger.TOP.meet(in(1)._type);
}