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)
|
|
|
|
{
|
2024-03-27 10:49:10 +00:00
|
|
|
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;
|
|
|
|
|
2024-03-27 10:49:10 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|