WIP change to store primitives in memory intead of code

This commit is contained in:
zongor 2025-08-23 21:29:46 -07:00
parent cc009b4a4a
commit 8aeeebc351
6 changed files with 202 additions and 123 deletions

View File

@ -1,5 +1,6 @@
#include "../../compiler.h" #include "../../compiler.h"
#include "../../vm.h" #include "../../vm.h"
#include "../../test.h"
#define MAX_SRC_SIZE 16384 #define MAX_SRC_SIZE 16384
@ -55,12 +56,14 @@ int main(int argc, char **argv) {
vm.memory_size = MEMORY_SIZE; vm.memory_size = MEMORY_SIZE;
if (argc == 1) { if (argc == 1) {
repl(&vm); test_loop_compile(&vm);
/* repl(&vm); */
} else if (argc == 2) { } else if (argc == 2) {
compileFile(argv[1], &vm); compileFile(argv[1], &vm);
} else { } else {
fprintf(stderr, "Usage: %s <file.zrl>\n", argv[0]); fprintf(stderr, "Usage: %s <file.zrl>\n", argv[0]);
return 64; return 64;
repl(&vm);
} }
bool running = true; bool running = true;

View File

@ -31,6 +31,7 @@ typedef struct {
} ParseRule; } ParseRule;
Parser parser; Parser parser;
SymbolTable st;
void errorAt(Token *token, const char *message) { void errorAt(Token *token, const char *message) {
if (parser.panicMode) if (parser.panicMode)
@ -309,11 +310,29 @@ static void expressionStatement(VM *vm) {
static void intDeclaration(VM *vm) { static void intDeclaration(VM *vm) {
/* insert variable name in symbol table */ /* insert variable name in symbol table */
uint32_t length = parser.previous.length - 2;
if (length > SYMBOL_NAME_SIZE) {
error("Variable names cannot be longer than 24 characters.");
return;
}
st.symbols[st.sc].type = INT;
st.symbols[st.sc].frame = vm->fp;
Frame f = vm->frames[vm->fp];
st.symbols[st.sc].reg = f.rp;
uint32_t i;
for (i = 0; i < length; i++) {
st.symbols[st.sc].name[i] = parser.previous.start[i + 1];
}
st.sc++;
if (match(TOKEN_EQ)) { if (match(TOKEN_EQ)) {
expression(vm); expression(vm);
} else { } else {
/* not sure here yet */ /* initialize as zero/null */
emitOp(vm, OP_LOADI, vm->frames[vm->fp].rp++, 0, 0);
vm->code[vm->cp++].i = 0;
} }
consume(TOKEN_SEMICOLON, "Expect ';' after expression."); consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
@ -337,6 +356,12 @@ bool compile(const char *source, VM *vm) {
parser.hadError = false; parser.hadError = false;
parser.panicMode = false; parser.panicMode = false;
st.sc = 0;
st.name[0] = 'm';
st.name[1] = 'a';
st.name[2] = 'i';
st.name[3] = 'n';
advance(); advance();
while (!match(TOKEN_EOF)) { while (!match(TOKEN_EOF)) {

View File

@ -18,7 +18,7 @@ typedef struct array_def_t {
#define SYMBOL_NAME_SIZE 24 #define SYMBOL_NAME_SIZE 24
typedef struct symbol_table_t { typedef struct symbol_t {
char name[SYMBOL_NAME_SIZE]; char name[SYMBOL_NAME_SIZE];
SymbolType type; SymbolType type;
union { union {
@ -26,6 +26,7 @@ typedef struct symbol_table_t {
ArrayDef ad; ArrayDef ad;
}; };
int8_t reg; int8_t reg;
uint8_t flags[3]; /* only use for padding now, might be used later*/
union { union {
uint32_t frame; uint32_t frame;
uint32_t ptr; uint32_t ptr;
@ -35,10 +36,13 @@ typedef struct symbol_table_t {
#define MODULE_NAME_SIZE 32 #define MODULE_NAME_SIZE 32
#define SYMBOL_COUNT 256 #define SYMBOL_COUNT 256
typedef struct module_t { typedef struct symbol_table_t {
char name[MODULE_NAME_SIZE]; char name[MODULE_NAME_SIZE];
Symbol symbols[SYMBOL_COUNT]; Symbol symbols[SYMBOL_COUNT];
} Module; uint32_t sc;
} SymbolTable;
extern SymbolTable st;
bool compile(const char *source, VM *vm); bool compile(const char *source, VM *vm);

View File

@ -1,109 +1,117 @@
#include "test.h" #include "test.h"
#include "vm.h" #include "vm.h"
bool test_add_compile(VM *vm) { bool test_add_compile(VM *vm) {
vm->code[vm->cp++].u = OP(OP_LOADU, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADU, 0, 0, 0);
vm->code[vm->cp++].u = 1; vm->code[vm->cp++].u = 0;
vm->code[vm->cp++].u = OP(OP_LOADU, 1, 0, 0); int_alloc(vm, 1);
vm->code[vm->cp++].u = 2; vm->code[vm->cp++].u = OP(OP_LOADU, 1, 1, 0);
vm->code[vm->cp++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */ vm->code[vm->cp++].u = 1;
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 2, 0); int_alloc(vm, 2);
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */ vm->code[vm->cp++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */ vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 2, 0);
return true; vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */
} vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* explicit halt */
return true;
bool test_loop_compile(VM *vm) { }
vm->code[vm->cp++].u = OP(OP_LOADF, 0, 0, 0); /* let a = 5.0 */
vm->code[vm->cp++].f = 5.0f; bool test_loop_compile(VM *vm) {
vm->code[vm->cp++].u = OP(OP_LOADI, 1, 0, 0); /* do (i = 50000, 0, -1) { */ vm->code[vm->cp++].u = OP(OP_LOADF, 0, 0, 0); /* let a = 5.0 */
vm->code[vm->cp++].i = 50000; uint32_t addr = real_alloc(vm, 5.0f);
vm->code[vm->cp++].u = OP(OP_LOADI, 2, 0, 0); /* loop check value */ vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].i = 0; vm->code[vm->cp++].u = OP(OP_LOADI, 1, 0, 0); /* do (i = 50000, 0, -1) { */
vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* loop incriment value */ addr = int_alloc(vm, 50000);
vm->code[vm->cp++].i = -1; vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_LOADU, 4, 0, 0); /* loop start */ vm->code[vm->cp++].u = OP(OP_LOADI, 2, 0, 0); /* loop check value */
uint32_t jmp = vm->cp + 1; addr = int_alloc(vm, 0);
vm->code[vm->cp++].u = jmp; vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_LOADF, 5, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* loop incriment value */
vm->code[vm->cp++].f = 5.0f; addr = int_alloc(vm, -1);
vm->code[vm->cp++].u = OP(OP_ADD_REAL, 0, 0, 5); /* a += 5.0; */ vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */ vm->code[vm->cp++].u = OP(OP_LOADU, 4, 0, 0); /* loop start */
vm->code[vm->cp++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */ int_alloc(vm, vm->cp + 1);
vm->code[vm->cp++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */ vm->code[vm->cp++].u = 4;
uint32_t prompt_addr = str_alloc(vm, "Enter a string:", 0); vm->code[vm->cp++].u = OP(OP_LOADF, 5, 0, 0);
vm->code[vm->cp++].u = OP(OP_LOADU, 5, 0, 0); addr = real_alloc(vm, 5.0f);
vm->code[vm->cp++].u = prompt_addr; vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 5, 0); /* print("Enter a string: "); */ vm->code[vm->cp++].u = OP(OP_ADD_REAL, 0, 0, 5); /* a += 5.0; */
vm->code[vm->cp++].u = OP(OP_READ_STRING, 2, 0, 0); /* let user_string = gets(); */ vm->code[vm->cp++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 1, 0); vm->code[vm->cp++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */ vm->code[vm->cp++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */
vm->code[vm->cp++].u = OP(OP_REAL_TO_STRING, 3, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADU, 5, 0, 0);
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(b.toS()); */ addr = str_alloc(vm, "Enter a string:", 0);
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 2, 0); /* print(user_string); */ printf("addr=%d\n", addr);
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* program done */ vm->code[vm->cp++].u = addr;
return true; vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 5, 0); /* print("Enter a string: "); */
} vm->code[vm->cp++].u = OP(OP_READ_STRING, 2, 0, 0); /* let user_string = gets(); */
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 1, 0);
bool test_add_function_compile(VM *vm) { vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */
/* fn main() */ vm->code[vm->cp++].u = OP(OP_REAL_TO_STRING, 3, 0, 0);
vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(b.toS()); */
vm->code[vm->cp++].i = 1; vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 2, 0); /* print(user_string); */
vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); /* program done */
vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */ return true;
vm->code[vm->cp++].i = 1; }
vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */ bool test_add_function_compile(VM *vm) {
vm->code[vm->cp++].u = 12; /* fn main() */
vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* get return value */ vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */
vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0); vm->code[vm->cp++].i = 1;
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(sum.toS()); */ vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */
/* fn add() */ vm->code[vm->cp++].i = 1;
vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* a int */ vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_POPI, 1, 0, 0); /* b int */ vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */
vm->code[vm->cp++].u = OP(OP_ADD_INT, 2, 1, 0); /* a + b */ vm->code[vm->cp++].u = 12;
vm->code[vm->cp++].u = OP(OP_PUSHI, 2, 0, 0); /* push on stack */ vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
return true; vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(sum.toS()); */
} vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0);
/* fn add() */
bool test_recursive_function_compile(VM *vm) { vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* a int */
/* fn main() */ vm->code[vm->cp++].u = OP(OP_POPI, 1, 0, 0); /* b int */
vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */ vm->code[vm->cp++].u = OP(OP_ADD_INT, 2, 1, 0); /* a + b */
vm->code[vm->cp++].i = 35; vm->code[vm->cp++].u = OP(OP_PUSHI, 2, 0, 0); /* push on stack */
vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */ return true;
vm->code[vm->cp++].u = 9; }
vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0); bool test_recursive_function_compile(VM *vm) {
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(fib(35).toS()); */ /* fn main() */
vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */
/* fn fib() */ vm->code[vm->cp++].i = 35;
vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* n int */ vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_LOADI, 1, 0, 0); /* 2 */ vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* ); */
vm->code[vm->cp++].i = 2; vm->code[vm->cp++].u = 9;
vm->code[vm->cp++].u = OP(OP_LOADI, 2, 0, 0); /* &fib */ vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
vm->code[vm->cp++].i = 32; vm->code[vm->cp++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
vm->code[vm->cp++].u = OP(OP_JLT_INT, 2, 0, 1); vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(fib(35).toS()); */
vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* 2 */ vm->code[vm->cp++].u = OP(OP_HALT, 0, 0, 0);
vm->code[vm->cp++].i = 2; /* fn fib() */
vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3); vm->code[vm->cp++].u = OP(OP_POPI, 0, 0, 0); /* n int */
vm->code[vm->cp++].u = OP(OP_PUSHI, 4, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADI, 1, 0, 0); /* 2 */
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 2) */ vm->code[vm->cp++].i = 2;
vm->code[vm->cp++].u = 9; vm->code[vm->cp++].u = OP(OP_LOADI, 2, 0, 0); /* &fib */
vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* 1 */ vm->code[vm->cp++].i = 32;
vm->code[vm->cp++].i = 1; vm->code[vm->cp++].u = OP(OP_JLT_INT, 2, 0, 1);
vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3); vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* 2 */
vm->code[vm->cp++].u = OP(OP_PUSHI, 4, 0, 0); vm->code[vm->cp++].i = 2;
vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 1) */ vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3);
vm->code[vm->cp++].u = 9; vm->code[vm->cp++].u = OP(OP_PUSHI, 4, 0, 0);
vm->code[vm->cp++].u = OP(OP_POPI, 4, 0, 0); vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 2) */
vm->code[vm->cp++].u = OP(OP_POPI, 5, 0, 0); vm->code[vm->cp++].u = 9;
vm->code[vm->cp++].u = OP(OP_ADD_INT, 6, 5, 4); vm->code[vm->cp++].u = OP(OP_LOADI, 3, 0, 0); /* 1 */
vm->code[vm->cp++].u = OP(OP_PUSHI, 6, 0, 0); vm->code[vm->cp++].i = 1;
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_SUB_INT, 4, 0, 3);
vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_PUSHI, 4, 0, 0);
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 1) */
return true; vm->code[vm->cp++].u = 9;
} vm->code[vm->cp++].u = OP(OP_POPI, 4, 0, 0);
vm->code[vm->cp++].u = OP(OP_POPI, 5, 0, 0);
vm->code[vm->cp++].u = OP(OP_ADD_INT, 6, 5, 4);
vm->code[vm->cp++].u = OP(OP_PUSHI, 6, 0, 0);
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_PUSHI, 0, 0, 0);
vm->code[vm->cp++].u = OP(OP_RETURN, 0, 0, 0);
return true;
}

