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