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.
This commit is contained in:
Damien George 2020-04-07 12:23:08 +10:00
parent 40e9227733
commit 4ede703687
3 changed files with 15 additions and 4 deletions

View File

@ -618,8 +618,9 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
mp_obj_t arg0; mp_obj_t arg0;
if (rule_id == RULE_expr if (rule_id == RULE_expr
|| rule_id == RULE_xor_expr || rule_id == RULE_xor_expr
|| rule_id == RULE_and_expr) { || rule_id == RULE_and_expr
// folding for binary ops: | ^ & || rule_id == RULE_power) {
// folding for binary ops: | ^ & **
mp_parse_node_t pn = peek_result(parser, num_args - 1); mp_parse_node_t pn = peek_result(parser, num_args - 1);
if (!mp_parse_node_get_int_maybe(pn, &arg0)) { if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
return false; 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; op = MP_BINARY_OP_OR;
} else if (rule_id == RULE_xor_expr) { } else if (rule_id == RULE_xor_expr) {
op = MP_BINARY_OP_XOR; op = MP_BINARY_OP_XOR;
} else { } else if (rule_id == RULE_and_expr) {
op = MP_BINARY_OP_AND; op = MP_BINARY_OP_AND;
} else {
op = MP_BINARY_OP_POWER;
} }
for (ssize_t i = num_args - 2; i >= 0; --i) { for (ssize_t i = num_args - 2; i >= 0; --i) {
pn = peek_result(parser, 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)) { if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
return false; 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); arg0 = mp_binary_op(op, arg0, arg1);
} }
} else if (rule_id == RULE_shift_expr } else if (rule_id == RULE_shift_expr

View File

@ -30,6 +30,10 @@ print(-123 // 7, -123 % 7)
print(123 // -7, 123 % -7) 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 # won't fold so an exception can be raised at runtime
try: try:
1 << -1 1 << -1

View File

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