moka/lib/exec.c

114 lines
2.8 KiB
C
Raw Normal View History

2024-03-26 18:31:33 +00:00
#include "exec.h"
void exec_init(struct exec* self)
{
assert(self);
self->pc = 0;
}
void exec_free(struct exec* self)
{
assert(self);
}
void exec_prog(struct exec* self,
struct moka* moka,
struct prog* prog)
{
assert(self); assert(moka); assert(prog);
self->pc = 0;
while (self->pc < prog->instructions.size)
{
exec_instr(self,
moka,
prog,
prog->instructions.data[self->pc]);
}
}
void exec_instr(struct exec* self,
struct moka* moka,
struct prog* prog,
struct instruction* instr)
{
assert(self); assert(moka); assert(instr);
int param = instr->param;
switch (instr->opcode)
{
case OP_CALL: {
MOKA fun = moka_pop(moka);
struct vec args;
vec_init(&args);
for (ssize_t i=0; i<param; i++)
{
MOKA arg = moka_pop(moka);
vec_push(&args, (void*) arg);
}
struct value* val = moka->global_values.data[
moka_get_ref(moka, fun)
];
assert(val->type == TY_NATIVE);
struct native* native = val->data.native;
(native->fun)(moka, &args);
vec_free(&args);
self->pc++;
} break;
case OP_GLOBAL_LOAD: {
moka_push_ref(moka, param, 0);
self->pc++;
} break;
2024-03-26 18:31:33 +00:00
case OP_PUSH: {
struct value* value = prog->values.data[param];
switch (value->type)
{
case TY_INT: {
moka_push_int(moka, value->data.integer, value->line);
} break;
case TY_FLOAT: {
moka_push_float(moka, value->data.real, value->line);
} break;
case TY_BOOL: {
moka_push_bool(moka, value->data.boolean, value->line);
} break;
case TY_STRING: {
moka_push_string(moka, value->data.str, value->line);
} break;
case TY_SYMBOL: {
moka_push_symbol(moka, value->data.sym, value->line);
} break;
case TY_LAZY: {
moka_push_lazy(moka, value->data.lazy, value->line);
} break;
2024-03-26 18:31:33 +00:00
default: {
fprintf(stderr,
"cannot push value of type <%s>\n",
TypeKindStr[value->type]
);
abort();
} break;
}
self->pc++;
} break;
default: {
fprintf(stderr, "cannot execute opcode <%s>\n",
OpcodeKindStr[instr->opcode]);
abort();
} break;
}
}