diff options
Diffstat (limited to 'interpreter.c')
-rw-r--r-- | interpreter.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/interpreter.c b/interpreter.c index fec9087..9f389c1 100644 --- a/interpreter.c +++ b/interpreter.c @@ -147,6 +147,41 @@ InterRet ir_err_c(const char *errstr){ return ir_err(copystring(errstr)); } +static char* replace_arguments(AST *ast,int nargs,AST **args){ + switch(ast->type){ + case AST_LIST: + for(int i=0;i<ast->li.len;i++){ + replace_arguments(ast->li.nodes[i],nargs,args); + } + break; + + case AST_LAMBDAARG:{ + assert(ast->ar.idx>=0); + if(ast->ar.idx>=nargs){ + return copystring("Too few arguments passed to lambda function"); + } + AST *copy=ast_copy(args[ast->ar.idx]); + memcpy(ast,copy,sizeof(AST)); + break; + } + + case AST_QUOTED: + replace_arguments(ast->qu.ast,nargs,args); + break; + + case AST_LAMBDA: + case AST_WORD: + case AST_NUMBER: + case AST_STRING: + case AST_SYMBOL: + break; + + default: + assert(false); + } + return NULL; +} + static InterRet interpret(InterState *is,const AST *ast){ switch(ast->type){ case AST_LIST:{ @@ -169,8 +204,11 @@ static InterRet interpret(InterState *is,const AST *ast){ return ir_err_c("First node in evaluated list not a function"); } -#define NOT_IMPLEMENTED false - if(nodes[0]->la.body)assert(NOT_IMPLEMENTED); + if(nodes[0]->la.body){ + char *errstr=replace_arguments(nodes[0]->la.body,ast->li.len-1,nodes+1); + if(errstr)return ir_err(errstr); + return interpret(is,nodes[0]->la.body); + } InterRet ir=nodes[0]->la.cfunc(is,ast->li.len-1,nodes+1); for(int i=0;i<ast->li.len;i++)ast_free(nodes[i]); |