summaryrefslogtreecommitdiffstatshomepage
path: root/py/compile.c
diff options
context:
space:
mode:
authorDamien <damien.p.george@gmail.com>2013-12-10 18:28:17 +0000
committerDamien <damien.p.george@gmail.com>2013-12-10 18:28:17 +0000
commit318aec6ba984e6c559401fd99fef4f1a9c327417 (patch)
treea98a0aeefdf6f30ecec0d5cfb2ce4edbe30f5449 /py/compile.c
parent6332174ab45c3ac3433e4311a344bcfbb0bde652 (diff)
downloadmicropython-318aec6ba984e6c559401fd99fef4f1a9c327417.tar.gz
micropython-318aec6ba984e6c559401fd99fef4f1a9c327417.zip
py: emit correct id for closed over variables.
Diffstat (limited to 'py/compile.c')
-rw-r--r--py/compile.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/py/compile.c b/py/compile.c
index 5a4d2dae49..17aa20d249 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -717,13 +717,19 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) {
// stuff for lambda and comprehensions and generators
void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
// make closed over variables, if any
+ // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
int nfree = 0;
if (comp->scope_cur->kind != SCOPE_MODULE) {
- for (int i = 0; i < this_scope->id_info_len; i++) {
- id_info_t *id_info = &this_scope->id_info[i];
- if (id_info->kind == ID_INFO_KIND_FREE) {
- EMIT(load_closure, id_info->qstr, id_info->local_num);
- nfree += 1;
+ for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
+ id_info_t *id = &comp->scope_cur->id_info[i];
+ if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
+ for (int j = 0; j < this_scope->id_info_len; j++) {
+ id_info_t *id2 = &this_scope->id_info[j];
+ if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
+ EMIT(load_closure, id->qstr, id->local_num);
+ nfree += 1;
+ }
+ }
}
}
}
@@ -2836,7 +2842,9 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
// in functions, turn implicit globals into explicit globals
// compute num_locals, and the index of each local
+ // compute the index of free and cell vars (freevars[idx] in CPython)
scope->num_locals = 0;
+ int num_closed = 0;
for (int i = 0; i < scope->id_info_len; i++) {
id_info_t *id = &scope->id_info[i];
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) {
if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
id->local_num = scope->num_locals;
scope->num_locals += 1;
+ } else if (id->kind == ID_INFO_KIND_CELL) {
+ id->local_num = num_closed;
+ num_closed += 1;
+ } else if (id->kind == ID_INFO_KIND_FREE) {
+ id_info_t *id_parent = scope_find_local_in_parent(scope, id->qstr);
+ assert(id_parent != NULL); // should never be NULL
+ id->local_num = id_parent->local_num;
}
}
- // TODO compute the index of free and cell vars (freevars[idx] in CPython)
-
// compute flags
//scope->flags = 0; since we set some things in parameters
if (scope->kind != SCOPE_MODULE) {