Skip to content

Commit b2f2c25

Browse files
committed
Fix AST generation asymmetry for unary positive in match statements
1 parent 003d362 commit b2f2c25

4 files changed

Lines changed: 60 additions & 17 deletions

File tree

Grammar/python.gram

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -554,20 +554,20 @@ complex_number[expr_ty]:
554554

555555
signed_number[expr_ty]:
556556
| NUMBER
557-
| '+' number=NUMBER { number }
557+
| '+' number=NUMBER { _PyAST_UnaryOp(UAdd, number, EXTRA) }
558558
| '-' number=NUMBER { _PyAST_UnaryOp(USub, number, EXTRA) }
559559

560560
signed_real_number[expr_ty]:
561561
| real_number
562-
| '+' real=real_number { real }
562+
| '+' real=real_number { _PyAST_UnaryOp(UAdd, real, EXTRA) }
563563
| '-' real=real_number { _PyAST_UnaryOp(USub, real, EXTRA) }
564564

565565
real_number[expr_ty]:
566566
| real=NUMBER { _PyPegen_ensure_real(p, real) }
567567

568568
imaginary_number[expr_ty]:
569569
| imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) }
570-
| '+' imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) }
570+
| '+' imag=NUMBER { _PyAST_UnaryOp(UAdd, _PyPegen_ensure_imaginary(p, imag), EXTRA) }
571571

572572
capture_pattern[pattern_ty]:
573573
| target=pattern_capture_target { _PyAST_MatchAs(NULL, target->v.Name.id, EXTRA) }

Parser/parser.c

Lines changed: 39 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/ast.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,11 @@ ensure_literal_number(expr_ty exp, bool allow_real, bool allow_imaginary)
426426
}
427427

428428
static int
429-
ensure_literal_negative(expr_ty exp, bool allow_real, bool allow_imaginary)
429+
ensure_literal_signed(expr_ty exp, bool allow_real, bool allow_imaginary)
430430
{
431431
assert(exp->kind == UnaryOp_kind);
432-
// Must be negation ...
433-
if (exp->v.UnaryOp.op != USub) {
432+
// Must be negation or positive ...
433+
if (exp->v.UnaryOp.op != USub && exp->v.UnaryOp.op != UAdd) {
434434
return 0;
435435
}
436436
// ... of a constant ...
@@ -461,7 +461,7 @@ ensure_literal_complex(expr_ty exp)
461461
}
462462
break;
463463
case UnaryOp_kind:
464-
if (!ensure_literal_negative(left, /*real=*/true, /*imaginary=*/false)) {
464+
if (!ensure_literal_signed(left, /*real=*/true, /*imaginary=*/false)) {
465465
return 0;
466466
}
467467
break;
@@ -512,9 +512,9 @@ validate_pattern_match_value(expr_ty exp)
512512
// Constants and attribute lookups are always permitted
513513
return 1;
514514
case UnaryOp_kind:
515-
// Negated numbers are permitted (whether real or imaginary)
515+
// Signed numbers are permitted (whether real or imaginary)
516516
// Compiler will complain if AST folding doesn't create a constant
517-
if (ensure_literal_negative(exp, /*real=*/true, /*imaginary=*/true)) {
517+
if (ensure_literal_signed(exp, /*real=*/true, /*imaginary=*/true)) {
518518
return 1;
519519
}
520520
break;

Python/ast_preprocess.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -867,26 +867,33 @@ fold_const_match_patterns(expr_ty node, PyArena *ctx_, _PyASTPreprocessState *st
867867
{
868868
case UnaryOp_kind:
869869
{
870-
if (node->v.UnaryOp.op == USub &&
870+
if ((node->v.UnaryOp.op == USub || node->v.UnaryOp.op == UAdd) &&
871871
node->v.UnaryOp.operand->kind == Constant_kind)
872872
{
873873
PyObject *operand = node->v.UnaryOp.operand->v.Constant.value;
874-
PyObject *folded = PyNumber_Negative(operand);
874+
PyObject *folded = node->v.UnaryOp.op == USub ? PyNumber_Negative(operand) : PyNumber_Positive(operand);
875+
if (folded == NULL) {
876+
return 0;
877+
}
875878
return make_const(node, folded, ctx_);
876879
}
877880
break;
878881
}
879882
case BinOp_kind:
880883
{
881884
operator_ty op = node->v.BinOp.op;
882-
if ((op == Add || op == Sub) &&
883-
node->v.BinOp.right->kind == Constant_kind)
885+
if (op == Add || op == Sub)
884886
{
885887
CALL(fold_const_match_patterns, expr_ty, node->v.BinOp.left);
886-
if (node->v.BinOp.left->kind == Constant_kind) {
888+
CALL(fold_const_match_patterns, expr_ty, node->v.BinOp.right);
889+
if (node->v.BinOp.left->kind == Constant_kind &&
890+
node->v.BinOp.right->kind == Constant_kind) {
887891
PyObject *left = node->v.BinOp.left->v.Constant.value;
888892
PyObject *right = node->v.BinOp.right->v.Constant.value;
889893
PyObject *folded = op == Add ? PyNumber_Add(left, right) : PyNumber_Subtract(left, right);
894+
if (folded == NULL) {
895+
return 0;
896+
}
890897
return make_const(node, folded, ctx_);
891898
}
892899
}

0 commit comments

Comments
 (0)