// SPDX-License-Identifier: MIT // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "bytecode.h" #include "error.h" #include "number.h" #include "object.h" #include "vm.h" #include <stddef.h> enum opcodes { OP_NUM = 0x01, OP_RET = 0x03, OP_CALL = 0x04, OP_NULL = 0x05, OP_GET = 0x06, OP_SET = 0x07, OP_DROP = 0x08, OP_DEPTH_CHECK = 0x09, }; // clang-format off static const unsigned char bytecode[] = { 0x09, 0x01, 0x05, 0x05, 0x05, 0x01, 0x6a, 0x02, 0x00, 0x00, 0x07, 0x01, 0x05, 0x06, 0x01, 0x06, 0x01, 0x04, 0x02, 0x41, 0x64, 0x64, 0x00, 0x07, 0x02, 0x05, 0x01, 0x02, 0x00, 0x00, 0x00, 0x06, 0x02, 0x04, 0x02, 0x4d, 0x69, 0x6e, 0x75, 0x73, 0x00, 0x07, 0x03, 0x06, 0x03, 0x07, 0x00, 0x08, 0x03, 0x03, }; // clang-format on void bytecode_run(VmState state) { const unsigned char *pos_code = &bytecode[0]; unsigned char op = OP_RET; while ((op = *pos_code++) != OP_RET) { switch (op) { case OP_NUM: { int num = 0; num |= *pos_code++ << 0; num |= *pos_code++ << 8; num |= *pos_code++ << 16; num |= *pos_code++ << 24; vm_stack_push(state, number_create(num)); break; } case OP_CALL: { int arg_count = *pos_code++; const char *dispatch = (const char *)pos_code; Object obj = vm_stack_pop(state); vm_call(state, obj, dispatch, arg_count); object_drop(&obj); break; } case OP_NULL: { vm_stack_push(state, NULL); break; } case OP_GET: { Object obj = vm_stack_get(state, *pos_code++); vm_stack_push(state, obj); break; } case OP_SET: { Object obj = vm_stack_pop(state); vm_stack_set(state, *pos_code++, obj); break; } case OP_DROP: { vm_stack_drop(state, *pos_code++); break; } case OP_DEPTH_CHECK: { int depth = *pos_code++; abort_if(vm_stack_depth(state) != depth, "stack depth mismatch"); break; } default: // Skip over ASCII and unknown OPs break; } } }