summaryrefslogtreecommitdiff
path: root/inter_builtins.c
blob: cc96afdf600967e700655ad136440c825cf02534 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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