diff options
Diffstat (limited to 'src/builtin.h')
-rw-r--r-- | src/builtin.h | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/builtin.h b/src/builtin.h new file mode 100644 index 0000000..144ed4c --- /dev/null +++ b/src/builtin.h @@ -0,0 +1,98 @@ +#include "value.h" + +#define PROCEDURES(X) \ +/* X(symbol, name, argc) */ \ + X(plus, "+", 2) \ + X(minus, "-", 2) \ + X(cons, "cons", 2) \ + X(car, "car", 1) \ + X(cdr, "cdr", 1) \ + +// Number of builtin procedures +#define PLUS_ONE(_symbol, _name, _argc) 1 + +#define BUILTIN_PROCEDURES PROCEDURES(PLUS_ONE) 0 + +// Forward decalration of the procedures +#define DECLARE_PROCEDURE(proc) value_t proc(value_t *args) +#define FORWARD_DECLARATION(symbol, _name, _argc) \ + DECLARE_PROCEDURE(symbol); + +PROCEDURES(FORWARD_DECLARATION) + +// Fill procedure struct for the value_t +#define PROC_DESCRIPTION(symbol, _name, argc) \ + {argc, symbol}, + +struct proc_builtin builtin_proc_descriptions[] = { + PROCEDURES(PROC_DESCRIPTION) +}; + +// List of ordered names of procedures +#define PROC_NAME(symbol, name, _argc) \ + name, + +const char *builtin_proc_name_list[] = { + PROCEDURES(PROC_NAME) +}; + +// ----- Definitions ----- + +#define ASSERT_TYPE(proc, args, pos, vtype, fail) \ + if(args[pos]->type != vtype) { \ + err("Expected arg %d of %s to be %s instead of %s", \ + pos, #proc, "", ""); \ + fail; \ + } + +#define PROC_ASSERT_TYPE(pos, vtype, fail) \ + ASSERT_TYPE(P, args, pos, vtype, fail) + +#define P plus +DECLARE_PROCEDURE(P) +{ + PROC_ASSERT_TYPE(0, VALUE_INT, return VALUE_EMPTY); + PROC_ASSERT_TYPE(1, VALUE_INT, return VALUE_EMPTY); + + int sum = args[0]->value.num + args[1]->value.num; + return value_create(VALUE_INT, &sum); +} +#undef P + +#define P minus +DECLARE_PROCEDURE(P) +{ + PROC_ASSERT_TYPE(0, VALUE_INT, return VALUE_EMPTY); + PROC_ASSERT_TYPE(1, VALUE_INT, return VALUE_EMPTY); + + int difference = args[0]->value.num - args[1]->value.num; + return value_create(VALUE_INT, &difference); +} +#undef P + +#define P cons +DECLARE_PROCEDURE(P) +{ + struct cons cons = {value_copy(args[0]), value_copy(args[1])}; + return value_create(VALUE_CONS, &cons); +} +#undef P + +#define P car +DECLARE_PROCEDURE(P) +{ + PROC_ASSERT_TYPE(0, VALUE_CONS, return VALUE_EMPTY); + + value_t left = value_copy(args[0]->value.cons.left); + return left; +} +#undef P + +#define P cdr +DECLARE_PROCEDURE(P) +{ + PROC_ASSERT_TYPE(0, VALUE_CONS, return VALUE_EMPTY); + + value_t right = value_copy(args[0]->value.cons.right); + return right; +} +#undef P |