Skip to content

Commit 318aec6

Browse files
committed
py: emit correct id for closed over variables.
1 parent 6332174 commit 318aec6

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

py/compile.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -717,13 +717,19 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) {
717717
// stuff for lambda and comprehensions and generators
718718
void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
719719
// make closed over variables, if any
720+
// ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
720721
int nfree = 0;
721722
if (comp->scope_cur->kind != SCOPE_MODULE) {
722-
for (int i = 0; i < this_scope->id_info_len; i++) {
723-
id_info_t *id_info = &this_scope->id_info[i];
724-
if (id_info->kind == ID_INFO_KIND_FREE) {
725-
EMIT(load_closure, id_info->qstr, id_info->local_num);
726-
nfree += 1;
723+
for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
724+
id_info_t *id = &comp->scope_cur->id_info[i];
725+
if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
726+
for (int j = 0; j < this_scope->id_info_len; j++) {
727+
id_info_t *id2 = &this_scope->id_info[j];
728+
if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
729+
EMIT(load_closure, id->qstr, id->local_num);
730+
nfree += 1;
731+
}
732+
}
727733
}
728734
}
729735
}
@@ -2836,7 +2842,9 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
28362842
void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
28372843
// in functions, turn implicit globals into explicit globals
28382844
// compute num_locals, and the index of each local
2845+
// compute the index of free and cell vars (freevars[idx] in CPython)
28392846
scope->num_locals = 0;
2847+
int num_closed = 0;
28402848
for (int i = 0; i < scope->id_info_len; i++) {
28412849
id_info_t *id = &scope->id_info[i];
28422850
if (scope->kind == SCOPE_CLASS && id->qstr == comp->qstr___class__) {
@@ -2849,11 +2857,16 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
28492857
if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
28502858
id->local_num = scope->num_locals;
28512859
scope->num_locals += 1;
2860+
} else if (id->kind == ID_INFO_KIND_CELL) {
2861+
id->local_num = num_closed;
2862+
num_closed += 1;
2863+
} else if (id->kind == ID_INFO_KIND_FREE) {
2864+
id_info_t *id_parent = scope_find_local_in_parent(scope, id->qstr);
2865+
assert(id_parent != NULL); // should never be NULL
2866+
id->local_num = id_parent->local_num;
28522867
}
28532868
}
28542869

2855-
// TODO compute the index of free and cell vars (freevars[idx] in CPython)
2856-
28572870
// compute flags
28582871
//scope->flags = 0; since we set some things in parameters
28592872
if (scope->kind != SCOPE_MODULE) {

0 commit comments

Comments
 (0)