summaryrefslogtreecommitdiff
path: root/inter_builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'inter_builtins.c')
-rw-r--r--inter_builtins.c77
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*)));
+}