#include "vm.h" #include "lib/commons.h" #include "lib/type.h" void vm_init(vm_t* vm, err_t* err) { assert(vm); vm->pc = 0; vm->bp = 0; vm->sp = 0; vm->err = err; } void vm_free(vm_t* vm) { assert(vm); } param_t vm_pop(vm_t* vm) { assert(vm); assert(vm->sp > 0); param_t param = vm->stack[vm->sp - 1]; vm->sp--; return param; } size_t vm_stack_str(vm_t* vm, char* buffer, size_t size) { assert(vm); assert(buffer); size_t sz = 0; for (size_t i=0; isp; i++) { sz += snprintf(buffer + sz, size - sz, "| %d |\n", vm->stack[vm->sp - 1 - i]); } return sz; } void vm_exec_mod(vm_t* vm, mod_t* mod) { assert(vm); vm->pc = 0; while (vm->pc < mod->program.size) { int status = vm_exec_instr(vm, mod, mod->program.ops[vm->pc], mod->program.params[vm->pc]); if (!status) { return; } } } int vm_exec_instr(vm_t* vm, mod_t* mod, Opcode op, param_t param) { assert(vm); switch (op) { case OP_PUSH: { if (vm->sp + 1 >= RZ_STACK_LIMIT) { fprintf(stderr, "Stack overflow\n"); abort(); } vm->stack[vm->sp] = param; vm->sp++; vm->pc++; } break; case OP_ASSERT: { param_t top = vm_pop(vm); value_t* value = mod->values.data[top]; if (value->type->kind != TYPE_BOOL) { char msg[RZ_STR_LIMIT]; snprintf(msg, RZ_STR_LIMIT, "type mismatch: BOOL expected, got %s.", TypeKindStr[value->type->kind] + strlen("TYPE_")); err_fatal(vm->err, msg, value->line); vm->pc++; break; } if (!value->value.bool) { fprintf(stderr, "\33[31mASSERT\33[0m[:%d] assertion failed\n", value->line); return 0; } vm->pc++; } break; default: { fprintf(stderr, "Cannot execute unknown opcode '%s'.\n", OpcodeStr[op]); abort(); }; } return 1; }