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 *