diff options
Diffstat (limited to 'chapter18/src')
3 files changed, 63 insertions, 6 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index 1105c2b7..7301f63b 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -955,8 +955,9 @@ public class Parser { if( matchx("true" ) ) return con(1); if( matchx("false") ) return ZERO; if( matchx("null" ) ) return NIL; - if( match("(") ) return require(parseAsgn(), ")"); + if( match ("(" ) ) return require(parseAsgn(), ")"); if( matchx("new" ) ) return alloc(); + if( match ("{" ) ) return func(); // Expect an identifier now ScopeMinNode.Var n = requireLookupId("an identifier or expression"); Node rvalue = _scope.in(n); @@ -1091,8 +1092,8 @@ public class Parser { public static String memName(int alias) { return ("$"+alias).intern(); } /** - * Parse postfix expression. For now this is just a field - * expression, but in future could be array index too. + * Parse postfix expression; this can be a field expression, an array + * lookup or a postfix operator like '#' * * <pre> * expr ('.' IDENTIFIER)* [ = expr ] @@ -1202,6 +1203,36 @@ public class Parser { return peep(new SarNode(peep(new ShlNode(val,shf.keep())),shf.unkeep())); } + /** + * Parse a function; the leading '{' is already parsed. + * + * <pre> + * { [type arg,]* -> expr } + * { expr } // The no-argument function + * </pre> + */ + private Node func() { + int old = pos(); // Record lexer position + Ary<Type> ts = new Ary<>(Type.class); + Ary<String> ids = new Ary<>(String.class); + ts .push(Type.BOTTOM); // Return type, unknown yet + ids.push(null); // Not an argument + while( true ) { + Type t = type(); // Arg type + if( t==null ) break; + String id = requireId(); + ts .push(t ); // Push type/arg pairs + ids.push(id); + match(","); + } + require("->"); + // Make a concrete function type, with a fidx + TypeFunPtr tfp = TypeFunPtr.makeFun(TypeTuple.make(ts.asAry())); + //FunNode fun = (FunNode)peep(new FunNode()); + + throw Utils.TODO(); + } + /** * Parse integer literal 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 0c66c20c..f1a16de4 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -3,6 +3,7 @@ package com.seaofnodes.simple.type; import com.seaofnodes.simple.SB; import com.seaofnodes.simple.Utils; import java.util.ArrayList; +import java.util.HashMap; /** * Represents a Pointer to a function. @@ -35,6 +36,19 @@ public class TypeFunPtr extends TypeNil { public static TypeFunPtr make( boolean nil, TypeTuple sig ) { return make((byte)(nil ? 3 : 2),sig,-1); } @Override TypeFunPtr makeFrom( byte nil ) { return nil==_nil ? this : make(nil,_sig,_fidxs); } + // Compute "function indices": FIDX + private static final HashMap<TypeTuple,Integer> FIDXS = new HashMap<>(); + private static int nextFIDX(TypeTuple sig) { + Integer i = FIDXS.get(sig); + int fidx = i==null ? 0 : i; + FIDXS.put(sig,fidx+1); // Track count per sig + assert fidx<64; // TODO: need a larger FIDX space + return fidx; // Return + } + public static TypeFunPtr makeFun( TypeTuple sig ) { + return make((byte)2,sig,1L<<nextFIDX(sig)); + } + public static TypeFunPtr BOT = make((byte)3,TypeTuple.SIGBOT,-1); public static TypeFunPtr TEST = make((byte)2,TypeTuple.SIGTEST,1); public static TypeFunPtr TEST0 = make((byte)3,TypeTuple.SIGTEST,3); diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 8ac98d72..369a0c39 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -4,8 +4,8 @@ import com.seaofnodes.simple.evaluator.Evaluator; import com.seaofnodes.simple.node.StopNode; import org.junit.Test; import org.junit.Ignore; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; + +import static org.junit.Assert.*; public class Chapter18Test { @@ -30,8 +30,20 @@ return x2; """); StopNode stop = parser.parse().iterate(); assertEquals("return null;", stop.toString()); - assertEquals(null, Evaluator.evaluate(stop, 0)); + assertNull( Evaluator.evaluate( stop, 0 ) ); } + @Ignore @Test + public void testFcn0() { + Parser parser = new Parser(""" +{int -> int}? sq = { int x -> + x*x +}; +return sq; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return fcn;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } } |
