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, 60 insertions, 0 deletions
diff --git a/inter_builtins.c b/inter_builtins.c
new file mode 100644
index 0000000..cc96afd
--- /dev/null
+++ b/inter_builtins.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "inter_builtins.h"
+#include "interpreter.h"
+#include "util.h"
+
+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]);
+ if(ir.errstr)return ir;
+ if(i<nargs-1)ast_free(ir.ast);
+ }
+ return ir;
+}
+
+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);
+ }
+ putchar('\n');
+ 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; \
+ assert(args); \
+ if(nargs==0)return ir_ast(ast_number(defval)); \
+ for(int i=0;i<nargs;i++){ \
+ assert(args[i]); \
+ if(args[i]->type!=AST_NUMBER){ \
+ return ir_err_c("Non-number argument passed to builtin '" #op "'"); \
+ } \
+ } \
+ double res=args[0]->nu.num; \
+ for(int i=1;i<nargs;i++){ \
+ double n=args[i]->nu.num; \
+ res=expr; \
+ } \
+ 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))
+
+#undef BUILTIN_ARITH_OP