#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; } }