diff --git a/lib/compiler.c b/lib/compiler.c index 5a2fd47..0bb7074 100644 --- a/lib/compiler.c +++ b/lib/compiler.c @@ -2,7 +2,9 @@ #include "lib/commons.h" #include "lib/mod.h" #include "lib/prepass.h" +#include "lib/program.h" #include "lib/sym.h" +#include "lib/tysy.h" #include "node.h" #include "fun.h" @@ -355,6 +357,8 @@ int compiler_run(compiler_t* compiler, node_t* node, program_t* program) fun_t* fun = malloc(sizeof(fun_t)); fun_init(fun, (struct tysy*) compiler->tysy, compiler->err); + value_t* value = tysy_new_fun(compiler->tysy, fun, node->line); + sym_entry_t* entry = sym_try_find_by_name(compiler->sym, fun_name, compiler->scope, @@ -378,6 +382,14 @@ int compiler_run(compiler_t* compiler, node_t* node, program_t* program) &tysolver, compiler->err); prepass_run(&pre, (node_t*) node->children.data[2]); + + // self + sym_declare((sym_t*) fun->sym, fun_name, + tysy_try_find_type(comp.tysy, "fun"), + comp.scope, + SYM_DECL, + node); + compiler_run(&comp, (node_t*) node->children.data[1], &fun->program); compiler_run(&comp, (node_t*) node->children.data[2], &fun->program); program_push_instr(&fun->program, OP_RET, RZ_NO_PARAM); @@ -387,7 +399,7 @@ int compiler_run(compiler_t* compiler, node_t* node, program_t* program) compiler_free(&comp); } - value_t* value = tysy_new_fun(compiler->tysy, fun, node->line); + // value_t* value = tysy_new_fun(compiler->tysy, fun, node->line); param_t param = program_push_new_value(program, (struct value*) value); program_push_instr(program, OP_PUSH, param); diff --git a/lib/vm.c b/lib/vm.c index d9bb131..c41aaed 100644 --- a/lib/vm.c +++ b/lib/vm.c @@ -505,17 +505,19 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) } break; case OP_CALL: { - size_t const ARG_SZ = param; + size_t const ARG_SZ = param + 1; value_t* args[ARG_SZ]; - fun_t* fun = vm_pop(vm)->value.fun; - for (size_t i=0; itype->kind == TYPE_FUN); + fun_t* fun = fun_val->value.fun; + vm->top_frame->pc++; vm_frame_push(vm, &fun->program); @@ -524,7 +526,7 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) value_t* arg = args[i]; vm_push(vm, arg); - vm_local_store(vm, i, vm->top_frame->sp - 1); + vm_local_store(vm, ARG_SZ - 1 - i, vm->top_frame->sp - 1); } } break; diff --git a/tests/acceptances/fun.roza b/tests/acceptances/fun.roza index d16b9db..777e79b 100644 --- a/tests/acceptances/fun.roza +++ b/tests/acceptances/fun.roza @@ -35,3 +35,26 @@ end assert max(7, 3) == 7 assert max(7, 9) == 9 + +# RECURSIVITY +# =========== + +fun fac(n) + if n == 0 then + return 1 + end + + return n * fac(n - 1) +end + +assert fac(5) == 120 + +fun fib(n) + if n == 0 or n == 1 then + return 1 + end + + return fib(n - 2) + fib(n - 1) +end + +assert fib(6) == 13 \ No newline at end of file