mirror of
https://github.com/python/cpython.git
synced 2024-11-28 04:15:11 +08:00
gh-121404: remove some accesses to compiler internals from codegen functions (#121538)
This commit is contained in:
parent
af9f6de6ea
commit
0177a34335
221
Python/compile.c
221
Python/compile.c
@ -71,11 +71,24 @@
|
||||
((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
|
||||
&& ((C)->u->u_ste->ste_type == ModuleBlock))
|
||||
|
||||
struct compiler;
|
||||
|
||||
typedef _PyInstruction instruction;
|
||||
typedef _PyInstructionSequence instr_sequence;
|
||||
|
||||
static instr_sequence *compiler_instr_sequence(struct compiler *c);
|
||||
static int compiler_future_features(struct compiler *c);
|
||||
static struct symtable *compiler_symtable(struct compiler *c);
|
||||
static PySTEntryObject *compiler_symtable_entry(struct compiler *c);
|
||||
|
||||
#define INSTR_SEQUENCE(C) compiler_instr_sequence(C)
|
||||
#define FUTURE_FEATURES(C) compiler_future_features(C)
|
||||
#define SYMTABLE(C) compiler_symtable(C)
|
||||
#define SYMTABLE_ENTRY(C) compiler_symtable_entry(C)
|
||||
|
||||
typedef _Py_SourceLocation location;
|
||||
typedef struct _PyCfgBuilder cfg_builder;
|
||||
|
||||
struct compiler;
|
||||
|
||||
static PyObject *compiler_maybe_mangle(struct compiler *c, PyObject *name);
|
||||
|
||||
#define LOCATION(LNO, END_LNO, COL, END_COL) \
|
||||
@ -133,12 +146,6 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
typedef _PyInstruction instruction;
|
||||
typedef _PyInstructionSequence instr_sequence;
|
||||
|
||||
#define INITIAL_INSTR_SEQUENCE_SIZE 100
|
||||
#define INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE 10
|
||||
|
||||
static const int compare_masks[] = {
|
||||
[Py_LT] = COMPARISON_LESS_THAN,
|
||||
[Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS,
|
||||
@ -258,8 +265,6 @@ struct compiler {
|
||||
*/
|
||||
};
|
||||
|
||||
#define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence)
|
||||
|
||||
|
||||
typedef struct {
|
||||
// A list of strings corresponding to name captures. It is used to track:
|
||||
@ -317,7 +322,6 @@ static int compiler_call_helper(struct compiler *c, location loc,
|
||||
asdl_keyword_seq *keywords);
|
||||
static int compiler_try_except(struct compiler *, stmt_ty);
|
||||
static int compiler_try_star_except(struct compiler *, stmt_ty);
|
||||
static int compiler_set_qualname(struct compiler *);
|
||||
|
||||
static int compiler_sync_comprehension_generator(
|
||||
struct compiler *c, location loc,
|
||||
@ -558,8 +562,8 @@ compiler_unit_free(struct compiler_unit *u)
|
||||
PyMem_Free(u);
|
||||
}
|
||||
|
||||
static struct compiler_unit *
|
||||
get_class_compiler_unit(struct compiler *c)
|
||||
static int
|
||||
compiler_add_static_attribute_to_class(struct compiler *c, PyObject *attr)
|
||||
{
|
||||
Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack);
|
||||
for (Py_ssize_t i = stack_size - 1; i >= 0; i--) {
|
||||
@ -568,10 +572,12 @@ get_class_compiler_unit(struct compiler *c)
|
||||
capsule, CAPSULE_NAME);
|
||||
assert(u);
|
||||
if (u->u_scope_type == COMPILER_SCOPE_CLASS) {
|
||||
return u;
|
||||
assert(u->u_static_attributes);
|
||||
RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, attr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -863,38 +869,37 @@ merge_consts_recursive(PyObject *const_cache, PyObject *o)
|
||||
}
|
||||
|
||||
static Py_ssize_t
|
||||
compiler_add_const(PyObject *const_cache, struct compiler_unit *u, PyObject *o)
|
||||
compiler_add_const(struct compiler *c, PyObject *o)
|
||||
{
|
||||
assert(PyDict_CheckExact(const_cache));
|
||||
PyObject *key = merge_consts_recursive(const_cache, o);
|
||||
PyObject *key = merge_consts_recursive(c->c_const_cache, o);
|
||||
if (key == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
Py_ssize_t arg = dict_add_o(u->u_metadata.u_consts, key);
|
||||
Py_ssize_t arg = dict_add_o(c->u->u_metadata.u_consts, key);
|
||||
Py_DECREF(key);
|
||||
return arg;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_addop_load_const(PyObject *const_cache, struct compiler_unit *u, location loc, PyObject *o)
|
||||
compiler_addop_load_const(struct compiler *c, location loc, PyObject *o)
|
||||
{
|
||||
Py_ssize_t arg = compiler_add_const(const_cache, u, o);
|
||||
Py_ssize_t arg = compiler_add_const(c, o);
|
||||
if (arg < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
return codegen_addop_i(u->u_instr_sequence, LOAD_CONST, arg, loc);
|
||||
return codegen_addop_i(INSTR_SEQUENCE(c), LOAD_CONST, arg, loc);
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_addop_o(struct compiler_unit *u, location loc,
|
||||
compiler_addop_o(struct compiler *c, location loc,
|
||||
int opcode, PyObject *dict, PyObject *o)
|
||||
{
|
||||
Py_ssize_t arg = dict_add_o(dict, o);
|
||||
if (arg < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
return codegen_addop_i(u->u_instr_sequence, opcode, arg, loc);
|
||||
return codegen_addop_i(INSTR_SEQUENCE(c), opcode, arg, loc);
|
||||
}
|
||||
|
||||
#define LOAD_METHOD -1
|
||||
@ -984,7 +989,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
|
||||
#define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
|
||||
|
||||
#define ADDOP_LOAD_CONST(C, LOC, O) \
|
||||
RETURN_IF_ERROR(compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), (O)))
|
||||
RETURN_IF_ERROR(compiler_addop_load_const((C), (LOC), (O)))
|
||||
|
||||
/* Same as ADDOP_LOAD_CONST, but steals a reference. */
|
||||
#define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \
|
||||
@ -992,7 +997,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
|
||||
if (__new_const == NULL) { \
|
||||
return ERROR; \
|
||||
} \
|
||||
if (compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), __new_const) < 0) { \
|
||||
if (compiler_addop_load_const((C), (LOC), __new_const) < 0) { \
|
||||
Py_DECREF(__new_const); \
|
||||
return ERROR; \
|
||||
} \
|
||||
@ -1001,7 +1006,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
|
||||
|
||||
#define ADDOP_N(C, LOC, OP, O, TYPE) { \
|
||||
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
|
||||
if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
|
||||
if (compiler_addop_o((C), (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
|
||||
Py_DECREF((O)); \
|
||||
return ERROR; \
|
||||
} \
|
||||
@ -1514,7 +1519,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
|
||||
/* If from __future__ import annotations is active,
|
||||
* every annotated class and module should have __annotations__.
|
||||
* Else __annotate__ is created when necessary. */
|
||||
if ((c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) && c->u->u_ste->ste_annotations_used) {
|
||||
if ((FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) && SYMTABLE_ENTRY(c)->ste_annotations_used) {
|
||||
ADDOP(c, loc, SETUP_ANNOTATIONS);
|
||||
}
|
||||
if (!asdl_seq_LEN(stmts)) {
|
||||
@ -1546,7 +1551,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
|
||||
// If there are annotations and the future import is not on, we
|
||||
// collect the annotations in a separate pass and generate an
|
||||
// __annotate__ function. See PEP 649.
|
||||
if (!(c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) &&
|
||||
if (!(FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) &&
|
||||
c->u->u_deferred_annotations != NULL) {
|
||||
|
||||
// It's possible that ste_annotations_block is set but
|
||||
@ -1554,11 +1559,12 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
|
||||
// set if there are only non-simple annotations (i.e., annotations
|
||||
// for attributes, subscripts, or parenthesized names). However, the
|
||||
// reverse should not be possible.
|
||||
assert(c->u->u_ste->ste_annotation_block != NULL);
|
||||
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||
assert(ste->ste_annotation_block != NULL);
|
||||
PyObject *deferred_anno = Py_NewRef(c->u->u_deferred_annotations);
|
||||
void *key = (void *)((uintptr_t)c->u->u_ste->ste_id + 1);
|
||||
void *key = (void *)((uintptr_t)ste->ste_id + 1);
|
||||
if (compiler_setup_annotations_scope(c, loc, key,
|
||||
c->u->u_ste->ste_annotation_block->ste_name) == -1) {
|
||||
ste->ste_annotation_block->ste_name) == -1) {
|
||||
Py_DECREF(deferred_anno);
|
||||
return ERROR;
|
||||
}
|
||||
@ -1642,13 +1648,8 @@ finally:
|
||||
return co;
|
||||
}
|
||||
|
||||
/* The test for LOCAL must come before the test for FREE in order to
|
||||
handle classes where name is both local and free. The local var is
|
||||
a method and the free var is a free var referenced within a method.
|
||||
*/
|
||||
|
||||
static int
|
||||
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 &&
|
||||
@ -1656,15 +1657,16 @@ get_ref_type(struct compiler *c, PyObject *name)
|
||||
_PyUnicode_EqualToASCIIString(name, "__classdict__"))) {
|
||||
return CELL;
|
||||
}
|
||||
scope = _PyST_GetScope(c->u->u_ste, name);
|
||||
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||
scope = _PyST_GetScope(ste, name);
|
||||
if (scope == 0) {
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"_PyST_GetScope(name=%R) failed: "
|
||||
"unknown scope in unit %S (%R); "
|
||||
"symbols: %R; locals: %R; globals: %R",
|
||||
name,
|
||||
c->u->u_metadata.u_name, c->u->u_ste->ste_id,
|
||||
c->u->u_ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names);
|
||||
c->u->u_metadata.u_name, ste->ste_id,
|
||||
ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names);
|
||||
return ERROR;
|
||||
}
|
||||
return scope;
|
||||
@ -1698,7 +1700,7 @@ compiler_make_closure(struct compiler *c, location loc,
|
||||
class. It should be handled by the closure, as
|
||||
well as by the normal name lookup logic.
|
||||
*/
|
||||
int reftype = get_ref_type(c, name);
|
||||
int reftype = compiler_get_ref_type(c, name);
|
||||
if (reftype == -1) {
|
||||
return ERROR;
|
||||
}
|
||||
@ -1858,7 +1860,7 @@ compiler_argannotation(struct compiler *c, identifier id,
|
||||
ADDOP_LOAD_CONST(c, loc, mangled);
|
||||
Py_DECREF(mangled);
|
||||
|
||||
if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {
|
||||
if (FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) {
|
||||
VISIT(c, annexpr, annotation);
|
||||
}
|
||||
else {
|
||||
@ -1940,7 +1942,7 @@ compiler_annotations(struct compiler *c, location loc,
|
||||
Py_ssize_t annotations_len = 0;
|
||||
|
||||
PySTEntryObject *ste;
|
||||
if (_PySymtable_LookupOptional(c->c_st, args, &ste) < 0) {
|
||||
if (_PySymtable_LookupOptional(SYMTABLE(c), args, &ste) < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
assert(ste != NULL);
|
||||
@ -2239,7 +2241,7 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
|
||||
docstring = NULL;
|
||||
}
|
||||
}
|
||||
if (compiler_add_const(c->c_const_cache, c->u, docstring ? docstring : Py_None) < 0) {
|
||||
if (compiler_add_const(c, docstring ? docstring : Py_None) < 0) {
|
||||
Py_XDECREF(docstring);
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
@ -2252,7 +2254,8 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
|
||||
|
||||
NEW_JUMP_TARGET_LABEL(c, start);
|
||||
USE_LABEL(c, start);
|
||||
bool add_stopiteration_handler = c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator;
|
||||
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||
bool add_stopiteration_handler = ste->ste_coroutine || ste->ste_generator;
|
||||
if (add_stopiteration_handler) {
|
||||
/* wrap_in_stopiteration_handler will push a block, so we need to account for that */
|
||||
RETURN_IF_ERROR(
|
||||
@ -2463,14 +2466,14 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
if (c->u->u_ste->ste_needs_classdict) {
|
||||
if (SYMTABLE_ENTRY(c)->ste_needs_classdict) {
|
||||
ADDOP(c, loc, LOAD_LOCALS);
|
||||
|
||||
// We can't use compiler_nameop here because we need to generate a
|
||||
// STORE_DEREF in a class namespace, and compiler_nameop() won't do
|
||||
// that by default.
|
||||
PyObject *cellvars = c->u->u_metadata.u_cellvars;
|
||||
if (compiler_addop_o(c->u, loc, STORE_DEREF, cellvars,
|
||||
if (compiler_addop_o(c, loc, STORE_DEREF, cellvars,
|
||||
&_Py_ID(__classdict__)) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
@ -2495,7 +2498,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
|
||||
}
|
||||
/* The following code is artificial */
|
||||
/* Set __classdictcell__ if necessary */
|
||||
if (c->u->u_ste->ste_needs_classdict) {
|
||||
if (SYMTABLE_ENTRY(c)->ste_needs_classdict) {
|
||||
/* Store __classdictcell__ into class namespace */
|
||||
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__));
|
||||
if (i < 0) {
|
||||
@ -2509,7 +2512,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
|
||||
}
|
||||
}
|
||||
/* Return __classcell__ if it is referenced, otherwise return None */
|
||||
if (c->u->u_ste->ste_needs_class_closure) {
|
||||
if (SYMTABLE_ENTRY(c)->ste_needs_class_closure) {
|
||||
/* Store __classcell__ into class namespace & return it */
|
||||
int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));
|
||||
if (i < 0) {
|
||||
@ -2667,7 +2670,7 @@ compiler_typealias_body(struct compiler *c, stmt_ty s)
|
||||
compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno, NULL));
|
||||
/* Make None the first constant, so the evaluate function can't have a
|
||||
docstring. */
|
||||
RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));
|
||||
RETURN_IF_ERROR(compiler_add_const(c, Py_None));
|
||||
VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value);
|
||||
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
|
||||
PyCodeObject *co = optimize_and_assemble(c, 0);
|
||||
@ -2705,7 +2708,7 @@ compiler_typealias(struct compiler *c, stmt_ty s)
|
||||
}
|
||||
Py_DECREF(type_params_name);
|
||||
RETURN_IF_ERROR_IN_SCOPE(
|
||||
c, compiler_addop_load_const(c->c_const_cache, c->u, loc, name)
|
||||
c, compiler_addop_load_const(c, loc, name)
|
||||
);
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));
|
||||
}
|
||||
@ -2972,13 +2975,13 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||
|
||||
/* Make None the first constant, so the lambda can't have a
|
||||
docstring. */
|
||||
RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));
|
||||
RETURN_IF_ERROR(compiler_add_const(c, Py_None));
|
||||
|
||||
c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
|
||||
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
|
||||
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
|
||||
if (c->u->u_ste->ste_generator) {
|
||||
if (SYMTABLE_ENTRY(c)->ste_generator) {
|
||||
co = optimize_and_assemble(c, 0);
|
||||
}
|
||||
else {
|
||||
@ -3154,12 +3157,12 @@ compiler_return(struct compiler *c, stmt_ty s)
|
||||
location loc = LOC(s);
|
||||
int preserve_tos = ((s->v.Return.value != NULL) &&
|
||||
(s->v.Return.value->kind != Constant_kind));
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
|
||||
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||
if (!_PyST_IsFunctionLike(ste)) {
|
||||
return compiler_error(c, loc, "'return' outside function");
|
||||
}
|
||||
if (s->v.Return.value != NULL &&
|
||||
c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator)
|
||||
{
|
||||
if (s->v.Return.value != NULL && ste->ste_coroutine && ste->ste_generator) {
|
||||
return compiler_error(c, loc, "'return' with value in async generator");
|
||||
}
|
||||
|
||||
@ -4109,7 +4112,8 @@ addop_binary(struct compiler *c, location loc, operator_ty binop,
|
||||
|
||||
static int
|
||||
addop_yield(struct compiler *c, location loc) {
|
||||
if (c->u->u_ste->ste_generator && c->u->u_ste->ste_coroutine) {
|
||||
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||
if (ste->ste_generator && ste->ste_coroutine) {
|
||||
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_ASYNC_GEN_WRAP);
|
||||
}
|
||||
ADDOP_I(c, loc, YIELD_VALUE, 0);
|
||||
@ -4143,7 +4147,7 @@ compiler_nameop(struct compiler *c, location loc,
|
||||
|
||||
op = 0;
|
||||
optype = OP_NAME;
|
||||
scope = _PyST_GetScope(c->u->u_ste, mangled);
|
||||
scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled);
|
||||
switch (scope) {
|
||||
case FREE:
|
||||
dict = c->u->u_metadata.u_freevars;
|
||||
@ -4154,7 +4158,7 @@ compiler_nameop(struct compiler *c, location loc,
|
||||
optype = OP_DEREF;
|
||||
break;
|
||||
case LOCAL:
|
||||
if (_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
if (_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
|
||||
optype = OP_FAST;
|
||||
}
|
||||
else {
|
||||
@ -4170,7 +4174,7 @@ compiler_nameop(struct compiler *c, location loc,
|
||||
}
|
||||
break;
|
||||
case GLOBAL_IMPLICIT:
|
||||
if (_PyST_IsFunctionLike(c->u->u_ste))
|
||||
if (_PyST_IsFunctionLike(SYMTABLE_ENTRY(c)))
|
||||
optype = OP_GLOBAL;
|
||||
break;
|
||||
case GLOBAL_EXPLICIT:
|
||||
@ -4188,17 +4192,17 @@ compiler_nameop(struct compiler *c, location loc,
|
||||
case OP_DEREF:
|
||||
switch (ctx) {
|
||||
case Load:
|
||||
if (c->u->u_ste->ste_type == ClassBlock && !c->u->u_in_inlined_comp) {
|
||||
if (SYMTABLE_ENTRY(c)->ste_type == ClassBlock && !c->u->u_in_inlined_comp) {
|
||||
op = LOAD_FROM_DICT_OR_DEREF;
|
||||
// First load the locals
|
||||
if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (c->u->u_ste->ste_can_see_class_scope) {
|
||||
else if (SYMTABLE_ENTRY(c)->ste_can_see_class_scope) {
|
||||
op = LOAD_FROM_DICT_OR_DEREF;
|
||||
// First load the classdict
|
||||
if (compiler_addop_o(c->u, loc, LOAD_DEREF,
|
||||
if (compiler_addop_o(c, loc, LOAD_DEREF,
|
||||
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
@ -4222,10 +4226,10 @@ compiler_nameop(struct compiler *c, location loc,
|
||||
case OP_GLOBAL:
|
||||
switch (ctx) {
|
||||
case Load:
|
||||
if (c->u->u_ste->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) {
|
||||
if (SYMTABLE_ENTRY(c)->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) {
|
||||
op = LOAD_FROM_DICT_OR_GLOBALS;
|
||||
// First load the classdict
|
||||
if (compiler_addop_o(c->u, loc, LOAD_DEREF,
|
||||
if (compiler_addop_o(c, loc, LOAD_DEREF,
|
||||
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
@ -4240,7 +4244,7 @@ compiler_nameop(struct compiler *c, location loc,
|
||||
case OP_NAME:
|
||||
switch (ctx) {
|
||||
case Load:
|
||||
op = (c->u->u_ste->ste_type == ClassBlock
|
||||
op = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock
|
||||
&& c->u->u_in_inlined_comp)
|
||||
? LOAD_GLOBAL
|
||||
: LOAD_NAME;
|
||||
@ -4745,7 +4749,7 @@ is_import_originated(struct compiler *c, expr_ty e)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long flags = _PyST_GetSymbol(c->c_st->st_top, e->v.Name.id);
|
||||
long flags = _PyST_GetSymbol(SYMTABLE(c)->st_top, e->v.Name.id);
|
||||
return flags & DEF_IMPORT;
|
||||
}
|
||||
|
||||
@ -4764,11 +4768,11 @@ can_optimize_super_call(struct compiler *c, expr_ty attr)
|
||||
|
||||
PyObject *super_name = e->v.Call.func->v.Name.id;
|
||||
// detect statically-visible shadowing of 'super' name
|
||||
int scope = _PyST_GetScope(c->u->u_ste, super_name);
|
||||
int scope = _PyST_GetScope(SYMTABLE_ENTRY(c), super_name);
|
||||
if (scope != GLOBAL_IMPLICIT) {
|
||||
return 0;
|
||||
}
|
||||
scope = _PyST_GetScope(c->c_st->st_top, super_name);
|
||||
scope = _PyST_GetScope(SYMTABLE(c)->st_top, super_name);
|
||||
if (scope != 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -4796,7 +4800,7 @@ can_optimize_super_call(struct compiler *c, expr_ty attr)
|
||||
return 0;
|
||||
}
|
||||
// __class__ cell should be available
|
||||
if (get_ref_type(c, &_Py_ID(__class__)) == FREE) {
|
||||
if (compiler_get_ref_type(c, &_Py_ID(__class__)) == FREE) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -4818,7 +4822,7 @@ load_args_for_super(struct compiler *c, expr_ty e) {
|
||||
|
||||
// load __class__ cell
|
||||
PyObject *name = &_Py_ID(__class__);
|
||||
assert(get_ref_type(c, name) == FREE);
|
||||
assert(compiler_get_ref_type(c, name) == FREE);
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, name, Load));
|
||||
|
||||
// load self (first argument)
|
||||
@ -5490,7 +5494,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
|
||||
PySTEntryObject *entry,
|
||||
inlined_comprehension_state *state)
|
||||
{
|
||||
int in_class_block = (c->u->u_ste->ste_type == ClassBlock) && !c->u->u_in_inlined_comp;
|
||||
int in_class_block = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock) && !c->u->u_in_inlined_comp;
|
||||
c->u->u_in_inlined_comp++;
|
||||
// iterate over names bound in the comprehension and ensure we isolate
|
||||
// them from the outer scope as needed
|
||||
@ -5500,7 +5504,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
|
||||
assert(PyLong_Check(v));
|
||||
long symbol = PyLong_AS_LONG(v);
|
||||
long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK;
|
||||
PyObject *outv = PyDict_GetItemWithError(c->u->u_ste->ste_symbols, k);
|
||||
PyObject *outv = PyDict_GetItemWithError(SYMTABLE_ENTRY(c)->ste_symbols, k);
|
||||
if (outv == NULL) {
|
||||
if (PyErr_Occurred()) {
|
||||
return ERROR;
|
||||
@ -5529,7 +5533,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
|
||||
// the outer version; we'll restore it after running the
|
||||
// comprehension
|
||||
Py_INCREF(outv);
|
||||
if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v) < 0) {
|
||||
if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v) < 0) {
|
||||
Py_DECREF(outv);
|
||||
return ERROR;
|
||||
}
|
||||
@ -5542,7 +5546,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
|
||||
// locals handling for names bound in comprehension (DEF_LOCAL |
|
||||
// DEF_NONLOCAL occurs in assignment expression to nonlocal)
|
||||
if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) {
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
|
||||
// non-function scope: override this name to use fast locals
|
||||
PyObject *orig;
|
||||
if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) {
|
||||
@ -5644,7 +5648,7 @@ pop_inlined_comprehension_state(struct compiler *c, location loc,
|
||||
Py_ssize_t pos = 0;
|
||||
if (state.temp_symbols) {
|
||||
while (PyDict_Next(state.temp_symbols, &pos, &k, &v)) {
|
||||
if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v)) {
|
||||
if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v)) {
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
@ -5713,7 +5717,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
|
||||
comprehension_ty outermost;
|
||||
int scope_type = c->u->u_scope_type;
|
||||
int is_top_level_await = IS_TOP_LEVEL_AWAIT(c);
|
||||
PySTEntryObject *entry = _PySymtable_Lookup(c->c_st, (void *)e);
|
||||
PySTEntryObject *entry = _PySymtable_Lookup(SYMTABLE(c), (void *)e);
|
||||
if (entry == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@ -6150,7 +6154,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
||||
case DictComp_kind:
|
||||
return compiler_dictcomp(c, e);
|
||||
case Yield_kind:
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
|
||||
return compiler_error(c, loc, "'yield' outside function");
|
||||
}
|
||||
if (e->v.Yield.value) {
|
||||
@ -6162,7 +6166,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
||||
ADDOP_YIELD(c, loc);
|
||||
break;
|
||||
case YieldFrom_kind:
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
|
||||
return compiler_error(c, loc, "'yield' outside function");
|
||||
}
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) {
|
||||
@ -6175,7 +6179,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
||||
break;
|
||||
case Await_kind:
|
||||
if (!IS_TOP_LEVEL_AWAIT(c)){
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
|
||||
return compiler_error(c, loc, "'await' outside function");
|
||||
}
|
||||
|
||||
@ -6215,13 +6219,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
||||
if (e->v.Attribute.value->kind == Name_kind &&
|
||||
_PyUnicode_EqualToASCIIString(e->v.Attribute.value->v.Name.id, "self"))
|
||||
{
|
||||
struct compiler_unit *class_u = get_class_compiler_unit(c);
|
||||
if (class_u != NULL) {
|
||||
assert(class_u->u_scope_type == COMPILER_SCOPE_CLASS);
|
||||
assert(class_u->u_static_attributes);
|
||||
RETURN_IF_ERROR(
|
||||
PySet_Add(class_u->u_static_attributes, e->v.Attribute.attr));
|
||||
}
|
||||
RETURN_IF_ERROR(compiler_add_static_attribute_to_class(c, e->v.Attribute.attr));
|
||||
}
|
||||
VISIT(c, expr, e->v.Attribute.value);
|
||||
loc = LOC(e);
|
||||
@ -6368,7 +6366,7 @@ check_annotation(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
/* Annotations of complex targets does not produce anything
|
||||
under annotations future */
|
||||
if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {
|
||||
if (FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -6415,7 +6413,7 @@ compiler_annassign(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
location loc = LOC(s);
|
||||
expr_ty targ = s->v.AnnAssign.target;
|
||||
bool future_annotations = c->c_future.ff_features & CO_FUTURE_ANNOTATIONS;
|
||||
bool future_annotations = FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS;
|
||||
PyObject *mangled;
|
||||
|
||||
assert(s->kind == AnnAssign_kind);
|
||||
@ -7485,19 +7483,41 @@ compiler_maybe_mangle(struct compiler *c, PyObject *name)
|
||||
return _Py_MaybeMangle(c->u->u_private, c->u->u_ste, name);
|
||||
}
|
||||
|
||||
static instr_sequence *
|
||||
compiler_instr_sequence(struct compiler *c)
|
||||
{
|
||||
return c->u->u_instr_sequence;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_future_features(struct compiler *c)
|
||||
{
|
||||
return c->c_future.ff_features;
|
||||
}
|
||||
|
||||
static struct symtable *
|
||||
compiler_symtable(struct compiler *c)
|
||||
{
|
||||
return c->c_st;
|
||||
}
|
||||
|
||||
static PySTEntryObject *
|
||||
compiler_symtable_entry(struct compiler *c)
|
||||
{
|
||||
return c->u->u_ste;
|
||||
}
|
||||
|
||||
static int
|
||||
compute_code_flags(struct compiler *c)
|
||||
{
|
||||
PySTEntryObject *ste = c->u->u_ste;
|
||||
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||
int flags = 0;
|
||||
if (_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
if (_PyST_IsFunctionLike(ste)) {
|
||||
flags |= CO_NEWLOCALS | CO_OPTIMIZED;
|
||||
if (ste->ste_nested)
|
||||
flags |= CO_NESTED;
|
||||
if (ste->ste_generator && !ste->ste_coroutine)
|
||||
flags |= CO_GENERATOR;
|
||||
if (!ste->ste_generator && ste->ste_coroutine)
|
||||
flags |= CO_COROUTINE;
|
||||
if (ste->ste_generator && ste->ste_coroutine)
|
||||
flags |= CO_ASYNC_GENERATOR;
|
||||
if (ste->ste_varargs)
|
||||
@ -7506,15 +7526,14 @@ compute_code_flags(struct compiler *c)
|
||||
flags |= CO_VARKEYWORDS;
|
||||
}
|
||||
|
||||
/* (Only) inherit compilerflags in PyCF_MASK */
|
||||
flags |= (c->c_flags.cf_flags & PyCF_MASK);
|
||||
|
||||
if ((IS_TOP_LEVEL_AWAIT(c)) &&
|
||||
ste->ste_coroutine &&
|
||||
!ste->ste_generator) {
|
||||
if (ste->ste_coroutine && !ste->ste_generator) {
|
||||
assert (IS_TOP_LEVEL_AWAIT(c) || _PyST_IsFunctionLike(ste));
|
||||
flags |= CO_COROUTINE;
|
||||
}
|
||||
|
||||
/* (Only) inherit compilerflags in PyCF_MASK */
|
||||
flags |= (c->c_flags.cf_flags & PyCF_MASK);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user