diff --git a/CHANGELOG.md b/CHANGELOG.md index 234a6ac2a8..87a1d2fe73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - Add shift (`<<`, `>>`, `>>>`) operators for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7183 - Add bitwise AND (`&`) operator for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7415 +- Add bitwise NOT (`~`) operator for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7418 - 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 - JSX: do not error on ref as prop anymore (which is allowed in React 19). https://github.com/rescript-lang/rescript/pull/7420 diff --git a/compiler/core/j.ml b/compiler/core/j.ml index f7d67e47e4..7465226ab9 100644 --- a/compiler/core/j.ml +++ b/compiler/core/j.ml @@ -88,6 +88,7 @@ and expression_desc = | Typeof of expression | In of expression * expression (* prop in obj *) | Js_not of expression (* !v *) + | Js_bnot of expression (* ~v *) (* TODO: Add some primitives so that [js inliner] can do a better job *) | Seq of expression * expression | Cond of expression * expression * expression diff --git a/compiler/core/js_analyzer.ml b/compiler/core/js_analyzer.ml index 7d666cd486..d728ae4f9c 100644 --- a/compiler/core/js_analyzer.ml +++ b/compiler/core/js_analyzer.ml @@ -110,7 +110,7 @@ let rec no_side_effect_expression_desc (x : J.expression_desc) = no_side_effect call_expr && Ext_list.for_all strings no_side_effect && Ext_list.for_all values no_side_effect - | Js_not e -> no_side_effect e + | Js_not e | Js_bnot e -> no_side_effect e | In (prop, obj) -> no_side_effect prop && no_side_effect obj | Cond (a, b, c) -> no_side_effect a && no_side_effect b && no_side_effect c | Call ({expression_desc = Str {txt = "Array.isArray"}}, [e], _) -> @@ -228,8 +228,8 @@ let rec eq_expression ({expression_desc = x0} : J.expression) eq_expression_list ls0 ls1 && flag0 = flag1 && eq_expression tag0 tag1 | _ -> false) | Length _ | Is_null_or_undefined _ | String_append _ | Typeof _ | Js_not _ - | In _ | Cond _ | FlatCall _ | New _ | Fun _ | Raw_js_code _ | Array _ - | Caml_block_tag _ | Object _ | Tagged_template _ | Await _ -> + | Js_bnot _ | In _ | Cond _ | FlatCall _ | New _ | Fun _ | Raw_js_code _ + | Array _ | Caml_block_tag _ | Object _ | Tagged_template _ | Await _ -> false | Spread _ -> false diff --git a/compiler/core/js_dump.ml b/compiler/core/js_dump.ml index bc174e7dd5..d3f725e6c2 100644 --- a/compiler/core/js_dump.ml +++ b/compiler/core/js_dump.ml @@ -166,8 +166,8 @@ let rec exp_need_paren ?(arrow = false) (e : J.expression) = | Length _ | Call _ | Caml_block_tag _ | Seq _ | Static_index _ | Cond _ | Bin _ | Is_null_or_undefined _ | String_index _ | Array_index _ | String_append _ | Var _ | Undefined _ | Null | Str _ | Array _ - | Caml_block _ | FlatCall _ | Typeof _ | Number _ | Js_not _ | In _ | Bool _ - | New _ -> + | Caml_block _ | FlatCall _ | Typeof _ | Number _ | Js_not _ | Js_bnot _ + | In _ | Bool _ | New _ -> false | Await _ -> false | Spread _ -> false @@ -677,6 +677,10 @@ and expression_desc cxt ~(level : int) f x : cxt = P.cond_paren_group f (level > 13) (fun _ -> P.string f "!"; expression ~level:13 cxt f e) + | Js_bnot e -> + P.cond_paren_group f (level > 13) (fun _ -> + P.string f "~"; + expression ~level:13 cxt f e) | In (prop, obj) -> P.cond_paren_group f (level > 12) (fun _ -> let cxt = expression ~level:0 cxt f prop in diff --git a/compiler/core/js_exp_make.ml b/compiler/core/js_exp_make.ml index e2e63885cf..4cf7f854e5 100644 --- a/compiler/core/js_exp_make.ml +++ b/compiler/core/js_exp_make.ml @@ -1616,6 +1616,11 @@ let int32_mul ?comment (e1 : J.expression) (e2 : J.expression) : J.expression = let unchecked_int32_mul ?comment e1 e2 : J.expression = {comment; expression_desc = Bin (Mul, e1, e2)} +let int_bnot ?comment (e : t) : J.expression = + match e.expression_desc with + | Number (Int {i}) -> int ?comment (Int32.lognot i) + | _ -> {comment; expression_desc = Js_bnot e} + let int32_pow ?comment (e1 : t) (e2 : t) : J.expression = match (e1.expression_desc, e2.expression_desc) with | Number (Int {i = i1}), Number (Int {i = i2}) -> diff --git a/compiler/core/js_exp_make.mli b/compiler/core/js_exp_make.mli index 6fa1296273..cd2e5e90c4 100644 --- a/compiler/core/js_exp_make.mli +++ b/compiler/core/js_exp_make.mli @@ -210,6 +210,8 @@ val float_equal : ?comment:string -> t -> t -> t val int_equal : ?comment:string -> t -> t -> t +val int_bnot : ?comment:string -> t -> t + val string_equal : ?comment:string -> t -> t -> t val eq_null_undefined_boolean : ?comment:string -> t -> t -> t diff --git a/compiler/core/js_fold.ml b/compiler/core/js_fold.ml index 71109c9966..1ffa5e0270 100644 --- a/compiler/core/js_fold.ml +++ b/compiler/core/js_fold.ml @@ -103,6 +103,9 @@ class fold = | Js_not _x0 -> let _self = _self#expression _x0 in _self + | Js_bnot _x0 -> + let _self = _self#expression _x0 in + _self | In (_x0, _x1) -> let _self = _self#expression _x0 in let _self = _self#expression _x1 in diff --git a/compiler/core/js_op.ml b/compiler/core/js_op.ml index 9bbe3b50a2..769af321af 100644 --- a/compiler/core/js_op.ml +++ b/compiler/core/js_op.ml @@ -38,6 +38,7 @@ type binop = | Le | Gt | Ge + | Bnot | Bor | Bxor | Band diff --git a/compiler/core/js_op_util.ml b/compiler/core/js_op_util.ml index 373657adfb..8d2d863639 100644 --- a/compiler/core/js_op_util.ml +++ b/compiler/core/js_op_util.ml @@ -39,7 +39,7 @@ let op_prec (op : Js_op.binop) = | Bxor -> (6, 6, 6) | Band -> (7, 7, 7) | Lsl | Lsr | Asr -> (10, 10, 11) - | Plus | Minus -> (11, 11, 12) + | Bnot | Plus | Minus -> (11, 11, 12) | Mul | Div | Mod -> (12, 12, 13) | Pow -> (13, 14, 12) @@ -55,6 +55,7 @@ let op_int_prec (op : Js_op.int_op) = let op_str (op : Js_op.binop) = match op with + | Bnot -> "~" | Bor -> "|" | Bxor -> "^" | Band -> "&" diff --git a/compiler/core/js_record_fold.ml b/compiler/core/js_record_fold.ml index 1756daaee6..fe71e6f5f1 100644 --- a/compiler/core/js_record_fold.ml +++ b/compiler/core/js_record_fold.ml @@ -109,6 +109,9 @@ let expression_desc : 'a. ('a, expression_desc) fn = | Js_not _x0 -> let st = _self.expression _self st _x0 in st + | Js_bnot _x0 -> + let st = _self.expression _self st _x0 in + st | In (_x0, _x1) -> let st = _self.expression _self st _x0 in let st = _self.expression _self st _x1 in diff --git a/compiler/core/js_record_iter.ml b/compiler/core/js_record_iter.ml index c43f41ff1b..e6c9ab9646 100644 --- a/compiler/core/js_record_iter.ml +++ b/compiler/core/js_record_iter.ml @@ -91,6 +91,7 @@ let expression_desc : expression_desc fn = | Bool _ -> () | Typeof _x0 -> _self.expression _self _x0 | Js_not _x0 -> _self.expression _self _x0 + | Js_bnot _x0 -> _self.expression _self _x0 | In (_x0, _x1) -> _self.expression _self _x0; _self.expression _self _x1 diff --git a/compiler/core/js_record_map.ml b/compiler/core/js_record_map.ml index 8c63435eaa..b13fdb2a55 100644 --- a/compiler/core/js_record_map.ml +++ b/compiler/core/js_record_map.ml @@ -109,6 +109,9 @@ let expression_desc : expression_desc fn = | Js_not _x0 -> let _x0 = _self.expression _self _x0 in Js_not _x0 + | Js_bnot _x0 -> + let _x0 = _self.expression _self _x0 in + Js_bnot _x0 | In (_x0, _x1) -> let _x0 = _self.expression _self _x0 in let _x1 = _self.expression _self _x1 in diff --git a/compiler/core/lam_analysis.ml b/compiler/core/lam_analysis.ml index 793d83b4ad..9ad08cee97 100644 --- a/compiler/core/lam_analysis.ml +++ b/compiler/core/lam_analysis.ml @@ -59,16 +59,16 @@ let rec no_side_effects (lam : Lam.t) : bool = (* bool primitives *) | Psequand | Psequor | Pnot | Pboolcomp _ | Pboolorder | Pboolmin | Pboolmax (* int primitives *) - | Pnegint | Paddint | Psubint | Pmulint | Ppowint | Pandint | Porint - | Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ | Pintorder | Pintmin - | Pintmax + | Pnegint | Paddint | Psubint | Pmulint | Ppowint | Pnotint | Pandint + | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintcomp _ | Pintorder + | Pintmin | Pintmax (* float primitives *) | Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat | Ppowfloat | Pdivfloat | Pmodfloat | Pfloatcomp _ | Pjscomp _ | Pfloatorder | Pfloatmin | Pfloatmax (* bigint primitives *) | Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Ppowbigint - | Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint + | Pnotbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint | Pbigintcomp _ | Pbigintorder | Pbigintmin | Pbigintmax (* string primitives *) | Pstringlength | Pstringrefu | Pstringrefs | Pstringcomp _ | Pstringorder diff --git a/compiler/core/lam_compile_primitive.ml b/compiler/core/lam_compile_primitive.ml index aac979d926..e8a3956057 100644 --- a/compiler/core/lam_compile_primitive.ml +++ b/compiler/core/lam_compile_primitive.ml @@ -283,6 +283,14 @@ let translate output_prefix loc (cxt : Lam_compile_context.t) match args with | [e1; e2] -> E.bigint_op Asr e1 e2 | _ -> assert false) + | Pnotint -> ( + match args with + | [e] -> E.int_bnot e + | _ -> assert false) + | Pnotbigint -> ( + match args with + | [e] -> E.int_bnot e + | _ -> assert false) | Pandint -> ( match args with | [e1; e2] -> E.int32_band e1 e2 diff --git a/compiler/core/lam_convert.ml b/compiler/core/lam_convert.ml index 3f252011ef..a4dc75a6e4 100644 --- a/compiler/core/lam_convert.ml +++ b/compiler/core/lam_convert.ml @@ -253,6 +253,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t = | Pandint -> prim ~primitive:Pandint ~args loc | Porint -> prim ~primitive:Porint ~args loc | Pxorint -> prim ~primitive:Pxorint ~args loc + | Pnotint -> prim ~primitive:Pnotint ~args loc | Plslint -> prim ~primitive:Plslint ~args loc | Plsrint -> prim ~primitive:Plsrint ~args loc | Pasrint -> prim ~primitive:Pasrint ~args loc @@ -296,6 +297,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t = | Pandbigint -> prim ~primitive:Pandbigint ~args loc | Porbigint -> prim ~primitive:Porbigint ~args loc | Pxorbigint -> prim ~primitive:Pxorbigint ~args loc + | Pnotbigint -> prim ~primitive:Pnotbigint ~args loc | Plslbigint -> prim ~primitive:Plslbigint ~args loc | Pasrbigint -> prim ~primitive:Pasrbigint ~args loc | Pbigintcomp x -> prim ~primitive:(Pbigintcomp x) ~args loc diff --git a/compiler/core/lam_primitive.ml b/compiler/core/lam_primitive.ml index e28c652cd9..17b1b923dd 100644 --- a/compiler/core/lam_primitive.ml +++ b/compiler/core/lam_primitive.ml @@ -77,6 +77,7 @@ type t = | Pandint | Porint | Pxorint + | Pnotint | Plslint | Plsrint | Pasrint @@ -111,6 +112,7 @@ type t = | Pandbigint | Porbigint | Pxorbigint + | Pnotbigint | Plslbigint | Pasrbigint | Pbigintcomp of Lam_compat.comparison @@ -201,15 +203,15 @@ let eq_primitive_approx (lhs : t) (rhs : t) = | Psequand | Psequor | Pnot | Pboolcomp _ | Pboolorder | Pboolmin | Pboolmax (* int primitives *) | Pisint | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint | Ppowint - | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintorder - | Pintmin | Pintmax + | Pnotint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint + | Pintorder | Pintmin | Pintmax (* float primitives *) | Pintoffloat | Pfloatofint | Pnegfloat | Paddfloat | Psubfloat | Pmulfloat | Pdivfloat | Pmodfloat | Ppowfloat | Pfloatorder | Pfloatmin | Pfloatmax (* bigint primitives *) | Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Pdivbigint | Pmodbigint - | Ppowbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint - | Pbigintorder | Pbigintmin | Pbigintmax + | Ppowbigint | Pnotbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint + | Pasrbigint | Pbigintorder | Pbigintmin | Pbigintmax (* string primitives *) | Pstringlength | Pstringrefu | Pstringrefs | Pstringadd | Pstringcomp _ | Pstringorder | Pstringmin | Pstringmax diff --git a/compiler/core/lam_primitive.mli b/compiler/core/lam_primitive.mli index 460ef392c4..e14261e3b9 100644 --- a/compiler/core/lam_primitive.mli +++ b/compiler/core/lam_primitive.mli @@ -72,6 +72,7 @@ type t = | Pandint | Porint | Pxorint + | Pnotint | Plslint | Plsrint | Pasrint @@ -106,6 +107,7 @@ type t = | Pandbigint | Porbigint | Pxorbigint + | Pnotbigint | Plslbigint | Pasrbigint | Pbigintcomp of Lam_compat.comparison diff --git a/compiler/core/lam_print.ml b/compiler/core/lam_print.ml index d82956cc93..afc50d10d6 100644 --- a/compiler/core/lam_print.ml +++ b/compiler/core/lam_print.ml @@ -108,7 +108,7 @@ let primitive ppf (prim : Lam_primitive.t) = | Pboolorder -> fprintf ppf "compare" | Pboolmin -> fprintf ppf "min" | Pboolmax -> fprintf ppf "max" - | Pnegint -> fprintf ppf "~" + | Pnegint -> fprintf ppf "~-" | Paddint -> fprintf ppf "+" | Pstringadd -> fprintf ppf "+*" | Psubint -> fprintf ppf "-" @@ -119,6 +119,7 @@ let primitive ppf (prim : Lam_primitive.t) = | Pandint -> fprintf ppf "and" | Porint -> fprintf ppf "or" | Pxorint -> fprintf ppf "xor" + | Pnotint -> fprintf ppf "~~" | Plslint -> fprintf ppf "lsl" | Plsrint -> fprintf ppf "lsr" | Pasrint -> fprintf ppf "asr" @@ -151,7 +152,7 @@ let primitive ppf (prim : Lam_primitive.t) = | Pfloatorder -> fprintf ppf "compare" | Pfloatmin -> fprintf ppf "min" | Pfloatmax -> fprintf ppf "max" - | Pnegbigint -> fprintf ppf "~" + | Pnegbigint -> fprintf ppf "~-" | Paddbigint -> fprintf ppf "+" | Psubbigint -> fprintf ppf "-" | Pmulbigint -> fprintf ppf "*" @@ -161,6 +162,7 @@ let primitive ppf (prim : Lam_primitive.t) = | Pandbigint -> fprintf ppf "and" | Porbigint -> fprintf ppf "or" | Pxorbigint -> fprintf ppf "xor" + | Pnotbigint -> fprintf ppf "~~" | Plslbigint -> fprintf ppf "lsl" | Pasrbigint -> fprintf ppf "asr" | Pbigintcomp Ceq -> fprintf ppf "==" diff --git a/compiler/ml/lambda.ml b/compiler/ml/lambda.ml index 26aa8a8c74..bf37659ded 100644 --- a/compiler/ml/lambda.ml +++ b/compiler/ml/lambda.ml @@ -210,6 +210,7 @@ type primitive = | Pandint | Porint | Pxorint + | Pnotint | Plslint | Plsrint | Pasrint @@ -245,6 +246,7 @@ type primitive = | Pandbigint | Porbigint | Pxorbigint + | Pnotbigint | Plslbigint | Pasrbigint | Pbigintcomp of comparison diff --git a/compiler/ml/lambda.mli b/compiler/ml/lambda.mli index 9e1c9b9d7c..782c8df0b3 100644 --- a/compiler/ml/lambda.mli +++ b/compiler/ml/lambda.mli @@ -177,6 +177,7 @@ type primitive = | Pandint | Porint | Pxorint + | Pnotint | Plslint | Plsrint | Pasrint @@ -212,6 +213,7 @@ type primitive = | Pandbigint | Porbigint | Pxorbigint + | Pnotbigint | Plslbigint | Pasrbigint | Pbigintcomp of comparison diff --git a/compiler/ml/pprintast.ml b/compiler/ml/pprintast.ml index 9a1c823cd8..ebbe4ea359 100644 --- a/compiler/ml/pprintast.ml +++ b/compiler/ml/pprintast.ml @@ -652,7 +652,7 @@ and expression ctxt f x = | `Prefix s -> ( let s = if - List.mem s ["~+"; "~-"; "~+."; "~-."] + List.mem s ["~+"; "~-"; "~+."; "~-."; "~~"] && match l with (* See #7200: avoid turning (~- 1) into (- 1) which is diff --git a/compiler/ml/printlambda.ml b/compiler/ml/printlambda.ml index f0ad4698bb..27f8873df1 100644 --- a/compiler/ml/printlambda.ml +++ b/compiler/ml/printlambda.ml @@ -142,7 +142,7 @@ let primitive ppf = function | Pboolorder -> fprintf ppf "compare" | Pboolmin -> fprintf ppf "min" | Pboolmax -> fprintf ppf "max" - | Pnegint -> fprintf ppf "~" + | Pnegint -> fprintf ppf "~-" | Paddint -> fprintf ppf "+" | Psubint -> fprintf ppf "-" | Pmulint -> fprintf ppf "*" @@ -152,6 +152,7 @@ let primitive ppf = function | Pandint -> fprintf ppf "and" | Porint -> fprintf ppf "or" | Pxorint -> fprintf ppf "xor" + | Pnotint -> fprintf ppf "~~" | Plslint -> fprintf ppf "lsl" | Plsrint -> fprintf ppf "lsr" | Pasrint -> fprintf ppf "asr" @@ -168,7 +169,7 @@ let primitive ppf = function | Poffsetref n -> fprintf ppf "+:=%i" n | Pintoffloat -> fprintf ppf "int_of_float" | Pfloatofint -> fprintf ppf "float_of_int" - | Pnegfloat -> fprintf ppf "~." + | Pnegfloat -> fprintf ppf "~-." | Pabsfloat -> fprintf ppf "abs." | Paddfloat -> fprintf ppf "+." | Psubfloat -> fprintf ppf "-." @@ -185,7 +186,7 @@ let primitive ppf = function | Pfloatorder -> fprintf ppf "compare" | Pfloatmin -> fprintf ppf "min" | Pfloatmax -> fprintf ppf "max" - | Pnegbigint -> fprintf ppf "~" + | Pnegbigint -> fprintf ppf "~-" | Paddbigint -> fprintf ppf "+" | Psubbigint -> fprintf ppf "-" | Pmulbigint -> fprintf ppf "*" @@ -193,6 +194,7 @@ let primitive ppf = function | Pandbigint -> fprintf ppf "and" | Porbigint -> fprintf ppf "or" | Pxorbigint -> fprintf ppf "xor" + | Pnotbigint -> fprintf ppf "~~" | Plslbigint -> fprintf ppf "lsl" | Pasrbigint -> fprintf ppf "asr" | Pdivbigint -> fprintf ppf "/" diff --git a/compiler/ml/translcore.ml b/compiler/ml/translcore.ml index 4cdeb34aa5..62abf3640f 100644 --- a/compiler/ml/translcore.ml +++ b/compiler/ml/translcore.ml @@ -276,6 +276,7 @@ let primitives_table = ("%mulint", Pmulint); ("%divint", Pdivint); ("%modint", Pmodint); + ("%bitnot_int", Pnotint); ("%andint", Pandint); ("%orint", Porint); ("%xorint", Pxorint); @@ -322,6 +323,7 @@ let primitives_table = ("%lebigint", Pbigintcomp Cle); ("%gtbigint", Pbigintcomp Cgt); ("%gebigint", Pbigintcomp Cge); + ("%bitnot_bigint", Pnotbigint); ("%andbigint", Pandbigint); ("%orbigint", Porbigint); ("%xorbigint", Pxorbigint); diff --git a/compiler/ml/unified_ops.ml b/compiler/ml/unified_ops.ml index 2b0bd4e59c..0eacbb5a65 100644 --- a/compiler/ml/unified_ops.ml +++ b/compiler/ml/unified_ops.ml @@ -207,6 +207,19 @@ let entries = string = None; }; }; + { + path = builtin "~~"; + name = "%bitnot"; + form = Unary; + specialization = + { + int = Pnotint; + bool = None; + float = None; + bigint = Some Pnotbigint; + string = None; + }; + }; { path = builtin "&"; name = "%bitand"; diff --git a/compiler/syntax/src/res_comments_table.ml b/compiler/syntax/src/res_comments_table.ml index 99308f2341..7b84296c6d 100644 --- a/compiler/syntax/src/res_comments_table.ml +++ b/compiler/syntax/src/res_comments_table.ml @@ -1462,7 +1462,8 @@ and walk_expression expr t comments = Pexp_ident { txt = - Longident.Lident ("~+" | "~+." | "~-" | "~-." | "not" | "!"); + Longident.Lident + ("~+" | "~+." | "~-" | "~-." | "~~" | "not" | "!"); }; }; args = [(Nolabel, arg_expr)]; diff --git a/compiler/syntax/src/res_core.ml b/compiler/syntax/src/res_core.ml index c9c36496c6..dd7376f2f2 100644 --- a/compiler/syntax/src/res_core.ml +++ b/compiler/syntax/src/res_core.ml @@ -268,7 +268,7 @@ let rec go_to_closing closing_token state = (* Madness *) let is_es6_arrow_expression ~in_ternary p = Parser.lookahead p (fun state -> - let async = + let _async = match state.Parser.token with | Lident "async" -> Parser.next state; @@ -315,7 +315,6 @@ let is_es6_arrow_expression ~in_ternary p = | EqualGreater -> true | _ -> false) | Dot (* uncurried *) -> true - | Tilde when not async -> true | Backtick -> false (* (` always indicates the start of an expr, can't be es6 parameter *) @@ -427,7 +426,7 @@ let make_unary_expr start_pos token_end token operand = } | (Minus | MinusDot), Pexp_constant (Pconst_float (n, m)) -> {operand with pexp_desc = Pexp_constant (Pconst_float (negate_string n, m))} - | (Token.Plus | PlusDot | Minus | MinusDot), _ -> + | (Token.Plus | PlusDot | Minus | MinusDot | Tilde), _ -> let token_loc = mk_loc start_pos token_end in let operator = "~" ^ Token.to_string token in Ast_helper.Exp.apply @@ -2078,7 +2077,7 @@ and parse_primary_expr ~operand ?(no_call = false) p = and parse_unary_expr p = let start_pos = p.Parser.start_pos in match p.Parser.token with - | (Minus | MinusDot | Plus | PlusDot | Bang) as token -> + | (Minus | MinusDot | Plus | PlusDot | Bang | Tilde) as token -> Parser.leave_breadcrumb p Grammar.ExprUnary; let token_end = p.end_pos in Parser.next p; diff --git a/compiler/syntax/src/res_grammar.ml b/compiler/syntax/src/res_grammar.ml index 63dc9d6c33..cfd7525a90 100644 --- a/compiler/syntax/src/res_grammar.ml +++ b/compiler/syntax/src/res_grammar.ml @@ -151,8 +151,8 @@ let is_atomic_typ_expr_start = function let is_expr_start = function | Token.Assert | At | Await | Backtick | Bang | Codepoint _ | False | Float _ | For | Hash | If | Int _ | Lbrace | Lbracket | LessThan | Lident _ | List - | Lparen | Minus | MinusDot | Module | Percent | Plus | PlusDot | String _ - | Switch | True | Try | Uident _ | Underscore (* _ => doThings() *) + | Lparen | Minus | MinusDot | Module | Percent | Plus | PlusDot | Tilde + | String _ | Switch | True | Try | Uident _ | Underscore (* _ => doThings() *) | While | Forwardslash | ForwardslashDot | Dict -> true | _ -> false diff --git a/compiler/syntax/src/res_parens.ml b/compiler/syntax/src/res_parens.ml index 94f39b0b4e..bdad87851e 100644 --- a/compiler/syntax/src/res_parens.ml +++ b/compiler/syntax/src/res_parens.ml @@ -129,6 +129,7 @@ let binary_expr_operand ~is_lhs expr = | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized | expr when ParsetreeViewer.is_binary_expression expr -> Parenthesized | expr when ParsetreeViewer.is_ternary_expr expr -> Parenthesized + | expr when ParsetreeViewer.is_unary_bitnot_expression expr -> Parenthesized | {pexp_desc = Pexp_lazy _ | Pexp_assert _} when is_lhs -> Parenthesized | _ when ParsetreeViewer.expr_is_await expr -> Parenthesized | {Parsetree.pexp_attributes = attrs} -> diff --git a/compiler/syntax/src/res_parsetree_viewer.ml b/compiler/syntax/src/res_parsetree_viewer.ml index 451e879862..b5591fb9e4 100644 --- a/compiler/syntax/src/res_parsetree_viewer.ml +++ b/compiler/syntax/src/res_parsetree_viewer.ml @@ -284,7 +284,7 @@ let operator_precedence operator = let is_unary_operator operator = match operator with - | "~+" | "~+." | "~-" | "~-." | "not" -> true + | "~+" | "~+." | "~-" | "~-." | "~~" | "not" -> true | _ -> false let is_unary_expression expr = @@ -298,6 +298,16 @@ let is_unary_expression expr = true | _ -> false +let is_unary_bitnot_expression expr = + match expr.pexp_desc with + | Pexp_apply + { + funct = {pexp_desc = Pexp_ident {txt = Longident.Lident "~~"}}; + args = [(Nolabel, _arg)]; + } -> + true + | _ -> false + let is_binary_operator operator = match operator with | ":=" | "||" | "&&" | "==" | "===" | "<" | ">" | "!=" | "!==" | "<=" | ">=" diff --git a/compiler/syntax/src/res_parsetree_viewer.mli b/compiler/syntax/src/res_parsetree_viewer.mli index c237a89e6f..242fc722a4 100644 --- a/compiler/syntax/src/res_parsetree_viewer.mli +++ b/compiler/syntax/src/res_parsetree_viewer.mli @@ -68,6 +68,7 @@ val operator_precedence : string -> int val not_ghost_operator : string -> Location.t -> bool val is_unary_expression : Parsetree.expression -> bool +val is_unary_bitnot_expression : Parsetree.expression -> bool val is_binary_operator : string -> bool val is_binary_expression : Parsetree.expression -> bool val is_rhs_binary_operator : string -> bool diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index 5b2a176068..8d23dabcf8 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -3705,6 +3705,7 @@ and print_unary_expression ~state expr cmt_tbl = | "~+." -> "+." | "~-" -> "-" | "~-." -> "-." + | "~~" -> "~" | "not" -> "!" | _ -> assert false) in @@ -5046,6 +5047,8 @@ and print_argument ~state (arg_lbl, arg) cmt_tbl = match Parens.expr expr with | Parenthesized -> add_parens doc | Braced braces -> print_braces doc expr braces + | Nothing when ParsetreeViewer.is_unary_bitnot_expression expr -> + add_parens doc | Nothing -> doc in let loc = {arg_loc with loc_end = expr.pexp_loc.loc_end} in diff --git a/compiler/syntax/src/res_token.ml b/compiler/syntax/src/res_token.ml index 9aa63a1716..4a4c1e0fd7 100644 --- a/compiler/syntax/src/res_token.ml +++ b/compiler/syntax/src/res_token.ml @@ -175,7 +175,7 @@ let to_string = function | AsteriskDot -> "*." | Exponentiation -> "**" | Assert -> "assert" - | Tilde -> "tilde" + | Tilde -> "~" | Question -> "?" | If -> "if" | Else -> "else" diff --git a/lib/es6/Pervasives.js b/lib/es6/Pervasives.js index 98f20a6e15..0bd2f188d2 100644 --- a/lib/es6/Pervasives.js +++ b/lib/es6/Pervasives.js @@ -28,10 +28,6 @@ function abs(x) { } } -function lnot(x) { - return x ^ -1; -} - let min_int = -2147483648; function classify_float(x) { @@ -132,7 +128,6 @@ export { invalid_arg, Exit, abs, - lnot, max_int, min_int, infinity, diff --git a/lib/es6/Stdlib_BigInt.js b/lib/es6/Stdlib_BigInt.js index 6a45c334ef..326071c643 100644 --- a/lib/es6/Stdlib_BigInt.js +++ b/lib/es6/Stdlib_BigInt.js @@ -13,13 +13,8 @@ function toInt(t) { return Number(t) | 0; } -function bitwiseNot(x) { - return x ^ -1n; -} - export { fromFloat, toInt, - bitwiseNot, } /* No side effect */ diff --git a/lib/es6/Stdlib_Int.js b/lib/es6/Stdlib_Int.js index 1f2f624f21..4993a6297c 100644 --- a/lib/es6/Stdlib_Int.js +++ b/lib/es6/Stdlib_Int.js @@ -62,10 +62,6 @@ function clamp(min, max, value) { } } -function bitwiseNot(x) { - return x ^ -1; -} - let Ref = {}; let Constants = { @@ -79,7 +75,6 @@ export { range, rangeWithOptions, clamp, - bitwiseNot, Ref, } /* No side effect */ diff --git a/lib/js/Pervasives.js b/lib/js/Pervasives.js index 92db18e121..6c2d4d092f 100644 --- a/lib/js/Pervasives.js +++ b/lib/js/Pervasives.js @@ -28,10 +28,6 @@ function abs(x) { } } -function lnot(x) { - return x ^ -1; -} - let min_int = -2147483648; function classify_float(x) { @@ -131,7 +127,6 @@ exports.failwith = failwith; exports.invalid_arg = invalid_arg; exports.Exit = Exit; exports.abs = abs; -exports.lnot = lnot; exports.max_int = max_int; exports.min_int = min_int; exports.infinity = infinity; diff --git a/lib/js/Stdlib_BigInt.js b/lib/js/Stdlib_BigInt.js index 88012bc1b6..7965b80715 100644 --- a/lib/js/Stdlib_BigInt.js +++ b/lib/js/Stdlib_BigInt.js @@ -13,11 +13,6 @@ function toInt(t) { return Number(t) | 0; } -function bitwiseNot(x) { - return x ^ -1n; -} - exports.fromFloat = fromFloat; exports.toInt = toInt; -exports.bitwiseNot = bitwiseNot; /* No side effect */ diff --git a/lib/js/Stdlib_Int.js b/lib/js/Stdlib_Int.js index 6e2858f4b2..5e6dbb7ced 100644 --- a/lib/js/Stdlib_Int.js +++ b/lib/js/Stdlib_Int.js @@ -62,10 +62,6 @@ function clamp(min, max, value) { } } -function bitwiseNot(x) { - return x ^ -1; -} - let Ref = {}; let Constants = { @@ -78,6 +74,5 @@ exports.fromString = fromString; exports.range = range; exports.rangeWithOptions = rangeWithOptions; exports.clamp = clamp; -exports.bitwiseNot = bitwiseNot; exports.Ref = Ref; /* No side effect */ diff --git a/runtime/Pervasives.res b/runtime/Pervasives.res index bdeb7d8f23..30d8e24ae8 100644 --- a/runtime/Pervasives.res +++ b/runtime/Pervasives.res @@ -68,6 +68,7 @@ external \"%": ('a, 'a) => 'a = "%mod" external \"<<": ('a, 'a) => 'a = "%lsl" external mod: ('a, 'a) => 'a = "%mod" external \"**": ('a, 'a) => 'a = "%pow" +external \"~~": 'a => 'a = "%bitnot" external \"&": ('a, 'a) => 'a = "%bitand" external \"^": ('a, 'a) => 'a = "%bitxor" external \">>": ('a, 'a) => 'a = "%asr" @@ -122,7 +123,7 @@ external lor: (int, int) => int = "%orint" external lxor: (int, int) => int = "%xorint" @deprecated("Use `Int.bitwiseNot` instead. This will be removed in v13") -let lnot = x => lxor(x, -1) +external lnot: int => int = "%bitnot_int" @deprecated("Use `Int.shiftLeft` instead. This will be removed in v13") external lsl: (int, int) => int = "%lslint" diff --git a/runtime/Stdlib_BigInt.res b/runtime/Stdlib_BigInt.res index 6ba756aa4e..f43e109313 100644 --- a/runtime/Stdlib_BigInt.res +++ b/runtime/Stdlib_BigInt.res @@ -94,8 +94,7 @@ external bitwiseAnd: (bigint, bigint) => bigint = "%andbigint" external bitwiseOr: (bigint, bigint) => bigint = "%orbigint" external bitwiseXor: (bigint, bigint) => bigint = "%xorbigint" -// TODO: make it a primitive -let bitwiseNot = x => bitwiseXor(x, -1n) +external bitwiseNot: bigint => bigint = "%bitnot_bigint" external shiftLeft: (bigint, bigint) => bigint = "%lslbigint" external shiftRight: (bigint, bigint) => bigint = "%asrbigint" diff --git a/runtime/Stdlib_Int.res b/runtime/Stdlib_Int.res index 01ee088058..3228ed4114 100644 --- a/runtime/Stdlib_Int.res +++ b/runtime/Stdlib_Int.res @@ -99,8 +99,7 @@ external bitwiseAnd: (int, int) => int = "%andint" external bitwiseOr: (int, int) => int = "%orint" external bitwiseXor: (int, int) => int = "%xorint" -// TODO: make it a primitive -let bitwiseNot = x => bitwiseXor(x, -1) +external bitwiseNot: int => int = "%bitnot_int" external shiftLeft: (int, int) => int = "%lslint" external shiftRight: (int, int) => int = "%asrint" diff --git a/runtime/Stdlib_Int.resi b/runtime/Stdlib_Int.resi index b9d7959e05..915a685f68 100644 --- a/runtime/Stdlib_Int.resi +++ b/runtime/Stdlib_Int.resi @@ -435,7 +435,7 @@ external bitwiseXor: (int, int) => int = "%xorint" Int.bitwiseNot(2) == -3 ``` */ -let bitwiseNot: int => int +external bitwiseNot: int => int = "%bitnot_int" /** `shiftLeft(n, length)` calculates the shifted value of an integer `n` by `length` bits to the left. diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/apply.res b/tests/syntax_tests/data/parsing/grammar/expressions/apply.res index a22f887fbe..41b0409fc7 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/apply.res +++ b/tests/syntax_tests/data/parsing/grammar/expressions/apply.res @@ -10,4 +10,9 @@ let unitUncurried = apply(.) call(~a: int) +// pass the result of bitwise NOT expression +call((~a)) +call(~a=a ^ ~a) +call(~a=~a) + call_partial(3, ...) diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/expected/apply.res.txt b/tests/syntax_tests/data/parsing/grammar/expressions/expected/apply.res.txt index 106a05e81e..984c017cd8 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/expected/apply.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/expressions/expected/apply.res.txt @@ -6,4 +6,7 @@ ;;List.reduce (fun [arity:2]acc -> fun curr -> acc + curr) 0 myList let unitUncurried = apply () ;;call ~a:(a : int) +;;call (~ a) +;;call ~a:(a ^ (~ a)) +;;call ~a:(~ a) ;;call_partial 3 ... \ No newline at end of file diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/expected/unary.res.txt b/tests/syntax_tests/data/parsing/grammar/expressions/expected/unary.res.txt index c919555529..debc6dd93e 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/expected/unary.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/expressions/expected/unary.res.txt @@ -1,8 +1,15 @@ let x = not true let m = (-1) let m = (-2.5) +let m = ~~ 2 let x = 5 let x = 5.4 let b = (-1n) let b = 1n -let sum = (- a) - (- b) \ No newline at end of file +let m = ~~ 2n +let sum = (- a) - (- b) +let bitop = (~ a) ^ (~ b) +let x = ~~ (-1n) +let x = - (~~ 1n) +let x = ~~ (-1n) +let x = - (~~ 1n) \ No newline at end of file diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/unary.res b/tests/syntax_tests/data/parsing/grammar/expressions/unary.res index b675fba28f..7eb5cf8366 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/unary.res +++ b/tests/syntax_tests/data/parsing/grammar/expressions/unary.res @@ -2,9 +2,18 @@ let x = !true let m = -1 let m = -.2.5 +let m = ~2 let x = +5 let x = +.5.4 let b = -1n let b = +1n +let m = ~2n let sum = -a - -b + +let bitop = ~a ^ ~b + +let x = ~-1n +let x = -~1n +let x = ~(-1n) +let x = -(~1n) diff --git a/tests/syntax_tests/data/printer/expr/apply.res b/tests/syntax_tests/data/printer/expr/apply.res index 3c9d1aed48..aaf6f70790 100644 --- a/tests/syntax_tests/data/printer/expr/apply.res +++ b/tests/syntax_tests/data/printer/expr/apply.res @@ -5,6 +5,8 @@ let rbt = make(~compare?) let rbt = make(~compare=intCompare) let rbt = make(~compare=?intCompare) let rbt = make(~compare=?intCompare: (int, int) => int) +let rbt = make((~compare)) +let rbt = make((~-compare) ^ ~x) let () = applyFunctionToArguments( superLongIdentifierWooooooowThisIsSuchLong, diff --git a/tests/syntax_tests/data/printer/expr/expected/apply.res.txt b/tests/syntax_tests/data/printer/expr/expected/apply.res.txt index abe9fa030c..dff09412d9 100644 --- a/tests/syntax_tests/data/printer/expr/expected/apply.res.txt +++ b/tests/syntax_tests/data/printer/expr/expected/apply.res.txt @@ -5,6 +5,8 @@ let rbt = make(~compare?) let rbt = make(~compare=intCompare) let rbt = make(~compare=?intCompare) let rbt = make(~compare=?(intCompare: (int, int) => int)) +let rbt = make((~compare)) +let rbt = make((~(-compare)) ^ (~x)) let () = applyFunctionToArguments( superLongIdentifierWooooooowThisIsSuchLong, diff --git a/tests/syntax_tests/data/printer/expr/expected/unary.res.txt b/tests/syntax_tests/data/printer/expr/expected/unary.res.txt index d1b390b6a2..e749a963c1 100644 --- a/tests/syntax_tests/data/printer/expr/expected/unary.res.txt +++ b/tests/syntax_tests/data/printer/expr/expected/unary.res.txt @@ -1,6 +1,12 @@ let x = -a let x = -.a let x = !a +let x = ~a + +let x = ~(-a) +let x = -(~a) +let x = ~(-a) +let x = -(~a) let isMale = !user["female"] diff --git a/tests/syntax_tests/data/printer/expr/unary.res b/tests/syntax_tests/data/printer/expr/unary.res index bfbc90f9f0..e58874dd37 100644 --- a/tests/syntax_tests/data/printer/expr/unary.res +++ b/tests/syntax_tests/data/printer/expr/unary.res @@ -1,6 +1,12 @@ let x = -a let x = -.a let x = !a +let x = ~a + +let x = ~-a +let x = -~a +let x = ~(-a) +let x = -(~a) let isMale = !user["female"] diff --git a/tests/tests/src/belt_int_test.mjs b/tests/tests/src/belt_int_test.mjs index fe660cd9a1..bf3dff34ae 100644 --- a/tests/tests/src/belt_int_test.mjs +++ b/tests/tests/src/belt_int_test.mjs @@ -37,9 +37,11 @@ Mocha.describe("Belt_int_test", () => { Test_utils.eq("File \"belt_int_test.res\", line 42, characters 7-14", 0, 0); Test_utils.eq("File \"belt_int_test.res\", line 43, characters 7-14", 0, 0); Test_utils.eq("File \"belt_int_test.res\", line 44, characters 7-14", 1, 1); - Test_utils.eq("File \"belt_int_test.res\", line 45, characters 7-14", 16, 16); - Test_utils.eq("File \"belt_int_test.res\", line 46, characters 7-14", 2, 2); - Test_utils.eq("File \"belt_int_test.res\", line 47, characters 7-14", 2, 2); + Test_utils.eq("File \"belt_int_test.res\", line 45, characters 7-14", -1, -1); + Test_utils.eq("File \"belt_int_test.res\", line 46, characters 7-14", 1, 1); + Test_utils.eq("File \"belt_int_test.res\", line 47, characters 7-14", 16, 16); + Test_utils.eq("File \"belt_int_test.res\", line 48, characters 7-14", 2, 2); + Test_utils.eq("File \"belt_int_test.res\", line 49, characters 7-14", 2, 2); }); }); diff --git a/tests/tests/src/belt_int_test.res b/tests/tests/src/belt_int_test.res index 8a2ee86238..e25de142aa 100644 --- a/tests/tests/src/belt_int_test.res +++ b/tests/tests/src/belt_int_test.res @@ -41,6 +41,8 @@ describe(__MODULE__, () => { eq(__LOC__, 2 * 3, 6) eq(__LOC__, 2 / 3, 0) eq(__LOC__, 2 % 2, 0) + eq(__LOC__, (~-2), 1) + eq(__LOC__, 2 ^ (~2), -1) eq(__LOC__, 2 ^ 3, 1) eq(__LOC__, 2 << 3, 16) eq(__LOC__, 16 >> 3, 2) diff --git a/tests/tests/src/belt_sortarray_test.mjs b/tests/tests/src/belt_sortarray_test.mjs index 6c6ab7f7c4..e5760dbe62 100644 --- a/tests/tests/src/belt_sortarray_test.mjs +++ b/tests/tests/src/belt_sortarray_test.mjs @@ -3,7 +3,6 @@ import * as Mocha from "mocha"; import * as Belt_Array from "rescript/lib/es6/Belt_Array.js"; import * as Belt_Range from "rescript/lib/es6/Belt_Range.js"; -import * as Pervasives from "rescript/lib/es6/Pervasives.js"; import * as Test_utils from "./test_utils.mjs"; import * as Belt_SortArray from "rescript/lib/es6/Belt_SortArray.js"; import * as Array_data_util from "./array_data_util.mjs"; @@ -215,12 +214,12 @@ Mocha.describe("Belt_sortarray_test", () => { ]); }); Mocha.test("binarySearchBy", () => { - Test_utils.eq("File \"belt_sortarray_test.res\", line 108, characters 7-14", Pervasives.lnot(Belt_SortArray.binarySearchBy([ + Test_utils.eq("File \"belt_sortarray_test.res\", line 108, characters 7-14", ~Belt_SortArray.binarySearchBy([ 1, 3, 5, 7 - ], 4, cmp)), 2); + ], 4, cmp), 2); Test_utils.eq("File \"belt_sortarray_test.res\", line 109, characters 7-14", Belt_SortArray.binarySearchBy([ 1, 2, @@ -269,11 +268,11 @@ Mocha.describe("Belt_sortarray_test", () => { let aa = Array_data_util.range(0, 1000); Test_utils.ok("File \"belt_sortarray_test.res\", line 115, characters 7-14", Belt_Range.every(0, 1000, i => Belt_SortArray.binarySearchBy(aa, i, cmp) === i)); let cc = Belt_Array.map(Array_data_util.range(0, 2000), x => (x << 1)); - Test_utils.eq("File \"belt_sortarray_test.res\", line 118, characters 7-14", Pervasives.lnot(Belt_SortArray.binarySearchBy(cc, 5000, cmp)), 2001); - Test_utils.eq("File \"belt_sortarray_test.res\", line 119, characters 7-14", Pervasives.lnot(Belt_SortArray.binarySearchBy(cc, -1, cmp)), 0); + Test_utils.eq("File \"belt_sortarray_test.res\", line 118, characters 7-14", ~Belt_SortArray.binarySearchBy(cc, 5000, cmp), 2001); + Test_utils.eq("File \"belt_sortarray_test.res\", line 119, characters 7-14", ~Belt_SortArray.binarySearchBy(cc, -1, cmp), 0); Test_utils.eq("File \"belt_sortarray_test.res\", line 120, characters 7-14", Belt_SortArray.binarySearchBy(cc, 0, cmp), 0); - Test_utils.eq("File \"belt_sortarray_test.res\", line 122, characters 7-14", Pervasives.lnot(Belt_SortArray.binarySearchBy(cc, 1, cmp)), 1); - Test_utils.ok("File \"belt_sortarray_test.res\", line 124, characters 6-13", Belt_Range.every(0, 1999, i => Pervasives.lnot(Belt_SortArray.binarySearchBy(cc, (i << 1) + 1 | 0, cmp)) === (i + 1 | 0))); + Test_utils.eq("File \"belt_sortarray_test.res\", line 122, characters 7-14", ~Belt_SortArray.binarySearchBy(cc, 1, cmp), 1); + Test_utils.ok("File \"belt_sortarray_test.res\", line 124, characters 6-13", Belt_Range.every(0, 1999, i => ~Belt_SortArray.binarySearchBy(cc, (i << 1) + 1 | 0, cmp) === (i + 1 | 0))); }); Mocha.test("strictlySortedLength", () => { let lt = (x, y) => x < y; diff --git a/tests/tests/src/test_pervasive.mjs b/tests/tests/src/test_pervasive.mjs index 98fbe62c03..7d11ae6586 100644 --- a/tests/tests/src/test_pervasive.mjs +++ b/tests/tests/src/test_pervasive.mjs @@ -96,7 +96,6 @@ let Pervasives$1 = { invalid_arg: Pervasives.invalid_arg, Exit: Pervasives.Exit, abs: Pervasives.abs, - lnot: Pervasives.lnot, max_int: Pervasives.max_int, min_int: Pervasives.min_int, infinity: Pervasives.infinity, diff --git a/tests/tests/src/test_pervasives3.mjs b/tests/tests/src/test_pervasives3.mjs index b124938e7d..8bf1d03542 100644 --- a/tests/tests/src/test_pervasives3.mjs +++ b/tests/tests/src/test_pervasives3.mjs @@ -8,7 +8,6 @@ let Pervasives$1 = { invalid_arg: Pervasives.invalid_arg, Exit: Pervasives.Exit, abs: Pervasives.abs, - lnot: Pervasives.lnot, max_int: Pervasives.max_int, min_int: Pervasives.min_int, infinity: Pervasives.infinity, diff --git a/tests/tests/src/unified_ops_test.mjs b/tests/tests/src/unified_ops_test.mjs index d1479454a6..68d97b5ef9 100644 --- a/tests/tests/src/unified_ops_test.mjs +++ b/tests/tests/src/unified_ops_test.mjs @@ -67,6 +67,14 @@ let pow3 = 2n ** 2n; let pow_overflow = 0; +function bnot_int(a) { + return ~a; +} + +function bnot_bigint(a) { + return ~a; +} + function bxor_int(a, b) { return a ^ b; } @@ -117,6 +125,8 @@ export { pow2, pow3, pow_overflow, + bnot_int, + bnot_bigint, bxor_int, bxor_bigint, band_int, diff --git a/tests/tests/src/unified_ops_test.res b/tests/tests/src/unified_ops_test.res index 765919c9c0..938fd9b8b8 100644 --- a/tests/tests/src/unified_ops_test.res +++ b/tests/tests/src/unified_ops_test.res @@ -27,6 +27,9 @@ let pow3 = 2n ** 2n let pow_overflow = 2147483647 ** 2 +let bnot_int = a => ~a +let bnot_bigint = (a: bigint) => ~a + let bxor_int = (a, b) => a ^ b let bxor_bigint = (a: bigint, b) => a ^ b