Skip to content

Commit 9c6856d

Browse files
authored
Upgrade exponentiation to unified operator (#7153)
* Upgrade exponentiation to unified operator Also make its output to use ES7 exponentiation (`**`) operator. `**` is more concise, faster than `Math.pow()`, works well with all numeric types include bigint. We were already using it for bigint, now for int and float too. * adjust parens * result into int32 * more exponentiation tests * make sure it is int32 * remove unnecessary guard for constants * add changelog * add a test * update changelog * add a failing case * fix `Ext_int.int32_pow` to behave like JavaScript
1 parent 55d0837 commit 9c6856d

30 files changed

+187
-44
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- Make reanalyze exception tracking work with the new stdlib. https://github.com/rescript-lang/rescript/pull/7328
2222
- Fix Pervasive.max using boolean comparison for floats. https://github.com/rescript-lang/rescript/pull/7333
2323
- Experimental: Support nested/inline record types - records defined inside of other records, without needing explicit separate type definitions. https://github.com/rescript-lang/rescript/pull/7241
24+
- Add unified exponentiation (`**`) operator for numeric types using ES7 `**`. https://github.com/rescript-lang/rescript-compiler/pull/7153
2425

2526
#### :boom: Breaking Change
2627

compiler/core/js_exp_make.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,7 @@ let unchecked_int32_minus ?comment e1 e2 : J.expression =
15491549
float_minus ?comment e1 e2
15501550

15511551
let float_div ?comment e1 e2 = bin ?comment Div e1 e2
1552+
let float_pow ?comment e1 e2 = bin ?comment Pow e1 e2
15521553
let float_notequal ?comment e1 e2 = bin ?comment NotEqEq e1 e2
15531554

15541555
let int32_asr ?comment e1 e2 : J.expression =
@@ -1618,6 +1619,12 @@ let int32_mul ?comment (e1 : J.expression) (e2 : J.expression) : J.expression =
16181619
let unchecked_int32_mul ?comment e1 e2 : J.expression =
16191620
{comment; expression_desc = Bin (Mul, e1, e2)}
16201621

1622+
let int32_pow ?comment (e1 : t) (e2 : t) : J.expression =
1623+
match (e1.expression_desc, e2.expression_desc) with
1624+
| Number (Int {i = i1}), Number (Int {i = i2}) ->
1625+
int ?comment (Ext_int.int32_pow i1 i2)
1626+
| _ -> to_int32 (float_pow ?comment e1 e2)
1627+
16211628
let rec int32_bxor ?comment (e1 : t) (e2 : t) : J.expression =
16221629
match (e1.expression_desc, e2.expression_desc) with
16231630
| Number (Int {i = i1}), Number (Int {i = i2}) ->

compiler/core/js_exp_make.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ val int32_div : checked:bool -> ?comment:string -> t -> t -> t
254254

255255
val int32_mod : checked:bool -> ?comment:string -> t -> t -> t
256256

257+
val int32_pow : ?comment:string -> t -> t -> t
258+
257259
val int32_lsl : ?comment:string -> t -> t -> t
258260

259261
val int32_lsr : ?comment:string -> t -> t -> t
@@ -278,6 +280,8 @@ val float_notequal : ?comment:string -> t -> t -> t
278280

279281
val float_mod : ?comment:string -> t -> t -> t
280282

283+
val float_pow : ?comment:string -> t -> t -> t
284+
281285
val int_comp : Lam_compat.comparison -> ?comment:string -> t -> t -> t
282286

283287
val bool_comp : Lam_compat.comparison -> ?comment:string -> t -> t -> t

compiler/core/js_op.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ type int_op =
105105
| Div
106106
(* x / y | 0 *)
107107
| Mod
108-
(* x % y *)
108+
(* x % y *)
109+
| Pow (* x ** y | 0 *)
109110

110111
(* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Bitwise_operators
111112
{[

compiler/core/js_op_util.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ let op_prec (op : Js_op.binop) =
4040
| Band -> (7, 7, 7)
4141
| Lsl | Lsr | Asr -> (10, 10, 11)
4242
| Plus | Minus -> (11, 11, 12)
43-
| Mul | Div | Mod | Pow -> (12, 12, 13)
43+
| Mul | Div | Mod -> (12, 12, 13)
44+
| Pow -> (13, 14, 12)
4445

4546
let op_int_prec (op : Js_op.int_op) =
4647
match op with
@@ -50,6 +51,7 @@ let op_int_prec (op : Js_op.int_op) =
5051
| Lsl | Lsr | Asr -> (10, 10, 11)
5152
| Plus | Minus -> (11, 11, 12)
5253
| Mul | Div | Mod -> (12, 12, 13)
54+
| Pow -> (13, 14, 12)
5355

5456
let op_str (op : Js_op.binop) =
5557
match op with
@@ -89,6 +91,7 @@ let op_int_str (op : Js_op.int_op) =
8991
| Mul -> "*"
9092
| Div -> "/"
9193
| Mod -> "%"
94+
| Pow -> "**"
9295

9396
let str_of_used_stats x =
9497
match (x : Js_op.used_stats) with

compiler/core/lam_analysis.ml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,13 @@ let rec no_side_effects (lam : Lam.t) : bool =
5959
(* bool primitives *)
6060
| Psequand | Psequor | Pnot | Pboolcomp _ | Pboolorder | Pboolmin | Pboolmax
6161
(* int primitives *)
62-
| Pnegint | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint
63-
| Plslint | Plsrint | Pasrint | Pintcomp _ | Pintorder | Pintmin | Pintmax
62+
| Pnegint | Paddint | Psubint | Pmulint | Ppowint | Pandint | Porint
63+
| Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ | Pintorder | Pintmin
64+
| Pintmax
6465
(* float primitives *)
6566
| Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat
66-
| Pdivfloat | Pmodfloat | Pfloatcomp _ | Pjscomp _ | Pfloatorder | Pfloatmin
67-
| Pfloatmax
67+
| Ppowfloat | Pdivfloat | Pmodfloat | Pfloatcomp _ | Pjscomp _ | Pfloatorder
68+
| Pfloatmin | Pfloatmax
6869
(* bigint primitives *)
6970
| Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Ppowbigint
7071
| Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint

compiler/core/lam_compile_primitive.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,14 @@ let translate output_prefix loc (cxt : Lam_compile_context.t)
250250
match args with
251251
| [e1; e2] -> E.bigint_mod ~checked:!Js_config.check_div_by_zero e1 e2
252252
| _ -> assert false)
253+
| Ppowint -> (
254+
match args with
255+
| [e1; e2] -> E.int32_pow e1 e2
256+
| _ -> assert false)
257+
| Ppowfloat -> (
258+
match args with
259+
| [e1; e2] -> E.float_pow e1 e2
260+
| _ -> assert false)
253261
| Ppowbigint -> (
254262
match args with
255263
| [e1; e2] -> E.bigint_op Pow e1 e2

compiler/core/lam_convert.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
249249
| Pmulint -> prim ~primitive:Pmulint ~args loc
250250
| Pdivint -> prim ~primitive:Pdivint ~args loc
251251
| Pmodint -> prim ~primitive:Pmodint ~args loc
252+
| Ppowint -> prim ~primitive:Ppowint ~args loc
252253
| Pandint -> prim ~primitive:Pandint ~args loc
253254
| Porint -> prim ~primitive:Porint ~args loc
254255
| Pxorint -> prim ~primitive:Pxorint ~args loc
@@ -281,6 +282,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
281282
| Pmulfloat -> prim ~primitive:Pmulfloat ~args loc
282283
| Pdivfloat -> prim ~primitive:Pdivfloat ~args loc
283284
| Pmodfloat -> prim ~primitive:Pmodfloat ~args loc
285+
| Ppowfloat -> prim ~primitive:Ppowfloat ~args loc
284286
| Pfloatorder -> prim ~primitive:Pfloatorder ~args loc
285287
| Pfloatmin -> prim ~primitive:Pfloatmin ~args loc
286288
| Pfloatmax -> prim ~primitive:Pfloatmax ~args loc

compiler/core/lam_primitive.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ type t =
7373
| Pmulint
7474
| Pdivint
7575
| Pmodint
76+
| Ppowint
7677
| Pandint
7778
| Porint
7879
| Pxorint
@@ -94,6 +95,7 @@ type t =
9495
| Pmulfloat
9596
| Pdivfloat
9697
| Pmodfloat
98+
| Ppowfloat
9799
| Pfloatcomp of Lam_compat.comparison
98100
| Pfloatorder
99101
| Pfloatmin
@@ -197,12 +199,12 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
197199
(* bool primitives *)
198200
| Psequand | Psequor | Pnot | Pboolcomp _ | Pboolorder | Pboolmin | Pboolmax
199201
(* int primitives *)
200-
| Pisint | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint | Pandint
201-
| Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintorder | Pintmin
202-
| Pintmax
202+
| Pisint | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint | Ppowint
203+
| Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintorder
204+
| Pintmin | Pintmax
203205
(* float primitives *)
204206
| Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat
205-
| Pdivfloat | Pmodfloat | Pfloatorder | Pfloatmin | Pfloatmax
207+
| Pdivfloat | Pmodfloat | Ppowfloat | Pfloatorder | Pfloatmin | Pfloatmax
206208
(* bigint primitives *)
207209
| Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Pdivbigint | Pmodbigint
208210
| Ppowbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint

compiler/core/lam_primitive.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type t =
6868
| Pmulint
6969
| Pdivint
7070
| Pmodint
71+
| Ppowint
7172
| Pandint
7273
| Porint
7374
| Pxorint
@@ -89,6 +90,7 @@ type t =
8990
| Pmulfloat
9091
| Pdivfloat
9192
| Pmodfloat
93+
| Ppowfloat
9294
| Pfloatcomp of Lam_compat.comparison
9395
| Pfloatorder
9496
| Pfloatmin

0 commit comments

Comments
 (0)