2023-12-20 19:54:58 +00:00
|
|
|
#include "fun.h"
|
|
|
|
#include "sym.h"
|
2023-12-23 20:17:12 +00:00
|
|
|
#include "locals.h"
|
|
|
|
#include "value.h"
|
2023-12-20 19:54:58 +00:00
|
|
|
|
|
|
|
void fun_init(fun_t* fun, struct tysy* tysy, err_t* err)
|
|
|
|
{
|
|
|
|
assert(fun);
|
2023-12-24 19:24:41 +00:00
|
|
|
fun->program = malloc(sizeof(program_t));
|
|
|
|
program_init(fun->program);
|
|
|
|
|
2023-12-23 20:17:12 +00:00
|
|
|
fun->err = err;
|
2023-12-20 19:54:58 +00:00
|
|
|
fun->sym = malloc(sizeof(sym_t));
|
|
|
|
sym_init((sym_t*) fun->sym, (tysy_t*) tysy, err);
|
2023-12-23 20:17:12 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2023-12-24 19:24:41 +00:00
|
|
|
program_free(clone->program);
|
|
|
|
free(clone->program);
|
|
|
|
clone->program = program_new_clone(fun->program);
|
|
|
|
|
2023-12-23 20:17:12 +00:00
|
|
|
for (size_t i=0; i<fun->closure.size; i++)
|
|
|
|
{
|
|
|
|
fun_capture(clone,
|
|
|
|
fun->closure.data[i]->id,
|
|
|
|
fun->closure.data[i]->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return clone;
|
2023-12-20 19:54:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void fun_free(fun_t* fun)
|
|
|
|
{
|
|
|
|
assert(fun);
|
2023-12-24 19:24:41 +00:00
|
|
|
|
|
|
|
program_free(fun->program);
|
|
|
|
free(fun->program);
|
|
|
|
fun->program = NULL;
|
2023-12-20 19:54:58 +00:00
|
|
|
|
|
|
|
sym_free((sym_t*) fun->sym);
|
|
|
|
free(fun->sym);
|
2023-12-23 20:17:12 +00:00
|
|
|
|
|
|
|
locals_free((locals_t*) fun->locals);
|
|
|
|
free(fun->locals);
|
|
|
|
|
|
|
|
for (size_t i=0; i<fun->closure.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; i<fun->closure.size; i++)
|
|
|
|
{
|
|
|
|
if (fun->closure.data[i]->id == id)
|
|
|
|
{
|
|
|
|
return fun->closure.data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
2023-12-20 19:54:58 +00:00
|
|
|
}
|