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.return_stack_size = STACK_SIZE;
|
||||||
vm.stack_size = STACK_SIZE;
|
vm.stack_size = STACK_SIZE;
|
||||||
vm.memory_size = MEMORY_SIZE;
|
vm.memory_size = MEMORY_SIZE;
|
||||||
test_add_function_compile(vm.memory);
|
test_recursive_function_compile(vm.memory);
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
emscripten_set_main_loop(mainloop, 0, 1);
|
emscripten_set_main_loop(mainloop, 0, 1);
|
||||||
|
|
|
@ -23,7 +23,7 @@ typedef struct {
|
||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
#define MEMORY_SIZE 65536
|
#define MEMORY_SIZE 65536
|
||||||
#define FRAMES_SIZE 32
|
#define FRAMES_SIZE 128
|
||||||
#define STACK_SIZE 256
|
#define STACK_SIZE 256
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t pc; /* Program counter */
|
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 test_recursive_function_compile(Value *memory) {
|
||||||
uint32_t i = 3;
|
uint32_t i = 0;
|
||||||
memory[i++].u = OP(OP_POPU, 0, 0, 0); /* return ptr */
|
/* fn main() */
|
||||||
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' */
|
|
||||||
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */
|
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */
|
||||||
memory[i++].i = 35;
|
memory[i++].i = 35;
|
||||||
memory[i++].u = OP(OP_PUSHI, 0, 0, 0);
|
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_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_POPI, 0, 0, 0); /* get return value */
|
||||||
memory[i++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
|
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);
|
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;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
19
src/vm.c
19
src/vm.c
|
@ -49,7 +49,23 @@ bool step_vm(VM *vm) {
|
||||||
/* Advance to next instruction */
|
/* Advance to next instruction */
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
printOp(opcode, dest, src1, src2);
|
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) {
|
switch (opcode) {
|
||||||
case OP_HALT:
|
case OP_HALT:
|
||||||
|
@ -66,9 +82,6 @@ bool step_vm(VM *vm) {
|
||||||
case OP_RETURN:
|
case OP_RETURN:
|
||||||
vm->pc = vm->return_stack[--vm->rp].u; /* set pc to return address */
|
vm->pc = vm->return_stack[--vm->rp].u; /* set pc to return address */
|
||||||
Slice s = vm->frames[vm->fp].allocated; /* get allocated slice */
|
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->fp--; /* pop the frame */
|
||||||
vm->mp = s.start; /* reset memory pointer to start of old slice */
|
vm->mp = s.start; /* reset memory pointer to start of old slice */
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -13,4 +13,5 @@ add:
|
||||||
popi $0 ; int a
|
popi $0 ; int a
|
||||||
popi $1 ; int b
|
popi $1 ; int b
|
||||||
addi $2 $1 $0 ; a + 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) {
|
if (n < 2) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue