#include "fun.h" #include "sym.h" #include "locals.h" #include "value.h" void fun_init(fun_t* fun, struct tysy* tysy, err_t* err) { assert(fun); program_init(&fun->program); fun->err = err; fun->sym = malloc(sizeof(sym_t)); sym_init((sym_t*) fun->sym, (tysy_t*) tysy, err); fun->locals = malloc(sizeof(locals_t)); locals_init((locals_t*) fun->locals); fun->base = 0; fun->closure.size = 0; fun->closure.cap = 0; fun->closure.data = NULL; } fun_t* fun_new_clone(fun_t* fun) { assert(fun); fun_t* clone = malloc(sizeof(fun_t)); fun_init(clone, fun->tysy, fun->err); locals_free((locals_t*) clone->locals); free(clone->locals); clone->locals = (struct locals*) locals_new_clone((locals_t*) fun->locals); clone->base = fun->base; clone->arg_base = fun->arg_base; for (size_t i=0; iclosure.size; i++) { fun_capture(clone, fun->closure.data[i]->id, fun->closure.data[i]->value); } return clone; } void fun_free(fun_t* fun) { assert(fun); program_free(&fun->program); sym_free((sym_t*) fun->sym); free(fun->sym); locals_free((locals_t*) fun->locals); free(fun->locals); for (size_t i=0; iclosure.size; i++) { value_free((value_t*) fun->closure.data[i]->value); free(fun->closure.data[i]->value); free(fun->closure.data[i]); } free(fun->closure.data); fun->closure.data = NULL; } void fun_capture(fun_t* fun, int id, struct value* value) { assert(fun); assert(value); if (fun->closure.data == NULL) { fun->closure.cap = 2; fun->closure.data = malloc(sizeof(closure_entry_t*) * fun->closure.cap); } if (fun->closure.size >= fun->closure.cap) { fun->closure.cap *= 2; fun->closure.data = realloc(fun->closure.data, sizeof(closure_entry_t*) * fun->closure.cap); } fun->closure.data[fun->closure.size] = malloc(sizeof(closure_entry_t)); fun->closure.data[fun->closure.size]->id = id; fun->closure.data[fun->closure.size]->value = value_new_clone(value); fun->closure.size++; } closure_entry_t* fun_try_find_closure(fun_t* fun, int id) { assert(fun); for (size_t i=0; iclosure.size; i++) { if (fun->closure.data[i]->id == id) { return fun->closure.data[i]; } } return NULL; }