add function example
This commit is contained in:
parent
c63d149bdb
commit
7ec2f90d38
|
@ -44,19 +44,39 @@ uint32_t test_loop_compile(Value *memory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t test_add_function_compile(Value *memory) {
|
uint32_t test_add_function_compile(Value *memory) {
|
||||||
uint32_t i = 0;
|
uint32_t i = 3;
|
||||||
memory[i++].u = OP(OP_POP_ARGS, 0, 0, 0);
|
memory[i++].u = OP(OP_POPU, 0, 0, 0); /* return ptr */
|
||||||
memory[i++].u = OP(OP_ADD_INT, 2, 1, 0);
|
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);
|
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);
|
memory[i++].u = OP(OP_HALT, 0, 0, 0);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t test_recursive_function_compile(Value *memory) {
|
uint32_t test_recursive_function_compile(Value *memory) {
|
||||||
uint32_t i = 0;
|
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);
|
memory[i++].u = OP(OP_HALT, 0, 0, 0);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
24
src/debug.c
24
src/debug.c
|
@ -23,6 +23,12 @@ void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
|
||||||
case OP_HALT:
|
case OP_HALT:
|
||||||
printf("[HALT] $%d, $%d, $%d\n", dest, src1, src2);
|
printf("[HALT] $%d, $%d, $%d\n", dest, src1, src2);
|
||||||
break;
|
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:
|
case OP_LOADI:
|
||||||
printf("[LOADI] $%d, $%d, $%d\n", dest, src1, src2);
|
printf("[LOADI] $%d, $%d, $%d\n", dest, src1, src2);
|
||||||
break;
|
break;
|
||||||
|
@ -41,6 +47,24 @@ void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
|
||||||
case OP_STOREF:
|
case OP_STOREF:
|
||||||
printf("[STOREF] $%d, $%d, $%d\n", dest, src1, src2);
|
printf("[STOREF] $%d, $%d, $%d\n", dest, src1, src2);
|
||||||
break;
|
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:
|
case OP_ADD_INT:
|
||||||
printf("[ADD_INT] $%d, $%d, $%d\n", dest, src1, src2);
|
printf("[ADD_INT] $%d, $%d, $%d\n", dest, src1, src2);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -54,7 +54,7 @@ int main(int argc, char **argv) {
|
||||||
vm.frames_size = FRAMES_SIZE;
|
vm.frames_size = FRAMES_SIZE;
|
||||||
vm.stack_size = STACK_SIZE;
|
vm.stack_size = STACK_SIZE;
|
||||||
vm.memory_size = MEMORY_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__
|
#ifdef __EMSCRIPTEN__
|
||||||
emscripten_set_main_loop(mainloop, 0, 1);
|
emscripten_set_main_loop(mainloop, 0, 1);
|
||||||
|
|
|
@ -17,7 +17,7 @@ typedef struct {
|
||||||
|
|
||||||
#define MAX_REGS 256
|
#define MAX_REGS 256
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Value registers[MAX_REGS]; /* R0-R[MAX_REGS-1] */
|
Value registers[MAX_REGS]; /* R0-R255 */
|
||||||
uint32_t rp; /* register pointer (last unused) */
|
uint32_t rp; /* register pointer (last unused) */
|
||||||
Slice allocated; /* start and end of global allocated block */
|
Slice allocated; /* start and end of global allocated block */
|
||||||
} Frame;
|
} Frame;
|
||||||
|
@ -31,11 +31,11 @@ typedef struct {
|
||||||
uint32_t rp; /* Return stack pointer (top of stack) */
|
uint32_t rp; /* Return stack pointer (top of stack) */
|
||||||
uint32_t mp; /* Memory pointer (last allocated value) */
|
uint32_t mp; /* Memory pointer (last allocated value) */
|
||||||
uint32_t frames_size;
|
uint32_t frames_size;
|
||||||
Frame frames[FRAMES_SIZE];
|
Frame frames[FRAMES_SIZE]; /* function call frames */
|
||||||
uint32_t stack_size;
|
uint32_t stack_size;
|
||||||
Value stack[STACK_SIZE];
|
Value stack[STACK_SIZE]; /* main stack */
|
||||||
uint32_t memory_size;
|
uint32_t memory_size;
|
||||||
Value memory[MEMORY_SIZE]; /* Memory array */
|
Value memory[MEMORY_SIZE]; /* memory array */
|
||||||
} VM;
|
} VM;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
27
src/vm.c
27
src/vm.c
|
@ -54,7 +54,6 @@ bool step_vm(VM *vm) {
|
||||||
case OP_HALT:
|
case OP_HALT:
|
||||||
return false;
|
return false;
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
vm->stack[++vm->rp].u = vm->pc; /* push return address */
|
|
||||||
vm->pc = vm->frames[vm->fp]
|
vm->pc = vm->frames[vm->fp]
|
||||||
.registers[dest]
|
.registers[dest]
|
||||||
.u; /* set pc to location of function in memory */
|
.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;
|
vm->frames[vm->fp].registers[dest].f = vm->memory[vm->pc++].f;
|
||||||
return true;
|
return true;
|
||||||
case OP_STOREI:
|
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;
|
return true;
|
||||||
case OP_STOREU:
|
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;
|
return true;
|
||||||
case OP_STOREF:
|
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;
|
return true;
|
||||||
case OP_ADD_INT:
|
case OP_ADD_INT:
|
||||||
MATH_OP(i, +);
|
MATH_OP(i, +);
|
||||||
|
@ -137,7 +154,7 @@ bool step_vm(VM *vm) {
|
||||||
vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
|
vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
|
||||||
return true;
|
return true;
|
||||||
case OP_JMP:
|
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;
|
return true;
|
||||||
case OP_JEQ_UINT: {
|
case OP_JEQ_UINT: {
|
||||||
COMPARE_AND_JUMP(uint32_t, u, ==);
|
COMPARE_AND_JUMP(uint32_t, u, ==);
|
||||||
|
|
Loading…
Reference in New Issue