gh-121404: extract compiler_lookup_arg out of compiler_make_closure (#122181)

This commit is contained in:
Irit Katriel 2024-07-24 17:22:18 +01:00 committed by GitHub
parent 794546fd53
commit 9ac606080a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1611,29 +1611,30 @@ finally:
static int static int
compiler_get_ref_type(struct compiler *c, PyObject *name) compiler_get_ref_type(struct compiler *c, PyObject *name)
{ {
int scope;
if (c->u->u_scope_type == COMPILER_SCOPE_CLASS && if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
(_PyUnicode_EqualToASCIIString(name, "__class__") || (_PyUnicode_EqualToASCIIString(name, "__class__") ||
_PyUnicode_EqualToASCIIString(name, "__classdict__"))) { _PyUnicode_EqualToASCIIString(name, "__classdict__"))) {
return CELL; return CELL;
} }
PySTEntryObject *ste = SYMTABLE_ENTRY(c); PySTEntryObject *ste = SYMTABLE_ENTRY(c);
scope = _PyST_GetScope(ste, name); int scope = _PyST_GetScope(ste, name);
if (scope == 0) { if (scope == 0) {
PyErr_Format(PyExc_SystemError, PyErr_Format(PyExc_SystemError,
"_PyST_GetScope(name=%R) failed: " "_PyST_GetScope(name=%R) failed: "
"unknown scope in unit %S (%R); " "unknown scope in unit %S (%R); "
"symbols: %R; locals: %R; globals: %R", "symbols: %R; locals: %R; "
"globals: %R",
name, name,
c->u->u_metadata.u_name, ste->ste_id, c->u->u_metadata.u_name, ste->ste_id,
ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names); ste->ste_symbols, c->u->u_metadata.u_varnames,
c->u->u_metadata.u_names);
return ERROR; return ERROR;
} }
return scope; return scope;
} }
static int static int
compiler_lookup_arg(PyObject *dict, PyObject *name) dict_lookup_arg(PyObject *dict, PyObject *name)
{ {
PyObject *v = PyDict_GetItemWithError(dict, name); PyObject *v = PyDict_GetItemWithError(dict, name);
if (v == NULL) { if (v == NULL) {
@ -1643,22 +1644,13 @@ compiler_lookup_arg(PyObject *dict, PyObject *name)
} }
static int static int
compiler_make_closure(struct compiler *c, location loc, compiler_lookup_arg(struct compiler *c, PyCodeObject *co, PyObject *name)
PyCodeObject *co, Py_ssize_t flags)
{ {
if (co->co_nfreevars) {
int i = PyUnstable_Code_GetFirstFree(co);
for (; i < co->co_nlocalsplus; ++i) {
/* Bypass com_addop_varname because it will generate
LOAD_DEREF but LOAD_CLOSURE is needed.
*/
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
/* Special case: If a class contains a method with a /* Special case: If a class contains a method with a
free variable that has the same name as a method, * free variable that has the same name as a method,
the name will be considered free *and* local in the * the name will be considered free *and* local in the
class. It should be handled by the closure, as * class. It should be handled by the closure, as
well as by the normal name lookup logic. * well as by the normal name lookup logic.
*/ */
int reftype = compiler_get_ref_type(c, name); int reftype = compiler_get_ref_type(c, name);
if (reftype == -1) { if (reftype == -1) {
@ -1666,10 +1658,10 @@ compiler_make_closure(struct compiler *c, location loc,
} }
int arg; int arg;
if (reftype == CELL) { if (reftype == CELL) {
arg = compiler_lookup_arg(c->u->u_metadata.u_cellvars, name); arg = dict_lookup_arg(c->u->u_metadata.u_cellvars, name);
} }
else { else {
arg = compiler_lookup_arg(c->u->u_metadata.u_freevars, name); arg = dict_lookup_arg(c->u->u_metadata.u_freevars, name);
} }
if (arg == -1) { if (arg == -1) {
PyObject *freevars = _PyCode_GetFreevars(co); PyObject *freevars = _PyCode_GetFreevars(co);
@ -1687,6 +1679,22 @@ compiler_make_closure(struct compiler *c, location loc,
Py_DECREF(freevars); Py_DECREF(freevars);
return ERROR; return ERROR;
} }
return arg;
}
static int
compiler_make_closure(struct compiler *c, location loc,
PyCodeObject *co, Py_ssize_t flags)
{
if (co->co_nfreevars) {
int i = PyUnstable_Code_GetFirstFree(co);
for (; i < co->co_nlocalsplus; ++i) {
/* Bypass com_addop_varname because it will generate
LOAD_DEREF but LOAD_CLOSURE is needed.
*/
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
int arg = compiler_lookup_arg(c, co, name);
RETURN_IF_ERROR(arg);
ADDOP_I(c, loc, LOAD_CLOSURE, arg); ADDOP_I(c, loc, LOAD_CLOSURE, arg);
} }
flags |= MAKE_FUNCTION_CLOSURE; flags |= MAKE_FUNCTION_CLOSURE;
@ -2460,7 +2468,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
/* Set __classdictcell__ if necessary */ /* Set __classdictcell__ if necessary */
if (SYMTABLE_ENTRY(c)->ste_needs_classdict) { if (SYMTABLE_ENTRY(c)->ste_needs_classdict) {
/* Store __classdictcell__ into class namespace */ /* Store __classdictcell__ into class namespace */
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__)); int i = dict_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__));
if (i < 0) { if (i < 0) {
compiler_exit_scope(c); compiler_exit_scope(c);
return ERROR; return ERROR;
@ -2474,7 +2482,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
/* Return __classcell__ if it is referenced, otherwise return None */ /* Return __classcell__ if it is referenced, otherwise return None */
if (SYMTABLE_ENTRY(c)->ste_needs_class_closure) { if (SYMTABLE_ENTRY(c)->ste_needs_class_closure) {
/* Store __classcell__ into class namespace & return it */ /* Store __classcell__ into class namespace & return it */
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__)); int i = dict_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));
if (i < 0) { if (i < 0) {
compiler_exit_scope(c); compiler_exit_scope(c);
return ERROR; return ERROR;