summaryrefslogtreecommitdiff
path: root/chapter17
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-11-07 16:30:43 -0800
committerCliff Click <cliffc@acm.org>2024-11-23 09:03:20 -0800
commitefc81d5afc9983258db267894ce3f141962793a5 (patch)
treee748baca01e0ed86c73fc195fbc66e630205807e /chapter17
parent6d96985f9d297f6dee9ee6f877b9986dec797d4c (diff)
downloadSimple-efc81d5afc9983258db267894ce3f141962793a5.tar.gz
Simple-efc81d5afc9983258db267894ce3f141962793a5.zip
var/val
Diffstat (limited to 'chapter17')
-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
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/BrainFuckTest.java15
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java38
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java50
5 files changed, 94 insertions, 30 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);
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter17/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
index 88dccc49..abb8b834 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
@@ -23,11 +23,12 @@ public class BrainFuckTest {
Parser parser = new Parser(
encoded + """
-int pc = 0, d = 0;
-u8[] data = new u8[100], output = new u8[0];
+var pc = 0, d = 0;
+u8[] output = new u8[0];
+val data = new u8[100];
while (pc < program#) {
- int command = program[pc];
+ var command = program[pc];
if (command == 62) {
d++;
} else if (command == 60) {
@@ -37,9 +38,9 @@ while (pc < program#) {
} else if (command == 45) {
data[d]--;
} else if (command == 46) {
- u8[] old = output;
+ var old = output;
output = new u8[output# + 1];
- int i = 0;
+ var i = 0;
while (i < old#)
output[i] = old[i++];
output[i] = data[d];
@@ -47,7 +48,7 @@ while (pc < program#) {
data[d] = 42;
} else if (command == 91) {
if (data[d] == 0) {
- int d = 1;
+ var d = 1;
while (d > 0) {
pc++;
command = program[pc];
@@ -57,7 +58,7 @@ while (pc < program#) {
}
} else if (command == 93) {
if (data[d]) {
- int d = 1;
+ var d = 1;
while (d > 0) {
pc--;
command = program[pc];
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index 8161862f..4226c201 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -216,38 +216,36 @@ return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6
public void sieveOEratosthenes() {
Parser parser = new Parser(
"""
-int[] ary = new int[arg];
-int[] primes = new int[arg];
-int nprimes = 0;
-// Find primes
-int j=2;
-while( j*j < arg ) {
- while( ary[j]==1 ) j = j + 1;
- // j is now a prime
- primes[nprimes] = j; nprimes = nprimes + 1;
+int[] ary = new int[arg], primes = new int[arg];
+int nprimes = 0, p=2;
+// Find primes while p^2 < arg
+while( p*p < arg ) {
+ // skip marked non-primes
+ while( ary[p]==1 ) p = p + 1;
+ // p is now a prime
+ primes[nprimes] = p; nprimes = nprimes + 1;
// Mark out the rest non-primes
- int i = j + j;
+ int i = p + p;
while( i < ary# ) {
ary[i] = 1;
- i = i + j;
+ i = i + p;
}
- j = j + 1;
+ p = p + 1;
}
-// Now just collect the remaining primes
-while( j < arg ) {
- if( ary[j] == 0 ) {
- primes[nprimes] = j; nprimes = nprimes + 1;
+// Now just collect the remaining primes, no more marking
+while( p < arg ) {
+ if( ary[p] == 0 ) {
+ primes[nprimes] = p; nprimes = nprimes + 1;
}
- j = j + 1;
+ p = p + 1;
}
-// Shrink the result array to size
+// Copy/shrink the result array
int[] rez = new int[nprimes];
-j = 0;
+int j = 0;
while( j < nprimes ) {
rez[j] = primes[j];
j = j + 1;
}
-
return rez;
""");
StopNode stop = parser.parse().iterate();
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java
index 45e3ef0f..ffb9bfc2 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java
@@ -88,6 +88,16 @@ return s.x;
}
@Test
+ public void testVar0() {
+ Parser parser = new Parser("""
+var d;
+return d;
+""");
+ try { parser.parse().iterate(); fail(); }
+ catch( Exception e ) { assertEquals("Syntax error, expected expression: ;",e.getMessage()); }
+ }
+
+ @Test
public void testLinkedList2() {
Parser parser = new Parser("""
struct LLI { LLI? next; int i; };
@@ -106,4 +116,44 @@ return sum;
assertEquals(45L, Evaluator.evaluate(stop, 10));
}
+ @Test
+ public void sieveOEratosthenes() {
+ Parser parser = new Parser(
+"""
+val ary = new bool[arg], primes = new int[arg];
+var nprimes=0, p=2;
+// Find primes while p^2 < arg
+while( p*p < arg ) {
+ // skip marked non-primes
+ while( ary[p] ) p++;
+ // p is now a prime
+ primes[nprimes++] = p;
+ // Mark out the rest non-primes
+ int i = p + p;
+ while( i < ary# ) {
+ ary[i] = true;
+ i = i + p;
+ }
+ p++;
+}
+// Now just collect the remaining primes, no more marking
+while( p++ < arg )
+ if( !ary[p-1] )
+ primes[nprimes++] = p-1;
+// Copy/shrink the result array
+var rez = new int[nprimes], j = 0;
+while( j < nprimes )
+ rez[j] = primes[j++];
+return rez;
+""");
+ StopNode stop = parser.parse().iterate();
+ assertEquals("return [int];", stop.toString());
+ Evaluator.Obj obj = (Evaluator.Obj)Evaluator.evaluate(stop, 20);
+ assertEquals("[int] { # :int; [] :int; }",obj.struct().toString());
+ long nprimes = (Long)obj.fields()[0];
+ long[] primes = new long[]{2,3,5,7,11,13,17,19};
+ for( int i=0; i<nprimes; i++ )
+ assertEquals(primes[i],(long)(Long)obj.fields()[i+1]);
+ }
+
}