@@ -717,13 +717,19 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) {
717
717
// stuff for lambda and comprehensions and generators
718
718
void close_over_variables_etc (compiler_t * comp , scope_t * this_scope , int n_dict_params , int n_default_params ) {
719
719
// 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)
720
721
int nfree = 0 ;
721
722
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
+ }
727
733
}
728
734
}
729
735
}
@@ -2836,7 +2842,9 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
2836
2842
void compile_scope_compute_things (compiler_t * comp , scope_t * scope ) {
2837
2843
// in functions, turn implicit globals into explicit globals
2838
2844
// compute num_locals, and the index of each local
2845
+ // compute the index of free and cell vars (freevars[idx] in CPython)
2839
2846
scope -> num_locals = 0 ;
2847
+ int num_closed = 0 ;
2840
2848
for (int i = 0 ; i < scope -> id_info_len ; i ++ ) {
2841
2849
id_info_t * id = & scope -> id_info [i ];
2842
2850
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) {
2849
2857
if (id -> param || id -> kind == ID_INFO_KIND_LOCAL ) {
2850
2858
id -> local_num = scope -> num_locals ;
2851
2859
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 ;
2852
2867
}
2853
2868
}
2854
2869
2855
- // TODO compute the index of free and cell vars (freevars[idx] in CPython)
2856
-
2857
2870
// compute flags
2858
2871
//scope->flags = 0; since we set some things in parameters
2859
2872
if (scope -> kind != SCOPE_MODULE ) {
0 commit comments