diff --git a/lib/compiler.c b/lib/compiler.c index e745f46..b3024c4 100644 --- a/lib/compiler.c +++ b/lib/compiler.c @@ -413,9 +413,9 @@ int compiler_run(compiler_t* compiler, node_t* node, program_t* program) fun->arg_base = *compiler->id; - 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); + 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); prepass_free(&pre); tysolver_free(&tysolver); diff --git a/lib/fun.c b/lib/fun.c index 63eab5f..7ed1795 100644 --- a/lib/fun.c +++ b/lib/fun.c @@ -6,7 +6,9 @@ void fun_init(fun_t* fun, struct tysy* tysy, err_t* err) { assert(fun); - program_init(&fun->program); + fun->program = malloc(sizeof(program_t)); + program_init(fun->program); + fun->err = err; fun->sym = malloc(sizeof(sym_t)); sym_init((sym_t*) fun->sym, (tysy_t*) tysy, err); @@ -34,6 +36,10 @@ fun_t* fun_new_clone(fun_t* fun) clone->base = fun->base; clone->arg_base = fun->arg_base; + program_free(clone->program); + free(clone->program); + clone->program = program_new_clone(fun->program); + for (size_t i=0; iclosure.size; i++) { fun_capture(clone, @@ -47,7 +53,10 @@ fun_t* fun_new_clone(fun_t* fun) void fun_free(fun_t* fun) { assert(fun); - program_free(&fun->program); + + program_free(fun->program); + free(fun->program); + fun->program = NULL; sym_free((sym_t*) fun->sym); free(fun->sym); diff --git a/lib/fun.h b/lib/fun.h index a498c30..b4d993d 100644 --- a/lib/fun.h +++ b/lib/fun.h @@ -15,7 +15,7 @@ typedef struct { } closure_entry_t; typedef struct { - program_t program; + program_t* program; err_t* err; struct sym* sym; struct tysy* tysy; diff --git a/lib/heap.c b/lib/heap.c index f355c72..87522bf 100644 --- a/lib/heap.c +++ b/lib/heap.c @@ -13,8 +13,8 @@ void heap_free(heap_t* heap) { for (size_t i=0; isize; i++) { - //value_free(heap->data[i]); - //free(heap->data[i]); + value_free(heap->data[i]); + free(heap->data[i]); } free(heap->data); diff --git a/lib/program.c b/lib/program.c index de08a74..e29439f 100644 --- a/lib/program.c +++ b/lib/program.c @@ -15,6 +15,32 @@ void program_init(program_t* program) program->values.data = NULL; } +program_t* program_new_clone(program_t* program) +{ + assert(program); + + program_t* clone = malloc(sizeof(program_t)); + program_init(clone); + + for (size_t i=0; isize; i++) + { + program_push_instr(clone, + program->ops[i], + program->params[i]); + + } + + for (size_t i=0; ivalues.size; i++) + { + char m[512]; value_str(program->values.data[i], m, 512); + + program_push_new_value(clone, + value_new_clone(program->values.data[i])); + } + + return clone; +} + void program_free(program_t* program) { assert(program); diff --git a/lib/program.h b/lib/program.h index 88ad1b2..6f35b51 100644 --- a/lib/program.h +++ b/lib/program.h @@ -21,6 +21,7 @@ typedef struct { } program_t; void program_init(program_t* program); +program_t* program_new_clone(program_t* program); void program_free(program_t* program); size_t program_push_instr(program_t* program, Opcode op, param_t param); diff --git a/lib/value.c b/lib/value.c index ea5af6b..3ac7da4 100644 --- a/lib/value.c +++ b/lib/value.c @@ -18,17 +18,32 @@ value_t* value_new_clone(value_t* value) value_t* clone = malloc(sizeof(value_t)); value_init(clone, value->type, value->line); - clone->value = value->value; - if (value->type->kind == TYPE_STR) { clone->value.str = strdup(value->value.str); } - - if (value->type->kind == TYPE_FUN) + else if (value->type->kind == TYPE_NUM) + { + clone->value.num = value->value.num; + } + else if (value->type->kind == TYPE_FUN) { clone->value.fun = fun_new_clone(value->value.fun); } + else if (value->type->kind == TYPE_REF) + { + clone->value.ref = value->value.ref; + } + else if (value->type->kind == TYPE_BOOL) + { + clone->value.bool = value->value.bool; + } + else + { + fprintf(stderr, "Cannot clone value of unknown type '%s'.", + TypeKindStr[value->type->kind]); + abort(); + } return clone; } diff --git a/lib/vm.c b/lib/vm.c index 82a20a3..d6be6a4 100644 --- a/lib/vm.c +++ b/lib/vm.c @@ -86,7 +86,7 @@ void vm_frame_push(vm_t* vm, fun_t* fun) if (fun != NULL) { - frame->program = &fun->program; + frame->program = fun->program; frame->locals = (locals_t*) fun->locals; } else @@ -103,8 +103,6 @@ int vm_frame_pop(vm_t* vm) if (vm->top_frame->fun) { - fun_free(vm->top_frame->fun); - free(vm->top_frame->fun); vm->top_frame->fun = NULL; } @@ -120,6 +118,7 @@ int vm_frame_pop(vm_t* vm) vm_frame_free(vm->top_frame); free(vm->top_frame); + vm->top_frame = NULL; vm->top_frame = prev; @@ -487,7 +486,6 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) if (vm->top_frame->fun) { - fun_t* fun = vm->top_frame->fun; closure_entry_t* closure = fun_try_find_closure(fun, param); @@ -508,7 +506,9 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) } break; case OP_MKFUN: { - value_t* value = vm_pop(vm); + value_t* value = value_new_clone(vm_pop(vm)); + + assert(value->type->kind == TYPE_FUN); size_t addr = heap_alloc(&vm->heap, value); value_t* ref = tysy_new_ref(vm->tysy, addr, value->line); @@ -518,7 +518,9 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) locals_t* loc = &vm->locals; assert(value->type->kind == TYPE_FUN); + fun_t* fun = value->value.fun; + frame_t* frame = vm->top_frame; if (vm->top_frame->fun) { @@ -527,18 +529,20 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) else if (prev && prev->fun) { loc = (locals_t*) prev->fun->locals; + frame = prev; } else if (prev) { loc = prev->locals; + frame = prev; } if (loc) { for (size_t i=0; isize; i++) { - int id = vm->top_frame->locals->data[i]->id; - value_t* loc_val = vm->top_frame->stack[addr]; + int id = frame->locals->data[i]->id; + value_t* loc_val = frame->stack[loc->data[i]->addr]; fun_capture(fun, id, loc_val); } @@ -571,10 +575,12 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) } value_t* fun_val = heap_deref(&vm->heap, fun_ref->value.ref); + assert(fun_val); assert(fun_val->type->kind == TYPE_FUN); - fun_t* fun = fun_new_clone(fun_val->value.fun); + assert(fun_val->value.fun); + fun_t* fun = fun_val->value.fun; vm->top_frame->pc++; vm_frame_push(vm, fun); @@ -595,6 +601,7 @@ int vm_exec_instr(vm_t* vm, Opcode op, param_t param) vm->top_frame->sp - 1); } + } break; case OP_RET: { diff --git a/tests/acceptances/fun.roza b/tests/acceptances/fun.roza index 51a2a5d..bef14aa 100644 --- a/tests/acceptances/fun.roza +++ b/tests/acceptances/fun.roza @@ -1,14 +1,14 @@ # FUNCTIONS # ========= fun double(n) - n * 2 + return n * 2 end assert double(4) == 8 assert 8 == double(4) -assert double(4) != 10 -assert 9 != double(4) +assert (double(4) == 10) == false +assert (9 == double(4)) == false assert double(double(double(3))) == 24