diff options
Diffstat (limited to 'inter_builtins.c')
-rw-r--r-- | inter_builtins.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/inter_builtins.c b/inter_builtins.c index cc96afd..6793c60 100644 --- a/inter_builtins.c +++ b/inter_builtins.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <assert.h> #include "inter_builtins.h" @@ -32,6 +33,7 @@ InterRet builtin_print(InterState *is,int nargs,AST **args){ return ir_ast(ast_list(0,malloc(1,AST*))); } + #define BUILTIN_ARITH_OP(op,name,defval,expr) \ InterRet builtin_##name(InterState *is,int nargs,AST **args){ \ (void)is; \ @@ -51,10 +53,75 @@ InterRet builtin_print(InterState *is,int nargs,AST **args){ return ir_ast(ast_number(res)); \ } -BUILTIN_ARITH_OP(+,sum,0,res+n) -BUILTIN_ARITH_OP(-,difference,0,res-n) -BUILTIN_ARITH_OP(*,product,1,res*n) -BUILTIN_ARITH_OP(/,quotient,1,res/n) -BUILTIN_ARITH_OP(%,remainder,1,floatmod(res,n)) +BUILTIN_ARITH_OP(+,sum,0,res+n); +BUILTIN_ARITH_OP(-,difference,0,res-n); +BUILTIN_ARITH_OP(*,product,1,res*n); +BUILTIN_ARITH_OP(/,quotient,1,res/n); +BUILTIN_ARITH_OP(%,remainder,1,floatmod(res,n)); #undef BUILTIN_ARITH_OP + + +void convert_arguments(AST *ast,int nargs,const char **args){ + switch(ast->type){ + case AST_LIST: + for(int i=0;i<ast->li.len;i++)convert_arguments(ast->li.nodes[i],nargs,args); + break; + + case AST_LAMBDA: + if(ast->la.body)convert_arguments(ast->la.body,nargs,args); + break; + + case AST_WORD:{ + int i; + for(i=0;i<nargs;i++){ + if(strcmp(ast->wo.word,args[i])==0)break; + } + if(i==nargs)break; + free(ast->wo.word); + ast->type=AST_LAMBDAARG; + ast->ar.idx=i; + break; + } + + case AST_QUOTED: + convert_arguments(ast->qu.ast,nargs,args); + break; + + case AST_LAMBDAARG: + case AST_NUMBER: + case AST_STRING: + case AST_SYMBOL: + break; + + default: + assert(false); + } +} + +InterRet builtin_define(InterState *is,int nargs,AST **args){ + if(nargs!=3)return ir_err_c("Invalid number of arguments to builtin 'define'"); + if(args[0]->type!=AST_SYMBOL){ + return ir_err_c("First argument to builtin 'define' should be symbol"); + } + if(args[1]->type!=AST_LIST){ + return ir_err_c("Second argument to builtin 'define' should be quoted list"); + } + const AST *arglist=args[1]; + for(int i=0;i<arglist->li.len;i++){ + if(arglist->li.nodes[i]->type!=AST_WORD){ + return ir_err_c("Second argument to builtin 'define' should contain words"); + } + } + + const char *funcname=args[0]->sy.name; + AST *body=args[2]; + + const char *argnames[arglist->li.len]; + for(int i=0;i<arglist->li.len;i++)argnames[i]=arglist->li.nodes[i]->wo.word; + + convert_arguments(body,arglist->li.len,argnames); + + inter_assign(is,funcname,ast_lambda(NULL,ast_copy(body))); + return ir_ast(ast_list(0,malloc(1,AST*))); +} |