add recursion, add benchmarks
This commit is contained in:
parent
19a69d3be5
commit
7598a93b31
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
50
src/test.c
50
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;
|
||||
}
|
||||
|
|
19
src/vm.c
19
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;
|
||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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";
|
|
@ -0,0 +1,7 @@
|
|||
def fib(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fib(n-1) + fib(n-2)
|
||||
|
||||
result = fib(35)
|
||||
print(result)
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
|||
fn fib(n) {
|
||||
if (n < 2) return n;
|
||||
return fib(n - 2) + fib(n - 1);
|
||||
}
|
||||
|
||||
print fib(35);
|
|
@ -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
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
int fib(int n) {
|
||||
fn fib(n int) {
|
||||
if (n < 2) {
|
||||
return n;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue