280 lines
5.9 KiB
C
280 lines
5.9 KiB
C
#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, "<", 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; i<args->size; 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; i<args->size; 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);
|
|
}
|
|
|
|
// 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; i<args->size; 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; i<args->size; 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; i<args->size; 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; i<args->size; 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; i<args->size; 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; i<args->size; i++)
|
|
{
|
|
MOKA arg = MK_EVAL((MOKA) args->data[i]);
|
|
moka_push(moka, arg);
|
|
}
|
|
|
|
return moka_pow(moka);
|
|
}
|