mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-119180: PEP 649 compiler changes (#119361)
This commit is contained in:
parent
02c1dfff07
commit
9b8611eeea
28 changed files with 610 additions and 329 deletions
|
@ -112,6 +112,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
ste->ste_varkeywords = 0;
|
||||
ste->ste_opt_lineno = 0;
|
||||
ste->ste_opt_col_offset = 0;
|
||||
ste->ste_annotations_used = 0;
|
||||
ste->ste_lineno = lineno;
|
||||
ste->ste_col_offset = col_offset;
|
||||
ste->ste_end_lineno = end_lineno;
|
||||
|
@ -132,6 +133,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
ste->ste_can_see_class_scope = 0;
|
||||
ste->ste_comp_iter_expr = 0;
|
||||
ste->ste_needs_classdict = 0;
|
||||
ste->ste_annotation_block = NULL;
|
||||
|
||||
ste->ste_symbols = PyDict_New();
|
||||
ste->ste_varnames = PyList_New(0);
|
||||
|
@ -167,6 +169,7 @@ ste_dealloc(PySTEntryObject *ste)
|
|||
Py_XDECREF(ste->ste_varnames);
|
||||
Py_XDECREF(ste->ste_children);
|
||||
Py_XDECREF(ste->ste_directives);
|
||||
Py_XDECREF(ste->ste_annotation_block);
|
||||
Py_XDECREF(ste->ste_mangled_names);
|
||||
PyObject_Free(ste);
|
||||
}
|
||||
|
@ -245,10 +248,11 @@ static int symtable_visit_alias(struct symtable *st, alias_ty);
|
|||
static int symtable_visit_comprehension(struct symtable *st, comprehension_ty);
|
||||
static int symtable_visit_keyword(struct symtable *st, keyword_ty);
|
||||
static int symtable_visit_params(struct symtable *st, asdl_arg_seq *args);
|
||||
static int symtable_visit_annotation(struct symtable *st, expr_ty annotation);
|
||||
static int symtable_visit_annotation(struct symtable *st, expr_ty annotation, void *key);
|
||||
static int symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args);
|
||||
static int symtable_implicit_arg(struct symtable *st, int pos);
|
||||
static int symtable_visit_annotations(struct symtable *st, stmt_ty, arguments_ty, expr_ty);
|
||||
static int symtable_visit_annotations(struct symtable *st, stmt_ty, arguments_ty, expr_ty,
|
||||
struct _symtable_entry *parent_ste);
|
||||
static int symtable_visit_withitem(struct symtable *st, withitem_ty item);
|
||||
static int symtable_visit_match_case(struct symtable *st, match_case_ty m);
|
||||
static int symtable_visit_pattern(struct symtable *st, pattern_ty s);
|
||||
|
@ -504,6 +508,21 @@ _PySymtable_Lookup(struct symtable *st, void *key)
|
|||
return (PySTEntryObject *)v;
|
||||
}
|
||||
|
||||
int
|
||||
_PySymtable_LookupOptional(struct symtable *st, void *key,
|
||||
PySTEntryObject **out)
|
||||
{
|
||||
PyObject *k = PyLong_FromVoidPtr(key);
|
||||
if (k == NULL) {
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
int result = PyDict_GetItemRef(st->st_blocks, k, (PyObject **)out);
|
||||
Py_DECREF(k);
|
||||
assert(*out == NULL || PySTEntry_Check(*out));
|
||||
return result;
|
||||
}
|
||||
|
||||
long
|
||||
_PyST_GetSymbol(PySTEntryObject *ste, PyObject *name)
|
||||
{
|
||||
|
@ -525,6 +544,7 @@ int
|
|||
_PyST_IsFunctionLike(PySTEntryObject *ste)
|
||||
{
|
||||
return ste->ste_type == FunctionBlock
|
||||
|| ste->ste_type == AnnotationBlock
|
||||
|| ste->ste_type == TypeVarBoundBlock
|
||||
|| ste->ste_type == TypeAliasBlock
|
||||
|| ste->ste_type == TypeParamBlock;
|
||||
|
@ -1317,20 +1337,12 @@ symtable_exit_block(struct symtable *st)
|
|||
}
|
||||
|
||||
static int
|
||||
symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
||||
void *ast, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset)
|
||||
symtable_enter_existing_block(struct symtable *st, PySTEntryObject* ste)
|
||||
{
|
||||
PySTEntryObject *prev = NULL, *ste;
|
||||
|
||||
ste = ste_new(st, name, block, ast, lineno, col_offset, end_lineno, end_col_offset);
|
||||
if (ste == NULL)
|
||||
return 0;
|
||||
if (PyList_Append(st->st_stack, (PyObject *)ste) < 0) {
|
||||
Py_DECREF(ste);
|
||||
return 0;
|
||||
}
|
||||
prev = st->st_cur;
|
||||
PySTEntryObject *prev = st->st_cur;
|
||||
/* bpo-37757: For now, disallow *all* assignment expressions in the
|
||||
* outermost iterator expression of a comprehension, even those inside
|
||||
* a nested comprehension or a lambda expression.
|
||||
|
@ -1340,21 +1352,20 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
}
|
||||
/* No need to inherit ste_mangled_names in classes, where all names
|
||||
* are mangled. */
|
||||
if (prev && prev->ste_mangled_names != NULL && block != ClassBlock) {
|
||||
if (prev && prev->ste_mangled_names != NULL && ste->ste_type != ClassBlock) {
|
||||
ste->ste_mangled_names = Py_NewRef(prev->ste_mangled_names);
|
||||
}
|
||||
/* The entry is owned by the stack. Borrow it for st_cur. */
|
||||
Py_DECREF(ste);
|
||||
st->st_cur = ste;
|
||||
|
||||
/* Annotation blocks shouldn't have any affect on the symbol table since in
|
||||
* the compilation stage, they will all be transformed to strings. They are
|
||||
* only created if future 'annotations' feature is activated. */
|
||||
if (block == AnnotationBlock) {
|
||||
/* If "from __future__ import annotations" is active,
|
||||
* annotation blocks shouldn't have any affect on the symbol table since in
|
||||
* the compilation stage, they will all be transformed to strings. */
|
||||
if (st->st_future->ff_features & CO_FUTURE_ANNOTATIONS && ste->ste_type == AnnotationBlock) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (block == ModuleBlock)
|
||||
if (ste->ste_type == ModuleBlock)
|
||||
st->st_global = st->st_cur->ste_symbols;
|
||||
|
||||
if (prev) {
|
||||
|
@ -1365,6 +1376,20 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
||||
void *ast, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset)
|
||||
{
|
||||
PySTEntryObject *ste = ste_new(st, name, block, ast,
|
||||
lineno, col_offset, end_lineno, end_col_offset);
|
||||
if (ste == NULL)
|
||||
return 0;
|
||||
int result = symtable_enter_existing_block(st, ste);
|
||||
Py_DECREF(ste);
|
||||
return result;
|
||||
}
|
||||
|
||||
static long
|
||||
symtable_lookup_entry(struct symtable *st, PySTEntryObject *ste, PyObject *name)
|
||||
{
|
||||
|
@ -1643,7 +1668,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
switch (s->kind) {
|
||||
case FunctionDef_kind:
|
||||
case FunctionDef_kind: {
|
||||
if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.FunctionDef.args->defaults)
|
||||
|
@ -1665,13 +1690,22 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
}
|
||||
VISIT_SEQ(st, type_param, s->v.FunctionDef.type_params);
|
||||
}
|
||||
PySTEntryObject *new_ste = ste_new(st, s->v.FunctionDef.name, FunctionBlock, (void *)s,
|
||||
LOCATION(s));
|
||||
if (!new_ste) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
|
||||
if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
|
||||
s->v.FunctionDef.returns))
|
||||
s->v.FunctionDef.returns, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
||||
FunctionBlock, (void *)s,
|
||||
LOCATION(s)))
|
||||
}
|
||||
if (!symtable_enter_existing_block(st, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
Py_DECREF(new_ste);
|
||||
VISIT(st, arguments, s->v.FunctionDef.args);
|
||||
VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
|
||||
if (!symtable_exit_block(st))
|
||||
|
@ -1681,6 +1715,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ClassDef_kind: {
|
||||
PyObject *tmp;
|
||||
if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
|
@ -1776,6 +1811,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT(st, expr, s->v.Assign.value);
|
||||
break;
|
||||
case AnnAssign_kind:
|
||||
st->st_cur->ste_annotations_used = 1;
|
||||
if (s->v.AnnAssign.target->kind == Name_kind) {
|
||||
expr_ty e_name = s->v.AnnAssign.target;
|
||||
long cur = symtable_lookup(st, e_name->v.Name.id);
|
||||
|
@ -1810,7 +1846,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
else {
|
||||
VISIT(st, expr, s->v.AnnAssign.target);
|
||||
}
|
||||
if (!symtable_visit_annotation(st, s->v.AnnAssign.annotation)) {
|
||||
if (!symtable_visit_annotation(st, s->v.AnnAssign.annotation,
|
||||
(void *)((uintptr_t)st->st_cur->ste_id + 1))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
|
||||
|
@ -1960,7 +1997,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_SEQ(st, withitem, s->v.With.items);
|
||||
VISIT_SEQ(st, stmt, s->v.With.body);
|
||||
break;
|
||||
case AsyncFunctionDef_kind:
|
||||
case AsyncFunctionDef_kind: {
|
||||
if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.AsyncFunctionDef.args->defaults)
|
||||
|
@ -1983,14 +2020,21 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
}
|
||||
VISIT_SEQ(st, type_param, s->v.AsyncFunctionDef.type_params);
|
||||
}
|
||||
PySTEntryObject *new_ste = ste_new(st, s->v.FunctionDef.name, FunctionBlock, (void *)s,
|
||||
LOCATION(s));
|
||||
if (!new_ste) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
|
||||
if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
|
||||
s->v.AsyncFunctionDef.returns))
|
||||
s->v.AsyncFunctionDef.returns, new_ste))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name,
|
||||
FunctionBlock, (void *)s,
|
||||
s->lineno, s->col_offset,
|
||||
s->end_lineno, s->end_col_offset))
|
||||
if (!symtable_enter_existing_block(st, new_ste)) {
|
||||
Py_DECREF(new_ste);
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
Py_DECREF(new_ste);
|
||||
|
||||
st->st_cur->ste_coroutine = 1;
|
||||
VISIT(st, arguments, s->v.AsyncFunctionDef.args);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body);
|
||||
|
@ -2001,6 +2045,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AsyncWith_kind:
|
||||
VISIT_SEQ(st, withitem, s->v.AsyncWith.items);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncWith.body);
|
||||
|
@ -2444,18 +2489,44 @@ symtable_visit_params(struct symtable *st, asdl_arg_seq *args)
|
|||
}
|
||||
|
||||
static int
|
||||
symtable_visit_annotation(struct symtable *st, expr_ty annotation)
|
||||
symtable_visit_annotation(struct symtable *st, expr_ty annotation, void *key)
|
||||
{
|
||||
int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;
|
||||
if (future_annotations &&
|
||||
!symtable_enter_block(st, &_Py_ID(_annotation), AnnotationBlock,
|
||||
(void *)annotation, annotation->lineno,
|
||||
annotation->col_offset, annotation->end_lineno,
|
||||
annotation->end_col_offset)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
struct _symtable_entry *parent_ste = st->st_cur;
|
||||
if (parent_ste->ste_annotation_block == NULL) {
|
||||
_Py_block_ty current_type = parent_ste->ste_type;
|
||||
if (!symtable_enter_block(st, &_Py_ID(__annotate__), AnnotationBlock,
|
||||
key, LOCATION(annotation))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
parent_ste->ste_annotation_block =
|
||||
(struct _symtable_entry *)Py_NewRef(st->st_cur);
|
||||
int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;
|
||||
if (current_type == ClassBlock && !future_annotations) {
|
||||
st->st_cur->ste_can_see_class_scope = 1;
|
||||
if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(annotation))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_Py_DECLARE_STR(format, ".format");
|
||||
// The generated __annotate__ function takes a single parameter with the
|
||||
// internal name ".format".
|
||||
if (!symtable_add_def(st, &_Py_STR(format), DEF_PARAM,
|
||||
LOCATION(annotation))) {
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_add_def(st, &_Py_STR(format), USE,
|
||||
LOCATION(annotation))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!symtable_enter_existing_block(st, parent_ste->ste_annotation_block)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
}
|
||||
VISIT(st, expr, annotation);
|
||||
if (future_annotations && !symtable_exit_block(st)) {
|
||||
if (!symtable_exit_block(st)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
return 1;
|
||||
|
@ -2471,37 +2542,58 @@ symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args)
|
|||
|
||||
for (i = 0; i < asdl_seq_LEN(args); i++) {
|
||||
arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
|
||||
if (arg->annotation)
|
||||
if (arg->annotation) {
|
||||
st->st_cur->ste_annotations_used = 1;
|
||||
VISIT(st, expr, arg->annotation);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ty returns)
|
||||
symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ty returns,
|
||||
struct _symtable_entry *function_ste)
|
||||
{
|
||||
int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;
|
||||
if (future_annotations &&
|
||||
!symtable_enter_block(st, &_Py_ID(_annotation), AnnotationBlock,
|
||||
(void *)o, o->lineno, o->col_offset, o->end_lineno,
|
||||
o->end_col_offset)) {
|
||||
int is_in_class = st->st_cur->ste_can_see_class_scope;
|
||||
_Py_block_ty current_type = st->st_cur->ste_type;
|
||||
if (!symtable_enter_block(st, &_Py_ID(__annotate__), AnnotationBlock,
|
||||
(void *)a, LOCATION(o))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
if (is_in_class || current_type == ClassBlock) {
|
||||
st->st_cur->ste_can_see_class_scope = 1;
|
||||
if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(o))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
_Py_DECLARE_STR(format, ".format");
|
||||
// We need to insert code that reads this "parameter" to the function.
|
||||
if (!symtable_add_def(st, &_Py_STR(format), DEF_PARAM, LOCATION(o))) {
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_add_def(st, &_Py_STR(format), USE, LOCATION(o))) {
|
||||
return 0;
|
||||
}
|
||||
if (a->posonlyargs && !symtable_visit_argannotations(st, a->posonlyargs))
|
||||
return 0;
|
||||
if (a->args && !symtable_visit_argannotations(st, a->args))
|
||||
return 0;
|
||||
if (a->vararg && a->vararg->annotation)
|
||||
if (a->vararg && a->vararg->annotation) {
|
||||
st->st_cur->ste_annotations_used = 1;
|
||||
VISIT(st, expr, a->vararg->annotation);
|
||||
if (a->kwarg && a->kwarg->annotation)
|
||||
}
|
||||
if (a->kwarg && a->kwarg->annotation) {
|
||||
st->st_cur->ste_annotations_used = 1;
|
||||
VISIT(st, expr, a->kwarg->annotation);
|
||||
}
|
||||
if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))
|
||||
return 0;
|
||||
if (future_annotations && !symtable_exit_block(st)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
if (returns) {
|
||||
st->st_cur->ste_annotations_used = 1;
|
||||
VISIT(st, expr, returns);
|
||||
}
|
||||
if (returns && !symtable_visit_annotation(st, returns)) {
|
||||
if (!symtable_exit_block(st)) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
return 1;
|
||||
|
@ -2733,7 +2825,7 @@ symtable_visit_dictcomp(struct symtable *st, expr_ty e)
|
|||
static int
|
||||
symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_ty e)
|
||||
{
|
||||
enum _block_type type = st->st_cur->ste_type;
|
||||
_Py_block_ty type = st->st_cur->ste_type;
|
||||
if (type == AnnotationBlock)
|
||||
PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
|
||||
else if (type == TypeVarBoundBlock)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue