diff options
| author | Cliff Click <cliffc@acm.org> | 2024-09-04 08:14:23 -0700 |
|---|---|---|
| committer | Thalia Archibald <thalia@archibald.dev> | 2024-09-07 10:54:48 -0700 |
| commit | 29db69cb40c2fda992a704a50e9159a1a3e23ac9 (patch) | |
| tree | e614204f3312a05c26ef1726251929c465903b7c /chapter13/src | |
| parent | fb0315e1d8911534c6ce5a4d3a8b63a2005d6fe5 (diff) | |
| download | Simple-29db69cb40c2fda992a704a50e9159a1a3e23ac9.tar.gz Simple-29db69cb40c2fda992a704a50e9159a1a3e23ac9.zip | |
Backport empty statement fix
Split Ch13 tests from Chapter12Test.java
Handle forward refs never defined.
Diffstat (limited to 'chapter13/src')
3 files changed, 171 insertions, 114 deletions
diff --git a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java index fee5215e..f04bf5c3 100644 --- a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java @@ -167,6 +167,7 @@ public class Parser { else if (matchx("continue")) return parseContinue(); else if (matchx("struct") ) return parseStruct(); else if (matchx("#showGraph")) return require(showGraph(),";"); + else if (matchx(";") ) return null; // Empty statement // declarations of vars with struct type are handled in parseExpressionStatement due // to ambiguity else return parseExpressionStatement(); @@ -190,7 +191,7 @@ public class Parser { * Only allowed in top level scope. * Structs cannot be redefined. * - * @return The statement following the struct + * @return null */ private Node parseStruct() { if (_xScopes.size() > 1) throw errorSyntax("struct declarations can only appear in top level scope"); @@ -209,7 +210,7 @@ public class Parser { TypeStruct ts = TypeStruct.make(typeName, fields); TYPES.put(typeName, ts); START.addMemProj(ts, _scope); // Insert memory edges - return parseStatement(); + return null; } /** @@ -579,7 +580,8 @@ public class Parser { if( matchx("new") ) { String structName = requireId(); Type t = TYPES.get(structName); - if( t == null || !(t instanceof TypeStruct obj) ) throw errorSyntax("Unknown struct type '" + structName + "'"); + if( !(t instanceof TypeStruct obj) || obj._fields==null ) + throw error("Unknown struct type '" + structName + "'"); return newStruct(obj); } String name = _lexer.matchId(); diff --git a/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java index 8eceb0fa..f711607b 100644 --- a/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java +++ b/chapter13/src/test/java/com/seaofnodes/simple/Chapter12Test.java @@ -60,115 +60,4 @@ return x+1==x; assertEquals(0L, Evaluator.evaluate(stop, 1)); } - - @Test - public void testLinkedList0() { - Parser parser = new Parser( -""" -struct LLI { LLI? next; int i; } -LLI? head = null; -while( arg ) { - LLI x = new LLI; - x.next = head; - x.i = arg; - head = x; - arg = arg-1; -} -return head.next.i; -"""); - try { parser.parse(true).iterate(true); fail(); } - catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); } - } - - @Test - public void testLinkedList1() { - Parser parser = new Parser( -""" -struct LLI { LLI? next; int i; } -LLI? head = null; -while( arg ) { - LLI x = new LLI; - x.next = head; - x.i = arg; - head = x; - arg = arg-1; -} -if( !head ) return 0; -LLI? next = head.next; -if( next==null ) return 1; -return next.i; -"""); - StopNode stop = parser.parse(false).iterate(false); - assertEquals("Stop[ return 0; return 1; return .i; ]", stop.toString()); - assertEquals(2L, Evaluator.evaluate(stop, 3)); - } - - @Test - public void testCoRecur() { - Parser parser = new Parser( -""" -struct int0 { int i; flt0? f; } -struct flt0 { flt f; int0? i; } -int0 i0 = new int0; -i0.i = 17; -flt0 f0 = new flt0; -f0.f = 3.14; -i0.f = f0; -f0.i = i0; -return f0.i.f.i.i; -"""); - StopNode stop = parser.parse(false).iterate(false); - 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()); } - } } diff --git a/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java new file mode 100644 index 00000000..f7d4d5a8 --- /dev/null +++ b/chapter13/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -0,0 +1,166 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.evaluator.Evaluator; +import com.seaofnodes.simple.node.StopNode; +import org.junit.Ignore; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class Chapter13Test { + @Test + public void testJig() { + Parser parser = new Parser( +""" +return 3.14; +"""); + StopNode stop = parser.parse(false).iterate(false); + assertEquals("return 3.14;", stop.toString()); + assertEquals(3.14, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testLinkedList0() { + Parser parser = new Parser( +""" +struct LLI { LLI? next; int i; } +LLI? head = null; +while( arg ) { + LLI x = new LLI; + x.next = head; + x.i = arg; + head = x; + arg = arg-1; +} +return head.next.i; +"""); + try { parser.parse(true).iterate(true); fail(); } + catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); } + } + + @Test + public void testLinkedList1() { + Parser parser = new Parser( +""" +struct LLI { LLI? next; int i; } +LLI? head = null; +while( arg ) { + LLI x = new LLI; + x.next = head; + x.i = arg; + head = x; + arg = arg-1; +} +if( !head ) return 0; +LLI? next = head.next; +if( next==null ) return 1; +return next.i; +"""); + StopNode stop = parser.parse(false).iterate(false); + assertEquals("Stop[ return 0; return 1; return .i; ]", stop.toString()); + assertEquals(2L, Evaluator.evaluate(stop, 3)); + } + + @Test + public void testCoRecur() { + Parser parser = new Parser( +""" +struct int0 { int i; flt0? f; } +struct flt0 { flt f; int0? i; } +int0 i0 = new int0; +i0.i = 17; +flt0 f0 = new flt0; +f0.f = 3.14; +i0.f = f0; +f0.i = i0; +return f0.i.f.i.i; +"""); + StopNode stop = parser.parse(false).iterate(false); + 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()); } + } + + @Test + public void testEmpty() { + Parser parser = new Parser( +""" +struct S{}; +"""); + StopNode stop = parser.parse(false).iterate(false); + assertEquals("return 0;", stop.toString()); + assertEquals(0L, Evaluator.evaluate(stop, 0)); + } + + @Test + public void testForwardRef0() { + Parser parser = new Parser( +""" +struct S1 { S2 s; } +return new S2; +"""); + try { parser.parse(true).iterate(true); fail(); } + catch( Exception e ) { assertEquals("Unknown struct type 'S2'",e.getMessage()); } + } + + @Test + public void testForwardRef1() { + Parser parser = new Parser( +""" +struct S1 { S2? s; } +struct S2 { int x; } +return new S1.s=new S2; +"""); + StopNode stop = parser.parse(false).iterate(false); + assertEquals("return new S1;", stop.toString()); + } +} |