View File

@ -43,6 +43,27 @@ uint32_t str_alloc(VM *vm, const char *str, uint32_t length) {
return str_addr; return str_addr;
} }
uint32_t real_alloc(VM *vm, float v) {
uint32_t addr = vm->mp;
vm->memory[vm->mp++].f = v;
vm->frames[vm->fp].allocated.end++;
return addr;
}
uint32_t nat_alloc(VM *vm, uint32_t v) {
uint32_t addr = vm->mp;
vm->memory[vm->mp++].u = v;
vm->frames[vm->fp].allocated.end++;
return addr;
}
uint32_t int_alloc(VM *vm, int32_t v) {
uint32_t addr = vm->mp;
vm->memory[vm->mp++].i = v;
vm->frames[vm->fp].allocated.end++;
return addr;
}
/** /**
* Step to the next opcode in the vm. * Step to the next opcode in the vm.
*/ */
@ -74,23 +95,35 @@ bool step_vm(VM *vm) {
vm->frames[vm->fp--].allocated.start; /* reset memory pointer to start vm->frames[vm->fp--].allocated.start; /* reset memory pointer to start
of old slice, pop the frame */ of old slice, pop the frame */
return true; return true;
case OP_LOADI: case OP_LOADI:{
vm->frames[vm->fp].registers[dest].i = vm->code[vm->pc++].i; uint32_t ptr = vm->code[vm->pc++].u;
int32_t v = vm->memory[ptr].i;
/* printf("loadi | ptr=%d value=%d dest=%d\n", ptr, v, dest); */
vm->frames[vm->fp].registers[dest].i = v;
return true; return true;
case OP_LOADU: }
vm->frames[vm->fp].registers[dest].u = vm->code[vm->pc++].u; case OP_LOADU:{
uint32_t ptr = vm->code[vm->pc++].u;
uint32_t v = vm->memory[ptr].u;
/* printf("loadu | ptr=%d value=%d dest=%d\n", ptr, v, dest); */
vm->frames[vm->fp].registers[dest].u = v;
return true; return true;
case OP_LOADF: }
vm->frames[vm->fp].registers[dest].f = vm->code[vm->pc++].f; case OP_LOADF: {
uint32_t ptr = vm->code[vm->pc++].u;
float v = vm->memory[ptr].f;
/* printf("loadf | ptr=%d value=%f dest=%d\n", ptr, v, dest); */
vm->frames[vm->fp].registers[dest].f = v;
return true; return true;
}
case OP_STOREI: case OP_STOREI:
vm->code[vm->pc++].i = vm->frames[vm->fp].registers[dest].i; vm->memory[vm->code[vm->pc++].u].i = vm->frames[vm->fp].registers[src1].i;
return true; return true;
case OP_STOREU: case OP_STOREU:
vm->code[vm->pc++].u = vm->frames[vm->fp].registers[dest].u; vm->memory[vm->code[vm->pc++].u].u = vm->frames[vm->fp].registers[src1].u;
return true; return true;
case OP_STOREF: case OP_STOREF:
vm->code[vm->pc++].f = vm->frames[vm->fp].registers[dest].f; vm->memory[vm->code[vm->pc++].u].f = vm->frames[vm->fp].registers[src1].f;
return true; return true;
case OP_PUSHI: case OP_PUSHI:
vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i; vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i;
@ -257,10 +290,13 @@ bool step_vm(VM *vm) {
case OP_PRINT_STRING: { case OP_PRINT_STRING: {
uint32_t ptr = (uint32_t)vm->frames[vm->fp].registers[src1].u; uint32_t ptr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
uint32_t length = vm->memory[ptr].u; uint32_t length = vm->memory[ptr].u;
printf("len=%d\n", length);
uint32_t str_src = ptr + 1; uint32_t str_src = ptr + 1;
uint32_t i; uint32_t i;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
uint8_t ch = vm->memory[str_src + (i / 4)].c[i % 4]; uint8_t ch = vm->memory[str_src + (i / 4)].c[i % 4];
printf("char=%c\n", ch);
if (ch == '\0') if (ch == '\0')
break; break;
putchar(ch); putchar(ch);

View File

@ -6,5 +6,8 @@
VM* init_vm(); VM* init_vm();
bool step_vm(VM *vm); bool step_vm(VM *vm);
uint32_t str_alloc(VM *vm, const char *str, uint32_t length); uint32_t str_alloc(VM *vm, const char *str, uint32_t length);
uint32_t real_alloc(VM *vm, float v);
uint32_t nat_alloc(VM *vm, uint32_t v);
uint32_t int_alloc(VM *vm, int32_t v);
#endif #endif