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;
|
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)")
|
||||||
|
|
Loading…
Reference in New Issue