summaryrefslogtreecommitdiff
path: root/chapter13/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-03 14:03:48 -0700
committerCliff Click <cliffc@acm.org>2026-10-03 14:03:48 -0700
commit22df891893d30e9906d0b14fc3ae5d8e67d500b2 (patch)
tree2bda142f92febc8b26f1cabd4bb0c46d1864f34b /chapter13/src/main/java/com/seaofnodes
parentc3958e34c0de21df52e57e47e4f47ffe6464f138 (diff)
downloadSimple-22df891893d30e9906d0b14fc3ae5d8e67d500b2.tar.gz
Simple-22df891893d30e9906d0b14fc3ae5d8e67d500b2.zip
Chapter renumber, and split ch 17
Renumber chapters 10a, 10b, 11, 12, 13, 14 -> 10, 11, 13, 12, [11,14]. Split ch 17 into a 17a and 17b; shuffle around im/mutable syntax to be consistent, and present it more slowly. THe new immutable syntax is pushed through all later chapters
Diffstat (limited to 'chapter13/src/main/java/com/seaofnodes')
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/Parser.java48
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java37
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java1
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java36
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java39
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java1
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java30
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java1
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java44
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java1
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/Node.java21
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java6
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java37
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java1
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java25
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java2
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/type/Type.java29
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/type/TypeFloat.java101
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/type/TypeStruct.java16
19 files changed, 49 insertions, 427 deletions
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java
index cc668f18..32a85173 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java
@@ -68,7 +68,6 @@ public class Parser {
add("continue");
add("else");
add("false");
- add("flt");
add("if");
add("int");
add("new");
@@ -98,7 +97,6 @@ public class Parser {
IterPeeps.reset();
TYPES.clear();
TYPES.put("int",TypeInteger.BOT);
- TYPES.put("flt",TypeFloat .BOT);
SCHEDULED = false;
_lexer = new Lexer(source);
_scope = new ScopeNode();
@@ -437,9 +435,6 @@ public class Parser {
throw error("Undefined name '" + name + "'");
t = _scope.lookupDeclaredType(name);
}
- // Auto-widen int to float
- if( expr._type instanceof TypeInteger && t instanceof TypeFloat )
- expr = new ToFloatNode(expr).peephole();
// Auto-deepen forward ref types
Type e = expr._type;
if( e instanceof TypeMemPtr tmp && tmp._obj._fields==null )
@@ -506,7 +501,7 @@ public class Parser {
else break;
// Peepholes can fire, but lhs is already "hooked", kept alive
lhs.setDef(idx,parseAddition());
- lhs = lhs.widen().peephole();
+ lhs = lhs.peephole();
if( negate ) // Extra negate for !=
lhs = new NotNode(lhs).peephole();
}
@@ -529,7 +524,7 @@ public class Parser {
else if( match("-") ) lhs = new SubNode(lhs,null);
else break;
lhs.setDef(2,parseMultiplication());
- lhs = lhs.widen().peephole();
+ lhs = lhs.peephole();
}
return lhs;
}
@@ -550,7 +545,7 @@ public class Parser {
else if( match("/") ) lhs = new DivNode(lhs,null);
else break;
lhs.setDef(2,parseUnary());
- lhs = lhs.widen().peephole();
+ lhs = lhs.peephole();
}
return lhs;
}
@@ -564,7 +559,7 @@ public class Parser {
* @return a unary expression {@link Node}, never {@code null}
*/
private Node parseUnary() {
- if (match("-")) return new MinusNode(parseUnary()).widen().peephole();
+ if (match("-")) return new MinusNode(parseUnary()).peephole();
if (match("!")) return new NotNode(parseUnary()).peephole();
return parsePostfix(parsePrimary());
}
@@ -663,7 +658,6 @@ public class Parser {
*
* <pre>
* integerLiteral: [1-9][0-9]* | [0]
- * floatLiteral: [digits].[digits]?[e [digits]]?
* </pre>
*/
private ConstantNode parseLiteral() {
@@ -821,37 +815,19 @@ public class Parser {
return String.valueOf(peek());
}
-
+ boolean isNumber() {return isNumber(peek());}
boolean isNumber(char ch) {return Character.isDigit(ch);}
- // Return a constant Type, either TypeInteger or TypeFloat
private Type parseNumber() {
- int old = _position;
- int len = isLongOrDouble();
- if( len > 0 ) {
- if( len > 1 && _input[old]=='0' )
- throw error("Syntax error: integer values cannot start with '0'");
- return TypeInteger.constant(Long.parseLong(new String(_input,old,len)));
- }
- return TypeFloat.constant(Double.parseDouble(new String(_input,old,-len)));
+ String snum = parseNumberString();
+ if (snum.length() > 1 && snum.charAt(0) == '0')
+ throw error("Syntax error: integer values cannot start with '0'");
+ return TypeInteger.constant(Long.parseLong(snum));
}
private String parseNumberString() {
- int old = _position;
- int len = Math.abs(isLongOrDouble());
- _position += len;
- return new String(_input,old,len);
- }
-
- // Return +len that ends a long
- // Return -len that ends a double
- private int isLongOrDouble() {
- int old = _position;
- char c;
- while( Character.isDigit(c=nextChar()) ) ;
- if( !(c=='e' || c=='.') )
- return --_position - old;
- while( Character.isDigit(c=nextChar()) || c=='e' || c=='.' ) ;
- return -(--_position - old);
+ int start = _position;
+ while (isNumber(nextChar())) ;
+ return new String(_input, start, --_position - start);
}
// First letter of an identifier
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java
deleted file mode 100644
index fd713156..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/AddFNode.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.seaofnodes.simple.node;
-
-
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
-
-
-public class AddFNode extends Node {
- public AddFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
-
- @Override public String label() { return "AddF"; }
-
- @Override protected String format() { return "(%1+%2)"; }
-
- @Override
- public Type compute() {
- if (in(1)._type instanceof TypeFloat i0 &&
- in(2)._type instanceof TypeFloat i1) {
- if (i0.isConstant() && i1.isConstant())
- return TypeFloat.constant(i0.value()+i1.value());
- }
- return in(1)._type.meet(in(2)._type);
- }
-
- @Override
- public Node idealize() {
- Node lhs = in(1);
- Type t2 = in(2)._type;
-
- // Add of 0.
- if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==0 )
- return lhs;
-
- return null;
- }
- @Override Node copy(Node lhs, Node rhs) { return new AddFNode(lhs,rhs); }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java
index 94fee330..eb7e2793 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -169,7 +169,6 @@ public class AddNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs); }
- @Override Node copyF() { return new AddFNode(null,null); }
@Override public String err() {
if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '"+label()+"' " + in(1)._type;
if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '"+label()+"' " + in(2)._type;
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index e515a5f1..63452dba 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -2,11 +2,8 @@ package com.seaofnodes.simple.node;
import com.seaofnodes.print.ExprPrinter;
-import com.seaofnodes.simple.Parser;
-import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
-import com.seaofnodes.simple.type.TypeFloat;
import com.seaofnodes.simple.type.TypeMemPtr;
@@ -27,21 +24,19 @@ abstract public class BoolNode extends Node {
@Override
public Type compute() {
- if( in(1)._type instanceof TypeInteger i0 &&
- in(2)._type instanceof TypeInteger i1 ) {
- if (i0.isConstant() && i1.isConstant())
- return TypeInteger.constant(doOp(i0.value(), i1.value()) ? 1 : 0);
- }
- if( in(1)._type instanceof TypeFloat i0 &&
- in(2)._type instanceof TypeFloat i1 ) {
+ Type t1 = in(1)._type, t2 = in(2)._type;
+ if( t1==Type.TOP || t1==TypeInteger.TOP ||
+ t2==Type.TOP || t2==TypeInteger.TOP )
+ return TypeInteger.TOP;
+ if( t1 instanceof TypeInteger i0 &&
+ t2 instanceof TypeInteger i1 ) {
if (i0.isConstant() && i1.isConstant())
return TypeInteger.constant(doOp(i0.value(), i1.value()) ? 1 : 0);
}
return TypeInteger.BOT;
}
- boolean doOp(long lhs, long rhs) { throw Utils.TODO(); }
- boolean doOp(double lhs, double rhs) { throw Utils.TODO(); }
+ abstract boolean doOp(long lhs, long rhs);
@Override
public Node idealize() {
@@ -53,9 +48,11 @@ abstract public class BoolNode extends Node {
if( this instanceof EQ ) {
if( !(in(2) instanceof ConstantNode) ) {
// con==noncon becomes noncon==con
- if( in(1) instanceof ConstantNode || in(1)._nid > in(2)._nid )
+ if( in(1) instanceof ConstantNode )
+ return new EQ(in(2),in(1));
// Equals sorts by NID otherwise: non.high == non.low becomes non.low == non.high
- return in(1)._type instanceof TypeFloat ? new EQF(in(2),in(1)) : new EQ(in(2),in(1));
+ else if( in(1)._nid > in(2)._nid )
+ return new EQ(in(2),in(1));
}
// Equals X==0 becomes a !X
if( (in(2)._type == TypeInteger.ZERO || in(2)._type == TypeMemPtr.NULLPTR) )
@@ -71,12 +68,7 @@ abstract public class BoolNode extends Node {
return null;
}
- public static class EQ extends BoolNode { public EQ(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "=="; } boolean doOp(long lhs, long rhs) { return lhs == rhs; } Node copy(Node lhs, Node rhs) { return new EQ(lhs,rhs); } Node copyF() { return new EQF(null,null); } }
- public static class LT extends BoolNode { public LT(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<" ; } boolean doOp(long lhs, long rhs) { return lhs < rhs; } Node copy(Node lhs, Node rhs) { return new LT(lhs,rhs); } Node copyF() { return new LTF(null,null); }}
- public static class LE extends BoolNode { public LE(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<="; } boolean doOp(long lhs, long rhs) { return lhs <= rhs; } Node copy(Node lhs, Node rhs) { return new LE(lhs,rhs); } Node copyF() { return new LEF(null,null); } }
-
- public static class EQF extends EQ { public EQF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs == rhs; } Node copyF() { return null; } }
- public static class LTF extends LT { public LTF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs < rhs; } Node copyF() { return null; } }
- public static class LEF extends LE { public LEF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs <= rhs; } Node copyF() { return null; } }
-
+ public static class EQ extends BoolNode { public EQ(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "=="; } boolean doOp(long lhs, long rhs) { return lhs == rhs; } Node copy(Node lhs, Node rhs) { return new EQ(lhs,rhs); } }
+ public static class LT extends BoolNode { public LT(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<" ; } boolean doOp(long lhs, long rhs) { return lhs < rhs; } Node copy(Node lhs, Node rhs) { return new LT(lhs,rhs); } }
+ public static class LE extends BoolNode { public LE(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<="; } boolean doOp(long lhs, long rhs) { return lhs <= rhs; } Node copy(Node lhs, Node rhs) { return new LE(lhs,rhs); } }
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java
deleted file mode 100644
index a3f4318d..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/DivFNode.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.seaofnodes.simple.node;
-
-
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
-
-
-public class DivFNode extends Node {
- public DivFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
-
- @Override public String label() { return "DivF"; }
-
- @Override protected String format() { return "(%1/%2)"; }
-
- @Override
- public Type compute() {
- if (in(1)._type instanceof TypeFloat i0 &&
- in(2)._type instanceof TypeFloat i1) {
- if (i0.isConstant() && i1.isConstant())
- return TypeFloat.constant(i0.value()/i1.value());
- }
- return in(1)._type.meet(in(2)._type);
- }
-
- @Override
- public Node idealize() {
- Node lhs = in(1);
- Node rhs = in(2);
- Type t1 = lhs._type;
- Type t2 = rhs._type;
-
- // Div of 1.
- if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==1 )
- return lhs;
-
- return null;
- }
- @Override Node copy(Node lhs, Node rhs) { return new DivFNode(lhs,rhs); }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java
index cd52d117..d7244ace 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -37,5 +37,4 @@ public class DivNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new DivNode(lhs,rhs); }
- @Override Node copyF() { return new DivFNode(null,null); }
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
deleted file mode 100644
index 1b45c7c5..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.seaofnodes.simple.node;
-
-
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
-
-
-public class MinusFNode extends Node {
- public MinusFNode(Node in) { super(null, in); }
-
- @Override public String label() { return "MinusF"; }
-
- @Override protected String format() { return "(-%1)"; }
-
- @Override
- public Type compute() {
- if (in(1)._type instanceof TypeFloat i0)
- return i0.isConstant() ? TypeFloat.constant(-i0.value()) : i0;
- return TypeFloat.BOT;
- }
-
- @Override
- public Node idealize() {
- // -(-x) is x
- if( in(1) instanceof MinusFNode minus )
- return minus.in(1);
-
- return null;
- }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index ae450b22..5b65b3fb 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -27,5 +27,4 @@ public class MinusNode extends Node {
return null;
}
- @Override Node copyF() { return new MinusFNode(null); }
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java
deleted file mode 100644
index 6a57f3c5..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MulFNode.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.seaofnodes.simple.node;
-
-
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
-
-
-public class MulFNode extends Node {
- public MulFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
-
- @Override public String label() { return "MulF"; }
-
- @Override protected String format() { return "(%1*%2)"; }
-
- @Override
- public Type compute() {
- if (in(1)._type instanceof TypeFloat i0 &&
- in(2)._type instanceof TypeFloat i1) {
- if (i0.isConstant() && i1.isConstant())
- return TypeFloat.constant(i0.value()*i1.value());
- }
- return in(1)._type.meet(in(2)._type);
- }
-
- @Override
- public Node idealize() {
- Node lhs = in(1);
- Node rhs = in(2);
- Type t1 = lhs._type;
- Type t2 = rhs._type;
-
- // Mul of 1. We do not check for (1*x) because this will already
- // canonicalize to (x*1)
- if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==1 )
- return lhs;
-
- // Move constants to RHS: con*arg becomes arg*con
- if ( t1.isConstant() && !t2.isConstant() )
- return swap12();
-
- return null;
- }
- @Override Node copy(Node lhs, Node rhs) { return new MulFNode(lhs,rhs); }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 7fd52399..b0359a52 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -51,7 +51,6 @@ public class MulNode extends Node {
return null;
}
@Override Node copy(Node lhs, Node rhs) { return new MulNode(lhs,rhs); }
- @Override Node copyF() { return new MulFNode(null,null); }
@Override public String err() {
if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '"+label()+"' " + in(1)._type;
if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '"+label()+"' " + in(2)._type;
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
index 7448e05e..2c8596fa 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -8,7 +8,6 @@ import com.seaofnodes.simple.IRPrinter;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
import java.util.*;
import java.util.function.Function;
@@ -497,26 +496,6 @@ public abstract class Node extends BaseNode<Node> implements OutNode, Cloneable
/** Return block start from a isCFG() */
public Node getBlockStart() { return null; }
- // Semantic change to the graph (so NOT a peephole), used by the Parser.
- // If any input is a float, flip to a float-flavored opcode and widen any
- // non-float input.
- public final Node widen() {
- if( !hasFloatInput() ) return this;
- Node flt = copyF();
- if( flt==null ) return this;
- for( int i=1; i<nIns(); i++ )
- flt.setDef(i, in(i)._type instanceof TypeFloat ? in(i) : new ToFloatNode(in(i)).peephole());
- kill();
- return flt;
- }
- private boolean hasFloatInput() {
- for( int i=1; i<nIns(); i++ )
- if( in(i)._type instanceof TypeFloat )
- return true;
- return false;
- }
- Node copyF() { return null; }
-
// ------------------------------------------------------------------------
// Peephole utilities
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java
index 4539f982..5e556390 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -15,10 +15,8 @@ public class NotNode extends Node {
public Type compute() {
Type t0 = in(1)._type;
switch( t0 ) {
- case TypeInteger i0: return i0.isConstant() ? TypeInteger.constant(i0.value()==0 ? 1 : 0) : i0;
- case TypeFloat i0:
- if( i0==TypeFloat.TOP ) return TypeInteger.TOP;
- return i0.isConstant() ? TypeInteger.constant(i0.value()==0 ? 1 : 0) : TypeInteger.BOT;
+ case TypeInteger i0:
+ return i0.isConstant() ? TypeInteger.constant(i0.value()==0 ? 1 : 0) : i0;
case TypeMemPtr p0:
// top->top, bot->bot, null->1, *void->0, not-null ptr->0, ptr/nil->bot
// If input in null then true
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java
deleted file mode 100644
index 7c1a5dde..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/SubFNode.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.seaofnodes.simple.node;
-
-
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
-
-
-public class SubFNode extends Node {
- public SubFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
-
- @Override public String label() { return "SubF"; }
-
- @Override protected String format() { return "(%1-%2)"; }
-
- @Override
- public Type compute() {
- if (in(1)._type instanceof TypeFloat i0 &&
- in(2)._type instanceof TypeFloat i1) {
- if (i0.isConstant() && i1.isConstant())
- return TypeFloat.constant(i0.value()-i1.value());
- }
- return in(1)._type.meet(in(2)._type);
- }
-
- @Override
- public Node idealize() {
- Node lhs = in(1);
- Type t2 = in(2)._type;
-
- // Sub of 1.
- if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==0 )
- return lhs;
-
- return null;
- }
- @Override Node copy(Node lhs, Node rhs) { return new SubFNode(lhs,rhs); }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java
index f36f2af5..1589abe7 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -57,5 +57,4 @@ public class SubNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new SubNode(lhs,rhs); }
- @Override Node copyF() { return new SubFNode(null,null); }
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
deleted file mode 100644
index 26cf50e1..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.seaofnodes.simple.node;
-
-
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeFloat;
-import com.seaofnodes.simple.type.TypeInteger;
-
-
-public class ToFloatNode extends Node {
- public ToFloatNode(Node lhs) { super(null, lhs); }
-
- @Override public String label() { return "ToFloat"; }
-
- @Override protected String format() { return "(flt)%1"; }
-
- @Override
- public Type compute() {
- if (in(1)._type instanceof TypeInteger i0 && i0.isConstant() )
- return TypeFloat.constant(i0.value());
- return TypeFloat.BOT;
- }
-
- @Override public Node idealize() { return null; }
- @Override Node copy(Node lhs, Node rhs) { return new ToFloatNode(lhs); }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
index 9d996c03..e65963db 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -6,7 +6,7 @@ import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.type.TypeMem;
-/** Chapter 13's view of the IR; browser, transport and layout are shared. */
+/** Chapter 12's view of the IR; browser, transport and layout are shared. */
public class SimpleGraphAdapter extends GraphAdapter<Node> {
@Override protected String[] edgeNames(Node n) {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter13/src/main/java/com/seaofnodes/simple/type/Type.java
index 1f211430..93e27c76 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/type/Type.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/type/Type.java
@@ -33,12 +33,11 @@ public class Type {
static final byte TXCTRL = 3; // Ctrl flow top (mini-lattice: any-xctrl-ctrl-all)
static final byte TSIMPLE = 4; // End of the Simple Types
static final byte TINT = 5; // All Integers; see TypeInteger
- static final byte TFLT = 6; // All Integers; see TypeInteger
- static final byte TTUPLE = 7; // Tuples; finite collections of unrelated Types, kept in parallel
- static final byte TMEM = 8; // All memory (alias 0) or A slice of memory - with specific alias
- static final byte TMEMPTR = 9; // Memory pointer type
- static final byte TSTRUCT =10; // Structs; tuples with named fields
- static final byte TFLD =11; // Fields into struct
+ static final byte TTUPLE = 6; // Tuples; finite collections of unrelated Types, kept in parallel
+ static final byte TMEM = 7; // All memory (alias 0) or A slice of memory - with specific alias
+ static final byte TMEMPTR = 8; // Memory pointer type
+ static final byte TSTRUCT = 9; // Structs; tuples with named fields
+ static final byte TFLD =10; // Fields into struct
public final byte _type;
@@ -82,16 +81,14 @@ public class Type {
// ----------------------------------------------------------
- // Notes on Type interning: At the moment it is not easy to reset the
- // interned types because we hold static references to several types and
- // these are scattered around. This means the INTERN cache will retain all
- // types from every run of the Parser. For this to work correctly types
- // must be rigorous about defining when they are the same. Also types need
- // to be immutable once defined. The rationale for interning is
- // *correctness* with cyclic type definitions. Simple structural recursive
- // checks go exponential with merely sharing, but with cycles they will
- // stack overflow and crash. Intering means we do not need to have sharing
- // checks with every type compare, only during interning.
+ // Notes on Type interning.
+ // At the moment it is not easy to reset the interned types
+ // because we hold static references to several types and these are scattered
+ // around. This means the INTERN cache will retain all types from
+ // every run of the Parser. For this to work correctly types must be
+ // rigorous about defining when they are the same. Also types need to be
+ // immutable once defined.
+ // The rationale for interning is performance.
// Factory method which interns "this"
public <T extends Type> T intern() {
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/type/TypeFloat.java b/chapter13/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
deleted file mode 100644
index 738aebc9..00000000
--- a/chapter13/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.seaofnodes.simple.type;
-
-import java.util.ArrayList;
-
-/**
- * Float Type
- */
-public class TypeFloat extends Type {
-
- public final static TypeFloat TOP = make(false, 0);
- public final static TypeFloat BOT = make(false, 1);
- public final static TypeFloat ZERO= make(true , 0);
-
- public final boolean _is_con;
-
- /**
- * The constant value or
- * if not constant then 1=bottom, 0=top.
- */
- public final double _con;
-
- private TypeFloat(boolean is_con, double con) {
- super(TFLT);
- _is_con = is_con;
- _con = con;
- }
- public static TypeFloat make(boolean is_con, double con) {
- return new TypeFloat(is_con,con).intern();
- }
-
- public static TypeFloat constant(double con) { return make(true, con); }
-
- public static void gather(ArrayList<Type> ts) { ts.add(ZERO); ts.add(BOT); }
-
- // FIXME this display format is problematic
- // In visualizer '#' gets prepended if its a constant
- @Override
- public StringBuilder print(StringBuilder sb) {
- if( this==TOP ) return sb.append("FltTop");
- if( this==BOT ) return sb.append("FltBot");
- return sb.append(_con);
- }
-
- @Override public String str() {
- if( this==TOP ) return "~flt";
- if( this==BOT ) return "flt";
- return ""+_con;
- }
-
- /**
- * Display Type name in a format that's good for IR printer
- */
- @Override
- public StringBuilder typeName(StringBuilder sb) {
- if( this==TOP ) return sb.append("FltTop");
- if( this==BOT ) return sb.append("FltBot");
- return sb.append("Int");
- }
-
- @Override
- public boolean isHighOrConst() { return _is_con || _con==0; }
-
- @Override
- public boolean isConstant() { return _is_con; }
-
- public double value() { return _con; }
-
- @Override
- public Type xmeet(Type other) {
- // Invariant from caller: 'this' != 'other' and same class (TypeFloat)
- TypeFloat i = (TypeFloat)other; // Contract
- // BOT wins
- if ( this==BOT ) return this;
- if ( i ==BOT ) return i ;
- // TOP loses
- if ( i ==TOP ) return this;
- if ( this==TOP ) return i ;
- // Since both are constants, and are never equals (contract) unequals
- // constants fall to bottom
- return BOT;
- }
-
- @Override
- public Type dual() {
- if( isConstant() ) return this; // Constants are a self-dual
- return _con==0 ? BOT : TOP;
- }
-
- @Override
- public Type glb() { return BOT; }
-
- @Override public TypeFloat makeInit() { return ZERO; }
-
- @Override
- int hash() { return (int)(Double.hashCode(_con) ^ (_is_con ? 0 : 0x4000)); }
- @Override
- public boolean eq( Type t ) {
- TypeFloat i = (TypeFloat)t; // Contract
- return _con==i._con && _is_con==i._is_con;
- }
-}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter13/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
index 2599a383..02de7cc8 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/type/TypeStruct.java
@@ -8,14 +8,12 @@ import java.util.ArrayList;
*/
public class TypeStruct extends Type {
- // A Struct has a name and a set of fields; the fields themselves have
- // names and types. Briefly during parsing its allowed to have a
- // forward-ref to a Struct; in this case the _fields array is null.
- // Its illegal to attempt to load a field from a forward-ref struct.
- //
- // During the normal optimization run, struct types "bottom out" at further
- // struct references, so we don't have to handle e.g. cyclic types. The
- // "bottom out" is again the forward-ref struct.
+ // Immutable shallow references, resolved by name in Parser.TYPES when needed.
+ // A name-only struct has _fields == null, even after its definition is known.
+ // For LLI { LLI? next; int i; }, L0 is name-only and L1.next points to L0;
+ // TYPES["LLI"] holds L1. We deliberately stop recursive type expansion here,
+ // keeping interning and lattice operations finite and acyclic. Never patch
+ // L0 into L1: field access looks up the complete declaration by name instead.
public final String _name;
public final Field[] _fields;
@@ -40,7 +38,7 @@ public class TypeStruct extends Type {
private static final TypeStruct S1F = make("S1");
private static final TypeStruct S2F = make("S2");
public static final TypeStruct S1 = make("S1", new Field[]{ Field.make("a", TypeInteger.BOT), Field.make("s2",TypeMemPtr.make(S2F,false)) });
- private static final TypeStruct S2 = make("S2", new Field[]{ Field.make("b", TypeFloat .BOT), Field.make("s1",TypeMemPtr.make(S1F,false)) });
+ private static final TypeStruct S2 = make("S2", new Field[]{ Field.make("b", TypeInteger.BOT), Field.make("s1",TypeMemPtr.make(S1F,false)) });
public static void gather(ArrayList<Type> ts) { ts.add(TEST); ts.add(BOT); ts.add(S1); ts.add(S2); }
public int find(String fname) {