Skip to content

Commit dff6374

Browse files
committed
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.
1 parent 7a58f3b commit dff6374

26 files changed

+103
-27
lines changed

compiler/core/js_exp_make.ml

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

15351535
let float_div ?comment e1 e2 = bin ?comment Div e1 e2
1536+
let float_pow ?comment e1 e2 = bin ?comment Pow e1 e2
15361537
let float_notequal ?comment e1 e2 = bin ?comment NotEqEq e1 e2
15371538

15381539
let int32_asr ?comment e1 e2 : J.expression =
@@ -1604,6 +1605,12 @@ let int32_mul ?comment (e1 : J.expression) (e2 : J.expression) : J.expression =
16041605
let unchecked_int32_mul ?comment e1 e2 : J.expression =
16051606
{comment; expression_desc = Bin (Mul, e1, e2)}
16061607

1608+
let int32_pow ?comment (e1 : t) (e2 : t) : J.expression =
1609+
match (e1.expression_desc, e2.expression_desc) with
1610+
| Number (Int {i = i1}), Number (Int {i = i2}) ->
1611+
int ?comment (Ext_int.int32_pow i1 i2)
1612+
| _ -> {comment; expression_desc = Bin (Pow, e1, e2)}
1613+
16071614
let rec int32_bxor ?comment (e1 : t) (e2 : t) : J.expression =
16081615
match (e1.expression_desc, e2.expression_desc) with
16091616
| 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
@@ -251,6 +251,8 @@ val int32_div : checked:bool -> ?comment:string -> t -> t -> t
251251

252252
val int32_mod : checked:bool -> ?comment:string -> t -> t -> t
253253

254+
val int32_pow : ?comment:string -> t -> t -> t
255+
254256
val int32_lsl : ?comment:string -> t -> t -> t
255257

256258
val int32_lsr : ?comment:string -> t -> t -> t
@@ -275,6 +277,8 @@ val float_notequal : ?comment:string -> t -> t -> t
275277

276278
val float_mod : ?comment:string -> t -> t -> t
277279

280+
val float_pow : ?comment:string -> t -> t -> t
281+
278282
val int_comp : Lam_compat.comparison -> ?comment:string -> t -> t -> t
279283

280284
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
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 -> (12, 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 -> (12, 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
@@ -251,6 +251,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
251251
| Pmulint -> prim ~primitive:Pmulint ~args loc
252252
| Pdivint _is_safe (*FIXME*) -> prim ~primitive:Pdivint ~args loc
253253
| Pmodint _is_safe (*FIXME*) -> prim ~primitive:Pmodint ~args loc
254+
| Ppowint -> prim ~primitive:Ppowint ~args loc
254255
| Pandint -> prim ~primitive:Pandint ~args loc
255256
| Porint -> prim ~primitive:Porint ~args loc
256257
| Pxorint -> prim ~primitive:Pxorint ~args loc
@@ -283,6 +284,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
283284
| Pmulfloat -> prim ~primitive:Pmulfloat ~args loc
284285
| Pdivfloat -> prim ~primitive:Pdivfloat ~args loc
285286
| Pmodfloat -> prim ~primitive:Pmodfloat ~args loc
287+
| Ppowfloat -> prim ~primitive:Ppowfloat ~args loc
286288
| Pfloatorder -> prim ~primitive:Pfloatorder ~args loc
287289
| Pfloatmin -> prim ~primitive:Pfloatmin ~args loc
288290
| 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
@@ -75,6 +75,7 @@ type t =
7575
| Pmulint
7676
| Pdivint
7777
| Pmodint
78+
| Ppowint
7879
| Pandint
7980
| Porint
8081
| Pxorint
@@ -96,6 +97,7 @@ type t =
9697
| Pmulfloat
9798
| Pdivfloat
9899
| Pmodfloat
100+
| Ppowfloat
99101
| Pfloatcomp of Lam_compat.comparison
100102
| Pfloatorder
101103
| Pfloatmin
@@ -199,12 +201,12 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
199201
(* bool primitives *)
200202
| Psequand | Psequor | Pnot | Pboolcomp _ | Pboolorder | Pboolmin | Pboolmax
201203
(* int primitives *)
202-
| Pisint | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint | Pandint
203-
| Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintorder | Pintmin
204-
| Pintmax
204+
| Pisint | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint | Ppowint
205+
| Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintorder
206+
| Pintmin | Pintmax
205207
(* float primitives *)
206208
| Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat
207-
| Pdivfloat | Pmodfloat | Pfloatorder | Pfloatmin | Pfloatmax
209+
| Pdivfloat | Pmodfloat | Ppowfloat | Pfloatorder | Pfloatmin | Pfloatmax
208210
(* bigint primitives *)
209211
| Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Pdivbigint | Pmodbigint
210212
| 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
@@ -69,6 +69,7 @@ type t =
6969
| Pmulint
7070
| Pdivint
7171
| Pmodint
72+
| Ppowint
7273
| Pandint
7374
| Porint
7475
| Pxorint
@@ -90,6 +91,7 @@ type t =
9091
| Pmulfloat
9192
| Pdivfloat
9293
| Pmodfloat
94+
| Ppowfloat
9395
| Pfloatcomp of Lam_compat.comparison
9496
| Pfloatorder
9597
| Pfloatmin

compiler/core/lam_print.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ let primitive ppf (prim : Lam_primitive.t) =
116116
| Pmulint -> fprintf ppf "*"
117117
| Pdivint -> fprintf ppf "/"
118118
| Pmodint -> fprintf ppf "mod"
119+
| Ppowint -> fprintf ppf "**"
119120
| Pandint -> fprintf ppf "and"
120121
| Porint -> fprintf ppf "or"
121122
| Pxorint -> fprintf ppf "xor"
@@ -141,6 +142,7 @@ let primitive ppf (prim : Lam_primitive.t) =
141142
| Pmulfloat -> fprintf ppf "*."
142143
| Pdivfloat -> fprintf ppf "/."
143144
| Pmodfloat -> fprintf ppf "mod"
145+
| Ppowfloat -> fprintf ppf "**"
144146
| Pfloatcomp Ceq -> fprintf ppf "==."
145147
| Pfloatcomp Cneq -> fprintf ppf "!=."
146148
| Pfloatcomp Clt -> fprintf ppf "<."

0 commit comments

Comments
 (0)