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:
parent
40e9227733
commit
4ede703687
13
py/parse.c
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
|
||||
|
@ -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
|
||||
|
@ -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…
Reference in New Issue
Block a user