Skip to content

Commit a7ea132

Browse files
committed
initial implementation of pep798 basics
1 parent 0288001 commit a7ea132

File tree

5 files changed

+118
-45
lines changed

5 files changed

+118
-45
lines changed

Grammar/python.gram

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,20 +1040,20 @@ for_if_clause[comprehension_ty]:
10401040
| invalid_for_target
10411041

10421042
listcomp[expr_ty]:
1043-
| '[' a=named_expression b=for_if_clauses ']' { _PyAST_ListComp(a, b, EXTRA) }
1043+
| '[' a=star_named_expression b=for_if_clauses ']' { _PyAST_ListComp(a, b, EXTRA) }
10441044
| invalid_comprehension
10451045

10461046
setcomp[expr_ty]:
1047-
| '{' a=named_expression b=for_if_clauses '}' { _PyAST_SetComp(a, b, EXTRA) }
1047+
| '{' a=star_named_expression b=for_if_clauses '}' { _PyAST_SetComp(a, b, EXTRA) }
10481048
| invalid_comprehension
10491049

10501050
genexp[expr_ty]:
1051-
| '(' a=( assignment_expression | expression !':=') b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) }
1051+
| '(' a=( assignment_expression | expression !':=' | starred_expression ) b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) }
10521052
| invalid_comprehension
10531053

10541054
dictcomp[expr_ty]:
10551055
| '{' a=kvpair b=for_if_clauses '}' { _PyAST_DictComp(a->key, a->value, b, EXTRA) }
1056-
| invalid_dict_comprehension
1056+
| '{' '**' a=expression b=for_if_clauses '}' { _PyAST_DictComp(a, NULL, b, EXTRA) }
10571057

10581058
# FUNCTION CALL ARGUMENTS
10591059
# =======================
@@ -1326,16 +1326,15 @@ invalid_assert_stmt:
13261326
invalid_block:
13271327
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
13281328
invalid_comprehension:
1329-
| ('[' | '(' | '{') a=starred_expression for_if_clauses {
1330-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") }
1329+
| '[' a='**' b=expression for_if_clauses {
1330+
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "dict unpacking cannot be used in list comprehension") }
1331+
| '(' a='**' b=expression for_if_clauses {
1332+
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "dict unpacking cannot be used in generator expression") }
13311333
| ('[' | '{') a=star_named_expression ',' b=star_named_expressions for_if_clauses {
13321334
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, PyPegen_last_item(b, expr_ty),
13331335
"did you forget parentheses around the comprehension target?") }
13341336
| ('[' | '{') a=star_named_expression b=',' for_if_clauses {
13351337
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "did you forget parentheses around the comprehension target?") }
1336-
invalid_dict_comprehension:
1337-
| '{' a='**' bitwise_or for_if_clauses '}' {
1338-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "dict unpacking cannot be used in dict comprehension") }
13391338
invalid_parameters:
13401339
| a="/" ',' {
13411340
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "at least one parameter must precede /") }

Parser/Python.asdl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ module Python
6767
| Set(expr* elts)
6868
| ListComp(expr elt, comprehension* generators)
6969
| SetComp(expr elt, comprehension* generators)
70-
| DictComp(expr key, expr value, comprehension* generators)
70+
| DictComp(expr key, expr? value, comprehension* generators)
7171
| GeneratorExp(expr elt, comprehension* generators)
7272
-- the grammar constrains where yield expressions can occur
7373
| Await(expr value)

Python/ast.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,10 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
305305
#undef COMP
306306
case DictComp_kind:
307307
ret = validate_comprehension(exp->v.DictComp.generators) &&
308-
validate_expr(exp->v.DictComp.key, Load) &&
309-
validate_expr(exp->v.DictComp.value, Load);
308+
validate_expr(exp->v.DictComp.key, Load);
309+
if (ret && exp->v.DictComp.value != NULL){
310+
ret = validate_expr(exp->v.DictComp.value, Load);
311+
}
310312
break;
311313
case Yield_kind:
312314
ret = !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);

Python/ast_preprocess.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,9 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTPreprocessState *state)
557557
break;
558558
case DictComp_kind:
559559
CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
560-
CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
560+
if (node_->v.DictComp.value != NULL){
561+
CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
562+
}
561563
CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
562564
break;
563565
case GeneratorExp_kind:

Python/codegen.c

