Newer
Older
Tardis / lang / bytecode.c
// SPDX-License-Identifier: MIT
// Copyright (c) 2023 John Watts and the LuminaSensum contributors

#include "bytecode.h"
#include "error.h"
#include "number.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,
};

// clang-format off
static const unsigned char bytecode[] = {
0x05, 0x05, 0x05, 0x01, 0x6a, 0x02, 0x00, 0x00, 0x07, 0x01,
0x05, 0x06, 0x01, 0x06, 0x01, 0x04, 0x02, 0x41, 0x64, 0x64,
0x00, 0x08, 0x01, 0x07, 0x02, 0x05, 0x01, 0x02, 0x00, 0x00,
0x00, 0x06, 0x02, 0x04, 0x02, 0x4d, 0x69, 0x6e, 0x75, 0x73,
0x00, 0x08, 0x01, 0x07, 0x03, 0x06, 0x03, 0x07, 0x00, 0x08,
0x03, 0x03,
};
// clang-format on

void bytecode_run(struct vm_state *state, int arg_count) {
	(void)arg_count;
	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;
			struct object *obj = vm_stack_pop(state);
			vm_call(obj, dispatch, arg_count, state);
			object_drop(&obj);
			break;
		}
		case OP_NULL: {
			vm_stack_push(state, NULL);
			break;
		}
		case OP_GET: {
			struct object *obj = vm_stack_get(state, *pos_code++);
			vm_stack_push(state, obj);
			break;
		}
		case OP_SET: {
			struct object *obj = vm_stack_pop(state);
			vm_stack_set(state, *pos_code++, obj);
			break;
		}
		case OP_DROP: {
			vm_stack_drop(state, *pos_code++);
			break;
		}
		default:
			// Skip over ASCII and unknown OPs
			break;
		}
	}
}