moka/lib/exec.c

117 lines
2.8 KiB
C

#include "exec.h"
#include "status.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]);
if (!status_is_ok(moka->status))
{
return;
}
}
}
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_MAKE_ARRAY: {
moka_make_array(moka, param);
self->pc++;
} break;
case OP_CALL: {
moka_call(moka, param);
if (!status_is_ok(moka->status))
{
return;
}
self->pc++;
} break;
case OP_GLOBAL_LOAD: {
moka_push_ref(moka, param, 0);
self->pc++;
} break;
case OP_LOCAL_LOAD: {
moka_push(moka, param);
self->pc++;
} break;
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;
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;
}
}