Lines changed: 102 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4479,28 +4479,63 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
44794479
/* comprehension specific code */
44804480
switch (type) {
44814481
case COMP_GENEXP:
4482-
VISIT(c, expr, elt);
4483-
ADDOP_YIELD(c, elt_loc);
4484-
ADDOP(c, elt_loc, POP_TOP);
4482+
if (elt->kind == Starred_kind){
4483+
NEW_JUMP_TARGET_LABEL(c, unpack_start);
4484+
NEW_JUMP_TARGET_LABEL(c, unpack_end);
4485+
VISIT(c, expr, elt->v.Starred.value);
4486+
ADDOP(c, elt_loc, GET_ITER);
4487+
USE_LABEL(c, unpack_start);
4488+
ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end);
4489+
ADDOP_YIELD(c, elt_loc);
4490+
ADDOP(c, elt_loc, POP_TOP);
4491+
ADDOP_JUMP(c, NO_LOCATION, JUMP, unpack_start);
4492+
USE_LABEL(c, unpack_end);
4493+
ADDOP(c, NO_LOCATION, END_FOR);
4494+
ADDOP(c, NO_LOCATION, POP_ITER);
4495+
}
4496+
else{
4497+
VISIT(c, expr, elt);
4498+
ADDOP_YIELD(c, elt_loc);
4499+
ADDOP(c, elt_loc, POP_TOP);
4500+
}
44854501
break;
44864502
case COMP_LISTCOMP:
4487-
VISIT(c, expr, elt);
4488-
ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);
4503+
if (elt->kind == Starred_kind){
4504+
VISIT(c, expr, elt->v.Starred.value);
4505+
ADDOP_I(c, elt_loc, LIST_EXTEND, depth + 1);
4506+
}
4507+
else{
4508+
VISIT(c, expr, elt);
4509+
ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);
4510+
}
44894511
break;
44904512
case COMP_SETCOMP:
4491-
VISIT(c, expr, elt);
4492-
ADDOP_I(c, elt_loc, SET_ADD, depth + 1);
4513+
if (elt->kind == Starred_kind){
4514+
VISIT(c, expr, elt->v.Starred.value);
4515+
ADDOP_I(c, elt_loc, SET_UPDATE, depth + 1);
4516+
}
4517+
else{
4518+
VISIT(c, expr, elt);
4519+
ADDOP_I(c, elt_loc, SET_ADD, depth + 1);
4520+
}
44934521
break;
44944522
case COMP_DICTCOMP:
4495-
/* With '{k: v}', k is evaluated before v, so we do
4496-
the same. */
4497-
VISIT(c, expr, elt);
4498-
VISIT(c, expr, val);
4499-
elt_loc = LOCATION(elt->lineno,
4500-
val->end_lineno,
4501-
elt->col_offset,
4502-
val->end_col_offset);
4503-
ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);
4523+
if (val == NULL){
4524+
/* unpacking (**) case */
4525+
VISIT(c, expr, elt);
4526+
ADDOP_I(c, elt_loc, DICT_UPDATE, depth+1);
4527+
}
4528+
else{
4529+
/* With '{k: v}', k is evaluated before v, so we do
4530+
the same. */
4531+
VISIT(c, expr, elt);
4532+
VISIT(c, expr, val);
4533+
elt_loc = LOCATION(elt->lineno,
4534+
val->end_lineno,
4535+
elt->col_offset,
4536+
val->end_col_offset);
4537+
ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);
4538+
}
45044539
break;
45054540
default:
45064541
return ERROR;
@@ -4584,28 +4619,63 @@ codegen_async_comprehension_generator(compiler *c, location loc,
45844619
/* comprehension specific code */
45854620
switch (type) {
45864621
case COMP_GENEXP:
4587-
VISIT(c, expr, elt);
4588-
ADDOP_YIELD(c, elt_loc);
4589-
ADDOP(c, elt_loc, POP_TOP);
4622+
if (elt->kind == Starred_kind){
4623+
NEW_JUMP_TARGET_LABEL(c, unpack_start);
4624+
NEW_JUMP_TARGET_LABEL(c, unpack_end);
4625+
VISIT(c, expr, elt->v.Starred.value);
4626+
ADDOP(c, elt_loc, GET_ITER);
4627+
USE_LABEL(c, unpack_start);
4628+
ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end);
4629+
ADDOP_YIELD(c, elt_loc);
4630+
ADDOP(c, elt_loc, POP_TOP);
4631+
ADDOP_JUMP(c, NO_LOCATION, JUMP, unpack_start);
4632+
USE_LABEL(c, unpack_end);
4633+
ADDOP(c, NO_LOCATION, END_FOR);
4634+
ADDOP(c, NO_LOCATION, POP_ITER);
4635+
}
4636+
else{
4637+
VISIT(c, expr, elt);
4638+
ADDOP_YIELD(c, elt_loc);
4639+
ADDOP(c, elt_loc, POP_TOP);
4640+
}
45904641
break;
45914642
case COMP_LISTCOMP:
4592-
VISIT(c, expr, elt);
4593-
ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);
4643+
if (elt->kind == Starred_kind){
4644+
VISIT(c, expr, elt->v.Starred.value);
4645+
ADDOP_I(c, elt_loc, LIST_EXTEND, depth + 1);
4646+
}
4647+
else{
4648+
VISIT(c, expr, elt);
4649+
ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);
4650+
}
45944651
break;
45954652
case COMP_SETCOMP:
4596-
VISIT(c, expr, elt);
4597-
ADDOP_I(c, elt_loc, SET_ADD, depth + 1);
4653+
if (elt->kind == Starred_kind){
4654+
VISIT(c, expr, elt->v.Starred.value);
4655+
ADDOP_I(c, elt_loc, SET_UPDATE, depth + 1);
4656+
}
4657+
else{
4658+
VISIT(c, expr, elt);
4659+
ADDOP_I(c, elt_loc, SET_ADD, depth + 1);
4660+
}
45984661
break;
45994662
case COMP_DICTCOMP:
4600-
/* With '{k: v}', k is evaluated before v, so we do
4601-
the same. */
4602-
VISIT(c, expr, elt);
4603-
VISIT(c, expr, val);
4604-
elt_loc = LOCATION(elt->lineno,
4605-
val->end_lineno,
4606-
elt->col_offset,
4607-
val->end_col_offset);
4608-
ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);
4663+
if (val == NULL){
4664+
/* unpacking (**) case */
4665+
VISIT(c, expr, elt);
4666+
ADDOP_I(c, elt_loc, DICT_UPDATE, depth+1);
4667+
}
4668+
else{
4669+
/* With '{k: v}', k is evaluated before v, so we do
4670+
the same. */
4671+
VISIT(c, expr, elt);
4672+
VISIT(c, expr, val);
4673+
elt_loc = LOCATION(elt->lineno,
4674+
val->end_lineno,
4675+
elt->col_offset,
4676+
val->end_col_offset);
4677+
ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);
4678+
}
46094679
break;
46104680
default:
46114681
return ERROR;

0 commit comments

Comments
 (0)