summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2013-10-20 21:50:28 (GMT)
committerBenjamin Peterson <benjamin@python.org>2013-10-20 21:50:28 (GMT)
commit6b4f7803f8be4b90c22dcf3737f4144cabff4d70 (patch)
treec0db1b6ecbe9b239c7fa6d741fb82eaf71a0fd7e /Python/compile.c
parenta7a150c7c65e8022027ed0f48cd6f867fcf31949 (diff)
downloadcpython-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.c152
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))