diff options
| author | Cliff Click <cliffc@acm.org> | 2025-01-06 16:53:20 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-01-15 15:07:30 -0800 |
| commit | a3db7b9938d01f7995398df9f07553074e15905e (patch) | |
| tree | 42150cfd3a1183a2784dbdabb563b2a518a4def5 | |
| parent | 1d1433a6e67224f545d9052f0bbdd019186dc68c (diff) | |
| download | Simple-a3db7b9938d01f7995398df9f07553074e15905e.tar.gz Simple-a3db7b9938d01f7995398df9f07553074e15905e.zip | |
Series of minor bugs
5 files changed, 66 insertions, 9 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index dc8f042a..f1cbf446 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -182,6 +182,8 @@ public class Parser { Node oldctrl = ctrl().keep(); Node oldmem = _scope.mem().keep(); FunNode oldfun = _fun; + ScopeNode breakScope = _breakScope; _breakScope = null; + ScopeNode continueScope = _continueScope; _continueScope = null; FunNode fun = _fun = (FunNode)peep(new FunNode(loc(),START,sig)); // Once the function header is available, install in linker table - @@ -245,6 +247,8 @@ public class Parser { // Function scope ends _scope.pop(); _fun = oldfun; + _breakScope = breakScope; + _continueScope = continueScope; // Reset control and memory to pre-function parsing days ctrl(oldctrl.unkeep()); _scope.mem(oldmem.unkeep()); @@ -1021,7 +1025,7 @@ public class Parser { if( n._final ) throw error("Cannot reassign final '"+n._name+"'"); Node expr = n.type() instanceof TypeFloat - ? peep(new AddFNode(_scope.in(n),con(TypeFloat.constant(-1)))) + ? peep(new AddFNode(_scope.in(n),con(TypeFloat.constant(delta)))) : zsMask(peep(new AddNode(_scope.in(n),con(delta))),n.type()); _scope.update(n,expr); return expr; @@ -1222,7 +1226,7 @@ public class Parser { if( match(".") ) name = requireId(); else if( match("#") ) name = "#"; else if( match("[") ) name = "[]"; - else if( match("(") ) return require(functionCall(expr),")"); + else if( match("(") ) return parsePostfix(require(functionCall(expr),")")); else return expr; // No postfix if( expr._type==Type.NIL ) @@ -1370,7 +1374,7 @@ public class Parser { for( Node arg : args ) arg.unkeep(); // Into the call - CallNode call = (CallNode)new CallNode(args.asAry()).peephole(); + CallNode call = (CallNode)new CallNode(loc(), args.asAry()).peephole(); // Post-call setup CallEndNode cend = (CallEndNode)new CallEndNode(call).peephole(); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/BoolNode.java index bf8f7455..ae968ca1 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/BoolNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/BoolNode.java @@ -33,11 +33,11 @@ abstract public class BoolNode extends Node { Type t1 = in(1)._type; Type t2 = in(2)._type; // Exactly equals? + if( t1.isHigh() || t2.isHigh() ) + return BOOL.dual(); if( in(1)==in(2) ) // LT fails, both EQ and LE succeed return this instanceof LT ? TypeInteger.FALSE : TypeInteger.TRUE; - if( t1.isHigh() || t2.isHigh() ) - return BOOL.dual(); if( t1 instanceof TypeInteger i1 && t2 instanceof TypeInteger i2 ) return doOp(i1,i2); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java index 6645d69d..6963ff2b 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -1,6 +1,7 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.CodeGen; +import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFunPtr; @@ -11,7 +12,10 @@ import java.util.BitSet; */ public class CallNode extends CFGNode { - public CallNode(Node... nodes) { super(nodes); } + // Source location for late reported errors + public final Parser.Lexer _loc; + + public CallNode(Parser.Lexer loc, Node... nodes) { super(nodes); _loc = loc; } @Override public String label() { return "Call"; } @@ -115,4 +119,18 @@ public class CallNode extends CFGNode { assert linked(fun); } + @Override + public Parser.ParseException err() { + if( !(fptr()._type instanceof TypeFunPtr tfp) ) + throw Utils.TODO(); + if( !tfp.notNull() ) + return Parser.error( "Might be null calling "+tfp, _loc); + // Check for args + for( int i=0; i<tfp.nargs(); i++ ) + if( !arg(i+2)._type.isa(tfp.arg(i)) ) + return Parser.error( "Argument #"+i+" isa "+arg(i+2)._type+", but must be a "+tfp.arg(i), _loc); + + return null; + } + } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index 9e2cec07..4814539f 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -81,6 +81,7 @@ public class TypeFunPtr extends TypeNil { public Type arg(int i) { return _sig._types[i]; } public long fidxs() { return _fidxs; } public Type ret() { return _ret; } + public int nargs() { return _sig._types.length; } @Override int hash() { return Utils.fold(_sig.hashCode() ^ _ret.hashCode() ^ _fidxs ^ super.hash()); } diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 75ad301e..545bb546 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -11,7 +11,9 @@ public class Chapter18Test { public void testJig() { CodeGen code = new CodeGen( """ -return 0; +struct S { int i; }; +val newS = { int x -> return new S { i=x; }; }; +return newS(1).i; """); code.parse(false).opto().typeCheck().GCM(); assertEquals("return 0;", code._stop.toString()); @@ -115,7 +117,7 @@ var fcn = arg ? { int x -> x*x; } : { int x -> x+x; }; return fcn(3); """); code.parse().opto(); - assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x(null,int)*x); return (Parm_x(null,int)*2); ]", code._stop.toString()); + assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int)*x); return (Parm_x($fun,int)*2); ]", code._stop.toString()); assertEquals("6", Eval2.eval(code, 0)); assertEquals("9", Eval2.eval(code, 1)); } @@ -133,9 +135,41 @@ return fcn(3); assertEquals("24", Eval2.eval(code, 4)); } + @Test + public void testFcn6() { + CodeGen code = new CodeGen( +""" +struct S { int i; }; +val newS = { int x -> return new S { i=x; }; }; +return newS(1).i; +"""); + code.parse(false).opto().typeCheck().GCM(); + assertEquals("Stop[ return .i; return S; ]", code._stop.toString()); + assertEquals("1", Eval2.eval(code, 0)); + } + + // Function break + @Test + public void testErr1() { + CodeGen code = new CodeGen( +""" +for(;;) { + val f = { -> + break; + }; + f(); + return 2; +} +return 1; +"""); + try { code.parse().opto(); fail(); } + catch( Exception e ) { assertEquals("No active loop for a break or continue",e.getMessage()); } + } + + // Mutual recursion. Fails without SCCP to lift the recursive return types. @Ignore @Test - public void testFcn6() { + public void testFcnMutRec() { CodeGen code = new CodeGen( """ val is_even = { int x -> x ? is_odd (x-1) : true ; }; |
