mirror of
https://github.com/python/cpython.git
synced 2025-10-02 21:25:24 +00:00
gh-121404: compiler_annassign --> codegen_annassign (#123245)
This commit is contained in:
parent
5d3201fe3f
commit
5fce482c9a
1 changed files with 100 additions and 63 deletions
163
Python/compile.c
163
Python/compile.c
|
@ -95,6 +95,7 @@ static PySTEntryObject *compiler_symtable_entry(struct compiler *c);
|
||||||
#define OPTIMIZATION_LEVEL(C) compiler_optimization_level(C)
|
#define OPTIMIZATION_LEVEL(C) compiler_optimization_level(C)
|
||||||
#define IS_INTERACTIVE(C) compiler_is_interactive(C)
|
#define IS_INTERACTIVE(C) compiler_is_interactive(C)
|
||||||
#define IS_NESTED_SCOPE(C) compiler_is_nested_scope(C)
|
#define IS_NESTED_SCOPE(C) compiler_is_nested_scope(C)
|
||||||
|
#define SCOPE_TYPE(C) compiler_scope_type(C)
|
||||||
|
|
||||||
typedef _Py_SourceLocation location;
|
typedef _Py_SourceLocation location;
|
||||||
typedef struct _PyCfgBuilder cfg_builder;
|
typedef struct _PyCfgBuilder cfg_builder;
|
||||||
|
@ -104,6 +105,7 @@ static PyObject *compiler_maybe_mangle(struct compiler *c, PyObject *name);
|
||||||
static int compiler_optimization_level(struct compiler *c);
|
static int compiler_optimization_level(struct compiler *c);
|
||||||
static int compiler_is_interactive(struct compiler *c);
|
static int compiler_is_interactive(struct compiler *c);
|
||||||
static int compiler_is_nested_scope(struct compiler *c);
|
static int compiler_is_nested_scope(struct compiler *c);
|
||||||
|
static int compiler_scope_type(struct compiler *c);
|
||||||
|
|
||||||
#define LOCATION(LNO, END_LNO, COL, END_COL) \
|
#define LOCATION(LNO, END_LNO, COL, END_COL) \
|
||||||
((const _Py_SourceLocation){(LNO), (END_LNO), (COL), (END_COL)})
|
((const _Py_SourceLocation){(LNO), (END_LNO), (COL), (END_COL)})
|
||||||
|
@ -314,7 +316,7 @@ static int compiler_visit_stmt(struct compiler *, stmt_ty);
|
||||||
static int compiler_visit_keyword(struct compiler *, keyword_ty);
|
static int compiler_visit_keyword(struct compiler *, keyword_ty);
|
||||||
static int compiler_visit_expr(struct compiler *, expr_ty);
|
static int compiler_visit_expr(struct compiler *, expr_ty);
|
||||||
static int codegen_augassign(struct compiler *, stmt_ty);
|
static int codegen_augassign(struct compiler *, stmt_ty);
|
||||||
static int compiler_annassign(struct compiler *, stmt_ty);
|
static int codegen_annassign(struct compiler *, stmt_ty);
|
||||||
static int codegen_subscript(struct compiler *, expr_ty);
|
static int codegen_subscript(struct compiler *, expr_ty);
|
||||||
static int codegen_slice(struct compiler *, expr_ty);
|
static int codegen_slice(struct compiler *, expr_ty);
|
||||||
|
|
||||||
|
@ -1481,7 +1483,7 @@ codegen_setup_annotations_scope(struct compiler *c, location loc,
|
||||||
ADDOP_I(c, loc, LOAD_COMMON_CONSTANT, CONSTANT_NOTIMPLEMENTEDERROR);
|
ADDOP_I(c, loc, LOAD_COMMON_CONSTANT, CONSTANT_NOTIMPLEMENTEDERROR);
|
||||||
ADDOP_I(c, loc, RAISE_VARARGS, 1);
|
ADDOP_I(c, loc, RAISE_VARARGS, 1);
|
||||||
USE_LABEL(c, body);
|
USE_LABEL(c, body);
|
||||||
return 0;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1501,11 +1503,69 @@ codegen_leave_annotations_scope(struct compiler *c, location loc,
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
compiler_deferred_annotations(struct compiler *c)
|
||||||
|
{
|
||||||
|
return c->u->u_deferred_annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
codegen_process_deferred_annotations(struct compiler *c, location loc)
|
||||||
|
{
|
||||||
|
PyObject *deferred_anno = compiler_deferred_annotations(c);
|
||||||
|
if (deferred_anno == NULL) {
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
Py_INCREF(deferred_anno);
|
||||||
|
|
||||||
|
// It's possible that ste_annotations_block is set but
|
||||||
|
// u_deferred_annotations is not, because the former is still
|
||||||
|
// set if there are only non-simple annotations (i.e., annotations
|
||||||
|
// for attributes, subscripts, or parenthesized names). However, the
|
||||||
|
// reverse should not be possible.
|
||||||
|
PySTEntryObject *ste = SYMTABLE_ENTRY(c);
|
||||||
|
assert(ste->ste_annotation_block != NULL);
|
||||||
|
void *key = (void *)((uintptr_t)ste->ste_id + 1);
|
||||||
|
if (codegen_setup_annotations_scope(c, loc, key,
|
||||||
|
ste->ste_annotation_block->ste_name) < 0) {
|
||||||
|
Py_DECREF(deferred_anno);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
Py_ssize_t annotations_len = PyList_Size(deferred_anno);
|
||||||
|
for (Py_ssize_t i = 0; i < annotations_len; i++) {
|
||||||
|
PyObject *ptr = PyList_GET_ITEM(deferred_anno, i);
|
||||||
|
stmt_ty st = (stmt_ty)PyLong_AsVoidPtr(ptr);
|
||||||
|
if (st == NULL) {
|
||||||
|
compiler_exit_scope(c);
|
||||||
|
Py_DECREF(deferred_anno);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
PyObject *mangled = compiler_mangle(c, st->v.AnnAssign.target->v.Name.id);
|
||||||
|
if (!mangled) {
|
||||||
|
compiler_exit_scope(c);
|
||||||
|
Py_DECREF(deferred_anno);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
ADDOP_LOAD_CONST_NEW(c, LOC(st), mangled);
|
||||||
|
VISIT(c, expr, st->v.AnnAssign.annotation);
|
||||||
|
}
|
||||||
|
Py_DECREF(deferred_anno);
|
||||||
|
|
||||||
|
RETURN_IF_ERROR(
|
||||||
|
codegen_leave_annotations_scope(c, loc, annotations_len)
|
||||||
|
);
|
||||||
|
RETURN_IF_ERROR(
|
||||||
|
compiler_nameop(c, loc, &_Py_ID(__annotate__), Store)
|
||||||
|
);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compile a sequence of statements, checking for a docstring
|
/* Compile a sequence of statements, checking for a docstring
|
||||||
and for annotations. */
|
and for annotations. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
|
codegen_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
|
||||||
{
|
{
|
||||||
/* If from __future__ import annotations is active,
|
/* If from __future__ import annotations is active,
|
||||||
* every annotated class and module should have __annotations__.
|
* every annotated class and module should have __annotations__.
|
||||||
|
@ -1542,44 +1602,8 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
|
||||||
// If there are annotations and the future import is not on, we
|
// If there are annotations and the future import is not on, we
|
||||||
// collect the annotations in a separate pass and generate an
|
// collect the annotations in a separate pass and generate an
|
||||||
// __annotate__ function. See PEP 649.
|
// __annotate__ function. See PEP 649.
|
||||||
if (!(FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS) &&
|
if (!(FUTURE_FEATURES(c) & CO_FUTURE_ANNOTATIONS)) {
|
||||||
c->u->u_deferred_annotations != NULL) {
|
RETURN_IF_ERROR(codegen_process_deferred_annotations(c, loc));
|
||||||
|
|
||||||
// It's possible that ste_annotations_block is set but
|
|
||||||
// u_deferred_annotations is not, because the former is still
|
|
||||||
// set if there are only non-simple annotations (i.e., annotations
|
|
||||||
// for attributes, subscripts, or parenthesized names). However, the
|
|
||||||
// reverse should not be possible.
|
|
||||||
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)ste->ste_id + 1);
|
|
||||||
if (codegen_setup_annotations_scope(c, loc, key,
|
|
||||||
ste->ste_annotation_block->ste_name) == -1) {
|
|
||||||
Py_DECREF(deferred_anno);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
Py_ssize_t annotations_len = PyList_Size(deferred_anno);
|
|
||||||
for (Py_ssize_t i = 0; i < annotations_len; i++) {
|
|
||||||
PyObject *ptr = PyList_GET_ITEM(deferred_anno, i);
|
|
||||||
stmt_ty st = (stmt_ty)PyLong_AsVoidPtr(ptr);
|
|
||||||
if (st == NULL) {
|
|
||||||
compiler_exit_scope(c);
|
|
||||||
Py_DECREF(deferred_anno);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
PyObject *mangled = compiler_mangle(c, st->v.AnnAssign.target->v.Name.id);
|
|
||||||
ADDOP_LOAD_CONST_NEW(c, LOC(st), mangled);
|
|
||||||
VISIT(c, expr, st->v.AnnAssign.annotation);
|
|
||||||
}
|
|
||||||
Py_DECREF(deferred_anno);
|
|
||||||
|
|
||||||
RETURN_IF_ERROR(
|
|
||||||
codegen_leave_annotations_scope(c, loc, annotations_len)
|
|
||||||
);
|
|
||||||
RETURN_IF_ERROR(
|
|
||||||
compiler_nameop(c, loc, &_Py_ID(__annotate__), Store)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1606,13 +1630,13 @@ compiler_codegen(struct compiler *c, mod_ty mod)
|
||||||
switch (mod->kind) {
|
switch (mod->kind) {
|
||||||
case Module_kind: {
|
case Module_kind: {
|
||||||
asdl_stmt_seq *stmts = mod->v.Module.body;
|
asdl_stmt_seq *stmts = mod->v.Module.body;
|
||||||
RETURN_IF_ERROR(compiler_body(c, start_location(stmts), stmts));
|
RETURN_IF_ERROR(codegen_body(c, start_location(stmts), stmts));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Interactive_kind: {
|
case Interactive_kind: {
|
||||||
c->c_interactive = 1;
|
c->c_interactive = 1;
|
||||||
asdl_stmt_seq *stmts = mod->v.Interactive.body;
|
asdl_stmt_seq *stmts = mod->v.Interactive.body;
|
||||||
RETURN_IF_ERROR(compiler_body(c, start_location(stmts), stmts));
|
RETURN_IF_ERROR(codegen_body(c, start_location(stmts), stmts));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Expression_kind: {
|
case Expression_kind: {
|
||||||
|
@ -2385,7 +2409,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
|
||||||
ADDOP_N_IN_SCOPE(c, loc, STORE_DEREF, &_Py_ID(__classdict__), cellvars);
|
ADDOP_N_IN_SCOPE(c, loc, STORE_DEREF, &_Py_ID(__classdict__), cellvars);
|
||||||
}
|
}
|
||||||
/* compile the body proper */
|
/* compile the body proper */
|
||||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_body(c, loc, s->v.ClassDef.body));
|
RETURN_IF_ERROR_IN_SCOPE(c, codegen_body(c, loc, s->v.ClassDef.body));
|
||||||
assert(c->u->u_static_attributes);
|
assert(c->u->u_static_attributes);
|
||||||
PyObject *static_attributes = PySequence_Tuple(c->u->u_static_attributes);
|
PyObject *static_attributes = PySequence_Tuple(c->u->u_static_attributes);
|
||||||
if (static_attributes == NULL) {
|
if (static_attributes == NULL) {
|
||||||
|
@ -3847,7 +3871,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
|
||||||
case AugAssign_kind:
|
case AugAssign_kind:
|
||||||
return codegen_augassign(c, s);
|
return codegen_augassign(c, s);
|
||||||
case AnnAssign_kind:
|
case AnnAssign_kind:
|
||||||
return compiler_annassign(c, s);
|
return codegen_annassign(c, s);
|
||||||
case For_kind:
|
case For_kind:
|
||||||
return codegen_for(c, s);
|
return codegen_for(c, s);
|
||||||
case While_kind:
|
case While_kind:
|
||||||
|
@ -6287,7 +6311,28 @@ codegen_check_ann_subscr(struct compiler *c, expr_ty e)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_annassign(struct compiler *c, stmt_ty s)
|
compiler_add_deferred_annotation(struct compiler *c, stmt_ty s)
|
||||||
|
{
|
||||||
|
if (c->u->u_deferred_annotations == NULL) {
|
||||||
|
c->u->u_deferred_annotations = PyList_New(0);
|
||||||
|
if (c->u->u_deferred_annotations == NULL) {
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PyObject *ptr = PyLong_FromVoidPtr((void *)s);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
if (PyList_Append(c->u->u_deferred_annotations, ptr) < 0) {
|
||||||
|
Py_DECREF(ptr);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
Py_DECREF(ptr);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
codegen_annassign(struct compiler *c, stmt_ty s)
|
||||||
{
|
{
|
||||||
location loc = LOC(s);
|
location loc = LOC(s);
|
||||||
expr_ty targ = s->v.AnnAssign.target;
|
expr_ty targ = s->v.AnnAssign.target;
|
||||||
|
@ -6305,8 +6350,8 @@ compiler_annassign(struct compiler *c, stmt_ty s)
|
||||||
case Name_kind:
|
case Name_kind:
|
||||||
/* If we have a simple name in a module or class, store annotation. */
|
/* If we have a simple name in a module or class, store annotation. */
|
||||||
if (s->v.AnnAssign.simple &&
|
if (s->v.AnnAssign.simple &&
|
||||||
(c->u->u_scope_type == COMPILER_SCOPE_MODULE ||
|
(SCOPE_TYPE(c) == COMPILER_SCOPE_MODULE ||
|
||||||
c->u->u_scope_type == COMPILER_SCOPE_CLASS)) {
|
SCOPE_TYPE(c) == COMPILER_SCOPE_CLASS)) {
|
||||||
if (future_annotations) {
|
if (future_annotations) {
|
||||||
VISIT(c, annexpr, s->v.AnnAssign.annotation);
|
VISIT(c, annexpr, s->v.AnnAssign.annotation);
|
||||||
ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__annotations__), names);
|
ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__annotations__), names);
|
||||||
|
@ -6315,21 +6360,7 @@ compiler_annassign(struct compiler *c, stmt_ty s)
|
||||||
ADDOP(c, loc, STORE_SUBSCR);
|
ADDOP(c, loc, STORE_SUBSCR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (c->u->u_deferred_annotations == NULL) {
|
RETURN_IF_ERROR(compiler_add_deferred_annotation(c, s));
|
||||||
c->u->u_deferred_annotations = PyList_New(0);
|
|
||||||
if (c->u->u_deferred_annotations == NULL) {
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PyObject *ptr = PyLong_FromVoidPtr((void *)s);
|
|
||||||
if (ptr == NULL) {
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
if (PyList_Append(c->u->u_deferred_annotations, ptr) < 0) {
|
|
||||||
Py_DECREF(ptr);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
Py_DECREF(ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -7399,6 +7430,12 @@ compiler_is_nested_scope(struct compiler *c)
|
||||||
return PyList_GET_SIZE(c->c_stack) > 0;
|
return PyList_GET_SIZE(c->c_stack) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compiler_scope_type(struct compiler *c)
|
||||||
|
{
|
||||||
|
return c->u->u_scope_type;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compute_code_flags(struct compiler *c)
|
compute_code_flags(struct compiler *c)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue