Skip to content

Commit c65c6c0

Browse files
authored
Add support for the bitwise NOT(~) unary operator (#7418)
1 parent 80c96a1 commit c65c6c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+178
-78
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
- Add shift (`<<`, `>>`, `>>>`) operators for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7183
2323
- Add bitwise AND (`&`) operator for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7415
24+
- Add bitwise NOT (`~`) operator for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7418
2425
- Significantly reduced the download size by splitting binaries into optional platform-specific dependencies (e.g, `@rescript/linux-x64`). https://github.com/rescript-lang/rescript/pull/7395
2526
- JSX: do not error on ref as prop anymore (which is allowed in React 19). https://github.com/rescript-lang/rescript/pull/7420
2627

compiler/core/j.ml

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ and expression_desc =
8888
| Typeof of expression
8989
| In of expression * expression (* prop in obj *)
9090
| Js_not of expression (* !v *)
91+
| Js_bnot of expression (* ~v *)
9192
(* TODO: Add some primitives so that [js inliner] can do a better job *)
9293
| Seq of expression * expression
9394
| Cond of expression * expression * expression

compiler/core/js_analyzer.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ let rec no_side_effect_expression_desc (x : J.expression_desc) =
110110
no_side_effect call_expr
111111
&& Ext_list.for_all strings no_side_effect
112112
&& Ext_list.for_all values no_side_effect
113-
| Js_not e -> no_side_effect e
113+
| Js_not e | Js_bnot e -> no_side_effect e
114114
| In (prop, obj) -> no_side_effect prop && no_side_effect obj
115115
| Cond (a, b, c) -> no_side_effect a && no_side_effect b && no_side_effect c
116116
| Call ({expression_desc = Str {txt = "Array.isArray"}}, [e], _) ->
@@ -228,8 +228,8 @@ let rec eq_expression ({expression_desc = x0} : J.expression)
228228
eq_expression_list ls0 ls1 && flag0 = flag1 && eq_expression tag0 tag1
229229
| _ -> false)
230230
| Length _ | Is_null_or_undefined _ | String_append _ | Typeof _ | Js_not _
231-
| In _ | Cond _ | FlatCall _ | New _ | Fun _ | Raw_js_code _ | Array _
232-
| Caml_block_tag _ | Object _ | Tagged_template _ | Await _ ->
231+
| Js_bnot _ | In _ | Cond _ | FlatCall _ | New _ | Fun _ | Raw_js_code _
232+
| Array _ | Caml_block_tag _ | Object _ | Tagged_template _ | Await _ ->
233233
false
234234
| Spread _ -> false
235235

compiler/core/js_dump.ml

