diff options
Diffstat (limited to 'inter_builtins.c')
-rw-r--r-- | inter_builtins.c | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/inter_builtins.c b/inter_builtins.c index ba00935..b4bcf22 100644 --- a/inter_builtins.c +++ b/inter_builtins.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE //asprintf #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -7,33 +8,84 @@ #include "interpreter.h" #include "util.h" +extern InterRet interpret(InterState *is,const AST *ast); + + InterRet builtin_do(InterState *is,int nargs,AST **args){ assert(args); InterRet ir; for(int i=0;i<nargs;i++){ assert(args[i]); - ir=inter_runcode(is,args[i]); + ir=interpret(is,args[i]); if(ir.errstr)return ir; if(i<nargs-1)ast_free(ir.ast); } return ir; } +InterRet builtin_if(InterState *is,int nargs,AST **args){ + assert(args); + if(nargs!=2&&nargs!=3){ + char *buf; + asprintf(&buf,"Builtin 'if' needs 2 or 3 arguments, got %d",nargs); + if(!buf)outofmem(); + return ir_err(buf); + } + bool cond; + switch(args[0]->type){ + case AST_LIST: cond=args[0]->li.len!=0; break; + case AST_LAMBDAARG: assert(false); + case AST_WORD: assert(false); + case AST_NUMBER: cond=args[0]->nu.num!=0; break; + case AST_STRING: cond=args[0]->st.len!=0; break; + default: + return ir_err_c("Invalid node type in condition of builtin 'if'"); + } + if(cond)return interpret(is,args[1]); + else if(nargs==3)return interpret(is,args[2]); + else return ir_ast(ast_list(0,malloc(1,AST*))); +} + InterRet builtin_print(InterState *is,int nargs,AST **args){ (void)is; assert(args); for(int i=0;i<nargs;i++){ assert(args[i]); - char *s=ast_stringify(args[i]); if(i>0)putchar(' '); - printf("%s",s); - free(s); + if(args[i]->type==AST_STRING){ + fwrite(args[i]->st.str,1,args[i]->st.len,stdout); + } else { + char *s=ast_stringify(args[i]); + printf("%s",s); + free(s); + } } putchar('\n'); return ir_ast(ast_list(0,malloc(1,AST*))); } +#define BUILTIN_LOGICAL_OP(op,name) \ + InterRet builtin_##name(InterState *is,int nargs,AST **args){ \ + (void)is; \ + assert(args); \ + if(nargs!=2||args[0]->type!=AST_NUMBER||args[1]->type!=AST_NUMBER){ \ + return ir_err_c("Logical operator '" #op "' expects two number arguments"); \ + } \ + return ir_ast(ast_number(args[0]->nu.num op args[1]->nu.num)); \ + } + + +BUILTIN_LOGICAL_OP(==,equals); +BUILTIN_LOGICAL_OP(>,greater); +BUILTIN_LOGICAL_OP(>=,greaterequals); +BUILTIN_LOGICAL_OP(<,less); +BUILTIN_LOGICAL_OP(<=,lessequals); + + +#undef BUILTIN_LOGICAL_OP + + #define BUILTIN_ARITH_OP(op,name,defval,expr) \ InterRet builtin_##name(InterState *is,int nargs,AST **args){ \ (void)is; \ |