From 7598a93b318c2a3452d79ecac6e6b56ee2c0af85 Mon Sep 17 00:00:00 2001 From: zongor Date: Sat, 12 Jul 2025 23:14:23 -0400 Subject: [PATCH] add recursion, add benchmarks --- src/main.c | 2 +- src/opcodes.h | 2 +- src/test.c | 50 ++++++++++++++++++++++++----------------- src/vm.c | 19 +++++++++++++--- test/{add.asm => add.s} | 3 ++- test/bench/fib.lua | 8 +++++++ test/bench/fib.pl | 12 ++++++++++ test/bench/fib.py | 7 ++++++ test/bench/fib.wren | 10 +++++++++ test/bench/fib.zre | 6 +++++ test/bench/run.sh | 29 ++++++++++++++++++++++++ test/fib.s | 29 ++++++++++++++++++++++++ test/fib.zre | 2 +- 13 files changed, 152 insertions(+), 27 deletions(-) rename test/{add.asm => add.s} (88%) create mode 100644 test/bench/fib.lua create mode 100644 test/bench/fib.pl create mode 100644 test/bench/fib.py create mode 100644 test/bench/fib.wren create mode 100644 test/bench/fib.zre create mode 100755 test/bench/run.sh create mode 100644 test/fib.s diff --git a/src/main.c b/src/main.c index e63a6f7..a38fe34 100644 --- a/src/main.c +++ b/src/main.c @@ -30,7 +30,7 @@ int main(int argc, char **argv) { vm.return_stack_size = STACK_SIZE; vm.stack_size = STACK_SIZE; vm.memory_size = MEMORY_SIZE; - test_add_function_compile(vm.memory); + test_recursive_function_compile(vm.memory); #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(mainloop, 0, 1); diff --git a/src/opcodes.h b/src/opcodes.h index a0b878d..7d3ca6d 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -23,7 +23,7 @@ typedef struct { } Frame; #define MEMORY_SIZE 65536 -#define FRAMES_SIZE 32 +#define FRAMES_SIZE 128 #define STACK_SIZE 256 typedef struct { uint32_t pc; /* Program counter */ diff --git a/src/test.c b/src/test.c index 78e70f4..17aecb2 100644 --- a/src/test.c +++ b/src/test.c @@ -67,32 +67,42 @@ uint32_t test_add_function_compile(Value *memory) { } uint32_t test_recursive_function_compile(Value *memory) { - uint32_t i = 3; - memory[i++].u = OP(OP_POPU, 0, 0, 0); /* return ptr */ - memory[i++].u = OP(OP_POPI, 1, 0, 0); /* n int */ - /* if (n < 2) */ - /* return n; */ - memory[i++].u = OP(OP_POPI, 2, 0, 0); /* fib(n - 2) */ - memory[i++].u = OP(OP_POPI, 3, 0, 0); /* fib(n - 1) */ - memory[i++].u = OP(OP_ADD_INT, 4, 3, 2); /* add */ - memory[i++].u = OP(OP_PUSHI, 4, 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' */ + uint32_t i = 0; + /* fn main() */ memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */ memory[i++].i = 35; 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 = 9; 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(fib(35).toS()); */ memory[i++].u = OP(OP_HALT, 0, 0, 0); + /* fn fib() */ + memory[i++].u = OP(OP_POPI, 0, 0, 0); /* n int */ + memory[i++].u = OP(OP_LOADI, 1, 0, 0); /* 2 */ + memory[i++].i = 2; + memory[i++].u = OP(OP_LOADI, 2, 0, 0); /* &fib */ + memory[i++].i = 32; + memory[i++].u = OP(OP_JLT_INT, 2, 0, 1); + memory[i++].u = OP(OP_LOADI, 3, 0, 0); /* 2 */ + memory[i++].i = 2; + memory[i++].u = OP(OP_SUB_INT, 4, 0, 3); + memory[i++].u = OP(OP_PUSHI, 4, 0, 0); + memory[i++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 2) */ + memory[i++].u = 9; + memory[i++].u = OP(OP_LOADI, 3, 0, 0); /* 1 */ + memory[i++].i = 1; + memory[i++].u = OP(OP_SUB_INT, 4, 0, 3); + memory[i++].u = OP(OP_PUSHI, 4, 0, 0); + memory[i++].u = OP(OP_CALL, 0, 0, 0); /* fib(n - 1) */ + memory[i++].u = 9; + memory[i++].u = OP(OP_POPI, 4, 0, 0); + memory[i++].u = OP(OP_POPI, 5, 0, 0); + memory[i++].u = OP(OP_ADD_INT, 6, 5, 4); + memory[i++].u = OP(OP_PUSHI, 6, 0, 0); + memory[i++].u = OP(OP_RETURN, 0, 0, 0); + memory[i++].u = OP(OP_PUSHI, 0, 0, 0); + memory[i++].u = OP(OP_RETURN, 0, 0, 0); return i; } diff --git a/src/vm.c b/src/vm.c index bdfe93f..d3f4fe6 100644 --- a/src/vm.c +++ b/src/vm.c @@ -49,7 +49,23 @@ bool step_vm(VM *vm) { /* Advance to next instruction */ vm->pc++; + #ifdef DEBUG printOp(opcode, dest, src1, src2); + printf("dest=%d, src1=%d, src2=%d\n", vm->frames[vm->fp].registers[dest].u, + vm->frames[vm->fp].registers[src1].i, + vm->frames[vm->fp].registers[src2].i); + + uint32_t i; + printf("return_stack["); + for (i = 0; i < vm->rp; i++) + printf("%d,", vm->return_stack[i].u); + printf("]\n"); + + printf("stack["); + for (i = 0; i < vm->sp; i++) + printf("%d,", vm->stack[i].i); + printf("]\n"); + #endif switch (opcode) { case OP_HALT: @@ -66,9 +82,6 @@ bool step_vm(VM *vm) { case OP_RETURN: vm->pc = vm->return_stack[--vm->rp].u; /* set pc to return address */ Slice s = vm->frames[vm->fp].allocated; /* get allocated slice */ - memset(&vm->memory[s.start], 0, - s.end - s.start); /* deallocate memory from slice */ - memset(&vm->frames[vm->fp], 0, sizeof(Frame)); /* reset the frame */ vm->fp--; /* pop the frame */ vm->mp = s.start; /* reset memory pointer to start of old slice */ return true; diff --git a/test/add.asm b/test/add.s similarity index 88% rename from test/add.asm rename to test/add.s index 1ff3b38..e58002f 100644 --- a/test/add.asm +++ b/test/add.s @@ -13,4 +13,5 @@ add: popi $0 ; int a popi $1 ; int b addi $2 $1 $0 ; a + b - return $2 ; actually do the return + pushi $2 + return ; actually do the return diff --git a/test/bench/fib.lua b/test/bench/fib.lua new file mode 100644 index 0000000..d7ce19a --- /dev/null +++ b/test/bench/fib.lua @@ -0,0 +1,8 @@ +function fib(n) + if n < 2 then return n end + return fib(n-1) + fib(n-2) +end + +local result = fib(35) + +print(result) diff --git a/test/bench/fib.pl b/test/bench/fib.pl new file mode 100644 index 0000000..e246993 --- /dev/null +++ b/test/bench/fib.pl @@ -0,0 +1,12 @@ +use strict; +use warnings; + +sub fib { + my $n = shift; + return $n if $n < 2; + return fib($n-1) + fib($n-2); +} + +my $result = fib(35); + +print "$result\n"; diff --git a/test/bench/fib.py b/test/bench/fib.py new file mode 100644 index 0000000..c4ea615 --- /dev/null +++ b/test/bench/fib.py @@ -0,0 +1,7 @@ +def fib(n): + if n < 2: + return n + return fib(n-1) + fib(n-2) + +result = fib(35) +print(result) diff --git a/test/bench/fib.wren b/test/bench/fib.wren new file mode 100644 index 0000000..564109b --- /dev/null +++ b/test/bench/fib.wren @@ -0,0 +1,10 @@ +class Fib { + static fib(n) { + if (n < 2) return n + return fib(n-1) + fib(n-2) + } +} + +var result = Fib.fib(35) + +System.print(result) diff --git a/test/bench/fib.zre b/test/bench/fib.zre new file mode 100644 index 0000000..4eb78d1 --- /dev/null +++ b/test/bench/fib.zre @@ -0,0 +1,6 @@ +fn fib(n) { + if (n < 2) return n; + return fib(n - 2) + fib(n - 1); +} + +print fib(35); diff --git a/test/bench/run.sh b/test/bench/run.sh new file mode 100755 index 0000000..cc6d61b --- /dev/null +++ b/test/bench/run.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# Exit on error +set -e + +# Function to print section headers +print_section() { + printf '\n\e[1;34m%s\e[0m\n' "$1" +} + +# Lua Implementation +print_section "Lua (fib.lua)" +time lua fib.lua + +# Perl Implementation +print_section "Perl (fib.pl)" +time perl fib.pl + +# Python Implementation +print_section "Python (fib.py)" +time python3 fib.py + +# Wren Implementation +print_section "Wren (fib.wren)" +time wren fib.wren + +# ZRE Implementation +print_section "zre (fib.zre)" +time ../../src/zre #currently hardcoded diff --git a/test/fib.s b/test/fib.s new file mode 100644 index 0000000..d0895bf --- /dev/null +++ b/test/fib.s @@ -0,0 +1,29 @@ +main: + loadi $0 23 + pushi $0 + call &fib + popi $0 + itos $1 $0 + puts $1 + halt +fib: + popi $0 + loadi $1 2 + loadi $2 &base_case + jlt $2 $0 $1 + loadi $2 2 + subi $4 $0 $3 + pushi $4 + call &fib + load $2 1 + subi $4 $0 $3 + pushi $4 + call &fib + popi $4 + popi $5 + addi $6 $5 $4 + pushi $6 + return +base_case: + pushi $0 + return diff --git a/test/fib.zre b/test/fib.zre index 6f75023..50d0378 100644 --- a/test/fib.zre +++ b/test/fib.zre @@ -1,4 +1,4 @@ -int fib(int n) { +fn fib(n int) { if (n < 2) { return n; }