From fcd6dcf5265b4b23fd69af761316c064b8f9f7ce Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 22 Dec 2024 10:28:32 -0800 Subject: Intercept first function definition --- .../main/java/com/seaofnodes/simple/Parser.java | 37 ++++++++++++++++++++-- .../com/seaofnodes/simple/type/TypeFunPtr.java | 14 ++++++++ .../java/com/seaofnodes/simple/Chapter18Test.java | 18 +++++++++-- 3 files changed, 63 insertions(+), 6 deletions(-) (limited to 'chapter18/src') 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 '#' * *
      *     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.
+     *
+     * 
+     *     { [type arg,]* -> expr }
+     *     { expr } // The no-argument function
+     * 
+ */ + private Node func() { + int old = pos(); // Record lexer position + Ary ts = new Ary<>(Type.class); + Ary 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 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< int}? sq = { int x -> + x*x +}; +return sq; +"""); + StopNode stop = parser.parse().iterate(); + assertEquals("return fcn;", stop.toString()); + assertEquals(1L, Evaluator.evaluate(stop, 0)); + } } -- cgit v1.2.3