+6-2
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ let rec exp_need_paren ?(arrow = false) (e : J.expression) =
166166
| Length _ | Call _ | Caml_block_tag _ | Seq _ | Static_index _ | Cond _
167167
| Bin _ | Is_null_or_undefined _ | String_index _ | Array_index _
168168
| String_append _ | Var _ | Undefined _ | Null | Str _ | Array _
169-
| Caml_block _ | FlatCall _ | Typeof _ | Number _ | Js_not _ | In _ | Bool _
170-
| New _ ->
169+
| Caml_block _ | FlatCall _ | Typeof _ | Number _ | Js_not _ | Js_bnot _
170+
| In _ | Bool _ | New _ ->
171171
false
172172
| Await _ -> false
173173
| Spread _ -> false
@@ -677,6 +677,10 @@ and expression_desc cxt ~(level : int) f x : cxt =
677677
P.cond_paren_group f (level > 13) (fun _ ->
678678
P.string f "!";
679679
expression ~level:13 cxt f e)
680+
| Js_bnot e ->
681+
P.cond_paren_group f (level > 13) (fun _ ->
682+
P.string f "~";
683+
expression ~level:13 cxt f e)
680684
| In (prop, obj) ->
681685
P.cond_paren_group f (level > 12) (fun _ ->
682686
let cxt = expression ~level:0 cxt f prop in

compiler/core/js_exp_make.ml

+5
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,11 @@ let int32_mul ?comment (e1 : J.expression) (e2 : J.expression) : J.expression =
16161616
let unchecked_int32_mul ?comment e1 e2 : J.expression =
16171617
{comment; expression_desc = Bin (Mul, e1, e2)}
16181618

1619+
let int_bnot ?comment (e : t) : J.expression =
1620+
match e.expression_desc with
1621+
| Number (Int {i}) -> int ?comment (Int32.lognot i)
1622+
| _ -> {comment; expression_desc = Js_bnot e}
1623+
16191624
let int32_pow ?comment (e1 : t) (e2 : t) : J.expression =
16201625
match (e1.expression_desc, e2.expression_desc) with
16211626
| Number (Int {i = i1}), Number (Int {i = i2}) ->

compiler/core/js_exp_make.mli

+2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ val float_equal : ?comment:string -> t -> t -> t
210210

211211
val int_equal : ?comment:string -> t -> t -> t
212212

213+
val int_bnot : ?comment:string -> t -> t
214+
213215
val string_equal : ?comment:string -> t -> t -> t
214216

215217
val eq_null_undefined_boolean : ?comment:string -> t -> t -> t

compiler/core/js_fold.ml

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ class fold =
103103
| Js_not _x0 ->
104104
let _self = _self#expression _x0 in
105105
_self
106+
| Js_bnot _x0 ->
107+
let _self = _self#expression _x0 in
108+
_self
106109
| In (_x0, _x1) ->
107110
let _self = _self#expression _x0 in
108111
let _self = _self#expression _x1 in

compiler/core/js_op.ml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type binop =
3838
| Le
3939
| Gt
4040
| Ge
41+
| Bnot
4142
| Bor
4243
| Bxor
4344
| Band

compiler/core/js_op_util.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ let op_prec (op : Js_op.binop) =
3939
| Bxor -> (6, 6, 6)
4040
| Band -> (7, 7, 7)
4141
| Lsl | Lsr | Asr -> (10, 10, 11)
42-
| Plus | Minus -> (11, 11, 12)
42+
| Bnot | Plus | Minus -> (11, 11, 12)
4343
| Mul | Div | Mod -> (12, 12, 13)
4444
| Pow -> (13, 14, 12)
4545

@@ -55,6 +55,7 @@ let op_int_prec (op : Js_op.int_op) =
5555

5656
let op_str (op : Js_op.binop) =
5757
match op with
58+
| Bnot -> "~"
5859
| Bor -> "|"
5960
| Bxor -> "^"
6061
| Band -> "&"

compiler/core/js_record_fold.ml

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ let expression_desc : 'a. ('a, expression_desc) fn =
109109
| Js_not _x0 ->
110110
let st = _self.expression _self st _x0 in
111111
st
112+
| Js_bnot _x0 ->
113+
let st = _self.expression _self st _x0 in
114+
st
112115
| In (_x0, _x1) ->
113116
let st = _self.expression _self st _x0 in
114117
let st = _self.expression _self st _x1 in

compiler/core/js_record_iter.ml

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ let expression_desc : expression_desc fn =
9191
| Bool _ -> ()
9292
| Typeof _x0 -> _self.expression _self _x0
9393
| Js_not _x0 -> _self.expression _self _x0
94+
| Js_bnot _x0 -> _self.expression _self _x0
9495
| In (_x0, _x1) ->
9596
_self.expression _self _x0;
9697
_self.expression _self _x1

compiler/core/js_record_map.ml

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ let expression_desc : expression_desc fn =
109109
| Js_not _x0 ->
110110
let _x0 = _self.expression _self _x0 in
111111
Js_not _x0
112+
| Js_bnot _x0 ->
113+
let _x0 = _self.expression _self _x0 in
114+
Js_bnot _x0
112115
| In (_x0, _x1) ->
113116
let _x0 = _self.expression _self _x0 in
114117
let _x1 = _self.expression _self _x1 in

