#include "prim.h" #include "env.h" #include #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) typedef struct { const char *name; prim_proc_t prim_proc; } prim_table_entry_t; static void add(am_t *am) { assert(AM_ARGL(am)); int64_t total = 0; for (expr_t *list = AM_ARGL(am); !list->is_atom; list = list->pair.cdr) { assert(list->pair.car->is_atom); assert(list->pair.car->atom.type == ATOM_TYPE_INTEGER); total += list->pair.car->atom.integer; } AM_VAL(am) = expr_integer(am, total); } static void mul(am_t *am) { assert(AM_ARGL(am)); int64_t total = 1; for (expr_t *list = AM_ARGL(am); !list->is_atom; list = list->pair.cdr) { assert(list->pair.car->is_atom); assert(list->pair.car->atom.type == ATOM_TYPE_INTEGER); total *= list->pair.car->atom.integer; } AM_VAL(am) = expr_integer(am, total); } static void sub(am_t *am) { assert(AM_ARGL(am)); assert(!AM_ARGL(am)->is_atom); assert(AM_ARGL(am)->pair.car->is_atom); assert(AM_ARGL(am)->pair.car->atom.type == ATOM_TYPE_INTEGER); int64_t total = AM_ARGL(am)->pair.car->atom.integer; if (!AM_ARGL(am)->is_atom && AM_ARGL(am)->pair.cdr->is_atom) { total *= -1; } else { for (expr_t *list = AM_ARGL(am)->pair.cdr; !list->is_atom; list = list->pair.cdr) { assert(list->pair.car->is_atom); assert(list->pair.car->atom.type == ATOM_TYPE_INTEGER); total -= list->pair.car->atom.integer; } } AM_VAL(am) = expr_integer(am, total); } static const prim_table_entry_t prim_table[] = { { "+", add }, { "*", mul }, { "-", sub }, }; void prim_load(am_t *am) { for (unsigned i = 0; i < NELEMS(prim_table); ++i) { AM_EXPR(am) = expr_str_symbol(am, prim_table[i].name); AM_VAL(am) = expr_prim_proc(am, prim_table[i].prim_proc); env_set(am); } }