shithub: lpa

Download patch

ref: 5af5764e62f81ec4057e99a3bd03902b723cd7b8
parent: 2e8f865a978cba527282aacebfc99b9a6317c051
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Sat Jul 27 07:00:17 EDT 2024

Support optional left argument in function definitions

--- a/dat.h
+++ b/dat.h
@@ -179,6 +179,7 @@
 	char *name;
 	int nameclass;
 	int prim;
+	int optional; /* optional left arg */
 
 	Ast *funcname;
 	Ast *funcresult;
--- a/eval.c
+++ b/eval.c
@@ -72,9 +72,11 @@
 		{
 			Function *fn = alloc(DataFunction);
 			fn->ast = a;
-			if(fn->ast->funcleftarg)
+			if(fn->ast->funcleftarg){
 				fn->valence = Dyadic;
-			else if(fn->ast->funcrightarg)
+				if(fn->ast->funcleftarg->optional)
+					fn->valence |= Monadic;
+			}else if(fn->ast->funcrightarg)
 				fn->valence = Monadic;
 			else
 				fn->valence = Niladic;
@@ -347,6 +349,8 @@
 						error(ESyntax, "Function %s does not produce a result", funcname(func));
 				}
 				pushval(values, y);
+				if(func->valence & Dyadic) /* ambivalent function */
+					pushval(values, nil);
 				pushcall(calls, func->code, &c, &o);
 			}else{
 				z = primmonad(func->prim, y);
--- a/parse.c
+++ b/parse.c
@@ -18,6 +18,7 @@
 static Ast *parseprog(TokenList *);
 static Ast *parsefuncdef(TokenList *);
 static Ast *parsefuncheader(TokenList *);
+static Ast *parsefuncleftopt(TokenList *);
 static Ast *parselocals(TokenList *);
 static Ast *parseexpr(TokenList *, Symtab *, Ast *);
 static Ast *parseexprsub(TokenList *);
@@ -202,15 +203,18 @@
 
 	match(t, TokDel);
 
+	func->funcleftarg = parsefuncleftopt(t); /* optional left arg */
+
 	func->funcname = parsename(t);
-	if(peek(t) == TokLarrow){
+	if(peek(t) == TokLarrow && !func->funcleftarg){
 		match(t, TokLarrow);
 		func->funcresult = func->funcname;
+		func->funcleftarg = parsefuncleftopt(t);
 		func->funcname = parsename(t);
 	}
 	if(peek(t) == TokName)
 		func->funcrightarg = parsename(t);
-	if(peek(t) == TokName){
+	if(peek(t) == TokName && !func->funcleftarg){
 		func->funcleftarg = func->funcname;
 		func->funcname = func->funcrightarg;
 		func->funcrightarg = parsename(t);
@@ -218,6 +222,19 @@
 	func->funclocals = parselocals(t);
 
 	return func;
+}
+
+static Ast *
+parsefuncleftopt(TokenList *t)
+{
+	Ast *name = nil;
+	if(peek(t) == TokLbrace){
+		match(t, TokLbrace);
+		name = parsename(t);
+		name->optional = 1;
+		match(t, TokRbrace);
+	}
+	return name;
 }
 
 static Ast *