diff options
author | Benjamin Peterson <benjamin@python.org> | 2013-10-20 21:50:28 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2013-10-20 21:50:28 (GMT) |
commit | 6b4f7803f8be4b90c22dcf3737f4144cabff4d70 (patch) | |
tree | c0db1b6ecbe9b239c7fa6d741fb82eaf71a0fd7e /Python/compile.c | |
parent | a7a150c7c65e8022027ed0f48cd6f867fcf31949 (diff) | |
download | cpython-6b4f7803f8be4b90c22dcf3737f4144cabff4d70.zip cpython-6b4f7803f8be4b90c22dcf3737f4144cabff4d70.tar.gz cpython-6b4f7803f8be4b90c22dcf3737f4144cabff4d70.tar.bz2 |
cleanup the construction of __qualname__ (closes #19301 again)
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 152 |
1 files changed, 82 insertions, 70 deletions
diff --git a/Python/compile.c b/Python/compile.c index 5b23e61..32465f7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -94,6 +94,7 @@ enum { COMPILER_SCOPE_MODULE, COMPILER_SCOPE_CLASS, COMPILER_SCOPE_FUNCTION, + COMPILER_SCOPE_LAMBDA, COMPILER_SCOPE_COMPREHENSION, }; @@ -104,6 +105,7 @@ struct compiler_unit { PySTEntryObject *u_ste; PyObject *u_name; + PyObject *u_qualname; /* dot-separated qualified name (lazy) */ int u_scope_type; /* The following fields are dicts that map objects to @@ -199,6 +201,7 @@ static int compiler_call_helper(struct compiler *c, int n, expr_ty starargs, expr_ty kwargs); static int compiler_try_except(struct compiler *, stmt_ty); +static int compiler_set_qualname(struct compiler *); static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; @@ -506,6 +509,7 @@ compiler_unit_free(struct compiler_unit *u) } Py_CLEAR(u->u_ste); Py_CLEAR(u->u_name); + Py_CLEAR(u->u_qualname); Py_CLEAR(u->u_consts); Py_CLEAR(u->u_names); Py_CLEAR(u->u_varnames); @@ -620,6 +624,11 @@ compiler_enter_scope(struct compiler *c, identifier name, if (compiler_use_new_block(c) == NULL) return 0; + if (u->u_scope_type != COMPILER_SCOPE_MODULE) { + if (!compiler_set_qualname(c)) + return 0; + } + return 1; } @@ -647,71 +656,77 @@ compiler_exit_scope(struct compiler *c) } -static PyObject * -compiler_scope_qualname(struct compiler *c, identifier scope_name) +static int +compiler_set_qualname(struct compiler *c) { - Py_ssize_t stack_size; - int global_scope; _Py_static_string(dot, "."); - _Py_static_string(locals, "<locals>"); - struct compiler_unit *u; - PyObject *capsule, *name, *seq, *dot_str, *locals_str; - - u = c->u; - seq = PyList_New(0); - if (seq == NULL) - return NULL; + _Py_static_string(dot_locals, ".<locals>"); + Py_ssize_t stack_size; + struct compiler_unit *u = c->u; + PyObject *name, *base, *dot_str, *dot_locals_str; + base = NULL; stack_size = PyList_GET_SIZE(c->c_stack); assert(stack_size >= 1); - global_scope = stack_size == 1; - if (scope_name != NULL && !global_scope) { - int scope; - PyObject *mangled; + if (stack_size > 1) { + int scope, force_global = 0; + struct compiler_unit *parent; + PyObject *mangled, *capsule; + capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); - u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); - assert(u); - mangled = _Py_Mangle(u->u_private, scope_name); - if (!mangled) - return NULL; - scope = PyST_GetScope(u->u_ste, mangled); - Py_DECREF(mangled); - assert(scope != GLOBAL_IMPLICIT); - if (scope == GLOBAL_EXPLICIT) - global_scope = 1; - } - if (!global_scope) { - Py_ssize_t i; - for (i = 1; i < stack_size; i++) { - capsule = PyList_GET_ITEM(c->c_stack, i); - u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); - assert(u); - assert(u->u_scope_type != COMPILER_SCOPE_MODULE); - if (PyList_Append(seq, u->u_name)) - goto _error; - if (u->u_scope_type == COMPILER_SCOPE_FUNCTION) { - locals_str = _PyUnicode_FromId(&locals); - if (locals_str == NULL) - goto _error; - if (PyList_Append(seq, locals_str)) - goto _error; + parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + assert(parent); + + if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) { + assert(u->u_name); + mangled = _Py_Mangle(parent->u_private, u->u_name); + if (!mangled) + return 0; + scope = PyST_GetScope(parent->u_ste, mangled); + Py_DECREF(mangled); + assert(scope != GLOBAL_IMPLICIT); + if (scope == GLOBAL_EXPLICIT) + force_global = 1; + } + + if (!force_global) { + if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION + || parent->u_scope_type == COMPILER_SCOPE_LAMBDA) { + dot_locals_str = _PyUnicode_FromId(&dot_locals); + if (dot_locals_str == NULL) + return 0; + base = PyUnicode_Concat(parent->u_qualname, dot_locals_str); + if (base == NULL) + return 0; + } + else { + Py_INCREF(parent->u_qualname); + base = parent->u_qualname; } } } - u = c->u; - if (PyList_Append(seq, u->u_name)) - goto _error; - dot_str = _PyUnicode_FromId(&dot); - if (dot_str == NULL) - goto _error; - name = PyUnicode_Join(dot_str, seq); - Py_DECREF(seq); - return name; - -_error: - Py_XDECREF(seq); - return NULL; + if (base != NULL) { + dot_str = _PyUnicode_FromId(&dot); + if (dot_str == NULL) { + Py_DECREF(base); + return 0; + } + name = PyUnicode_Concat(base, dot_str); + Py_DECREF(base); + if (name == NULL) + return 0; + PyUnicode_Append(&name, u->u_name); + if (name == NULL) + return 0; + } + else { + Py_INCREF(u->u_name); + name = u->u_name; + } + u->u_qualname = name; + + return 1; } /* Allocate a new block and return a pointer to it. @@ -1661,9 +1676,10 @@ compiler_function(struct compiler *c, stmt_ty s) VISIT_IN_SCOPE(c, stmt, st); } co = assemble(c, 1); - qualname = compiler_scope_qualname(c, s->v.FunctionDef.name); + qualname = c->u->u_qualname; + Py_INCREF(qualname); compiler_exit_scope(c); - if (qualname == NULL || co == NULL) { + if (co == NULL) { Py_XDECREF(qualname); Py_XDECREF(co); return 0; @@ -1733,14 +1749,8 @@ compiler_class(struct compiler *c, stmt_ty s) return 0; } Py_DECREF(str); - /* store the __qualname__ */ - str = compiler_scope_qualname(c, s->v.ClassDef.name); - if (!str) { - compiler_exit_scope(c); - return 0; - } - ADDOP_O(c, LOAD_CONST, str, consts); - Py_DECREF(str); + assert(c->u->u_qualname); + ADDOP_O(c, LOAD_CONST, c->u->u_qualname, consts); str = PyUnicode_InternFromString("__qualname__"); if (!str || !compiler_nameop(c, str, Store)) { Py_XDECREF(str); @@ -1855,7 +1865,7 @@ compiler_lambda(struct compiler *c, expr_ty e) if (res < 0) return 0; kw_default_count = res; } - if (!compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, + if (!compiler_enter_scope(c, name, COMPILER_SCOPE_LAMBDA, (void *)e, e->lineno)) return 0; @@ -1874,9 +1884,10 @@ compiler_lambda(struct compiler *c, expr_ty e) ADDOP_IN_SCOPE(c, RETURN_VALUE); } co = assemble(c, 1); - qualname = compiler_scope_qualname(c, NULL); + qualname = c->u->u_qualname; + Py_INCREF(qualname); compiler_exit_scope(c); - if (qualname == NULL || co == NULL) + if (co == NULL) return 0; arglength = asdl_seq_LEN(args->defaults); @@ -3151,9 +3162,10 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, } co = assemble(c, 1); - qualname = compiler_scope_qualname(c, NULL); + qualname = c->u->u_qualname; + Py_INCREF(qualname); compiler_exit_scope(c); - if (qualname == NULL || co == NULL) + if (co == NULL) goto error; if (!compiler_make_closure(c, co, 0, qualname)) |