mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
gh-103763: Implement PEP 695 (#103764)
This implements PEP 695, Type Parameter Syntax. It adds support for: - Generic functions (def func[T](): ...) - Generic classes (class X[T](): ...) - Type aliases (type X = ...) - New scoping when the new syntax is used within a class body - Compiler and interpreter changes to support the new syntax and scoping rules Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Co-authored-by: Eric Traut <eric@traut.com> Co-authored-by: Larry Hastings <larry@hastings.org> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
fdafdc235e
commit
24d8b88420
56 changed files with 11405 additions and 5469 deletions
767
Python/Python-ast.c
generated
767
Python/Python-ast.c
generated
File diff suppressed because it is too large
Load diff
45
Python/ast.c
45
Python/ast.c
|
@ -17,10 +17,12 @@ struct validator {
|
|||
static int validate_stmts(struct validator *, asdl_stmt_seq *);
|
||||
static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int);
|
||||
static int validate_patterns(struct validator *, asdl_pattern_seq *, int);
|
||||
static int validate_typeparams(struct validator *, asdl_typeparam_seq *);
|
||||
static int _validate_nonempty_seq(asdl_seq *, const char *, const char *);
|
||||
static int validate_stmt(struct validator *, stmt_ty);
|
||||
static int validate_expr(struct validator *, expr_ty, expr_context_ty);
|
||||
static int validate_pattern(struct validator *, pattern_ty, int);
|
||||
static int validate_typeparam(struct validator *, typeparam_ty);
|
||||
|
||||
#define VALIDATE_POSITIONS(node) \
|
||||
if (node->lineno > node->end_lineno) { \
|
||||
|
@ -726,6 +728,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
|
|||
switch (stmt->kind) {
|
||||
case FunctionDef_kind:
|
||||
ret = validate_body(state, stmt->v.FunctionDef.body, "FunctionDef") &&
|
||||
validate_typeparams(state, stmt->v.FunctionDef.typeparams) &&
|
||||
validate_arguments(state, stmt->v.FunctionDef.args) &&
|
||||
validate_exprs(state, stmt->v.FunctionDef.decorator_list, Load, 0) &&
|
||||
(!stmt->v.FunctionDef.returns ||
|
||||
|
@ -733,6 +736,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
|
|||
break;
|
||||
case ClassDef_kind:
|
||||
ret = validate_body(state, stmt->v.ClassDef.body, "ClassDef") &&
|
||||
validate_typeparams(state, stmt->v.ClassDef.typeparams) &&
|
||||
validate_exprs(state, stmt->v.ClassDef.bases, Load, 0) &&
|
||||
validate_keywords(state, stmt->v.ClassDef.keywords) &&
|
||||
validate_exprs(state, stmt->v.ClassDef.decorator_list, Load, 0);
|
||||
|
@ -763,6 +767,11 @@ validate_stmt(struct validator *state, stmt_ty stmt)
|
|||
validate_expr(state, stmt->v.AnnAssign.value, Load)) &&
|
||||
validate_expr(state, stmt->v.AnnAssign.annotation, Load);
|
||||
break;
|
||||
case TypeAlias_kind:
|
||||
ret = validate_expr(state, stmt->v.TypeAlias.name, Store) &&
|
||||
validate_typeparams(state, stmt->v.TypeAlias.typeparams) &&
|
||||
validate_expr(state, stmt->v.TypeAlias.value, Load);
|
||||
break;
|
||||
case For_kind:
|
||||
ret = validate_expr(state, stmt->v.For.target, Store) &&
|
||||
validate_expr(state, stmt->v.For.iter, Load) &&
|
||||
|
@ -910,6 +919,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
|
|||
break;
|
||||
case AsyncFunctionDef_kind:
|
||||
ret = validate_body(state, stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
|
||||
validate_typeparams(state, stmt->v.AsyncFunctionDef.typeparams) &&
|
||||
validate_arguments(state, stmt->v.AsyncFunctionDef.args) &&
|
||||
validate_exprs(state, stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
|
||||
(!stmt->v.AsyncFunctionDef.returns ||
|
||||
|
@ -982,6 +992,41 @@ validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_typeparam(struct validator *state, typeparam_ty tp)
|
||||
{
|
||||
VALIDATE_POSITIONS(tp);
|
||||
int ret = -1;
|
||||
switch (tp->kind) {
|
||||
case TypeVar_kind:
|
||||
ret = validate_name(tp->v.TypeVar.name) &&
|
||||
(!tp->v.TypeVar.bound ||
|
||||
validate_expr(state, tp->v.TypeVar.bound, Load));
|
||||
break;
|
||||
case ParamSpec_kind:
|
||||
ret = validate_name(tp->v.ParamSpec.name);
|
||||
break;
|
||||
case TypeVarTuple_kind:
|
||||
ret = validate_name(tp->v.TypeVarTuple.name);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_typeparams(struct validator *state, asdl_typeparam_seq *tps)
|
||||
{
|
||||
Py_ssize_t i;
|
||||
for (i = 0; i < asdl_seq_LEN(tps); i++) {
|
||||
typeparam_ty tp = asdl_seq_GET(tps, i);
|
||||
if (tp) {
|
||||
if (!validate_typeparam(state, tp))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* See comments in symtable.c. */
|
||||
#define COMPILER_STACK_FRAME_SCALE 3
|
||||
|
|
|
@ -642,6 +642,7 @@ static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeStat
|
|||
static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
|
||||
static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
|
||||
static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
|
||||
static int astfold_typeparam(typeparam_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
|
||||
|
||||
#define CALL(FUNC, TYPE, ARG) \
|
||||
if (!FUNC((ARG), ctx_, state)) \
|
||||
|
@ -880,6 +881,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
|||
}
|
||||
switch (node_->kind) {
|
||||
case FunctionDef_kind:
|
||||
CALL_SEQ(astfold_typeparam, typeparam, node_->v.FunctionDef.typeparams);
|
||||
CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
|
||||
CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
|
||||
CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
|
||||
|
@ -888,6 +890,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
|||
}
|
||||
break;
|
||||
case AsyncFunctionDef_kind:
|
||||
CALL_SEQ(astfold_typeparam, typeparam, node_->v.AsyncFunctionDef.typeparams);
|
||||
CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
|
||||
CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
|
||||
CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
|
||||
|
@ -896,6 +899,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
|||
}
|
||||
break;
|
||||
case ClassDef_kind:
|
||||
CALL_SEQ(astfold_typeparam, typeparam, node_->v.ClassDef.typeparams);
|
||||
CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
|
||||
CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
|
||||
CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
|
||||
|
@ -922,6 +926,11 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
|||
}
|
||||
CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
|
||||
break;
|
||||
case TypeAlias_kind:
|
||||
CALL(astfold_expr, expr_ty, node_->v.TypeAlias.name);
|
||||
CALL_SEQ(astfold_typeparam, typeparam, node_->v.TypeAlias.typeparams);
|
||||
CALL(astfold_expr, expr_ty, node_->v.TypeAlias.value);
|
||||
break;
|
||||
case For_kind:
|
||||
CALL(astfold_expr, expr_ty, node_->v.For.target);
|
||||
CALL(astfold_expr, expr_ty, node_->v.For.iter);
|
||||
|
@ -1074,6 +1083,21 @@ astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
astfold_typeparam(typeparam_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
|
||||
{
|
||||
switch (node_->kind) {
|
||||
case TypeVar_kind:
|
||||
CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.bound);
|
||||
break;
|
||||
case ParamSpec_kind:
|
||||
break;
|
||||
case TypeVarTuple_kind:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef CALL
|
||||
#undef CALL_OPT
|
||||
#undef CALL_SEQ
|
||||
|
|
|
@ -56,7 +56,7 @@ static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub
|
|||
static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;
|
||||
static PyObject *list, *tuple, *dict, *owner, *set, *str, *tup, *map, *keys;
|
||||
static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter;
|
||||
static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc;
|
||||
static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc, *locals;
|
||||
static PyObject *orig, *excs, *update, *b, *fromlist, *level, *from;
|
||||
static PyObject **pieces, **values;
|
||||
static size_t jump;
|
||||
|
@ -125,6 +125,7 @@ dummy_func(
|
|||
PyObject *subject;
|
||||
PyObject *top;
|
||||
PyObject *type;
|
||||
PyObject *typevars;
|
||||
int values_or_none;
|
||||
|
||||
switch (opcode) {
|
||||
|
@ -1002,6 +1003,7 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
inst(STORE_NAME, (v -- )) {
|
||||
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
|
||||
PyObject *ns = LOCALS();
|
||||
|
@ -1158,31 +1160,41 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
inst(LOAD_NAME, ( -- v)) {
|
||||
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
|
||||
PyObject *locals = LOCALS();
|
||||
op(_LOAD_LOCALS, ( -- locals)) {
|
||||
locals = LOCALS();
|
||||
if (locals == NULL) {
|
||||
_PyErr_Format(tstate, PyExc_SystemError,
|
||||
"no locals when loading %R", name);
|
||||
goto error;
|
||||
_PyErr_SetString(tstate, PyExc_SystemError,
|
||||
"no locals found");
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
if (PyDict_CheckExact(locals)) {
|
||||
v = PyDict_GetItemWithError(locals, name);
|
||||
Py_INCREF(locals);
|
||||
}
|
||||
|
||||
macro(LOAD_LOCALS) = _LOAD_LOCALS;
|
||||
|
||||
op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {
|
||||
PyObject *name = GETITEM(frame->f_code->co_names, oparg);
|
||||
if (PyDict_CheckExact(mod_or_class_dict)) {
|
||||
v = PyDict_GetItemWithError(mod_or_class_dict, name);
|
||||
if (v != NULL) {
|
||||
Py_INCREF(v);
|
||||
}
|
||||
else if (_PyErr_Occurred(tstate)) {
|
||||
Py_DECREF(mod_or_class_dict);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
v = PyObject_GetItem(locals, name);
|
||||
v = PyObject_GetItem(mod_or_class_dict, name);
|
||||
if (v == NULL) {
|
||||
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError))
|
||||
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||
Py_DECREF(mod_or_class_dict);
|
||||
goto error;
|
||||
}
|
||||
_PyErr_Clear(tstate);
|
||||
}
|
||||
}
|
||||
Py_DECREF(mod_or_class_dict);
|
||||
if (v == NULL) {
|
||||
v = PyDict_GetItemWithError(GLOBALS(), name);
|
||||
if (v != NULL) {
|
||||
|
@ -1219,6 +1231,10 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
macro(LOAD_NAME) = _LOAD_LOCALS + _LOAD_FROM_DICT_OR_GLOBALS;
|
||||
|
||||
macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS;
|
||||
|
||||
family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
|
||||
LOAD_GLOBAL,
|
||||
LOAD_GLOBAL_MODULE,
|
||||
|
@ -1339,29 +1355,32 @@ dummy_func(
|
|||
Py_DECREF(oldobj);
|
||||
}
|
||||
|
||||
inst(LOAD_CLASSDEREF, ( -- value)) {
|
||||
PyObject *name, *locals = LOCALS();
|
||||
assert(locals);
|
||||
inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {
|
||||
PyObject *name;
|
||||
assert(class_dict);
|
||||
assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
|
||||
name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
|
||||
if (PyDict_CheckExact(locals)) {
|
||||
value = PyDict_GetItemWithError(locals, name);
|
||||
if (PyDict_CheckExact(class_dict)) {
|
||||
value = PyDict_GetItemWithError(class_dict, name);
|
||||
if (value != NULL) {
|
||||
Py_INCREF(value);
|
||||
}
|
||||
else if (_PyErr_Occurred(tstate)) {
|
||||
Py_DECREF(class_dict);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = PyObject_GetItem(locals, name);
|
||||
value = PyObject_GetItem(class_dict, name);
|
||||
if (value == NULL) {
|
||||
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
|
||||
Py_DECREF(class_dict);
|
||||
goto error;
|
||||
}
|
||||
_PyErr_Clear(tstate);
|
||||
}
|
||||
}
|
||||
Py_DECREF(class_dict);
|
||||
if (!value) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
|
|
651
Python/compile.c
651
Python/compile.c
|
@ -147,6 +147,7 @@ enum {
|
|||
COMPILER_SCOPE_ASYNC_FUNCTION,
|
||||
COMPILER_SCOPE_LAMBDA,
|
||||
COMPILER_SCOPE_COMPREHENSION,
|
||||
COMPILER_SCOPE_TYPEPARAMS,
|
||||
};
|
||||
|
||||
|
||||
|
@ -231,6 +232,7 @@ instr_sequence_next_inst(instr_sequence *seq) {
|
|||
&seq->s_allocated,
|
||||
INITIAL_INSTR_SEQUENCE_SIZE,
|
||||
sizeof(instruction)));
|
||||
assert(seq->s_allocated >= 0);
|
||||
assert(seq->s_used < seq->s_allocated);
|
||||
return seq->s_used++;
|
||||
}
|
||||
|
@ -714,6 +716,19 @@ compiler_set_qualname(struct compiler *c)
|
|||
capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1);
|
||||
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
|
||||
assert(parent);
|
||||
if (parent->u_scope_type == COMPILER_SCOPE_TYPEPARAMS) {
|
||||
/* The parent is a type parameter scope, so we need to
|
||||
look at the grandparent. */
|
||||
if (stack_size == 2) {
|
||||
// If we're immediately within the module, we can skip
|
||||
// the rest and just set the qualname to be the same as name.
|
||||
u->u_metadata.u_qualname = Py_NewRef(u->u_metadata.u_name);
|
||||
return SUCCESS;
|
||||
}
|
||||
capsule = PyList_GET_ITEM(c->c_stack, stack_size - 2);
|
||||
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
|
||||
assert(parent);
|
||||
}
|
||||
|
||||
if (u->u_scope_type == COMPILER_SCOPE_FUNCTION
|
||||
|| u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
|
||||
|
@ -1114,16 +1129,18 @@ codegen_addop_j(instr_sequence *seq, location loc,
|
|||
return instr_sequence_addop(seq, opcode, target.id, loc);
|
||||
}
|
||||
|
||||
#define ADDOP(C, LOC, OP) \
|
||||
RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))
|
||||
|
||||
#define ADDOP_IN_SCOPE(C, LOC, OP) { \
|
||||
if (codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)) < 0) { \
|
||||
compiler_exit_scope(C); \
|
||||
#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \
|
||||
if ((CALL) < 0) { \
|
||||
compiler_exit_scope((C)); \
|
||||
return ERROR; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ADDOP(C, LOC, OP) \
|
||||
RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (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)))
|
||||
|
||||
|
@ -1183,12 +1200,8 @@ codegen_addop_j(instr_sequence *seq, location loc,
|
|||
#define VISIT(C, TYPE, V) \
|
||||
RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), (V)));
|
||||
|
||||
#define VISIT_IN_SCOPE(C, TYPE, V) {\
|
||||
if (compiler_visit_ ## TYPE((C), (V)) < 0) { \
|
||||
compiler_exit_scope(C); \
|
||||
return ERROR; \
|
||||
} \
|
||||
}
|
||||
#define VISIT_IN_SCOPE(C, TYPE, V) \
|
||||
RETURN_IF_ERROR_IN_SCOPE((C), compiler_visit_ ## TYPE((C), (V)))
|
||||
|
||||
#define VISIT_SEQ(C, TYPE, SEQ) { \
|
||||
int _i; \
|
||||
|
@ -1252,6 +1265,16 @@ compiler_enter_scope(struct compiler *c, identifier name,
|
|||
return ERROR;
|
||||
}
|
||||
}
|
||||
if (u->u_ste->ste_needs_classdict) {
|
||||
/* Cook up an implicit __classdict__ cell. */
|
||||
Py_ssize_t res;
|
||||
assert(u->u_scope_type == COMPILER_SCOPE_CLASS);
|
||||
res = dict_add_o(u->u_metadata.u_cellvars, &_Py_ID(__classdict__));
|
||||
if (res < 0) {
|
||||
compiler_unit_free(u);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
u->u_metadata.u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,
|
||||
PyDict_GET_SIZE(u->u_metadata.u_cellvars));
|
||||
|
@ -1718,8 +1741,10 @@ get_ref_type(struct compiler *c, PyObject *name)
|
|||
{
|
||||
int scope;
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&
|
||||
_PyUnicode_EqualToASCIIString(name, "__class__"))
|
||||
(_PyUnicode_EqualToASCIIString(name, "__class__") ||
|
||||
_PyUnicode_EqualToASCIIString(name, "__classdict__"))) {
|
||||
return CELL;
|
||||
}
|
||||
scope = _PyST_GetScope(c->u->u_ste, name);
|
||||
if (scope == 0) {
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
|
@ -2085,26 +2110,81 @@ wrap_in_stopiteration_handler(struct compiler *c)
|
|||
}
|
||||
|
||||
static int
|
||||
compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
||||
compiler_type_params(struct compiler *c, asdl_typeparam_seq *typeparams)
|
||||
{
|
||||
if (!typeparams) {
|
||||
return SUCCESS;
|
||||
}
|
||||
Py_ssize_t n = asdl_seq_LEN(typeparams);
|
||||
|
||||
for (Py_ssize_t i = 0; i < n; i++) {
|
||||
typeparam_ty typeparam = asdl_seq_GET(typeparams, i);
|
||||
location loc = LOC(typeparam);
|
||||
switch(typeparam->kind) {
|
||||
case TypeVar_kind:
|
||||
ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVar.name);
|
||||
if (typeparam->v.TypeVar.bound) {
|
||||
expr_ty bound = typeparam->v.TypeVar.bound;
|
||||
if (compiler_enter_scope(c, typeparam->v.TypeVar.name, COMPILER_SCOPE_TYPEPARAMS,
|
||||
(void *)typeparam, bound->lineno) == -1) {
|
||||
return ERROR;
|
||||
}
|
||||
VISIT_IN_SCOPE(c, expr, bound);
|
||||
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
|
||||
PyCodeObject *co = optimize_and_assemble(c, 1);
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_make_closure(c, loc, co, 0) < 0) {
|
||||
Py_DECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(co);
|
||||
|
||||
int intrinsic = bound->kind == Tuple_kind
|
||||
? INTRINSIC_TYPEVAR_WITH_CONSTRAINTS
|
||||
: INTRINSIC_TYPEVAR_WITH_BOUND;
|
||||
ADDOP_I(c, loc, CALL_INTRINSIC_2, intrinsic);
|
||||
}
|
||||
else {
|
||||
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVAR);
|
||||
}
|
||||
ADDOP_I(c, loc, COPY, 1);
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVar.name, Store));
|
||||
break;
|
||||
case TypeVarTuple_kind:
|
||||
ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVarTuple.name);
|
||||
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVARTUPLE);
|
||||
ADDOP_I(c, loc, COPY, 1);
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVarTuple.name, Store));
|
||||
break;
|
||||
case ParamSpec_kind:
|
||||
ADDOP_LOAD_CONST(c, loc, typeparam->v.ParamSpec.name);
|
||||
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PARAMSPEC);
|
||||
ADDOP_I(c, loc, COPY, 1);
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.ParamSpec.name, Store));
|
||||
break;
|
||||
}
|
||||
}
|
||||
ADDOP_I(c, LOC(asdl_seq_GET(typeparams, 0)), BUILD_TUPLE, n);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags,
|
||||
int firstlineno)
|
||||
{
|
||||
PyCodeObject *co;
|
||||
PyObject *docstring = NULL;
|
||||
arguments_ty args;
|
||||
expr_ty returns;
|
||||
identifier name;
|
||||
asdl_expr_seq* decos;
|
||||
asdl_stmt_seq *body;
|
||||
Py_ssize_t i, funcflags;
|
||||
int annotations;
|
||||
int scope_type;
|
||||
int firstlineno;
|
||||
|
||||
if (is_async) {
|
||||
assert(s->kind == AsyncFunctionDef_kind);
|
||||
|
||||
args = s->v.AsyncFunctionDef.args;
|
||||
returns = s->v.AsyncFunctionDef.returns;
|
||||
decos = s->v.AsyncFunctionDef.decorator_list;
|
||||
name = s->v.AsyncFunctionDef.name;
|
||||
body = s->v.AsyncFunctionDef.body;
|
||||
|
||||
|
@ -2113,33 +2193,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
|||
assert(s->kind == FunctionDef_kind);
|
||||
|
||||
args = s->v.FunctionDef.args;
|
||||
returns = s->v.FunctionDef.returns;
|
||||
decos = s->v.FunctionDef.decorator_list;
|
||||
name = s->v.FunctionDef.name;
|
||||
body = s->v.FunctionDef.body;
|
||||
|
||||
scope_type = COMPILER_SCOPE_FUNCTION;
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(compiler_check_debug_args(c, args));
|
||||
RETURN_IF_ERROR(compiler_decorators(c, decos));
|
||||
|
||||
firstlineno = s->lineno;
|
||||
if (asdl_seq_LEN(decos)) {
|
||||
firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
|
||||
}
|
||||
|
||||
location loc = LOC(s);
|
||||
funcflags = compiler_default_arguments(c, loc, args);
|
||||
if (funcflags == -1) {
|
||||
return ERROR;
|
||||
}
|
||||
annotations = compiler_visit_annotations(c, loc, args, returns);
|
||||
RETURN_IF_ERROR(annotations);
|
||||
if (annotations > 0) {
|
||||
funcflags |= 0x04;
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(
|
||||
compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno));
|
||||
|
||||
|
@ -2155,7 +2214,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
|||
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);
|
||||
for (i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) {
|
||||
for (Py_ssize_t i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) {
|
||||
VISIT_IN_SCOPE(c, stmt, (stmt_ty)asdl_seq_GET(body, i));
|
||||
}
|
||||
if (c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator) {
|
||||
|
@ -2164,29 +2223,52 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
|||
return ERROR;
|
||||
}
|
||||
}
|
||||
co = optimize_and_assemble(c, 1);
|
||||
PyCodeObject *co = optimize_and_assemble(c, 1);
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
Py_XDECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
location loc = LOC(s);
|
||||
if (compiler_make_closure(c, loc, co, funcflags) < 0) {
|
||||
Py_DECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(co);
|
||||
|
||||
RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
|
||||
return compiler_nameop(c, loc, name, Store);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_class(struct compiler *c, stmt_ty s)
|
||||
compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
||||
{
|
||||
PyCodeObject *co;
|
||||
int i, firstlineno;
|
||||
asdl_expr_seq *decos = s->v.ClassDef.decorator_list;
|
||||
arguments_ty args;
|
||||
expr_ty returns;
|
||||
identifier name;
|
||||
asdl_expr_seq *decos;
|
||||
asdl_typeparam_seq *typeparams;
|
||||
Py_ssize_t funcflags;
|
||||
int annotations;
|
||||
int firstlineno;
|
||||
|
||||
if (is_async) {
|
||||
assert(s->kind == AsyncFunctionDef_kind);
|
||||
|
||||
args = s->v.AsyncFunctionDef.args;
|
||||
returns = s->v.AsyncFunctionDef.returns;
|
||||
decos = s->v.AsyncFunctionDef.decorator_list;
|
||||
name = s->v.AsyncFunctionDef.name;
|
||||
typeparams = s->v.AsyncFunctionDef.typeparams;
|
||||
} else {
|
||||
assert(s->kind == FunctionDef_kind);
|
||||
|
||||
args = s->v.FunctionDef.args;
|
||||
returns = s->v.FunctionDef.returns;
|
||||
decos = s->v.FunctionDef.decorator_list;
|
||||
name = s->v.FunctionDef.name;
|
||||
typeparams = s->v.FunctionDef.typeparams;
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(compiler_check_debug_args(c, args));
|
||||
RETURN_IF_ERROR(compiler_decorators(c, decos));
|
||||
|
||||
firstlineno = s->lineno;
|
||||
|
@ -2194,6 +2276,108 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
|
||||
}
|
||||
|
||||
location loc = LOC(s);
|
||||
|
||||
int is_generic = asdl_seq_LEN(typeparams) > 0;
|
||||
|
||||
if (is_generic) {
|
||||
// Used by the CALL to the type parameters function.
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
}
|
||||
|
||||
funcflags = compiler_default_arguments(c, loc, args);
|
||||
if (funcflags == -1) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
int num_typeparam_args = 0;
|
||||
|
||||
if (is_generic) {
|
||||
if (funcflags & 0x01) {
|
||||
num_typeparam_args += 1;
|
||||
}
|
||||
if (funcflags & 0x02) {
|
||||
num_typeparam_args += 1;
|
||||
}
|
||||
if (num_typeparam_args == 2) {
|
||||
ADDOP_I(c, loc, SWAP, 2);
|
||||
}
|
||||
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>", name);
|
||||
if (!typeparams_name) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
|
||||
(void *)typeparams, firstlineno) == -1) {
|
||||
Py_DECREF(typeparams_name);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(typeparams_name);
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, typeparams));
|
||||
if ((funcflags & 0x01) || (funcflags & 0x02)) {
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, 0, loc));
|
||||
}
|
||||
if ((funcflags & 0x01) && (funcflags & 0x02)) {
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, 1, loc));
|
||||
}
|
||||
}
|
||||
|
||||
annotations = compiler_visit_annotations(c, loc, args, returns);
|
||||
if (annotations < 0) {
|
||||
if (is_generic) {
|
||||
compiler_exit_scope(c);
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
if (annotations > 0) {
|
||||
funcflags |= 0x04;
|
||||
}
|
||||
|
||||
if (compiler_function_body(c, s, is_async, funcflags, firstlineno) < 0) {
|
||||
if (is_generic) {
|
||||
compiler_exit_scope(c);
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (is_generic) {
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(
|
||||
INSTR_SEQUENCE(c), SWAP, 2, loc));
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(
|
||||
INSTR_SEQUENCE(c), CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS, loc));
|
||||
|
||||
c->u->u_metadata.u_argcount = num_typeparam_args;
|
||||
PyCodeObject *co = optimize_and_assemble(c, 0);
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_make_closure(c, loc, co, 0) < 0) {
|
||||
Py_DECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(co);
|
||||
if (num_typeparam_args > 0) {
|
||||
ADDOP_I(c, loc, SWAP, num_typeparam_args + 1);
|
||||
}
|
||||
ADDOP_I(c, loc, CALL, num_typeparam_args);
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
|
||||
return compiler_nameop(c, loc, name, Store);
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_set_type_params_in_class(struct compiler *c, location loc)
|
||||
{
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_STR(type_params), Load));
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_ID(__type_params__), Store));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
|
||||
{
|
||||
/* ultimately generate code for:
|
||||
<name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
|
||||
where:
|
||||
|
@ -2204,68 +2388,100 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
<keywords> is the keyword arguments and **kwds argument
|
||||
This borrows from compiler_call.
|
||||
*/
|
||||
|
||||
/* 1. compile the class body into a code object */
|
||||
RETURN_IF_ERROR(
|
||||
compiler_enter_scope(c, s->v.ClassDef.name,
|
||||
COMPILER_SCOPE_CLASS, (void *)s, firstlineno));
|
||||
|
||||
/* this block represents what we do in the new scope */
|
||||
{
|
||||
location loc = LOCATION(firstlineno, firstlineno, 0, 0);
|
||||
/* use the class name for name mangling */
|
||||
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
|
||||
/* load (global) __name__ ... */
|
||||
if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
/* ... and store it as __module__ */
|
||||
if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
assert(c->u->u_metadata.u_qualname);
|
||||
ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname);
|
||||
if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
/* compile the body proper */
|
||||
if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
/* The following code is artificial */
|
||||
/* Return __classcell__ if it is referenced, otherwise return None */
|
||||
if (c->u->u_ste->ste_needs_class_closure) {
|
||||
/* Store __classcell__ into class namespace & return it */
|
||||
i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));
|
||||
if (i < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
|
||||
ADDOP_I(c, NO_LOCATION, COPY, 1);
|
||||
if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* No methods referenced __class__, so just return None */
|
||||
ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
|
||||
}
|
||||
ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE);
|
||||
/* create the code object */
|
||||
co = optimize_and_assemble(c, 1);
|
||||
location loc = LOCATION(firstlineno, firstlineno, 0, 0);
|
||||
/* use the class name for name mangling */
|
||||
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
|
||||
/* load (global) __name__ ... */
|
||||
if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
/* ... and store it as __module__ */
|
||||
if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
assert(c->u->u_metadata.u_qualname);
|
||||
ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname);
|
||||
if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
asdl_typeparam_seq *typeparams = s->v.ClassDef.typeparams;
|
||||
if (asdl_seq_LEN(typeparams) > 0) {
|
||||
if (!compiler_set_type_params_in_class(c, loc)) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
if (c->u->u_ste->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,
|
||||
&_Py_ID(__classdict__)) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
/* compile the body proper */
|
||||
if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
/* The following code is artificial */
|
||||
/* Set __classdictcell__ if necessary */
|
||||
if (c->u->u_ste->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) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
|
||||
if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classdictcell__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
/* Return __classcell__ if it is referenced, otherwise return None */
|
||||
if (c->u->u_ste->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) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);
|
||||
ADDOP_I(c, NO_LOCATION, COPY, 1);
|
||||
if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* No methods referenced __class__, so just return None */
|
||||
ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);
|
||||
}
|
||||
ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE);
|
||||
/* create the code object */
|
||||
PyCodeObject *co = optimize_and_assemble(c, 1);
|
||||
|
||||
/* leave the new scope */
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
location loc = LOC(s);
|
||||
/* 2. load the 'build_class' function */
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP(c, loc, LOAD_BUILD_CLASS);
|
||||
|
@ -2280,10 +2496,100 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
/* 4. load class name */
|
||||
ADDOP_LOAD_CONST(c, loc, s->v.ClassDef.name);
|
||||
|
||||
/* 5. generate the rest of the code for the call */
|
||||
RETURN_IF_ERROR(compiler_call_helper(c, loc, 2,
|
||||
s->v.ClassDef.bases,
|
||||
s->v.ClassDef.keywords));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_class(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
asdl_expr_seq *decos = s->v.ClassDef.decorator_list;
|
||||
|
||||
RETURN_IF_ERROR(compiler_decorators(c, decos));
|
||||
|
||||
int firstlineno = s->lineno;
|
||||
if (asdl_seq_LEN(decos)) {
|
||||
firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
|
||||
}
|
||||
location loc = LOC(s);
|
||||
|
||||
asdl_typeparam_seq *typeparams = s->v.ClassDef.typeparams;
|
||||
int is_generic = asdl_seq_LEN(typeparams) > 0;
|
||||
if (is_generic) {
|
||||
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>",
|
||||
s->v.ClassDef.name);
|
||||
if (!typeparams_name) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
|
||||
(void *)typeparams, firstlineno) == -1) {
|
||||
Py_DECREF(typeparams_name);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(typeparams_name);
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, typeparams));
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Store));
|
||||
}
|
||||
|
||||
if (compiler_class_body(c, s, firstlineno) < 0) {
|
||||
if (is_generic) {
|
||||
compiler_exit_scope(c);
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* generate the rest of the code for the call */
|
||||
|
||||
if (is_generic) {
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
_Py_DECLARE_STR(generic_base, ".generic_base");
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Load));
|
||||
RETURN_IF_ERROR_IN_SCOPE(
|
||||
c, codegen_addop_i(INSTR_SEQUENCE(c), CALL_INTRINSIC_1, INTRINSIC_SUBSCRIPT_GENERIC, loc)
|
||||
)
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(generic_base), Store));
|
||||
|
||||
Py_ssize_t original_len = asdl_seq_LEN(s->v.ClassDef.bases);
|
||||
asdl_expr_seq *bases = _Py_asdl_expr_seq_new(
|
||||
original_len + 1, c->c_arena);
|
||||
if (bases == NULL) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
for (Py_ssize_t i = 0; i < original_len; i++) {
|
||||
asdl_seq_SET(bases, i, asdl_seq_GET(s->v.ClassDef.bases, i));
|
||||
}
|
||||
expr_ty name_node = _PyAST_Name(
|
||||
&_Py_STR(generic_base), Load,
|
||||
loc.lineno, loc.col_offset, loc.end_lineno, loc.end_col_offset, c->c_arena
|
||||
);
|
||||
if (name_node == NULL) {
|
||||
compiler_exit_scope(c);
|
||||
return ERROR;
|
||||
}
|
||||
asdl_seq_SET(bases, original_len, name_node);
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_call_helper(c, loc, 2,
|
||||
bases,
|
||||
s->v.ClassDef.keywords));
|
||||
|
||||
PyCodeObject *co = optimize_and_assemble(c, 0);
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_make_closure(c, loc, co, 0) < 0) {
|
||||
Py_DECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(co);
|
||||
ADDOP_I(c, loc, CALL, 0);
|
||||
} else {
|
||||
RETURN_IF_ERROR(compiler_call_helper(c, loc, 2,
|
||||
s->v.ClassDef.bases,
|
||||
s->v.ClassDef.keywords));
|
||||
}
|
||||
|
||||
/* 6. apply decorators */
|
||||
RETURN_IF_ERROR(compiler_apply_decorators(c, decos));
|
||||
|
@ -2293,6 +2599,87 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_typealias_body(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
location loc = LOC(s);
|
||||
PyObject *name = s->v.TypeAlias.name->v.Name.id;
|
||||
RETURN_IF_ERROR(
|
||||
compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno));
|
||||
/* 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));
|
||||
VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value);
|
||||
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
|
||||
PyCodeObject *co = optimize_and_assemble(c, 0);
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_make_closure(c, loc, co, 0) < 0) {
|
||||
Py_DECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(co);
|
||||
ADDOP_I(c, loc, BUILD_TUPLE, 3);
|
||||
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEALIAS);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_typealias(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
location loc = LOC(s);
|
||||
asdl_typeparam_seq *typeparams = s->v.TypeAlias.typeparams;
|
||||
int is_generic = asdl_seq_LEN(typeparams) > 0;
|
||||
PyObject *name = s->v.TypeAlias.name->v.Name.id;
|
||||
if (is_generic) {
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>",
|
||||
name);
|
||||
if (!typeparams_name) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
|
||||
(void *)typeparams, loc.lineno) == -1) {
|
||||
Py_DECREF(typeparams_name);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(typeparams_name);
|
||||
RETURN_IF_ERROR_IN_SCOPE(
|
||||
c, compiler_addop_load_const(c->c_const_cache, c->u, loc, name)
|
||||
);
|
||||
RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, typeparams));
|
||||
}
|
||||
else {
|
||||
ADDOP_LOAD_CONST(c, loc, name);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
}
|
||||
|
||||
if (compiler_typealias_body(c, s) < 0) {
|
||||
if (is_generic) {
|
||||
compiler_exit_scope(c);
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (is_generic) {
|
||||
PyCodeObject *co = optimize_and_assemble(c, 0);
|
||||
compiler_exit_scope(c);
|
||||
if (co == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
if (compiler_make_closure(c, loc, co, 0) < 0) {
|
||||
Py_DECREF(co);
|
||||
return ERROR;
|
||||
}
|
||||
Py_DECREF(co);
|
||||
ADDOP_I(c, loc, CALL, 0);
|
||||
}
|
||||
RETURN_IF_ERROR(compiler_nameop(c, loc, name, Store));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* Return false if the expression is a constant value except named singletons.
|
||||
Return true otherwise. */
|
||||
static bool
|
||||
|
@ -2705,7 +3092,7 @@ 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 (c->u->u_ste->ste_type != FunctionBlock) {
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
return compiler_error(c, loc, "'return' outside function");
|
||||
}
|
||||
if (s->v.Return.value != NULL &&
|
||||
|
@ -3519,6 +3906,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
|
|||
return compiler_function(c, s, 0);
|
||||
case ClassDef_kind:
|
||||
return compiler_class(c, s);
|
||||
case TypeAlias_kind:
|
||||
return compiler_typealias(c, s);
|
||||
case Return_kind:
|
||||
return compiler_return(c, s);
|
||||
case Delete_kind:
|
||||
|
@ -3725,12 +4114,12 @@ compiler_nameop(struct compiler *c, location loc,
|
|||
optype = OP_DEREF;
|
||||
break;
|
||||
case LOCAL:
|
||||
if (c->u->u_ste->ste_type == FunctionBlock ||
|
||||
if (_PyST_IsFunctionLike(c->u->u_ste) ||
|
||||
(PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True))
|
||||
optype = OP_FAST;
|
||||
break;
|
||||
case GLOBAL_IMPLICIT:
|
||||
if (c->u->u_ste->ste_type == FunctionBlock)
|
||||
if (_PyST_IsFunctionLike(c->u->u_ste))
|
||||
optype = OP_GLOBAL;
|
||||
break;
|
||||
case GLOBAL_EXPLICIT:
|
||||
|
@ -3748,7 +4137,24 @@ compiler_nameop(struct compiler *c, location loc,
|
|||
case OP_DEREF:
|
||||
switch (ctx) {
|
||||
case Load:
|
||||
op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF;
|
||||
if (c->u->u_ste->ste_type == ClassBlock) {
|
||||
op = LOAD_FROM_DICT_OR_DEREF;
|
||||
// First load the locals
|
||||
if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
else if (c->u->u_ste->ste_can_see_class_scope) {
|
||||
op = LOAD_FROM_DICT_OR_DEREF;
|
||||
// First load the classdict
|
||||
if (compiler_addop_o(c->u, loc, LOAD_DEREF,
|
||||
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
op = LOAD_DEREF;
|
||||
}
|
||||
break;
|
||||
case Store: op = STORE_DEREF; break;
|
||||
case Del: op = DELETE_DEREF; break;
|
||||
|
@ -3764,7 +4170,18 @@ compiler_nameop(struct compiler *c, location loc,
|
|||
return SUCCESS;
|
||||
case OP_GLOBAL:
|
||||
switch (ctx) {
|
||||
case Load: op = LOAD_GLOBAL; break;
|
||||
case Load:
|
||||
if (c->u->u_ste->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,
|
||||
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
} else {
|
||||
op = LOAD_GLOBAL;
|
||||
}
|
||||
break;
|
||||
case Store: op = STORE_GLOBAL; break;
|
||||
case Del: op = DELETE_GLOBAL; break;
|
||||
}
|
||||
|
@ -5008,7 +5425,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
|
|||
// assignment expression to a nonlocal in the comprehension, these don't
|
||||
// need handling here since they shouldn't be isolated
|
||||
if (symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) {
|
||||
if (c->u->u_ste->ste_type != FunctionBlock) {
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
// non-function scope: override this name to use fast locals
|
||||
PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k);
|
||||
if (orig != Py_True) {
|
||||
|
@ -5604,7 +6021,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
|||
case DictComp_kind:
|
||||
return compiler_dictcomp(c, e);
|
||||
case Yield_kind:
|
||||
if (c->u->u_ste->ste_type != FunctionBlock) {
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
return compiler_error(c, loc, "'yield' outside function");
|
||||
}
|
||||
if (e->v.Yield.value) {
|
||||
|
@ -5616,7 +6033,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
|||
ADDOP_YIELD(c, loc);
|
||||
break;
|
||||
case YieldFrom_kind:
|
||||
if (c->u->u_ste->ste_type != FunctionBlock) {
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
return compiler_error(c, loc, "'yield' outside function");
|
||||
}
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) {
|
||||
|
@ -5629,7 +6046,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
|||
break;
|
||||
case Await_kind:
|
||||
if (!IS_TOP_LEVEL_AWAIT(c)){
|
||||
if (c->u->u_ste->ste_type != FunctionBlock){
|
||||
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
return compiler_error(c, loc, "'await' outside function");
|
||||
}
|
||||
|
||||
|
@ -6916,7 +7333,7 @@ compute_code_flags(struct compiler *c)
|
|||
{
|
||||
PySTEntryObject *ste = c->u->u_ste;
|
||||
int flags = 0;
|
||||
if (ste->ste_type == FunctionBlock) {
|
||||
if (_PyST_IsFunctionLike(c->u->u_ste)) {
|
||||
flags |= CO_NEWLOCALS | CO_OPTIMIZED;
|
||||
if (ste->ste_nested)
|
||||
flags |= CO_NESTED;
|
||||
|
@ -7114,7 +7531,7 @@ fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *
|
|||
case LOAD_DEREF:
|
||||
case STORE_DEREF:
|
||||
case DELETE_DEREF:
|
||||
case LOAD_CLASSDEREF:
|
||||
case LOAD_FROM_DICT_OR_DEREF:
|
||||
assert(oldoffset >= 0);
|
||||
assert(oldoffset < noffsets);
|
||||
assert(fixedmap[oldoffset] >= 0);
|
||||
|
|
1002
Python/generated_cases.c.h
generated
1002
Python/generated_cases.c.h
generated
File diff suppressed because it is too large
Load diff
|
@ -3,10 +3,12 @@
|
|||
|
||||
#include "Python.h"
|
||||
#include "pycore_frame.h"
|
||||
#include "pycore_function.h"
|
||||
#include "pycore_runtime.h"
|
||||
#include "pycore_global_objects.h"
|
||||
#include "pycore_intrinsics.h"
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_typevarobject.h"
|
||||
|
||||
|
||||
/******** Unary functions ********/
|
||||
|
@ -199,6 +201,13 @@ list_to_tuple(PyThreadState* unused, PyObject *v)
|
|||
return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
make_typevar(PyThreadState* Py_UNUSED(ignored), PyObject *v)
|
||||
{
|
||||
assert(PyUnicode_Check(v));
|
||||
return _Py_make_typevar(v, NULL, NULL);
|
||||
}
|
||||
|
||||
const instrinsic_func1
|
||||
_PyIntrinsics_UnaryFunctions[] = {
|
||||
[0] = no_intrinsic,
|
||||
|
@ -208,6 +217,11 @@ _PyIntrinsics_UnaryFunctions[] = {
|
|||
[INTRINSIC_ASYNC_GEN_WRAP] = _PyAsyncGenValueWrapperNew,
|
||||
[INTRINSIC_UNARY_POSITIVE] = unary_pos,
|
||||
[INTRINSIC_LIST_TO_TUPLE] = list_to_tuple,
|
||||
[INTRINSIC_TYPEVAR] = make_typevar,
|
||||
[INTRINSIC_PARAMSPEC] = _Py_make_paramspec,
|
||||
[INTRINSIC_TYPEVARTUPLE] = _Py_make_typevartuple,
|
||||
[INTRINSIC_SUBSCRIPT_GENERIC] = _Py_subscript_generic,
|
||||
[INTRINSIC_TYPEALIAS] = _Py_make_typealias,
|
||||
};
|
||||
|
||||
|
||||
|
@ -221,8 +235,26 @@ prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs)
|
|||
return _PyExc_PrepReraiseStar(orig, excs);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
make_typevar_with_bound(PyThreadState* Py_UNUSED(ignored), PyObject *name,
|
||||
PyObject *evaluate_bound)
|
||||
{
|
||||
assert(PyUnicode_Check(name));
|
||||
return _Py_make_typevar(name, evaluate_bound, NULL);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
make_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name,
|
||||
PyObject *evaluate_constraints)
|
||||
{
|
||||
assert(PyUnicode_Check(name));
|
||||
return _Py_make_typevar(name, NULL, evaluate_constraints);
|
||||
}
|
||||
|
||||
const instrinsic_func2
|
||||
_PyIntrinsics_BinaryFunctions[] = {
|
||||
[INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star,
|
||||
[INTRINSIC_TYPEVAR_WITH_BOUND] = make_typevar_with_bound,
|
||||
[INTRINSIC_TYPEVAR_WITH_CONSTRAINTS] = make_typevar_with_constraints,
|
||||
[INTRINSIC_SET_FUNCTION_TYPE_PARAMS] = _Py_set_function_type_params,
|
||||
};
|
||||
|
||||
|
|
|
@ -161,8 +161,12 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
|||
return 1;
|
||||
case DELETE_GLOBAL:
|
||||
return 0;
|
||||
case LOAD_NAME:
|
||||
case LOAD_LOCALS:
|
||||
return 0;
|
||||
case LOAD_NAME:
|
||||
return 0+1;
|
||||
case LOAD_FROM_DICT_OR_GLOBALS:
|
||||
return 1;
|
||||
case LOAD_GLOBAL:
|
||||
return 0;
|
||||
case LOAD_GLOBAL_MODULE:
|
||||
|
@ -175,8 +179,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
|||
return 0;
|
||||
case DELETE_DEREF:
|
||||
return 0;
|
||||
case LOAD_CLASSDEREF:
|
||||
return 0;
|
||||
case LOAD_FROM_DICT_OR_DEREF:
|
||||
return 1;
|
||||
case LOAD_DEREF:
|
||||
return 0;
|
||||
case STORE_DEREF:
|
||||
|
@ -551,7 +555,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
|||
return 0;
|
||||
case DELETE_GLOBAL:
|
||||
return 0;
|
||||
case LOAD_LOCALS:
|
||||
return 1;
|
||||
case LOAD_NAME:
|
||||
return 1+1;
|
||||
case LOAD_FROM_DICT_OR_GLOBALS:
|
||||
return 1;
|
||||
case LOAD_GLOBAL:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
|
@ -565,7 +573,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
|||
return 0;
|
||||
case DELETE_DEREF:
|
||||
return 0;
|
||||
case LOAD_CLASSDEREF:
|
||||
case LOAD_FROM_DICT_OR_DEREF:
|
||||
return 1;
|
||||
case LOAD_DEREF:
|
||||
return 1;
|
||||
|
@ -869,14 +877,16 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
|||
[DELETE_ATTR] = { true, INSTR_FMT_IB },
|
||||
[STORE_GLOBAL] = { true, INSTR_FMT_IB },
|
||||
[DELETE_GLOBAL] = { true, INSTR_FMT_IB },
|
||||
[LOAD_LOCALS] = { true, INSTR_FMT_IB },
|
||||
[LOAD_NAME] = { true, INSTR_FMT_IB },
|
||||
[LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB },
|
||||
[LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 },
|
||||
[LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 },
|
||||
[LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 },
|
||||
[DELETE_FAST] = { true, INSTR_FMT_IB },
|
||||
[MAKE_CELL] = { true, INSTR_FMT_IB },
|
||||
[DELETE_DEREF] = { true, INSTR_FMT_IB },
|
||||
[LOAD_CLASSDEREF] = { true, INSTR_FMT_IB },
|
||||
[LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB },
|
||||
[LOAD_DEREF] = { true, INSTR_FMT_IB },
|
||||
[STORE_DEREF] = { true, INSTR_FMT_IB },
|
||||
[COPY_FREE_VARS] = { true, INSTR_FMT_IB },
|
||||
|
|
10
Python/opcode_targets.h
generated
10
Python/opcode_targets.h
generated
|
@ -86,8 +86,8 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||
&&TARGET_SETUP_ANNOTATIONS,
|
||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||
&&TARGET_LOAD_LOCALS,
|
||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||
&&TARGET_POP_EXCEPT,
|
||||
&&TARGET_STORE_NAME,
|
||||
&&TARGET_DELETE_NAME,
|
||||
|
@ -110,9 +110,9 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_IMPORT_NAME,
|
||||
&&TARGET_IMPORT_FROM,
|
||||
&&TARGET_JUMP_FORWARD,
|
||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
||||
&&TARGET_STORE_ATTR_SLOT,
|
||||
&&TARGET_POP_JUMP_IF_FALSE,
|
||||
&&TARGET_POP_JUMP_IF_TRUE,
|
||||
&&TARGET_LOAD_GLOBAL,
|
||||
|
@ -147,7 +147,7 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_LIST_APPEND,
|
||||
&&TARGET_SET_ADD,
|
||||
&&TARGET_MAP_ADD,
|
||||
&&TARGET_LOAD_CLASSDEREF,
|
||||
&&TARGET_STORE_ATTR_SLOT,
|
||||
&&TARGET_COPY_FREE_VARS,
|
||||
&&TARGET_YIELD_VALUE,
|
||||
&&TARGET_RESUME,
|
||||
|
@ -174,8 +174,8 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_KW_NAMES,
|
||||
&&TARGET_CALL_INTRINSIC_1,
|
||||
&&TARGET_CALL_INTRINSIC_2,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_LOAD_FROM_DICT_OR_GLOBALS,
|
||||
&&TARGET_LOAD_FROM_DICT_OR_DEREF,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "pycore_sysmodule.h" // _PySys_ClearAuditHooks()
|
||||
#include "pycore_traceback.h" // _Py_DumpTracebackThreads()
|
||||
#include "pycore_typeobject.h" // _PyTypes_InitTypes()
|
||||
#include "pycore_typevarobject.h" // _Py_clear_generic_types()
|
||||
#include "pycore_unicodeobject.h" // _PyUnicode_InitTypes()
|
||||
#include "opcode.h"
|
||||
|
||||
|
@ -1698,6 +1699,7 @@ finalize_interp_clear(PyThreadState *tstate)
|
|||
int is_main_interp = _Py_IsMainInterpreter(tstate->interp);
|
||||
|
||||
_PyExc_ClearExceptionGroupType(tstate->interp);
|
||||
_Py_clear_generic_types(tstate->interp);
|
||||
|
||||
/* Clear interpreter state and all thread states */
|
||||
_PyInterpreterState_Clear(tstate);
|
||||
|
|
|
@ -47,6 +47,18 @@
|
|||
#define ANNOTATION_NOT_ALLOWED \
|
||||
"'%s' can not be used within an annotation"
|
||||
|
||||
#define TYPEVAR_BOUND_NOT_ALLOWED \
|
||||
"'%s' can not be used within a TypeVar bound"
|
||||
|
||||
#define TYPEALIAS_NOT_ALLOWED \
|
||||
"'%s' can not be used within a type alias"
|
||||
|
||||
#define TYPEPARAM_NOT_ALLOWED \
|
||||
"'%s' can not be used within the definition of a generic"
|
||||
|
||||
#define DUPLICATE_TYPE_PARAM \
|
||||
"duplicate type parameter '%U'"
|
||||
|
||||
|
||||
#define LOCATION(x) \
|
||||
(x)->lineno, (x)->col_offset, (x)->end_lineno, (x)->end_col_offset
|
||||
|
@ -95,7 +107,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
|
||||
if (st->st_cur != NULL &&
|
||||
(st->st_cur->ste_nested ||
|
||||
st->st_cur->ste_type == FunctionBlock))
|
||||
_PyST_IsFunctionLike(st->st_cur)))
|
||||
ste->ste_nested = 1;
|
||||
ste->ste_child_free = 0;
|
||||
ste->ste_generator = 0;
|
||||
|
@ -105,7 +117,9 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
ste->ste_needs_class_closure = 0;
|
||||
ste->ste_comp_inlined = 0;
|
||||
ste->ste_comp_iter_target = 0;
|
||||
ste->ste_can_see_class_scope = 0;
|
||||
ste->ste_comp_iter_expr = 0;
|
||||
ste->ste_needs_classdict = 0;
|
||||
|
||||
ste->ste_symbols = PyDict_New();
|
||||
ste->ste_varnames = PyList_New(0);
|
||||
|
@ -208,6 +222,7 @@ static int symtable_enter_block(struct symtable *st, identifier name,
|
|||
static int symtable_exit_block(struct symtable *st);
|
||||
static int symtable_visit_stmt(struct symtable *st, stmt_ty s);
|
||||
static int symtable_visit_expr(struct symtable *st, expr_ty s);
|
||||
static int symtable_visit_typeparam(struct symtable *st, typeparam_ty s);
|
||||
static int symtable_visit_genexp(struct symtable *st, expr_ty s);
|
||||
static int symtable_visit_listcomp(struct symtable *st, expr_ty s);
|
||||
static int symtable_visit_setcomp(struct symtable *st, expr_ty s);
|
||||
|
@ -403,6 +418,15 @@ _PyST_GetScope(PySTEntryObject *ste, PyObject *name)
|
|||
return (symbol >> SCOPE_OFFSET) & SCOPE_MASK;
|
||||
}
|
||||
|
||||
int
|
||||
_PyST_IsFunctionLike(PySTEntryObject *ste)
|
||||
{
|
||||
return ste->ste_type == FunctionBlock
|
||||
|| ste->ste_type == TypeVarBoundBlock
|
||||
|| ste->ste_type == TypeAliasBlock
|
||||
|| ste->ste_type == TypeParamBlock;
|
||||
}
|
||||
|
||||
static int
|
||||
error_at_directive(PySTEntryObject *ste, PyObject *name)
|
||||
{
|
||||
|
@ -495,7 +519,7 @@ error_at_directive(PySTEntryObject *ste, PyObject *name)
|
|||
static int
|
||||
analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
||||
PyObject *bound, PyObject *local, PyObject *free,
|
||||
PyObject *global)
|
||||
PyObject *global, PyObject *typeparams, PySTEntryObject *class_entry)
|
||||
{
|
||||
if (flags & DEF_GLOBAL) {
|
||||
if (flags & DEF_NONLOCAL) {
|
||||
|
@ -524,6 +548,12 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
|||
|
||||
return error_at_directive(ste, name);
|
||||
}
|
||||
if (PySet_Contains(typeparams, name)) {
|
||||
PyErr_Format(PyExc_SyntaxError,
|
||||
"nonlocal binding not allowed for type parameter '%U'",
|
||||
name);
|
||||
return error_at_directive(ste, name);
|
||||
}
|
||||
SET_SCOPE(scopes, name, FREE);
|
||||
ste->ste_free = 1;
|
||||
return PySet_Add(free, name) >= 0;
|
||||
|
@ -534,8 +564,34 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
|||
return 0;
|
||||
if (PySet_Discard(global, name) < 0)
|
||||
return 0;
|
||||
if (flags & DEF_TYPE_PARAM) {
|
||||
if (PySet_Add(typeparams, name) < 0)
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (PySet_Discard(typeparams, name) < 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// If we were passed class_entry (i.e., we're in an ste_can_see_class_scope scope)
|
||||
// and the bound name is in that set, then the name is potentially bound both by
|
||||
// the immediately enclosing class namespace, and also by an outer function namespace.
|
||||
// In that case, we want the runtime name resolution to look at only the class
|
||||
// namespace and the globals (not the namespace providing the bound).
|
||||
// Similarly, if the name is explicitly global in the class namespace (through the
|
||||
// global statement), we want to also treat it as a global in this scope.
|
||||
if (class_entry != NULL) {
|
||||
long class_flags = _PyST_GetSymbol(class_entry, name);
|
||||
if (class_flags & DEF_GLOBAL) {
|
||||
SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
|
||||
return 1;
|
||||
}
|
||||
else if (class_flags & DEF_BOUND && !(class_flags & DEF_NONLOCAL)) {
|
||||
SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* If an enclosing block has a binding for this name, it
|
||||
is a free variable rather than a global variable.
|
||||
Note that having a non-NULL bound implies that the block
|
||||
|
@ -611,7 +667,7 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
|
|||
if (PyLong_AsLong(existing) & DEF_BOUND) {
|
||||
// cell vars in comprehension that are locals in outer scope
|
||||
// must be promoted to cell so u_cellvars isn't wrong
|
||||
if (scope == CELL && ste->ste_type == FunctionBlock) {
|
||||
if (scope == CELL && _PyST_IsFunctionLike(ste)) {
|
||||
if (PySet_Add(promote_to_cell, k) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -682,6 +738,11 @@ drop_class_free(PySTEntryObject *ste, PyObject *free)
|
|||
return 0;
|
||||
if (res)
|
||||
ste->ste_needs_class_closure = 1;
|
||||
res = PySet_Discard(free, &_Py_ID(__classdict__));
|
||||
if (res < 0)
|
||||
return 0;
|
||||
if (res)
|
||||
ste->ste_needs_classdict = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -799,11 +860,13 @@ error:
|
|||
|
||||
static int
|
||||
analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
|
||||
PyObject *global, PyObject **child_free);
|
||||
PyObject *global, PyObject *typeparams,
|
||||
PySTEntryObject *class_entry, PyObject **child_free);
|
||||
|
||||
static int
|
||||
analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
|
||||
PyObject *global)
|
||||
PyObject *global, PyObject *typeparams,
|
||||
PySTEntryObject *class_entry)
|
||||
{
|
||||
PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL;
|
||||
PyObject *newglobal = NULL, *newfree = NULL, *promote_to_cell = NULL;
|
||||
|
@ -865,14 +928,14 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
|
|||
while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {
|
||||
long flags = PyLong_AS_LONG(v);
|
||||
if (!analyze_name(ste, scopes, name, flags,
|
||||
bound, local, free, global))
|
||||
bound, local, free, global, typeparams, class_entry))
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Populate global and bound sets to be passed to children. */
|
||||
if (ste->ste_type != ClassBlock) {
|
||||
/* Add function locals to bound set */
|
||||
if (ste->ste_type == FunctionBlock) {
|
||||
if (_PyST_IsFunctionLike(ste)) {
|
||||
temp = PyNumber_InPlaceOr(newbound, local);
|
||||
if (!temp)
|
||||
goto error;
|
||||
|
@ -892,9 +955,11 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
|
|||
Py_DECREF(temp);
|
||||
}
|
||||
else {
|
||||
/* Special-case __class__ */
|
||||
/* Special-case __class__ and __classdict__ */
|
||||
if (PySet_Add(newbound, &_Py_ID(__class__)) < 0)
|
||||
goto error;
|
||||
if (PySet_Add(newbound, &_Py_ID(__classdict__)) < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Recursively call analyze_child_block() on each child block.
|
||||
|
@ -910,13 +975,23 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
|
|||
assert(c && PySTEntry_Check(c));
|
||||
entry = (PySTEntryObject*)c;
|
||||
|
||||
PySTEntryObject *new_class_entry = NULL;
|
||||
if (entry->ste_can_see_class_scope) {
|
||||
if (ste->ste_type == ClassBlock) {
|
||||
new_class_entry = ste;
|
||||
}
|
||||
else if (class_entry) {
|
||||
new_class_entry = class_entry;
|
||||
}
|
||||
}
|
||||
|
||||
// we inline all non-generator-expression comprehensions
|
||||
int inline_comp =
|
||||
entry->ste_comprehension &&
|
||||
!entry->ste_generator;
|
||||
|
||||
if (!analyze_child_block(entry, newbound, newfree, newglobal,
|
||||
&child_free))
|
||||
typeparams, new_class_entry, &child_free))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
@ -952,7 +1027,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
|
|||
}
|
||||
|
||||
/* Check if any local variables must be converted to cell variables */
|
||||
if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, promote_to_cell))
|
||||
if (_PyST_IsFunctionLike(ste) && !analyze_cells(scopes, newfree, promote_to_cell))
|
||||
goto error;
|
||||
else if (ste->ste_type == ClassBlock && !drop_class_free(ste, newfree))
|
||||
goto error;
|
||||
|
@ -980,9 +1055,11 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
|
|||
|
||||
static int
|
||||
analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
|
||||
PyObject *global, PyObject** child_free)
|
||||
PyObject *global, PyObject *typeparams,
|
||||
PySTEntryObject *class_entry, PyObject** child_free)
|
||||
{
|
||||
PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL;
|
||||
PyObject *temp_typeparams = NULL;
|
||||
|
||||
/* Copy the bound/global/free sets.
|
||||
|
||||
|
@ -1000,24 +1077,30 @@ analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,
|
|||
temp_global = PySet_New(global);
|
||||
if (!temp_global)
|
||||
goto error;
|
||||
temp_typeparams = PySet_New(typeparams);
|
||||
if (!temp_typeparams)
|
||||
goto error;
|
||||
|
||||
if (!analyze_block(entry, temp_bound, temp_free, temp_global))
|
||||
if (!analyze_block(entry, temp_bound, temp_free, temp_global,
|
||||
temp_typeparams, class_entry))
|
||||
goto error;
|
||||
*child_free = temp_free;
|
||||
Py_DECREF(temp_bound);
|
||||
Py_DECREF(temp_global);
|
||||
Py_DECREF(temp_typeparams);
|
||||
return 1;
|
||||
error:
|
||||
Py_XDECREF(temp_bound);
|
||||
Py_XDECREF(temp_free);
|
||||
Py_XDECREF(temp_global);
|
||||
Py_XDECREF(temp_typeparams);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_analyze(struct symtable *st)
|
||||
{
|
||||
PyObject *free, *global;
|
||||
PyObject *free, *global, *typeparams;
|
||||
int r;
|
||||
|
||||
free = PySet_New(NULL);
|
||||
|
@ -1028,9 +1111,16 @@ symtable_analyze(struct symtable *st)
|
|||
Py_DECREF(free);
|
||||
return 0;
|
||||
}
|
||||
r = analyze_block(st->st_top, NULL, free, global);
|
||||
typeparams = PySet_New(NULL);
|
||||
if (!typeparams) {
|
||||
Py_DECREF(free);
|
||||
Py_DECREF(global);
|
||||
return 0;
|
||||
}
|
||||
r = analyze_block(st->st_top, NULL, free, global, typeparams, NULL);
|
||||
Py_DECREF(free);
|
||||
Py_DECREF(global);
|
||||
Py_DECREF(typeparams);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1133,6 +1223,13 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s
|
|||
end_lineno, end_col_offset + 1);
|
||||
goto error;
|
||||
}
|
||||
if ((flag & DEF_TYPE_PARAM) && (val & DEF_TYPE_PARAM)) {
|
||||
PyErr_Format(PyExc_SyntaxError, DUPLICATE_TYPE_PARAM, name);
|
||||
PyErr_RangedSyntaxLocationObject(st->st_filename,
|
||||
lineno, col_offset + 1,
|
||||
end_lineno, end_col_offset + 1);
|
||||
goto error;
|
||||
}
|
||||
val |= flag;
|
||||
}
|
||||
else if (PyErr_Occurred()) {
|
||||
|
@ -1204,6 +1301,65 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag,
|
|||
lineno, col_offset, end_lineno, end_col_offset);
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_enter_typeparam_block(struct symtable *st, identifier name,
|
||||
void *ast, int has_defaults, int has_kwdefaults,
|
||||
enum _stmt_kind kind,
|
||||
int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset)
|
||||
{
|
||||
_Py_block_ty current_type = st->st_cur->ste_type;
|
||||
if(!symtable_enter_block(st, name, TypeParamBlock, ast, lineno,
|
||||
col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
if (current_type == ClassBlock) {
|
||||
st->st_cur->ste_can_see_class_scope = 1;
|
||||
if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (kind == ClassDef_kind) {
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
// It gets "set" when we create the type params tuple and
|
||||
// "used" when we build up the bases.
|
||||
if (!symtable_add_def(st, &_Py_STR(type_params), DEF_LOCAL,
|
||||
lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_add_def(st, &_Py_STR(type_params), USE,
|
||||
lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
st->st_private = name;
|
||||
// This is used for setting the generic base
|
||||
_Py_DECLARE_STR(generic_base, ".generic_base");
|
||||
if (!symtable_add_def(st, &_Py_STR(generic_base), DEF_LOCAL,
|
||||
lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_add_def(st, &_Py_STR(generic_base), USE,
|
||||
lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (has_defaults) {
|
||||
_Py_DECLARE_STR(defaults, ".defaults");
|
||||
if (!symtable_add_def(st, &_Py_STR(defaults), DEF_PARAM,
|
||||
lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (has_kwdefaults) {
|
||||
_Py_DECLARE_STR(kwdefaults, ".kwdefaults");
|
||||
if (!symtable_add_def(st, &_Py_STR(kwdefaults), DEF_PARAM,
|
||||
lineno, col_offset, end_lineno, end_col_offset)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument.
|
||||
They use the ASDL name to synthesize the name of the C type and the visit
|
||||
function.
|
||||
|
@ -1275,6 +1431,17 @@ symtable_record_directive(struct symtable *st, identifier name, int lineno,
|
|||
return res == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
has_kwonlydefaults(asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)
|
||||
{
|
||||
for (int i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {
|
||||
expr_ty default_ = asdl_seq_GET(kw_defaults, i);
|
||||
if (default_) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||
|
@ -1292,11 +1459,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
|
||||
if (s->v.FunctionDef.args->kw_defaults)
|
||||
VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults);
|
||||
if (s->v.FunctionDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
|
||||
if (asdl_seq_LEN(s->v.FunctionDef.typeparams) > 0) {
|
||||
if (!symtable_enter_typeparam_block(
|
||||
st, s->v.FunctionDef.name,
|
||||
(void *)s->v.FunctionDef.typeparams,
|
||||
s->v.FunctionDef.args->defaults != NULL,
|
||||
has_kwonlydefaults(s->v.FunctionDef.args->kwonlyargs,
|
||||
s->v.FunctionDef.args->kw_defaults),
|
||||
s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
VISIT_SEQ(st, typeparam, s->v.FunctionDef.typeparams);
|
||||
}
|
||||
if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
|
||||
s->v.FunctionDef.returns))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.FunctionDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
|
||||
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
||||
FunctionBlock, (void *)s,
|
||||
LOCATION(s)))
|
||||
|
@ -1305,25 +1485,85 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (asdl_seq_LEN(s->v.FunctionDef.typeparams) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
case ClassDef_kind: {
|
||||
PyObject *tmp;
|
||||
if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
VISIT_SEQ(st, expr, s->v.ClassDef.bases);
|
||||
VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
|
||||
if (s->v.ClassDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
|
||||
if (asdl_seq_LEN(s->v.ClassDef.typeparams) > 0) {
|
||||
if (!symtable_enter_typeparam_block(st, s->v.ClassDef.name,
|
||||
(void *)s->v.ClassDef.typeparams,
|
||||
false, false, s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
VISIT_SEQ(st, typeparam, s->v.ClassDef.typeparams);
|
||||
}
|
||||
VISIT_SEQ(st, expr, s->v.ClassDef.bases);
|
||||
VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);
|
||||
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
|
||||
(void *)s, s->lineno, s->col_offset,
|
||||
s->end_lineno, s->end_col_offset))
|
||||
VISIT_QUIT(st, 0);
|
||||
tmp = st->st_private;
|
||||
st->st_private = s->v.ClassDef.name;
|
||||
if (asdl_seq_LEN(s->v.ClassDef.typeparams) > 0) {
|
||||
if (!symtable_add_def(st, &_Py_ID(__type_params__),
|
||||
DEF_LOCAL, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
if (!symtable_add_def(st, &_Py_STR(type_params),
|
||||
USE, LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
}
|
||||
VISIT_SEQ(st, stmt, s->v.ClassDef.body);
|
||||
st->st_private = tmp;
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (asdl_seq_LEN(s->v.ClassDef.typeparams) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeAlias_kind: {
|
||||
VISIT(st, expr, s->v.TypeAlias.name);
|
||||
assert(s->v.TypeAlias.name->kind == Name_kind);
|
||||
PyObject *name = s->v.TypeAlias.name->v.Name.id;
|
||||
int is_in_class = st->st_cur->ste_type == ClassBlock;
|
||||
int is_generic = asdl_seq_LEN(s->v.TypeAlias.typeparams) > 0;
|
||||
if (is_generic) {
|
||||
if (!symtable_enter_typeparam_block(
|
||||
st, name,
|
||||
(void *)s->v.TypeAlias.typeparams,
|
||||
false, false, s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
VISIT_SEQ(st, typeparam, s->v.TypeAlias.typeparams);
|
||||
}
|
||||
if (!symtable_enter_block(st, name, TypeAliasBlock,
|
||||
(void *)s, LOCATION(s)))
|
||||
VISIT_QUIT(st, 0);
|
||||
st->st_cur->ste_can_see_class_scope = is_in_class;
|
||||
if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(s->v.TypeAlias.value))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
VISIT(st, expr, s->v.TypeAlias.value);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (is_generic) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Return_kind:
|
||||
|
@ -1532,11 +1772,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
if (s->v.AsyncFunctionDef.args->kw_defaults)
|
||||
VISIT_SEQ_WITH_NULL(st, expr,
|
||||
s->v.AsyncFunctionDef.args->kw_defaults);
|
||||
if (s->v.AsyncFunctionDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list);
|
||||
if (asdl_seq_LEN(s->v.AsyncFunctionDef.typeparams) > 0) {
|
||||
if (!symtable_enter_typeparam_block(
|
||||
st, s->v.AsyncFunctionDef.name,
|
||||
(void *)s->v.AsyncFunctionDef.typeparams,
|
||||
s->v.AsyncFunctionDef.args->defaults != NULL,
|
||||
has_kwonlydefaults(s->v.AsyncFunctionDef.args->kwonlyargs,
|
||||
s->v.AsyncFunctionDef.args->kw_defaults),
|
||||
s->kind,
|
||||
LOCATION(s))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
VISIT_SEQ(st, typeparam, s->v.AsyncFunctionDef.typeparams);
|
||||
}
|
||||
if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
|
||||
s->v.AsyncFunctionDef.returns))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.AsyncFunctionDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list);
|
||||
if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name,
|
||||
FunctionBlock, (void *)s,
|
||||
s->lineno, s->col_offset,
|
||||
|
@ -1547,6 +1800,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (asdl_seq_LEN(s->v.AsyncFunctionDef.typeparams) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
case AsyncWith_kind:
|
||||
VISIT_SEQ(st, withitem, s->v.AsyncWith.items);
|
||||
|
@ -1598,7 +1855,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
|
|||
}
|
||||
|
||||
/* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */
|
||||
if (ste->ste_type == FunctionBlock) {
|
||||
if (_PyST_IsFunctionLike(ste)) {
|
||||
long target_in_scope = _PyST_GetSymbol(ste, target_name);
|
||||
if (target_in_scope & DEF_GLOBAL) {
|
||||
if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))
|
||||
|
@ -1633,7 +1890,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
|
|||
}
|
||||
}
|
||||
|
||||
/* We should always find either a FunctionBlock, ModuleBlock or ClassBlock
|
||||
/* We should always find either a function-like block, ModuleBlock or ClassBlock
|
||||
and should never fall to this case
|
||||
*/
|
||||
Py_UNREACHABLE();
|
||||
|
@ -1806,7 +2063,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
|||
VISIT_QUIT(st, 0);
|
||||
/* Special-case super: it counts as a use of __class__ */
|
||||
if (e->v.Name.ctx == Load &&
|
||||
st->st_cur->ste_type == FunctionBlock &&
|
||||
_PyST_IsFunctionLike(st->st_cur) &&
|
||||
_PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) {
|
||||
if (!symtable_add_def(st, &_Py_ID(__class__), USE, LOCATION(e)))
|
||||
VISIT_QUIT(st, 0);
|
||||
|
@ -1823,6 +2080,45 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
|||
VISIT_QUIT(st, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_visit_typeparam(struct symtable *st, typeparam_ty tp)
|
||||
{
|
||||
if (++st->recursion_depth > st->recursion_limit) {
|
||||
PyErr_SetString(PyExc_RecursionError,
|
||||
"maximum recursion depth exceeded during compilation");
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
switch(tp->kind) {
|
||||
case TypeVar_kind:
|
||||
if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (tp->v.TypeVar.bound) {
|
||||
int is_in_class = st->st_cur->ste_can_see_class_scope;
|
||||
if (!symtable_enter_block(st, tp->v.TypeVar.name,
|
||||
TypeVarBoundBlock, (void *)tp,
|
||||
LOCATION(tp)))
|
||||
VISIT_QUIT(st, 0);
|
||||
st->st_cur->ste_can_see_class_scope = is_in_class;
|
||||
if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(tp->v.TypeVar.bound))) {
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
VISIT(st, expr, tp->v.TypeVar.bound);
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
break;
|
||||
case TypeVarTuple_kind:
|
||||
if (!symtable_add_def(st, tp->v.TypeVarTuple.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
|
||||
VISIT_QUIT(st, 0);
|
||||
break;
|
||||
case ParamSpec_kind:
|
||||
if (!symtable_add_def(st, tp->v.ParamSpec.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
|
||||
VISIT_QUIT(st, 0);
|
||||
break;
|
||||
}
|
||||
VISIT_QUIT(st, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
symtable_visit_pattern(struct symtable *st, pattern_ty p)
|
||||
{
|
||||
|
@ -2194,11 +2490,18 @@ 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)
|
||||
{
|
||||
if (st->st_cur->ste_type != AnnotationBlock) {
|
||||
enum _block_type type = st->st_cur->ste_type;
|
||||
if (type == AnnotationBlock)
|
||||
PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
|
||||
else if (type == TypeVarBoundBlock)
|
||||
PyErr_Format(PyExc_SyntaxError, TYPEVAR_BOUND_NOT_ALLOWED, name);
|
||||
else if (type == TypeAliasBlock)
|
||||
PyErr_Format(PyExc_SyntaxError, TYPEALIAS_NOT_ALLOWED, name);
|
||||
else if (type == TypeParamBlock)
|
||||
PyErr_Format(PyExc_SyntaxError, TYPEPARAM_NOT_ALLOWED, name);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
|
||||
PyErr_RangedSyntaxLocationObject(st->st_filename,
|
||||
e->lineno,
|
||||
e->col_offset + 1,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue