Skip to content

Commit 2220217

Browse files
authored
Make exponentiation operator right-associative (#5959)
* Make exponentiation operator right-associative * update printer * chore: format * update CHANGELOG.md
1 parent ba47799 commit 2220217

10 files changed

+57
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ subset of the arguments, and return a curried type with the remaining ones https
3737
- Curried after uncurried is not fused anymore: `(. x) => y => 3` is not equivalent to `(. x, y) => 3` anymore. It's instead equivalent to `(. x) => { y => 3 }`.
3838
Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore.
3939
These are only breaking changes for unformatted code.
40+
- Exponentiation operator `**` is now right-associative. `2. ** 3. ** 2.` now compile to `Math.pow(2, Math.pow(3, 2))` and not anymore `Math.pow(Math.pow(2, 3), 2)`. Parentheses can be used to change precedence.
4041

4142
#### :bug: Bug Fix
4243

jscomp/test/build.ninja

Lines changed: 2 additions & 1 deletion
Large diffs are not rendered by default.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
3+
4+
var a = Math.pow(2, Math.pow(3, 2));
5+
6+
var b = Math.pow(2, Math.pow(-3, 2));
7+
8+
var c = Math.pow(Math.pow(2, 3), 2);
9+
10+
var d = Math.pow(-2, 2);
11+
12+
exports.a = a;
13+
exports.b = b;
14+
exports.c = c;
15+
exports.d = d;
16+
/* a Not a pure module */
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let a = 2. ** 3. ** 2.
2+
let b = 2. ** -3. ** 2.
3+
let c = (2. ** 3.) ** 2.
4+
let d = (-2.) ** 2.

res_syntax/src/res_core.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2200,7 +2200,11 @@ and parseBinaryExpr ?(context = OrdinaryExpr) ?a p prec =
22002200
let startPos = p.startPos in
22012201
Parser.next p;
22022202
let endPos = p.prevEndPos in
2203-
let b = parseBinaryExpr ~context p (tokenPrec + 1) in
2203+
let tokenPrec =
2204+
(* exponentiation operator is right-associative *)
2205+
if token = Exponentiation then tokenPrec else tokenPrec + 1
2206+
in
2207+
let b = parseBinaryExpr ~context p tokenPrec in
22042208
let loc = mkLoc a.Parsetree.pexp_loc.loc_start b.pexp_loc.loc_end in
22052209
let expr =
22062210
Ast_helper.Exp.apply ~loc

res_syntax/src/res_parsetree_viewer.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ let isEqualityOperator operator =
320320
| "=" | "==" | "<>" | "!=" -> true
321321
| _ -> false
322322

323+
let isRhsBinaryOperator operator =
324+
match operator with
325+
| "**" -> true
326+
| _ -> false
327+
323328
let flattenableOperators parentOperator childOperator =
324329
let precParent = operatorPrecedence parentOperator in
325330
let precChild = operatorPrecedence childOperator in

res_syntax/src/res_parsetree_viewer.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ val operatorPrecedence : string -> int
7777
val isUnaryExpression : Parsetree.expression -> bool
7878
val isBinaryOperator : string -> bool
7979
val isBinaryExpression : Parsetree.expression -> bool
80+
val isRhsBinaryOperator : string -> bool
8081

8182
val flattenableOperators : string -> string -> bool
8283

res_syntax/src/res_printer.ml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3672,7 +3672,11 @@ and printBinaryExpression ~state (expr : Parsetree.expression) cmtTbl =
36723672
[(Nolabel, lhs); (Nolabel, rhs)] ) ->
36733673
let right =
36743674
let operatorWithRhs =
3675-
let rhsDoc = printOperand ~isLhs:false rhs operator in
3675+
let rhsDoc =
3676+
printOperand
3677+
~isLhs:(ParsetreeViewer.isRhsBinaryOperator operator)
3678+
rhs operator
3679+
in
36763680
Doc.concat
36773681
[
36783682
printBinaryOperator
@@ -3686,7 +3690,14 @@ and printBinaryExpression ~state (expr : Parsetree.expression) cmtTbl =
36863690
else operatorWithRhs
36873691
in
36883692
let doc =
3689-
Doc.group (Doc.concat [printOperand ~isLhs:true lhs operator; right])
3693+
Doc.group
3694+
(Doc.concat
3695+
[
3696+
printOperand
3697+
~isLhs:(not @@ ParsetreeViewer.isRhsBinaryOperator operator)
3698+
lhs operator;
3699+
right;
3700+
])
36903701
in
36913702
Doc.group
36923703
(Doc.concat

res_syntax/tests/printer/expr/binary.res

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ let x = longIdentifier + longIdentifier * longIdentifier * longIdentifier / long
6666
let x = longIdentifier && longIdentifier && longIdentifier && longIdentifier && longIdentifier && longIdentifier;
6767
let x = longIdentifier && longIdentifier || longIdentifier && longIdentifier || longIdentifier && longIdentifier;
6868

69+
// exponentiation is right associative
70+
let x = 2. ** 3. ** 2.
71+
let x = (2. ** 3.) ** 2.
72+
let x = 2. ** (3. ** 2.)
73+
6974
if (
7075
successorParent.color === Black &&
7176
(sibling === None ||

res_syntax/tests/printer/expr/expected/binary.res.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ let x =
108108
longIdentifier && longIdentifier ||
109109
(longIdentifier && longIdentifier)
110110

111+
// exponentiation is right associative
112+
let x = 2. ** 3. ** 2.
113+
let x = (2. ** 3.) ** 2.
114+
let x = 2. ** 3. ** 2.
115+
111116
if (
112117
successorParent.color === Black &&
113118
(sibling === None ||

0 commit comments

Comments
 (0)