🐛 closure capture and local variables collisions.
parent
726b87cad5
commit
603dc6f53a
|
@ -66,3 +66,17 @@ assert i() eq 2
|
|||
assert h() eq 8
|
||||
assert i() eq 3
|
||||
|
||||
var j = fun (count)
|
||||
return fun ()
|
||||
count = count + 1
|
||||
count - 1
|
||||
end
|
||||
end
|
||||
|
||||
var k = j(37)
|
||||
assert k() eq 37
|
||||
assert k() eq 38
|
||||
assert k() eq 39
|
||||
assert k() eq 40
|
||||
assert k() eq 41
|
||||
|
||||
|
|
|
@ -149,6 +149,7 @@ void compiler_compile(struct compiler* self,
|
|||
}
|
||||
|
||||
compiler_compile(self, expr, prog, sym);
|
||||
|
||||
if (symbol->closure_id != SK_NO_CLOSURE)
|
||||
{
|
||||
prog_add_instr(prog, OP_CLOSURE_STORE, symbol->id);
|
||||
|
@ -167,7 +168,27 @@ void compiler_compile(struct compiler* self,
|
|||
break;
|
||||
}
|
||||
|
||||
if (symbol->closure_id != SK_NO_CLOSURE)
|
||||
struct env* itr = sym->env->parent;
|
||||
struct symbol* context = NULL;
|
||||
|
||||
while (itr)
|
||||
{
|
||||
struct symbol* s = env_try_get(itr, symbol->name);
|
||||
|
||||
if (s)
|
||||
{
|
||||
context = s;
|
||||
break;
|
||||
}
|
||||
|
||||
itr = itr->parent;
|
||||
}
|
||||
|
||||
if (0 && context)
|
||||
{
|
||||
prog_add_instr(prog, OP_LOCAL_LOAD, context->id);
|
||||
}
|
||||
else if (symbol->closure_id != SK_NO_CLOSURE)
|
||||
{
|
||||
prog_add_instr(prog, OP_CLOSURE_LOAD, symbol->id);
|
||||
}
|
||||
|
@ -189,14 +210,7 @@ void compiler_compile(struct compiler* self,
|
|||
prog_init(p);
|
||||
|
||||
fun_init(fun, p);
|
||||
|
||||
for (size_t i=0; i<sym->env->symbols.size; i++)
|
||||
{
|
||||
struct symbol* s = sym->env->symbols.data[i];
|
||||
sym_decl_closure(fun->sym, s->id, s->name);
|
||||
}
|
||||
|
||||
struct node* args = node->children.data[0];
|
||||
struct node* params = node->children.data[0];
|
||||
struct node* body = node->children.data[1];
|
||||
|
||||
char* var_name =
|
||||
|
@ -204,9 +218,9 @@ void compiler_compile(struct compiler* self,
|
|||
self->var_names.data[self->var_names.size - 1]
|
||||
: NULL;
|
||||
|
||||
for (size_t i=0; i<args->children.size; i++)
|
||||
for (size_t i=0; i<params->children.size; i++)
|
||||
{
|
||||
struct node* child = args->children.data[i];
|
||||
struct node* child = params->children.data[i];
|
||||
char* name = child->token->value;
|
||||
sym_decl_var(fun->sym, name);
|
||||
}
|
||||
|
@ -215,6 +229,30 @@ void compiler_compile(struct compiler* self,
|
|||
{
|
||||
sym_decl_var(fun->sym, var_name);
|
||||
}
|
||||
|
||||
// Closure
|
||||
{
|
||||
for (size_t i=0; i<sym->env->symbols.size; i++)
|
||||
{
|
||||
struct symbol* s = sym->env->symbols.data[i];
|
||||
sym_decl_closure(fun->sym, s->id, s->name);
|
||||
}
|
||||
|
||||
if (sym->env->parent)
|
||||
{
|
||||
for (
|
||||
size_t i=0;
|
||||
i<sym->env->parent->symbols.size;
|
||||
i++
|
||||
)
|
||||
{
|
||||
struct symbol* s =
|
||||
sym->env->parent->symbols.data[i];
|
||||
|
||||
sym_decl_closure(fun->sym, s->id, s->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
compiler_compile(self, body, p, fun->sym);
|
||||
|
||||
union val val;
|
||||
|
|
|
@ -308,6 +308,34 @@ void exec_capture_env(struct exec* self,
|
|||
struct env* env)
|
||||
{
|
||||
(void) self;
|
||||
|
||||
if (env->parent)
|
||||
{
|
||||
for (size_t i=0; i<env->parent->symbols.size; i++)
|
||||
{
|
||||
struct symbol* symbol = env->parent->symbols.data[i];
|
||||
if (symbol->closure_id != SK_NO_CLOSURE)
|
||||
{
|
||||
struct local* loc =
|
||||
state_try_get_local_by_id(
|
||||
state,
|
||||
symbol->closure_id
|
||||
);
|
||||
|
||||
if(!loc) { continue; }
|
||||
|
||||
struct value* val =
|
||||
state_try_get_value(
|
||||
state,
|
||||
loc->addr
|
||||
);
|
||||
|
||||
fun_capture(fun, symbol->id, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (env)
|
||||
{
|
||||
for (size_t i=0; i<env->symbols.size; i++)
|
||||
{
|
||||
struct symbol* symbol = env->symbols.data[i];
|
||||
|
@ -319,6 +347,8 @@ void exec_capture_env(struct exec* self,
|
|||
symbol->closure_id
|
||||
);
|
||||
|
||||
if(!loc) { continue; }
|
||||
|
||||
struct value* val =
|
||||
state_try_get_value(
|
||||
state,
|
||||
|
@ -328,4 +358,5 @@ void exec_capture_env(struct exec* self,
|
|||
fun_capture(fun, symbol->id, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,6 +314,7 @@ void state_closure_load(struct state* self,
|
|||
int id)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
struct frame* frame = state_frame(self);
|
||||
assert(frame->fun);
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ int sym_decl_closure(struct sym* self, int id, char const* name)
|
|||
{
|
||||
assert(self);
|
||||
assert(name);
|
||||
|
||||
struct symbol* symbol = malloc(sizeof(struct symbol));
|
||||
symbol_init(symbol, self->closure_counter, name, self->env);
|
||||
symbol->is_const = false;
|
||||
|
|
Loading…
Reference in New Issue