ccm/lib/exec.c

131 lines
3.1 KiB
C
Raw Normal View History

2024-03-18 17:20:40 +00:00
#include "exec.h"
#include "bytecode.h"
void exec_init(exec_t* self)
{
assert(self);
self->pc = 0;
err_init(&self->err);
}
void exec_free(exec_t* self)
{
assert(self);
err_free(&self->err);
}
void exec_module(exec_t* self, module_t* module)
{
assert(self);
assert(module);
self->pc = 0;
while (self->pc < module->prog.instrs.size)
{
if (!err_is_ok(&self->err))
{
return;
}
instr_t const* instr = module->prog.instrs.data[self->pc];
exec_instr(self, module, instr->opcode, instr->param);
}
}
void exec_instr(exec_t* self,
module_t* module,
Opcode op,
int param)
{
assert(self);
ccm_t* ccm = &module->ccm;
switch (op)
{
case OP_ASSERT_NE:
case OP_ASSERT_EQ: {
CCM val = ccm_pop(ccm);
vec_t* values = ccm_from_tuple(ccm, val);
assert(values->size == 2);
int oracle = 1;
if (op == OP_ASSERT_NE)
{
oracle = 0;
}
if (value_equals(values->data[0],
values->data[1]) == !oracle)
{
char lhs[CCM_STRLEN];
value_str(values->data[0], lhs, CCM_STRLEN);
char rhs[CCM_STRLEN];
value_str(values->data[1], rhs, CCM_STRLEN);
char const* operator = oracle ? "==" : "!=";
err_push(
&self->err,
((value_t*) values->data[0])->line,
"assertion failed: <%s> %s <%s>",
lhs, operator, rhs
);
}
self->pc++;
} break;
case OP_PUSH: {
CCM value = (CCM) module->prog.constants.data[param];
ccm_push(ccm, value);
self->pc++;
} break;
case OP_POP: {
ccm_pop(ccm);
self->pc++;
} break;
case OP_ADD: { ccm_add(ccm); self->pc++; } break;
case OP_SUB: { ccm_sub(ccm); self->pc++; } break;
case OP_USUB: { ccm_usub(ccm); self->pc++; } break;
case OP_MUL: { ccm_mul(ccm); self->pc++; } break;
case OP_DIV: { ccm_div(ccm); self->pc++; } break;
case OP_MOD: { ccm_mod(ccm); self->pc++; } break;
case OP_POW: { ccm_pow(ccm); self->pc++; } break;
case OP_MK_TUPLE: {
vec_t* values = malloc(sizeof(vec_t));
vec_init(values);
int line = -1;
for (int i=0; i<param; i++)
{
CCM val = ccm_pop(ccm);
value_t* v = value_new_clone(ccm->values.data[val]);
vec_push(values, v);
if (line == -1)
{
line = v->line;
}
}
CCM value = ccm_to_tuple(ccm, values, line);
ccm_push(ccm, value);
self->pc++;
} break;
default: {
fprintf(stderr,
"cannot exec opcode '%s'",
OpcodeStr[op]);
abort();
}
}
}