summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/Parser.java15
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/node/NewNode.java4
-rw-r--r--chapter15/src/test/java/com/seaofnodes/simple/BrainFuckTest.java4
-rw-r--r--chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java19
4 files changed, 35 insertions, 7 deletions
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java
index 64cde40f..012a010e 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java
@@ -805,13 +805,22 @@ public class Parser {
Node val = parseExpression();
// Auto-truncate when storing to narrow fields
val = zsMask(val,f._type);
- memAlias(f._alias, new StoreNode(name, f._alias, f._type, memAlias(f._alias), expr, off, val, false).peephole());
+ Node st = new StoreNode(name, f._alias, f._type, memAlias(f._alias), expr, off, val, false);
+ // Arrays include control, as a proxy for a safety range check.
+ // Structs dont need this; they only need a NPE check which is
+ // done via the type system.
+ if( base.isAry() ) st.setDef(0,ctrl());
+ memAlias(f._alias, st.peephole());
return val; // "obj.a = expr" returns the expression while updating memory
}
}
- Node load = new LoadNode(name, f._alias, f._type, memAlias(f._alias), expr, off).peephole();
- return parsePostfix(load);
+ Node load = new LoadNode(name, f._alias, f._type, memAlias(f._alias), expr, off);
+ // Arrays include control, as a proxy for a safety range check
+ // Structs dont need this; they only need a NPE check which is
+ // done via the type system.
+ if( base.isAry() ) load.setDef(0,ctrl());
+ return parsePostfix(load.peephole());
}
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter15/src/main/java/com/seaofnodes/simple/node/NewNode.java
index d7220bdc..f06564cd 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/node/NewNode.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/node/NewNode.java
@@ -38,10 +38,10 @@ public class NewNode extends Node implements MultiNode {
@Override
public TypeTuple compute() {
- Type[] ts = new Type[nIns()];
+ Field[] fs = _ptr._obj._fields;
+ Type[] ts = new Type[fs.length+2];
ts[0] = Type.CONTROL;
ts[1] = _ptr;
- Field[] fs = _ptr._obj._fields;
for( int i=0; i<fs.length; i++ )
ts[i+2] = TypeMem.make(fs[i]._alias,fs[i]._type.makeInit()).meet( in(i+2)._type );
return TypeTuple.make(ts);
diff --git a/chapter15/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter15/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
index 894abbf6..03a22c55 100644
--- a/chapter15/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
+++ b/chapter15/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
@@ -26,7 +26,7 @@ public class BrainFuckTest {
encoded + """
int pc = 0;
int d = 0;
-u8[] data = new u8[10000];
+u8[] data = new u8[100];
int i=0;
while(i < data#) {
data[i] = 0;
@@ -92,6 +92,6 @@ return result;
for (byte b : "Hello Wo".getBytes(StandardCharsets.UTF_8)) {
expected = (expected << 8) | b;
}
- assertEquals(expected, Evaluator.evaluate(stop, 0, 100000));
+ assertEquals(expected, Evaluator.evaluate(stop, 0, 10000));
}
}
diff --git a/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index 1aee2f0d..266d8a47 100644
--- a/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -24,6 +24,25 @@ return 3.14;
}
@Test
+ public void testSafetyCheck() {
+ Parser parser = new Parser(
+"""
+u8[] old = new u8[0];
+u8[] output = new u8[1];
+int i = 0;
+while (i < old#) {
+ output[i] = old[i];
+ i = i + 1;
+}
+output[i] = 1;
+return output;
+""");
+ StopNode stop = parser.parse(false).iterate(true);
+ assertEquals("return u8[];", stop.toString());
+ assertEquals("Obj<u8[]> {\n #=1\n []=1\n}", Evaluator.evaluate(stop, 0).toString());
+ }
+
+ @Test
public void testBasic1() {
Parser parser = new Parser(
"""