summaryrefslogtreecommitdiff
path: root/Python/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ast.c')
-rw-r--r--Python/ast.c100
1 files changed, 97 insertions, 3 deletions
diff --git a/Python/ast.c b/Python/ast.c
index 855acca29e..6560026109 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -94,6 +94,8 @@ expr_context_name(expr_context_ty ctx)
return "Load";
case Store:
return "Store";
+ case NamedStore:
+ return "NamedStore";
case Del:
return "Del";
case AugLoad:
@@ -975,14 +977,29 @@ 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;
@@ -995,10 +1012,20 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
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;
@@ -1060,17 +1087,27 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
case IfExp_kind:
expr_name = "conditional expression";
break;
+ case NamedExpr_kind:
+ expr_name = "named expression";
+ break;
default:
PyErr_Format(PyExc_SystemError,
- "unexpected expression in assignment %d (line %d)",
+ "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) {
- return ast_error(c, n, "cannot %s %s",
+ 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);
+ }
}
/* If the LHS is a list or tuple, we need to set the assignment
@@ -1198,7 +1235,7 @@ seq_for_testlist(struct compiling *c, const node *n)
for (i = 0; i < NCH(n); i += 2) {
const node *ch = CHILD(n, i);
- assert(TYPE(ch) == test || TYPE(ch) == test_nocond || TYPE(ch) == star_expr);
+ assert(TYPE(ch) == test || TYPE(ch) == test_nocond || TYPE(ch) == star_expr || TYPE(ch) == namedexpr_test);
expression = ast_for_expr(c, ch);
if (!expression)
@@ -1692,6 +1729,35 @@ ast_for_decorated(struct compiling *c, const node *n)
}
static expr_ty
+ast_for_namedexpr(struct compiling *c, const node *n)
+{
+ /* if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)*
+ ['else' ':' suite]
+ namedexpr_test: test [':=' test]
+ argument: ( test [comp_for] |
+ test ':=' test |
+ test '=' test |
+ '**' test |
+ '*' test )
+ */
+ expr_ty target, value;
+
+ target = ast_for_expr(c, CHILD(n, 0));
+ if (!target)
+ return NULL;
+
+ value = ast_for_expr(c, CHILD(n, 2));
+ if (!value)
+ return NULL;
+
+ if (!set_context(c, target, NamedStore, n))
+ return NULL;
+
+ return NamedExpr(target, value, LINENO(n), n->n_col_offset, n->n_end_lineno,
+ n->n_end_col_offset, c->c_arena);
+}
+
+static expr_ty
ast_for_lambdef(struct compiling *c, const node *n)
{
/* lambdef: 'lambda' [varargslist] ':' test
@@ -2568,6 +2634,7 @@ static expr_ty
ast_for_expr(struct compiling *c, const node *n)
{
/* handle the full range of simple expressions
+ namedexpr_test: test [':=' test]
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
or_test: and_test ('or' and_test)*
@@ -2591,6 +2658,10 @@ ast_for_expr(struct compiling *c, const node *n)
loop:
switch (TYPE(n)) {
+ case namedexpr_test:
+ if (NCH(n) == 3)
+ return ast_for_namedexpr(c, n);
+ /* Fallthrough */
case test:
case test_nocond:
if (TYPE(CHILD(n, 0)) == lambdef ||
@@ -2770,6 +2841,9 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
}
else if (TYPE(CHILD(ch, 0)) == STAR)
nargs++;
+ else if (TYPE(CHILD(ch, 1)) == COLONEQUAL) {
+ nargs++;
+ }
else
/* TYPE(CHILD(ch, 0)) == DOUBLESTAR or keyword argument */
nkeywords++;
@@ -2850,6 +2924,26 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func,
return NULL;
asdl_seq_SET(args, nargs++, e);
}
+ else if (TYPE(CHILD(ch, 1)) == COLONEQUAL) {
+ /* treat colon equal as positional argument */
+ if (nkeywords) {
+ if (ndoublestars) {
+ ast_error(c, chch,
+ "positional argument follows "
+ "keyword argument unpacking");
+ }
+ else {
+ ast_error(c, chch,
+ "positional argument follows "
+ "keyword argument");
+ }
+ return NULL;
+ }
+ e = ast_for_namedexpr(c, ch);
+ if (!e)
+ return NULL;
+ asdl_seq_SET(args, nargs++, e);
+ }
else {
/* a keyword argument */
keyword_ty kw;