add function example

This commit is contained in:
zongor 2025-07-05 23:29:07 -04:00
parent c63d149bdb
commit 7ec2f90d38
5 changed files with 77 additions and 16 deletions

View File

@ -44,19 +44,39 @@ uint32_t test_loop_compile(Value *memory) {
}
uint32_t test_add_function_compile(Value *memory) {
uint32_t i = 0;
memory[i++].u = OP(OP_POP_ARGS, 0, 0, 0);
memory[i++].u = OP(OP_ADD_INT, 2, 1, 0);
uint32_t i = 3;
memory[i++].u = OP(OP_POPU, 0, 0, 0); /* return ptr */
memory[i++].u = OP(OP_POPI, 1, 0, 0); /* a int */
memory[i++].u = OP(OP_POPI, 2, 0, 0); /* b int */
memory[i++].u = OP(OP_ADD_INT, 3, 2, 1); /* a + b */
memory[i++].u = OP(OP_PUSHI, 3, 0, 0); /* return */
memory[i++].u = OP(OP_RETURN, 0, 0, 0);
uint32_t main = i;
memory[0].u = OP(OP_LOADF, 0, 0, 0);
memory[1].u = main;
memory[2].u = OP(OP_JMP, 0, 0, 0); /* jump to 'main' */
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */
memory[i++].i = 1;
memory[i++].u = OP(OP_PUSHI, 0, 0, 0);
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 1 */
memory[i++].i = 1;
memory[i++].u = OP(OP_PUSHI, 0, 0, 0);
uint32_t add_fn_return = i + 6; /* after the call */
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* return */
memory[i++].u = add_fn_return;
memory[i++].u = OP(OP_PUSHU, 0, 0, 0);
memory[i++].u = OP(OP_LOADU, 0, 0, 0); /* add fn ptr */
memory[i++].u = 3;
memory[i++].u = OP(OP_CALL, 0, 0, 0); /* ); */
memory[i++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
memory[i++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
memory[i++].u = OP(OP_PRINT_STRING, 0, 1, 0); /* print(sum.toS()); */
memory[i++].u = OP(OP_HALT, 0, 0, 0);
return i;
}
uint32_t test_recursive_function_compile(Value *memory) {
uint32_t i = 0;
memory[i++].u = OP(OP_POP_ARGS, 0, 0, 0);
memory[i++].u = OP(OP_ADD_INT, 2, 1, 0);
memory[i++].u = OP(OP_RETURN, 0, 0, 0);
memory[i++].u = OP(OP_HALT, 0, 0, 0);
return i;
}

View File

@ -23,6 +23,12 @@ void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
case OP_HALT:
printf("[HALT] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_CALL:
printf("[CALL] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_RETURN:
printf("[RETURN] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_LOADI:
printf("[LOADI] $%d, $%d, $%d\n", dest, src1, src2);
break;
@ -41,6 +47,24 @@ void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
case OP_STOREF:
printf("[STOREF] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_PUSHI:
printf("[PUSHI] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_PUSHU:
printf("[PUSHU] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_PUSHF:
printf("[PUSHF] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_POPI:
printf("[POPI] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_POPU:
printf("[POPU] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_POPF:
printf("[POPF] $%d, $%d, $%d\n", dest, src1, src2);
break;
case OP_ADD_INT:
printf("[ADD_INT] $%d, $%d, $%d\n", dest, src1, src2);
break;

View File

@ -54,7 +54,7 @@ int main(int argc, char **argv) {
vm.frames_size = FRAMES_SIZE;
vm.stack_size = STACK_SIZE;
vm.memory_size = MEMORY_SIZE;
vm.frames[vm.fp].allocated.end = test_loop_compile(vm.memory);
vm.frames[vm.fp].allocated.end = test_add_function_compile(vm.memory);
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(mainloop, 0, 1);

View File

@ -17,7 +17,7 @@ typedef struct {
#define MAX_REGS 256
typedef struct {
Value registers[MAX_REGS]; /* R0-R[MAX_REGS-1] */
Value registers[MAX_REGS]; /* R0-R255 */
uint32_t rp; /* register pointer (last unused) */
Slice allocated; /* start and end of global allocated block */
} Frame;
@ -31,11 +31,11 @@ typedef struct {
uint32_t rp; /* Return stack pointer (top of stack) */
uint32_t mp; /* Memory pointer (last allocated value) */
uint32_t frames_size;
Frame frames[FRAMES_SIZE];
Frame frames[FRAMES_SIZE]; /* function call frames */
uint32_t stack_size;
Value stack[STACK_SIZE];
Value stack[STACK_SIZE]; /* main stack */
uint32_t memory_size;
Value memory[MEMORY_SIZE]; /* Memory array */
Value memory[MEMORY_SIZE]; /* memory array */
} VM;
typedef enum {

View File

@ -54,7 +54,6 @@ bool step_vm(VM *vm) {
case OP_HALT:
return false;
case OP_CALL:
vm->stack[++vm->rp].u = vm->pc; /* push return address */
vm->pc = vm->frames[vm->fp]
.registers[dest]
.u; /* set pc to location of function in memory */
@ -85,13 +84,31 @@ bool step_vm(VM *vm) {
vm->frames[vm->fp].registers[dest].f = vm->memory[vm->pc++].f;
return true;
case OP_STOREI:
vm->memory[vm->pc++].i = vm->frames[vm->fp].registers[src1].i;
vm->memory[vm->pc++].i = vm->frames[vm->fp].registers[dest].i;
return true;
case OP_STOREU:
vm->memory[vm->pc++].u = vm->frames[vm->fp].registers[src1].u;
vm->memory[vm->pc++].u = vm->frames[vm->fp].registers[dest].u;
return true;
case OP_STOREF:
vm->memory[vm->pc++].f = vm->frames[vm->fp].registers[src1].f;
vm->memory[vm->pc++].f = vm->frames[vm->fp].registers[dest].f;
return true;
case OP_PUSHI:
vm->stack[++vm->rp].i = vm->frames[vm->fp].registers[dest].i;
return true;
case OP_PUSHU:
vm->stack[++vm->rp].u = vm->frames[vm->fp].registers[dest].u;
return true;
case OP_PUSHF:
vm->stack[++vm->rp].f = vm->frames[vm->fp].registers[dest].f;
return true;
case OP_POPI:
vm->frames[vm->fp].registers[dest].i = vm->stack[vm->rp--].i;
return true;
case OP_POPU:
vm->frames[vm->fp].registers[dest].u = vm->stack[vm->rp--].u;
return true;
case OP_POPF:
vm->frames[vm->fp].registers[dest].f = vm->stack[vm->rp--].f;
return true;
case OP_ADD_INT:
MATH_OP(i, +);
@ -137,7 +154,7 @@ bool step_vm(VM *vm) {
vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
return true;
case OP_JMP:
vm->pc = vm->frames[vm->fp].registers[src1].u; /* Jump to address */
vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
return true;
case OP_JEQ_UINT: {
COMPARE_AND_JUMP(uint32_t, u, ==);