#include "builtins.h" #include "node.h" #include "path.h" #include "module.h" #include "moka.h" void register_builtins(struct moka* moka) { assert(moka); moka_decl_native(moka, "println", mk_println, -1); moka_decl_native(moka, "define", mk_define, 2); moka_decl_native(moka, "array", mk_array, -1); moka_decl_native(moka, "assert-eqv!", mk_assert_eqv_mut, 2); moka_decl_native(moka, "do", mk_do, -1); moka_decl_native(moka, "set!", mk_set_mut, 2); moka_decl_native(moka, "<", mk_lt, 2); moka_decl_native(moka, "<=", mk_le, 2); moka_decl_native(moka, ">", mk_gt, 2); moka_decl_native(moka, ">=", mk_ge, 2); moka_decl_native(moka, "eqv?", mk_is_eqv, 2); moka_decl_native(moka, "nev?", mk_is_nev, 2); moka_decl_native(moka, "+", mk_add, -1); moka_decl_native(moka, "-", mk_sub, -1); moka_decl_native(moka, "*", mk_mul, -1); moka_decl_native(moka, "/", mk_div, -1); moka_decl_native(moka, "%", mk_mod, 2); moka_decl_native(moka, "^", mk_pow, 2); } MOKA mk_println(struct moka* moka, struct vec* args) { assert(moka); assert(args); int line = 0; for (size_t i=0; isize; i++) { MOKA val = (MOKA) args->data[i]; if (i > 0) { printf(" "); } else { line = moka_get_lazy(moka, val)->line; } moka_dump(moka, MK_EVAL(val)); } printf("\n"); return moka_push_int(moka, 0, line); } MOKA mk_define(struct moka* moka, struct vec* args) { assert(moka); assert(args); assert(args->size == 2); MOKA target = (MOKA) args->data[0]; MOKA value = MK_EVAL((MOKA) args->data[1]); struct node* node = moka_get_lazy(moka, target); moka_push(moka, value); assert(node->token); moka_decl_var(moka, node->token->value, value); return value; } MOKA mk_array(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = (MOKA) args->data[i]; MOKA val = MK_EVAL(arg); moka_push(moka, val); } moka_make_array(moka, args->size); return moka_top(moka); } MOKA mk_assert_eqv_mut(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA) args->data[0]); MOKA rhs = MK_EVAL((MOKA) args->data[1]); int line = moka_line(moka, lhs); char lhs_buf[MK_STRLEN]; moka_str(moka, lhs, lhs_buf, MK_STRLEN); char rhs_buf[MK_STRLEN]; moka_str(moka, rhs, rhs_buf, MK_STRLEN); if (!moka_is_eqv(moka, lhs, rhs)) { status_push(moka->status, STATUS_ERROR, line, "assertion failed\nlhs = %s\nrhs = %s", lhs_buf, rhs_buf); return moka_push_bool(moka, false, line); } return moka_push_bool(moka, true, line); } MOKA mk_do(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA value = 0; symtable_open_scope(&moka->symtable); for (size_t i=0; isize; i++) { value = MK_EVAL((MOKA) args->data[i]); } symtable_close_scope(&moka->symtable); return value; } MOKA mk_set_mut(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA mk_name = (MOKA) args->data[0]; MOKA value = MK_EVAL((MOKA)args->data[1]); struct frame* frame = moka_frame(moka); struct value* name = frame->local_values.data[mk_name]; struct node* node = name->data.lazy; struct entry* entry = symtable_try_get( &moka->symtable, node->token->value ); moka_push(moka, value); entry->addr = frame->local_values.size - 1; return value; } // Comparisons // =========== MOKA mk_lt(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA)args->data[0]); MOKA rhs = MK_EVAL((MOKA)args->data[1]); return moka_push_bool( moka, moka_is_lt(moka, lhs, rhs), moka_line(moka, lhs) ); } MOKA mk_le(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA)args->data[0]); MOKA rhs = MK_EVAL((MOKA)args->data[1]); return moka_push_bool( moka, !moka_is_gt(moka, lhs, rhs), moka_line(moka, lhs) ); } MOKA mk_gt(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA)args->data[0]); MOKA rhs = MK_EVAL((MOKA)args->data[1]); return moka_push_bool( moka, moka_is_gt(moka, lhs, rhs), moka_line(moka, lhs) ); } MOKA mk_ge(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA)args->data[0]); MOKA rhs = MK_EVAL((MOKA)args->data[1]); return moka_push_bool( moka, !moka_is_lt(moka, lhs, rhs), moka_line(moka, lhs) ); } MOKA mk_is_eqv(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA)args->data[0]); MOKA rhs = MK_EVAL((MOKA)args->data[1]); return moka_push_bool( moka, moka_is_eqv(moka, lhs, rhs), moka_line(moka, lhs) ); } MOKA mk_is_nev(struct moka* moka, struct vec* args) { assert(moka); assert(args); MOKA lhs = MK_EVAL((MOKA)args->data[0]); MOKA rhs = MK_EVAL((MOKA)args->data[1]); return moka_push_bool( moka, !moka_is_eqv(moka, lhs, rhs), moka_line(moka, lhs) ); } MOKA mk_add(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = MK_EVAL((MOKA) args->data[i]); moka_push(moka, arg); } return moka_add(moka, args->size); } MOKA mk_sub(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = MK_EVAL((MOKA) args->data[i]); moka_push(moka, arg); } return moka_sub(moka, args->size); } MOKA mk_mul(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = MK_EVAL((MOKA) args->data[i]); moka_push(moka, arg); } return moka_mul(moka, args->size); } MOKA mk_div(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = MK_EVAL((MOKA) args->data[i]); moka_push(moka, arg); } return moka_div(moka, args->size); } MOKA mk_mod(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = MK_EVAL((MOKA) args->data[i]); moka_push(moka, arg); } return moka_mod(moka); } MOKA mk_pow(struct moka* moka, struct vec* args) { assert(moka); assert(args); for (size_t i=0; isize; i++) { MOKA arg = MK_EVAL((MOKA) args->data[i]); moka_push(moka, arg); } return moka_pow(moka); }