Browse Source

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 #5865.
pull/5891/head
Damien George 5 years ago
parent
commit
4ede703687
  1. 13
      py/parse.c
  2. 4
      tests/basics/int_constfolding.py
  3. 2
      tests/micropython/const_error.py

13
py/parse.c

@ -618,8 +618,9 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
mp_obj_t arg0;
if (rule_id == RULE_expr
|| rule_id == RULE_xor_expr
|| rule_id == RULE_and_expr) {
// folding for binary ops: | ^ &
|| rule_id == RULE_and_expr
|| rule_id == RULE_power) {
// folding for binary ops: | ^ & **
mp_parse_node_t pn = peek_result(parser, num_args - 1);
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
return false;
@ -629,8 +630,10 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
op = MP_BINARY_OP_OR;
} else if (rule_id == RULE_xor_expr) {
op = MP_BINARY_OP_XOR;
} else {
} else if (rule_id == RULE_and_expr) {
op = MP_BINARY_OP_AND;
} else {
op = MP_BINARY_OP_POWER;
}
for (ssize_t i = num_args - 2; i >= 0; --i) {
pn = peek_result(parser, i);
@ -638,6 +641,10 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
return false;
}
if (op == MP_BINARY_OP_POWER && mp_obj_int_sign(arg1) < 0) {
// ** can't have negative rhs
return false;
}
arg0 = mp_binary_op(op, arg0, arg1);
}
} else if (rule_id == RULE_shift_expr

4
tests/basics/int_constfolding.py

@ -30,6 +30,10 @@ print(-123 // 7, -123 % 7)
print(123 // -7, 123 % -7)
print(-123 // -7, -123 % -7)
# power
print(2 ** 3)
print(3 ** 4)
# won't fold so an exception can be raised at runtime
try:
1 << -1

2
tests/micropython/const_error.py

@ -19,7 +19,7 @@ test_syntax("A = const(1); A = const(2)")
# these operations are not supported within const
test_syntax("A = const(1 @ 2)")
test_syntax("A = const(1 / 2)")
test_syntax("A = const(1 ** 2)")
test_syntax("A = const(1 ** -2)")
test_syntax("A = const(1 << -2)")
test_syntax("A = const(1 >> -2)")
test_syntax("A = const(1 % 0)")

Loading…
Cancel
Save