Skip to content

Commit 932ab67

Browse files
authored
Fix exponentiation precedence for compound exponents (#8550)
* Fix exponentiation right operand precedence Signed-off-by: Christoph Knittel <ck@cca.io> * Update changelog for exponentiation precedence fix Signed-off-by: Christoph Knittel <ck@cca.io> --------- Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent 65cf698 commit 932ab67

4 files changed

Lines changed: 49 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#### :bug: Bug fix
2727

28+
- Preserve parentheses around multiplication, division, and modulo expressions used as exponents. https://github.com/rescript-lang/rescript/pull/8550
2829
- Preserve multibyte characters when wrapping long source lines in compiler code frames. https://github.com/rescript-lang/rescript/pull/8520
2930
- Fix reanalyze optional-argument diagnostics for functions passed or returned as first-class values. https://github.com/rescript-lang/rescript/pull/8321
3031

compiler/core/js_op_util.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ let op_prec (op : Js_op.binop) =
4141
| Lsl | Lsr | Asr -> (10, 10, 11)
4242
| Bnot | Plus | Minus -> (11, 11, 12)
4343
| Mul | Div | Mod -> (12, 12, 13)
44-
| Pow -> (13, 14, 12)
44+
| Pow -> (13, 14, 13)
4545

4646
let op_int_prec (op : Js_op.int_op) =
4747
match op with

tests/tests/src/exponentiation_test.mjs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,49 @@ let intPow = ((a, b) => Math.pow(a, b) | 0);
77

88
let four = 4;
99

10+
function floatPowDiv(base, numerator, denominator) {
11+
return base ** (numerator / denominator);
12+
}
13+
14+
function floatPowMul(base, left, right) {
15+
return base ** (left * right);
16+
}
17+
18+
function floatPowMod(base, value, modulus) {
19+
return base ** (value % modulus);
20+
}
21+
22+
function bigintPowMul(base, left, right) {
23+
return base ** (left * right);
24+
}
25+
1026
Mocha.describe("Exponentiation_test", () => {
1127
Mocha.test("exponentiation operations", () => {
12-
Test_utils.eq("File \"exponentiation_test.res\", line 11, characters 7-14", 2 ** 3 ** 2, Math.pow(2, Math.pow(3, 2)));
13-
Test_utils.eq("File \"exponentiation_test.res\", line 12, characters 7-14", 2 ** (-3) ** 2, Math.pow(2, Math.pow(-3, 2)));
14-
Test_utils.eq("File \"exponentiation_test.res\", line 13, characters 7-14", (2 ** 3) ** 2, Math.pow(Math.pow(2, 3), 2));
15-
Test_utils.eq("File \"exponentiation_test.res\", line 14, characters 7-14", (-2) ** 2, Math.pow(-2, 2));
16-
Test_utils.eq("File \"exponentiation_test.res\", line 16, characters 7-14", 512, intPow(2, intPow(3, 2)));
17-
Test_utils.eq("File \"exponentiation_test.res\", line 17, characters 7-14", 512, intPow(2, intPow(-3, 2)));
18-
Test_utils.eq("File \"exponentiation_test.res\", line 18, characters 7-14", 64, intPow(intPow(2, 3), 2));
19-
Test_utils.eq("File \"exponentiation_test.res\", line 19, characters 7-14", -2147483648, intPow(-2, 31));
20-
Test_utils.eq("File \"exponentiation_test.res\", line 20, characters 7-14", 0, intPow(2, 32));
21-
Test_utils.eq("File \"exponentiation_test.res\", line 21, characters 7-14", 0, intPow(2147483647, 2));
22-
Test_utils.eq("File \"exponentiation_test.res\", line 22, characters 7-14", 0, intPow(-2147483648, 2));
23-
Test_utils.eq("File \"exponentiation_test.res\", line 24, characters 7-14", 256, four ** four | 0);
28+
Test_utils.eq("File \"exponentiation_test.res\", line 17, characters 7-14", 2 ** 3 ** 2, Math.pow(2, Math.pow(3, 2)));
29+
Test_utils.eq("File \"exponentiation_test.res\", line 18, characters 7-14", 2 ** (-3) ** 2, Math.pow(2, Math.pow(-3, 2)));
30+
Test_utils.eq("File \"exponentiation_test.res\", line 19, characters 7-14", (2 ** 3) ** 2, Math.pow(Math.pow(2, 3), 2));
31+
Test_utils.eq("File \"exponentiation_test.res\", line 20, characters 7-14", (-2) ** 2, Math.pow(-2, 2));
32+
Test_utils.eq("File \"exponentiation_test.res\", line 22, characters 7-14", 512, intPow(2, intPow(3, 2)));
33+
Test_utils.eq("File \"exponentiation_test.res\", line 23, characters 7-14", 512, intPow(2, intPow(-3, 2)));
34+
Test_utils.eq("File \"exponentiation_test.res\", line 24, characters 7-14", 64, intPow(intPow(2, 3), 2));
35+
Test_utils.eq("File \"exponentiation_test.res\", line 25, characters 7-14", -2147483648, intPow(-2, 31));
36+
Test_utils.eq("File \"exponentiation_test.res\", line 26, characters 7-14", 0, intPow(2, 32));
37+
Test_utils.eq("File \"exponentiation_test.res\", line 27, characters 7-14", 0, intPow(2147483647, 2));
38+
Test_utils.eq("File \"exponentiation_test.res\", line 28, characters 7-14", 0, intPow(-2147483648, 2));
39+
Test_utils.eq("File \"exponentiation_test.res\", line 30, characters 7-14", 256, four ** four | 0);
40+
Test_utils.eq("File \"exponentiation_test.res\", line 32, characters 7-14", 2 ** (0 / 10000), 1);
41+
Test_utils.eq("File \"exponentiation_test.res\", line 33, characters 7-14", 2 ** (3 * 4), 4096);
42+
Test_utils.eq("File \"exponentiation_test.res\", line 34, characters 7-14", 2 ** (5 % 3), 4);
43+
Test_utils.eq("File \"exponentiation_test.res\", line 35, characters 7-14", 2n ** (3n * 2n), 64n);
2444
});
2545
});
2646

2747
export {
2848
intPow,
2949
four,
50+
floatPowDiv,
51+
floatPowMul,
52+
floatPowMod,
53+
bigintPowMul,
3054
}
3155
/* Not a pure module */

tests/tests/src/exponentiation_test.res

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ external jsPow: (float, float) => float = "Math.pow"
66
let intPow: (int, int) => int = %raw(`(a, b) => Math.pow(a, b) | 0`)
77
let four: int = %raw(`4`)
88

9+
let floatPowDiv = (base: float, numerator: float, denominator: float) =>
10+
base ** (numerator /. denominator)
11+
let floatPowMul = (base: float, left: float, right: float) => base ** (left *. right)
12+
let floatPowMod = (base: float, value: float, modulus: float) => base ** (value % modulus)
13+
let bigintPowMul = (base: bigint, left: bigint, right: bigint) => base ** (left * right)
14+
915
describe(__MODULE__, () => {
1016
test("exponentiation operations", () => {
1117
eq(__LOC__, 2. ** 3. ** 2., jsPow(2., jsPow(3., 2.)))
@@ -22,5 +28,10 @@ describe(__MODULE__, () => {
2228
eq(__LOC__, -2147483648 ** 2, intPow(-2147483648, 2))
2329

2430
eq(__LOC__, 4 ** 4, four ** four)
31+
32+
eq(__LOC__, floatPowDiv(2., 0., 10000.), 1.)
33+
eq(__LOC__, floatPowMul(2., 3., 4.), 4096.)
34+
eq(__LOC__, floatPowMod(2., 5., 3.), 4.)
35+
eq(__LOC__, bigintPowMul(2n, 3n, 2n), 64n)
2536
})
2637
})

0 commit comments

Comments
 (0)