Skip to content

Commit 4ede703

Browse files
committed
py/parse: Support constant folding of power operator for integers.
Constant expression like "2 ** 3" will now be folded, and the special form "X = const(2 ** 3)" will now compile because the argument to the const is now a constant. Fixes issue micropython#5865.
1 parent 40e9227 commit 4ede703

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

py/parse.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,9 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
618618
mp_obj_t arg0;
619619
if (rule_id == RULE_expr
620620
|| rule_id == RULE_xor_expr
621-
|| rule_id == RULE_and_expr) {
622-
// folding for binary ops: | ^ &
621+
|| rule_id == RULE_and_expr
622+
|| rule_id == RULE_power) {
623+
// folding for binary ops: | ^ & **
623624
mp_parse_node_t pn = peek_result(parser, num_args - 1);
624625
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
625626
return false;
@@ -629,15 +630,21 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
629630
op = MP_BINARY_OP_OR;
630631
} else if (rule_id == RULE_xor_expr) {
631632
op = MP_BINARY_OP_XOR;
632-
} else {
633+
} else if (rule_id == RULE_and_expr) {
633634
op = MP_BINARY_OP_AND;
635+
} else {
636+
op = MP_BINARY_OP_POWER;
634637
}
635638
for (ssize_t i = num_args - 2; i >= 0; --i) {
636639
pn = peek_result(parser, i);
637640
mp_obj_t arg1;
638641
if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
639642
return false;
640643
}
644+
if (op == MP_BINARY_OP_POWER && mp_obj_int_sign(arg1) < 0) {
645+
// ** can't have negative rhs
646+
return false;
647+
}
641648
arg0 = mp_binary_op(op, arg0, arg1);
642649
}
643650
} else if (rule_id == RULE_shift_expr

tests/basics/int_constfolding.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
print(123 // -7, 123 % -7)
3131
print(-123 // -7, -123 % -7)
3232

33+
# power
34+
print(2 ** 3)
35+
print(3 ** 4)
36+
3337
# won't fold so an exception can be raised at runtime
3438
try:
3539
1 << -1

tests/micropython/const_error.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def test_syntax(code):
1919
# these operations are not supported within const
2020
test_syntax("A = const(1 @ 2)")
2121
test_syntax("A = const(1 / 2)")
22-
test_syntax("A = const(1 ** 2)")
22+
test_syntax("A = const(1 ** -2)")
2323
test_syntax("A = const(1 << -2)")
2424
test_syntax("A = const(1 >> -2)")
2525
test_syntax("A = const(1 % 0)")

0 commit comments

Comments
 (0)