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