compiler/core/lam_analysis.ml

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,16 @@ 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 | Ppowint | Pandint | Porint
63-
| Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ | Pintorder | Pintmin
64-
| Pintmax
62+
| Pnegint | Paddint | Psubint | Pmulint | Ppowint | Pnotint | Pandint
63+
| Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ | Pintorder
64+
| Pintmin | Pintmax
6565
(* float primitives *)
6666
| Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat
6767
| Ppowfloat | Pdivfloat | Pmodfloat | Pfloatcomp _ | Pjscomp _ | Pfloatorder
6868
| Pfloatmin | Pfloatmax
6969
(* bigint primitives *)
7070
| Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Ppowbigint
71-
| Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint
71+
| Pnotbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint
7272
| Pbigintcomp _ | Pbigintorder | Pbigintmin | Pbigintmax
7373
(* string primitives *)
7474
| Pstringlength | Pstringrefu | Pstringrefs | Pstringcomp _ | Pstringorder

compiler/core/lam_compile_primitive.ml

+8
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,14 @@ let translate output_prefix loc (cxt : Lam_compile_context.t)
283283
match args with
284284
| [e1; e2] -> E.bigint_op Asr e1 e2
285285
| _ -> assert false)
286+
| Pnotint -> (
287+
match args with
288+
| [e] -> E.int_bnot e
289+
| _ -> assert false)
290+
| Pnotbigint -> (
291+
match args with
292+
| [e] -> E.int_bnot e
293+
| _ -> assert false)
286294
| Pandint -> (
287295
match args with
288296
| [e1; e2] -> E.int32_band e1 e2

compiler/core/lam_convert.ml

+2
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
253253
| Pandint -> prim ~primitive:Pandint ~args loc
254254
| Porint -> prim ~primitive:Porint ~args loc
255255
| Pxorint -> prim ~primitive:Pxorint ~args loc
256+
| Pnotint -> prim ~primitive:Pnotint ~args loc
256257
| Plslint -> prim ~primitive:Plslint ~args loc
257258
| Plsrint -> prim ~primitive:Plsrint ~args loc
258259
| Pasrint -> prim ~primitive:Pasrint ~args loc
@@ -296,6 +297,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
296297
| Pandbigint -> prim ~primitive:Pandbigint ~args loc
297298
| Porbigint -> prim ~primitive:Porbigint ~args loc
298299
| Pxorbigint -> prim ~primitive:Pxorbigint ~args loc
300+
| Pnotbigint -> prim ~primitive:Pnotbigint ~args loc
299301
| Plslbigint -> prim ~primitive:Plslbigint ~args loc
300302
| Pasrbigint -> prim ~primitive:Pasrbigint ~args loc
301303
| Pbigintcomp x -> prim ~primitive:(Pbigintcomp x) ~args loc

compiler/core/lam_primitive.ml

+6-4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type t =
7777
| Pandint
7878
| Porint
7979
| Pxorint
80+
| Pnotint
8081
| Plslint
8182
| Plsrint
8283
| Pasrint
@@ -111,6 +112,7 @@ type t =
111112
| Pandbigint
112113
| Porbigint
113114
| Pxorbigint
115+
| Pnotbigint
114116
| Plslbigint
115117
| Pasrbigint
116118
| Pbigintcomp of Lam_compat.comparison
@@ -201,15 +203,15 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
201203
| Psequand | Psequor | Pnot | Pboolcomp _ | Pboolorder | Pboolmin | Pboolmax
202204
(* int primitives *)
203205
| Pisint | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint | Ppowint
204-
| Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintorder
205-
| Pintmin | Pintmax
206+
| Pnotint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint
207+
| Pintorder | Pintmin | Pintmax
206208
(* float primitives *)
207209
| Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat
208210
| Pdivfloat | Pmodfloat | Ppowfloat | Pfloatorder | Pfloatmin | Pfloatmax
209211
(* bigint primitives *)
210212
| Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Pdivbigint | Pmodbigint
211-
| Ppowbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint
212-
| Pbigintorder | Pbigintmin | Pbigintmax
213+
| Ppowbigint | Pnotbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint
214+
| Pasrbigint | Pbigintorder | Pbigintmin | Pbigintmax
213215
(* string primitives *)
214216
| Pstringlength | Pstringrefu | Pstringrefs | Pstringadd | Pstringcomp _
215217
| Pstringorder | Pstringmin | Pstringmax

compiler/core/lam_primitive.mli

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type t =
7272
| Pandint
7373
| Porint
7474
| Pxorint
75+
| Pnotint
7576
| Plslint
7677
| Plsrint
7778
| Pasrint
@@ -106,6 +107,7 @@ type t =
106107
| Pandbigint
107108
| Porbigint
108109
| Pxorbigint
110+
| Pnotbigint
109111
| Plslbigint
110112
| Pasrbigint
111113
| Pbigintcomp of Lam_compat.comparison

compiler/core/lam_print.ml

+4-2
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ let primitive ppf (prim : Lam_primitive.t) =
108108
| Pboolorder -> fprintf ppf "compare"
109109
| Pboolmin -> fprintf ppf "min"
110110
| Pboolmax -> fprintf ppf "max"
111-
| Pnegint -> fprintf ppf "~"
111+
| Pnegint -> fprintf ppf "~-"
112112
| Paddint -> fprintf ppf "+"
113113
| Pstringadd -> fprintf ppf "+*"
114114
| Psubint -> fprintf ppf "-"
@@ -119,6 +119,7 @@ let primitive ppf (prim : Lam_primitive.t) =
119119
| Pandint -> fprintf ppf "and"
120120
| Porint -> fprintf ppf "or"
121121
| Pxorint -> fprintf ppf "xor"
122+
| Pnotint -> fprintf ppf "~~"
122123
| Plslint -> fprintf ppf "lsl"
123124
| Plsrint -> fprintf ppf "lsr"
124125
| Pasrint -> fprintf ppf "asr"
@@ -151,7 +152,7 @@ let primitive ppf (prim : Lam_primitive.t) =
151152
| Pfloatorder -> fprintf ppf "compare"
152153
| Pfloatmin -> fprintf ppf "min"
153154
| Pfloatmax -> fprintf ppf "max"
154-
| Pnegbigint -> fprintf ppf "~"
155+
| Pnegbigint -> fprintf ppf "~-"
155156
| Paddbigint -> fprintf ppf "+"
156157
| Psubbigint -> fprintf ppf "-"
157158
| Pmulbigint -> fprintf ppf "*"
@@ -161,6 +162,7 @@ let primitive ppf (prim : Lam_primitive.t) =
161162
| Pandbigint -> fprintf ppf "and"
162163
| Porbigint -> fprintf ppf "or"
163164
| Pxorbigint -> fprintf ppf "xor"
165+
| Pnotbigint -> fprintf ppf "~~"
164166
| Plslbigint -> fprintf ppf "lsl"
165167
| Pasrbigint -> fprintf ppf "asr"
166168
| Pbigintcomp Ceq -> fprintf ppf "=="

compiler/ml/lambda.ml

+2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ type primitive =
210210
| Pandint
211211
| Porint
212212
| Pxorint
213+
| Pnotint
213214
| Plslint
214215
| Plsrint
215216
| Pasrint
@@ -245,6 +246,7 @@ type primitive =
245246
| Pandbigint
246247
| Porbigint
247248
| Pxorbigint
249+
| Pnotbigint
248250
| Plslbigint
249251
| Pasrbigint
250252
| Pbigintcomp of comparison

compiler/ml/lambda.mli

+2
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ type primitive =
177177
| Pandint
178178
| Porint
179179
| Pxorint
180+
| Pnotint
180181
| Plslint
181182
| Plsrint
182183
| Pasrint
@@ -212,6 +213,7 @@ type primitive =
212213
| Pandbigint
213214
| Porbigint
214215
| Pxorbigint
216+
| Pnotbigint
215217
| Plslbigint
216218
| Pasrbigint
217219
| Pbigintcomp of comparison

compiler/ml/pprintast.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ and expression ctxt f x =
652652
| `Prefix s -> (
653653
let s =
654654
if
655-
List.mem s ["~+"; "~-"; "~+."; "~-."]
655+
List.mem s ["~+"; "~-"; "~+."; "~-."; "~~"]
656656
&&
657657
match l with
658658
(* See #7200: avoid turning (~- 1) into (- 1) which is

compiler/ml/printlambda.ml

+5-3
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ let primitive ppf = function
142142
| Pboolorder -> fprintf ppf "compare"
143143
| Pboolmin -> fprintf ppf "min"
144144
| Pboolmax -> fprintf ppf "max"
145-
| Pnegint -> fprintf ppf "~"
145+
| Pnegint -> fprintf ppf "~-"
146146
| Paddint -> fprintf ppf "+"
147147
| Psubint -> fprintf ppf "-"
148148
| Pmulint -> fprintf ppf "*"
@@ -152,6 +152,7 @@ let primitive ppf = function
152152
| Pandint -> fprintf ppf "and"
153153
| Porint -> fprintf ppf "or"
154154
| Pxorint -> fprintf ppf "xor"
155+
| Pnotint -> fprintf ppf "~~"
155156
| Plslint -> fprintf ppf "lsl"
156157
| Plsrint -> fprintf ppf "lsr"
157158
| Pasrint -> fprintf ppf "asr"
@@ -168,7 +169,7 @@ let primitive ppf = function
168169
| Poffsetref n -> fprintf ppf "+:=%i" n
169170
| Pintoffloat -> fprintf ppf "int_of_float"
170171
| Pfloatofint -> fprintf ppf "float_of_int"
171-
| Pnegfloat -> fprintf ppf "~."
172+
| Pnegfloat -> fprintf ppf "~-."
172173
| Pabsfloat -> fprintf ppf "abs."
173174
| Paddfloat -> fprintf ppf "+."
174175
| Psubfloat -> fprintf ppf "-."
@@ -185,14 +186,15 @@ let primitive ppf = function
185186
| Pfloatorder -> fprintf ppf "compare"
186187
| Pfloatmin -> fprintf ppf "min"
187188
| Pfloatmax -> fprintf ppf "max"
188-
| Pnegbigint -> fprintf ppf "~"
189+
| Pnegbigint -> fprintf ppf "~-"
189190
| Paddbigint -> fprintf ppf "+"
190191
| Psubbigint -> fprintf ppf "-"
191192
| Pmulbigint -> fprintf ppf "*"
192193
| Ppowbigint -> fprintf ppf "**"
193194
| Pandbigint -> fprintf ppf "and"
194195
| Porbigint -> fprintf ppf "or"
195196
| Pxorbigint -> fprintf ppf "xor"
197+
| Pnotbigint -> fprintf ppf "~~"
196198
| Plslbigint -> fprintf ppf "lsl"
197199
| Pasrbigint -> fprintf ppf "asr"
198200
| Pdivbigint -> fprintf ppf "/"

compiler/ml/translcore.ml

+2
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ let primitives_table =
276276
("%mulint", Pmulint);
277277
("%divint", Pdivint);
278278
("%modint", Pmodint);
279+
("%bitnot_int", Pnotint);
279280
("%andint", Pandint);
280281
("%orint", Porint);
281282
("%xorint", Pxorint);
@@ -322,6 +323,7 @@ let primitives_table =
322323
("%lebigint", Pbigintcomp Cle);
323324
("%gtbigint", Pbigintcomp Cgt);
324325
("%gebigint", Pbigintcomp Cge);
326+
("%bitnot_bigint", Pnotbigint);
325327
("%andbigint", Pandbigint);
326328
("%orbigint", Porbigint);
327329
("%xorbigint", Pxorbigint);

compiler/ml/unified_ops.ml

+13
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,19 @@ let entries =
207207
string = None;
208208
};
209209
};
210+
{
211+
path = builtin "~~";
212+
name = "%bitnot";
213+
form = Unary;
214+
specialization =
215+
{
216+
int = Pnotint;
217+
bool = None;
218+
float = None;
219+
bigint = Some Pnotbigint;
220+
string = None;
221+
};
222+
};
210223
{
211224
path = builtin "&";
212225
name = "%bitand";

0 commit comments

Comments
 (0)