From d8b3a98c9098c66a714fd5593e1928af0ffbc631 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 5 Mar 2019 20:42:06 +0200 Subject: bpo-36187: Remove NamedStore. (GH-12167) NamedStore has been replaced with Store. The difference between NamedStore and Store is handled when precess the NamedExpr node one level upper. --- Include/Python-ast.h | 2 +- Lib/test/test_syntax.py | 4 + Parser/Python.asdl | 2 +- Python/Python-ast.c | 21 +---- Python/ast.c | 199 ++++++++++++++++++++++-------------------------- Python/compile.c | 9 +-- Python/symtable.c | 9 +-- 7 files changed, 103 insertions(+), 143 deletions(-) diff --git a/Include/Python-ast.h b/Include/Python-ast.h index 106cecf..52ba127 100644 --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -17,7 +17,7 @@ typedef struct _stmt *stmt_ty; typedef struct _expr *expr_ty; typedef enum _expr_context { Load=1, Store=2, Del=3, AugLoad=4, AugStore=5, - Param=6, NamedStore=7 } expr_context_ty; + Param=6 } expr_context_ty; typedef struct _slice *slice_ty; diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index a0f487d..4a2899e 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -43,6 +43,10 @@ SyntaxError: invalid syntax Traceback (most recent call last): SyntaxError: cannot assign to True +>>> (True := 1) +Traceback (most recent call last): +SyntaxError: cannot use named assignment with True + >>> obj.__debug__ = 1 Traceback (most recent call last): SyntaxError: cannot assign to __debug__ diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 85b686d..1ccd2ca 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -91,7 +91,7 @@ module Python -- col_offset is the byte offset in the utf8 string the parser uses attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) - expr_context = Load | Store | Del | AugLoad | AugStore | Param | NamedStore + expr_context = Load | Store | Del | AugLoad | AugStore | Param slice = Slice(expr? lower, expr? upper, expr? step) | ExtSlice(slice* dims) diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 5467d19..92ec157 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -365,8 +365,7 @@ static char *Tuple_fields[]={ }; static PyTypeObject *expr_context_type; static PyObject *Load_singleton, *Store_singleton, *Del_singleton, -*AugLoad_singleton, *AugStore_singleton, *Param_singleton, -*NamedStore_singleton; +*AugLoad_singleton, *AugStore_singleton, *Param_singleton; static PyObject* ast2obj_expr_context(expr_context_ty); static PyTypeObject *Load_type; static PyTypeObject *Store_type; @@ -374,7 +373,6 @@ static PyTypeObject *Del_type; static PyTypeObject *AugLoad_type; static PyTypeObject *AugStore_type; static PyTypeObject *Param_type; -static PyTypeObject *NamedStore_type; static PyTypeObject *slice_type; static PyObject* ast2obj_slice(void*); static PyTypeObject *Slice_type; @@ -993,10 +991,6 @@ static int init_types(void) if (!Param_type) return 0; Param_singleton = PyType_GenericNew(Param_type, NULL, NULL); if (!Param_singleton) return 0; - NamedStore_type = make_type("NamedStore", expr_context_type, NULL, 0); - if (!NamedStore_type) return 0; - NamedStore_singleton = PyType_GenericNew(NamedStore_type, NULL, NULL); - if (!NamedStore_singleton) return 0; slice_type = make_type("slice", &AST_type, NULL, 0); if (!slice_type) return 0; if (!add_attributes(slice_type, NULL, 0)) return 0; @@ -3657,9 +3651,6 @@ PyObject* ast2obj_expr_context(expr_context_ty o) case Param: Py_INCREF(Param_singleton); return Param_singleton; - case NamedStore: - Py_INCREF(NamedStore_singleton); - return NamedStore_singleton; default: /* should never happen, but just in case ... */ PyErr_Format(PyExc_SystemError, "unknown expr_context found"); @@ -7608,14 +7599,6 @@ obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) *out = Param; return 0; } - isinstance = PyObject_IsInstance(obj, (PyObject *)NamedStore_type); - if (isinstance == -1) { - return 1; - } - if (isinstance) { - *out = NamedStore; - return 0; - } PyErr_Format(PyExc_TypeError, "expected some sort of expr_context, but got %R", obj); return 1; @@ -8828,8 +8811,6 @@ PyInit__ast(void) return NULL; if (PyDict_SetItemString(d, "Param", (PyObject*)Param_type) < 0) return NULL; - if (PyDict_SetItemString(d, "NamedStore", (PyObject*)NamedStore_type) < 0) - return NULL; if (PyDict_SetItemString(d, "slice", (PyObject*)slice_type) < 0) return NULL; if (PyDict_SetItemString(d, "Slice", (PyObject*)Slice_type) < 0) return diff --git a/Python/ast.c b/Python/ast.c index 62ff868..2e96048 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -94,8 +94,6 @@ expr_context_name(expr_context_ty ctx) return "Load"; case Store: return "Store"; - case NamedStore: - return "NamedStore"; case Del: return "Del"; case AugLoad: @@ -1029,6 +1027,80 @@ copy_location(expr_ty e, const node *n) return e; } +static const char * +get_expr_name(expr_ty e) +{ + switch (e->kind) { + case Attribute_kind: + return "attribute"; + case Subscript_kind: + return "subscript"; + case Starred_kind: + return "starred"; + case Name_kind: + return "name"; + case List_kind: + return "list"; + case Tuple_kind: + return "tuple"; + case Lambda_kind: + return "lambda"; + case Call_kind: + return "function call"; + case BoolOp_kind: + case BinOp_kind: + case UnaryOp_kind: + return "operator"; + case GeneratorExp_kind: + return "generator expression"; + case Yield_kind: + case YieldFrom_kind: + return "yield expression"; + case Await_kind: + return "await expression"; + case ListComp_kind: + return "list comprehension"; + case SetComp_kind: + return "set comprehension"; + case DictComp_kind: + return "dict comprehension"; + case Dict_kind: + return "dict display"; + case Set_kind: + return "set display"; + case JoinedStr_kind: + case FormattedValue_kind: + return "f-string expression"; + case Constant_kind: { + PyObject *value = e->v.Constant.value; + if (value == Py_None) { + return "None"; + } + if (value == Py_False) { + return "False"; + } + if (value == Py_True) { + return "True"; + } + if (value == Py_Ellipsis) { + return "Ellipsis"; + } + return "literal"; + } + case Compare_kind: + return "comparison"; + case IfExp_kind: + return "conditional expression"; + case NamedExpr_kind: + return "named expression"; + default: + PyErr_Format(PyExc_SystemError, + "unexpected expression in assignment %d (line %d)", + e->kind, e->lineno); + return NULL; + } +} + /* Set the context ctx for expr_ty e, recursively traversing e. Only sets context for expr kinds that "can appear in assignment context" @@ -1040,10 +1112,6 @@ static int set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) { asdl_seq *s = NULL; - /* If a particular expression type can't be used for assign / delete, - set expr_name to its name and an error message will be generated. - */ - const char* expr_name = NULL; /* The ast defines augmented store and load contexts, but the implementation here doesn't actually use them. The code may be @@ -1056,136 +1124,41 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) switch (e->kind) { case Attribute_kind: - if (ctx == NamedStore) { - expr_name = "attribute"; - break; - } - e->v.Attribute.ctx = ctx; if (ctx == Store && forbidden_name(c, e->v.Attribute.attr, n, 1)) return 0; break; case Subscript_kind: - if (ctx == NamedStore) { - expr_name = "subscript"; - break; - } - e->v.Subscript.ctx = ctx; break; case Starred_kind: - if (ctx == NamedStore) { - expr_name = "starred"; - break; - } - e->v.Starred.ctx = ctx; if (!set_context(c, e->v.Starred.value, ctx, n)) return 0; break; case Name_kind: - if (ctx == Store || ctx == NamedStore) { + if (ctx == Store) { if (forbidden_name(c, e->v.Name.id, n, 0)) return 0; /* forbidden_name() calls ast_error() */ } e->v.Name.ctx = ctx; break; case List_kind: - if (ctx == NamedStore) { - expr_name = "list"; - break; - } - e->v.List.ctx = ctx; s = e->v.List.elts; break; case Tuple_kind: - if (ctx == NamedStore) { - expr_name = "tuple"; - break; - } - e->v.Tuple.ctx = ctx; s = e->v.Tuple.elts; break; - case Lambda_kind: - expr_name = "lambda"; - break; - case Call_kind: - expr_name = "function call"; - break; - case BoolOp_kind: - case BinOp_kind: - case UnaryOp_kind: - expr_name = "operator"; - break; - case GeneratorExp_kind: - expr_name = "generator expression"; - break; - case Yield_kind: - case YieldFrom_kind: - expr_name = "yield expression"; - break; - case Await_kind: - expr_name = "await expression"; - break; - case ListComp_kind: - expr_name = "list comprehension"; - break; - case SetComp_kind: - expr_name = "set comprehension"; - break; - case DictComp_kind: - expr_name = "dict comprehension"; - break; - case Dict_kind: - expr_name = "dict display"; - break; - case Set_kind: - expr_name = "set display"; - break; - case JoinedStr_kind: - case FormattedValue_kind: - expr_name = "f-string expression"; - break; - case Constant_kind: { - PyObject *value = e->v.Constant.value; - if (value == Py_None || value == Py_False || value == Py_True - || value == Py_Ellipsis) - { - return ast_error(c, n, "cannot %s %R", - ctx == Store ? "assign to" : "delete", - value); + default: { + const char *expr_name = get_expr_name(e); + if (expr_name != NULL) { + ast_error(c, n, "cannot %s %s", + ctx == Store ? "assign to" : "delete", + expr_name); } - expr_name = "literal"; - break; - } - case Compare_kind: - expr_name = "comparison"; - break; - case IfExp_kind: - expr_name = "conditional expression"; - break; - case NamedExpr_kind: - expr_name = "named expression"; - break; - default: - PyErr_Format(PyExc_SystemError, - "unexpected expression in %sassignment %d (line %d)", - ctx == NamedStore ? "named ": "", - e->kind, e->lineno); return 0; - } - /* Check for error string set by switch */ - if (expr_name) { - if (ctx == NamedStore) { - return ast_error(c, n, "cannot use named assignment with %s", - expr_name); - } - else { - return ast_error(c, n, "cannot %s %s", - ctx == Store ? "assign to" : "delete", - expr_name); } } @@ -1895,7 +1868,15 @@ ast_for_namedexpr(struct compiling *c, const node *n) if (!value) return NULL; - if (!set_context(c, target, NamedStore, n)) + if (target->kind != Name_kind) { + const char *expr_name = get_expr_name(target); + if (expr_name != NULL) { + ast_error(c, n, "cannot use named assignment with %s", expr_name); + } + return NULL; + } + + if (!set_context(c, target, Store, n)) return NULL; return NamedExpr(target, value, LINENO(n), n->n_col_offset, n->n_end_lineno, diff --git a/Python/compile.c b/Python/compile.c index 18877d9..c262106 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3429,7 +3429,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF; break; case Store: - case NamedStore: op = STORE_DEREF; break; case AugLoad: @@ -3447,7 +3446,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) switch (ctx) { case Load: op = LOAD_FAST; break; case Store: - case NamedStore: op = STORE_FAST; break; case Del: op = DELETE_FAST; break; @@ -3466,7 +3464,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) switch (ctx) { case Load: op = LOAD_GLOBAL; break; case Store: - case NamedStore: op = STORE_GLOBAL; break; case Del: op = DELETE_GLOBAL; break; @@ -3484,7 +3481,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) switch (ctx) { case Load: op = LOAD_NAME; break; case Store: - case NamedStore: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; @@ -3604,7 +3600,7 @@ static int compiler_list(struct compiler *c, expr_ty e) { asdl_seq *elts = e->v.List.elts; - if (e->v.List.ctx == Store || e->v.List.ctx == NamedStore) { + if (e->v.List.ctx == Store) { return assignment_helper(c, elts); } else if (e->v.List.ctx == Load) { @@ -3620,7 +3616,7 @@ static int compiler_tuple(struct compiler *c, expr_ty e) { asdl_seq *elts = e->v.Tuple.elts; - if (e->v.Tuple.ctx == Store || e->v.Tuple.ctx == NamedStore) { + if (e->v.Tuple.ctx == Store) { return assignment_helper(c, elts); } else if (e->v.Tuple.ctx == Load) { @@ -5154,7 +5150,6 @@ compiler_handle_subscr(struct compiler *c, const char *kind, case AugStore:/* fall through to Store */ case Store: op = STORE_SUBSCR; break; case Del: op = DELETE_SUBSCR; break; - case NamedStore: case Param: PyErr_Format(PyExc_SystemError, "invalid %s kind %d in subscript\n", diff --git a/Python/symtable.c b/Python/symtable.c index 6e2df2f..1d68a7d 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1452,6 +1452,10 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } switch (e->kind) { case NamedExpr_kind: + if (st->st_cur->ste_comprehension) { + if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) + VISIT_QUIT(st, 0); + } VISIT(st, expr, e->v.NamedExpr.value); VISIT(st, expr, e->v.NamedExpr.target); break; @@ -1555,11 +1559,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.Starred.value); break; case Name_kind: - /* Special-case: named expr */ - if (e->v.Name.ctx == NamedStore && st->st_cur->ste_comprehension) { - if(!symtable_extend_namedexpr_scope(st, e)) - VISIT_QUIT(st, 0); - } if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) VISIT_QUIT(st, 0); -- cgit v0.12