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