summaryrefslogtreecommitdiff
path: root/chapter13/src
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-08-05 13:52:54 -0700
committerDibyendu Majumdar <dibyendumajumdar@users.noreply.github.com>2024-08-06 00:50:58 +0100
commite29c22656458e9252ca0fc32a396d605496b4b4d (patch)
tree30007cb51ba01bfcded2aab2807b6cb237ce0905 /chapter13/src
parent9bc99b3987f1daea61c329b9327814d9a9148ebe (diff)
downloadSimple-e29c22656458e9252ca0fc32a396d605496b4b4d.tar.gz
Simple-e29c22656458e9252ca0fc32a396d605496b4b4d.zip
More error cases, error checking
disallow e.g. "struct x { int i; }; x = new x; x.i=3.14;"
Diffstat (limited to 'chapter13/src')
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/Parser.java5
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java4
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/MemOpNode.java10
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/Node.java2
-rw-r--r--chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java14
-rw-r--r--chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java50
6 files changed, 74 insertions, 11 deletions
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java
index bde697d6..fee5215e 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java
@@ -596,7 +596,7 @@ public class Parser {
Node n = new NewNode(TypeMemPtr.make(obj), ctrl()).peephole().keep();
int alias = START._aliasStarts.get(obj._name);
for( Field field : obj._fields ) {
- memAlias(alias, new StoreNode(field._fname, alias, memAlias(alias), n, new ConstantNode(field._type.makeInit()).peephole()).peephole());
+ memAlias(alias, new StoreNode(field._fname, alias, field._type, memAlias(alias), n, new ConstantNode(field._type.makeInit()).peephole(),true).peephole());
alias++;
}
return n.unkeep();
@@ -637,7 +637,8 @@ public class Parser {
if( peek('=') ) _lexer._position--;
else {
Node val = parseExpression();
- memAlias(alias, new StoreNode(name, alias, memAlias(alias), expr, val).peephole());
+ Type glb = base._fields[idx]._type;
+ memAlias(alias, new StoreNode(name, alias,glb, memAlias(alias), expr, val, false).peephole());
return expr; // "obj.a = expr" returns the expression while updating memory
}
}
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index 0c5d72e5..4e1421fa 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/LoadNode.java
@@ -11,7 +11,6 @@ import java.util.BitSet;
*/
public class LoadNode extends MemOpNode {
- Type _declaredType;
/**
* Load a value from a ptr.field.
*
@@ -20,8 +19,7 @@ public class LoadNode extends MemOpNode {
* @param memPtr The ptr to the struct from where we load a field
*/
public LoadNode(String name, int alias, Type glb, Node memSlice, Node memPtr) {
- super(name, alias, memSlice, memPtr);
- _declaredType = glb;
+ super(name, alias, glb, memSlice, memPtr);
}
@Override public String label() { return _name; }
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/MemOpNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
index 7f8d060a..bc8e46d3 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
@@ -11,14 +11,18 @@ public abstract class MemOpNode extends Node {
public final String _name;
public final int _alias;
+ public final Type _declaredType;
- public MemOpNode(String name, int alias, Node memSlice, Node memPtr) {
+
+ public MemOpNode(String name, int alias, Type glb, Node memSlice, Node memPtr) {
super(null, memSlice, memPtr);
_name = name;
_alias = alias;
+ _declaredType = glb;
+
}
- public MemOpNode(String name, int alias, Node memSlice, Node memPtr, Node value) {
- this(name, alias, memSlice, memPtr);
+ public MemOpNode(String name, int alias, Type glb, Node memSlice, Node memPtr, Node value) {
+ this(name, alias, glb, memSlice, memPtr);
addDef(value);
}
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 52282737..d846fcef 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -137,7 +137,7 @@ public abstract class Node implements OutNode {
public boolean isUnused() { return nOuts() == 0; }
- public CFGNode cfg0() { return (CFGNode)in(0); }
+ public CFGNode cfg0() { return (CFGNode)in(0); }
/**
* Change a <em>def</em> into a Node. Keeps the edges correct, by removing
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index 89141892..44a14be1 100644
--- a/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter13/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -11,14 +11,17 @@ import java.util.BitSet;
*/
public class StoreNode extends MemOpNode {
+ private final boolean _init; // Initializing writes are allowed to write null
+
/**
* @param name The struct field we are assigning to
* @param memSlice The memory alias node - this is updated after a Store
* @param memPtr The ptr to the struct where we will store a value
* @param value Value to be stored
*/
- public StoreNode(String name, int alias, Node memSlice, Node memPtr, Node value) {
- super(name, alias, memSlice, memPtr, value);
+ public StoreNode(String name, int alias, Type glb, Node memSlice, Node memPtr, Node value, boolean init) {
+ super(name, alias, glb, memSlice, memPtr, value);
+ _init = init;
}
@Override public String label() { return "ST"+_name; }
@@ -65,4 +68,11 @@ public class StoreNode extends MemOpNode {
return false;
}
+ @Override
+ String err() {
+ String err = super.err();
+ if( err != null ) return err;
+ Type ptr = val()._type;
+ return _init || ptr.isa(_declaredType) ? null : "Cannot store "+ptr+" into field "+_declaredType+" "+_name;
+ }
}
diff --git a/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java
index e36c7577..8eceb0fa 100644
--- a/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java
+++ b/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java
@@ -121,4 +121,54 @@ return f0.i.f.i.i;
assertEquals("return 17;", stop.toString());
}
+ @Test
+ public void testNullRef0() {
+ Parser parser = new Parser(
+"""
+struct N { N next; int i; }
+N n = new N;
+return n.next;
+""");
+ StopNode stop = parser.parse(false).iterate(false);
+ assertEquals("return null;", stop.toString());
+ }
+
+ @Test
+ public void testNullRef1() {
+ Parser parser = new Parser(
+"""
+struct N { N next; int i; }
+N n = new N;
+n.next = new N;
+return n.next;
+""");
+ StopNode stop = parser.parse(false).iterate(false);
+ assertEquals("return new N;", stop.toString());
+ }
+
+ @Test
+ public void testNullRef2() {
+ Parser parser = new Parser(
+"""
+struct N { N next; int i; }
+N n = new N;
+n.next = null;
+return n.next;
+""");
+ try { parser.parse(true).iterate(true); fail(); }
+ catch( Exception e ) { assertEquals("Cannot store null into field *N next",e.getMessage()); }
+ }
+
+ @Test
+ public void testNullRef3() {
+ Parser parser = new Parser(
+"""
+struct N { N next; int i; }
+N n = new N;
+n.i = 3.14;
+return n.i;
+""");
+ try { parser.parse(true).iterate(true); fail(); }
+ catch( Exception e ) { assertEquals("Cannot store 3.14 into field IntBot i",e.getMessage()); }
+ }
}