id_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, bool *added) { id_info_t *id_info = scope_find(scope, qst); if (id_info != NULL) { *added = false; return id_info; } // make sure we have enough memory if (scope->id_info_len >= scope->id_info_alloc) { scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc + MICROPY_ALLOC_SCOPE_ID_INC); scope->id_info_alloc += MICROPY_ALLOC_SCOPE_ID_INC; } // add new id to end of array of all ids; this seems to match CPython // important thing is that function arguments are first, but that is // handled by the compiler because it adds arguments before compiling the body id_info = &scope->id_info[scope->id_info_len++]; id_info->kind = 0; id_info->flags = 0; id_info->local_num = 0; id_info->qst = qst; *added = true; return id_info; }
id_info_t *scope_find_local_in_parent(scope_t *scope, qstr qst) { if (scope->parent == NULL) { return NULL; } for (scope_t *s = scope->parent; s->parent != NULL; s = s->parent) { id_info_t *id = scope_find(s, qst); if (id != NULL) { return id; } } return NULL; }
void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst) { // assumes pass is greater than 1, ie that all identifiers are defined in the scope id_info_t *id = scope_find(scope, qst); assert(id != NULL); // call the emit backend with the correct code if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { emit_method_table->name(emit, qst); } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) { emit_method_table->global(emit, qst); } else if (id->kind == ID_INFO_KIND_LOCAL) { emit_method_table->fast(emit, qst, id->local_num); } else { assert(id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE); emit_method_table->deref(emit, qst, id->local_num); } }
void emit_common_delete_id(emit_t *emit, const emit_method_table_t *emit_method_table, scope_t *scope, qstr qst) { // assumes pass is greater than 1, ie that all identifiers are defined in the scope id_info_t *id = scope_find(scope, qst); assert(id != NULL); // TODO can this ever fail? // call the emit backend with the correct code if (id == NULL || id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { EMIT(delete_name, qst); } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) { EMIT(delete_global, qst); } else if (id->kind == ID_INFO_KIND_LOCAL) { EMIT(delete_fast, qst, id->local_num); } else if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) { EMIT(delete_deref, qst, id->local_num); } else { assert(0); } }
id_info_t *scope_find_global(scope_t *scope, qstr qst) { while (scope->parent != NULL) { scope = scope->parent; } return scope_find(scope, qst); }