Skip to content

Introducing the bigint #6670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 45 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1441f59
add primitive bigint
mununki Mar 8, 2024
db001fa
Js_bigint adding operations
mununki Mar 8, 2024
20410da
Js_json adding support of bigint
mununki Mar 8, 2024
2f6217b
rename test
mununki Mar 8, 2024
0b14c33
remove bigint from Js_json
mununki Mar 8, 2024
4f40575
stale comment
mununki Mar 8, 2024
6020820
remove unnecessary guard in pattern matching
mununki Mar 11, 2024
8d95ccd
fix literal_overlaps
mununki Mar 11, 2024
83070a0
primitive bigint instead of Js_bigint.t
mununki Mar 11, 2024
128aa20
variant coercion for bigint
mununki Mar 11, 2024
c1d39b2
add error test
mununki Mar 11, 2024
8835276
add optimization of comparisons
mununki Mar 12, 2024
51e2ab2
add bigint_test and binding bigint methods, NaN, etc
mununki Mar 13, 2024
84cf107
stale comment
mununki Mar 13, 2024
0f21844
add bigint pow operator
mununki Mar 13, 2024
6b01997
clean up Js_exp for bigint operations
mununki Mar 13, 2024
d386c4a
remove isNaN, isInfinite
mununki Mar 15, 2024
bc22261
remove NaN from BigInt
mununki Mar 15, 2024
3b34a01
fix compare function
mununki Mar 15, 2024
d3032e1
fix test
mununki Mar 15, 2024
d3090ff
add bitwise operations
mununki Mar 18, 2024
5683ca2
eta conversion for bigint
mununki Mar 18, 2024
da60074
optimization
mununki Mar 18, 2024
41ba70b
bitwise operators in Js_bigint
mununki Mar 18, 2024
3e9a471
add test for bitwise operations
mununki Mar 19, 2024
fee14cc
remove bigint operators from parser and pervasives
mununki Mar 21, 2024
fc1ea04
rebase clean up
mununki Mar 21, 2024
ec90078
update change log
mununki Mar 21, 2024
b8a5efd
fix incorrect compare bigint values
mununki Mar 21, 2024
79df62c
remove leftover
mununki Mar 21, 2024
dd6b0cf
removed leftover
mununki Mar 22, 2024
9852ad0
handling and testing bigint values with leading zeros and minus
mununki Mar 22, 2024
00d741a
remove optimization const_compare from parmatch and add test
mununki Mar 22, 2024
379dc31
add tests for pattern matching bigint liternal
mununki Mar 22, 2024
990e5ac
support only decimal bigint literal and pattern matching
mununki Mar 23, 2024
0d40dd9
fix test
mununki Mar 23, 2024
79c7013
handle delimiter '_'
mununki Mar 23, 2024
5748e83
throw Division_by_zero in bigint div, mod
mununki Mar 23, 2024
4a43e39
call runtime only when dividing by zero
mununki Mar 23, 2024
e7e41c4
fix incorrect dividing by zero with non constant
mununki Mar 25, 2024
e8e8050
remove is_safe from Pdivbigint, Pmodbigint
mununki Mar 25, 2024
5e963cd
stale comments
mununki Mar 26, 2024
84eecd7
fix bigint_utils.compare
mununki Mar 26, 2024
9652115
change bigint model to sign * string
mununki Mar 26, 2024
d82b4bc
clean up
mununki Mar 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

# 11.1.0-rc.6 (Unreleased)

#### :rocket: New Feature

- Add the primitive bigint type https://github.com/rescript-lang/rescript-compiler/pull/6670

#### :bug: Bug Fix

- Fix mishandling of uncurried functions in super errors. https://github.com/rescript-lang/rescript-compiler/pull/6694
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

Warning number 11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just todo note. maybe it will be better to disable ansi color for test snapshot, or to checkin both colored and not

/.../fixtures/bigint_match_literal.res:3:3-4

1 │ let m1 = switch 1n {
2 │ | 0001n => 1
3 │ | 1n => 1
4 │ | -0001n => -1
5 │ | _ => 0

this match case is unused.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/variant_coercion_bigint.res:5:10-20

3 │ let x = One(true)
4 │
5 │ let y = (x :> bigint)
6 │

Type x is not a subtype of bigint
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/variant_coercion_bigint_as.res:5:10-20

3 │ let x = One
4 │
5 │ let y = (x :> bigint)
6 │

Type x is not a subtype of bigint
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
14 │

You forgot to handle a possible case here, for example:
| #second(_) | #fourth | #third
| #second(_) | #fourth | #third
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,4 @@ Either bind these labels explicitly or add ', _' to the pattern.
60 │

You forgot to handle a possible case here, for example:
| (_, true)
| (_, true)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let m1 = switch 1n {
| 0001n => 1
| 1n => 1
| -0001n => -1
| _ => 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type x = | @as(1n) One(bool) | @as(2n) Two

let x = One(true)

let y = (x :> bigint)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type x = | @as(1n) One | Two

let x = One

let y = (x :> bigint)
2 changes: 2 additions & 0 deletions jscomp/core/js_analyzer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ let rec eq_expression ({ expression_desc = x0 } : J.expression)
| Undefined x -> y0 = Undefined x
| Number (Int { i }) -> (
match y0 with Number (Int { i = j }) -> i = j | _ -> false)
| Number (Bigint {positive = p0; value = v0}) -> (
match y0 with Number (Bigint {positive = p1; value = v1}) -> p0 = p1 && v0 = v1 | _ -> false)
| Number (Float _) -> false
(* begin match y0 with
| Number (Float j) ->
Expand Down
1 change: 1 addition & 0 deletions jscomp/core/js_dump.ml
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ and expression_desc cxt ~(level : int) f x : cxt =
Int32.to_string i
(* check , js convention with ocaml lexical convention *)
| Uint i -> Format.asprintf "%lu" i
| Bigint {positive; value} -> Format.asprintf "%sn" (Bigint_utils.to_string positive value)
in
let need_paren =
if s.[0] = '-' then level > 13
Expand Down
25 changes: 25 additions & 0 deletions jscomp/core/js_exp_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ let obj_int_tag_literal : t =

let int ?comment ?c i : t = { expression_desc = Number (Int { i; c }); comment }

let bigint ?comment sign i : t = { expression_desc = Number (Bigint {positive=sign; value=i}); comment}

let zero_bigint_literal : t = {expression_desc = Number (Bigint {positive=true; value="0"}); comment = None}

let small_int i : t =
match i with
| 0 -> zero_int_literal
Expand Down Expand Up @@ -803,11 +807,15 @@ let tag_type = function
| Ast_untagged_variants.String s -> str s ~delim:DStarJ
| Int i -> small_int i
| Float f -> float f
| Bigint i ->
let sign, i = Bigint_utils.parse_bigint i in
bigint sign i
| Bool b -> bool b
| Null -> nil
| Undefined -> undefined
| Untagged IntType -> str "number"
| Untagged FloatType -> str "number"
| Untagged BigintType -> str "bigint"
| Untagged BooleanType -> str "boolean"
| Untagged FunctionType -> str "function"
| Untagged StringType -> str "string"
Expand Down Expand Up @@ -1253,6 +1261,23 @@ let rec int32_band ?comment (e1 : J.expression) (e2 : J.expression) :
(* let int32_bin ?comment op e1 e2 : J.expression = *)
(* {expression_desc = Int32_bin(op,e1, e2); comment} *)

let bigint_op ?comment op (e1: t) (e2: t) = bin ?comment op e1 e2

let bigint_comp (cmp : Lam_compat.comparison) ?comment (e0: t) (e1: t) =
bin ?comment (Lam_compile_util.jsop_of_comp cmp) e0 e1

let bigint_div ~checked ?comment (e0: t) (e1: t) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like the option to disable checking divide by zero is really only hidden under some ancient internal-only configuration

at some point, it can be removed, perhaps in a later PR

if checked then
runtime_call Js_runtime_modules.bigint "div" [e0; e1]
else
bigint_op ?comment Div e0 e1

let bigint_mod ~checked ?comment (e0: t) (e1: t) =
if checked then
runtime_call Js_runtime_modules.bigint "mod_" [e0; e1]
else
bigint_op ?comment Mod e0 e1

(* TODO -- alpha conversion
remember to add parens..
*)
Expand Down
12 changes: 12 additions & 0 deletions jscomp/core/js_exp_make.mli
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ val uint32 : ?comment:string -> int32 -> t

val small_int : int -> t

val bigint : ?comment:string -> bool -> string -> t

val float : ?comment:string -> string -> t

(* val empty_string_literal : t *)
Expand All @@ -121,6 +123,8 @@ val zero_int_literal : t
val zero_float_lit : t
(* val obj_int_tag_literal : t *)

val zero_bigint_literal : t

val is_out : ?comment:string -> t -> t -> t
(** [is_out e range] is equivalent to [e > range or e <0]

Expand Down Expand Up @@ -272,6 +276,14 @@ val string_comp : Js_op.binop -> ?comment:string -> t -> t -> t

val float_comp : Lam_compat.comparison -> ?comment:string -> t -> t -> t

val bigint_op : ?comment: string -> Js_op.binop -> t -> t -> t

val bigint_comp : Lam_compat.comparison -> ?comment:string -> t -> t -> t

val bigint_div : checked:bool -> ?comment:string -> t -> t -> t

val bigint_mod : checked:bool -> ?comment:string -> t -> t -> t

val js_comp : Lam_compat.comparison -> ?comment:string -> t -> t -> t

val not : t -> t
Expand Down
4 changes: 4 additions & 0 deletions jscomp/core/js_op.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type binop =
| Mul
| Div
| Mod
| Pow
| InstanceOf

(**
Expand Down Expand Up @@ -125,10 +126,13 @@ type 'a access = Getter | Setter
(* literal char *)
type float_lit = { f : string } [@@unboxed]

type bigint_lit = { positive: bool; value: string }

type number =
| Float of float_lit
| Int of { i : int32; c : int option }
| Uint of int32
| Bigint of bigint_lit

(* becareful when constant folding +/-,
since we treat it as js nativeint, bitwise operators:
Expand Down
3 changes: 2 additions & 1 deletion jscomp/core/js_op_util.ml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ let op_prec (op : Js_op.binop) =
| Band -> (7, 7, 7)
| Lsl | Lsr | Asr -> (10, 10, 11)
| Plus | Minus -> (11, 11, 12)
| Mul | Div | Mod -> (12, 12, 13)
| Mul | Div | Mod | Pow -> (12, 12, 13)

let op_int_prec (op : Js_op.int_op) =
match op with
Expand All @@ -64,6 +64,7 @@ let op_str (op : Js_op.binop) =
| Mul -> "*"
| Div -> "/"
| Mod -> "%"
| Pow -> "**"
| Eq -> "="
| Or -> "||"
| And -> "&&"
Expand Down
2 changes: 1 addition & 1 deletion jscomp/core/js_stmt_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ let string_switch ?(comment : string option)
match switch_case with
| String s ->
if s = txt then Some x.switch_body else None
| Int _ | Float _| Bool _ | Null | Undefined | Untagged _ ->
| Int _ | Float _ | Bigint _ | Bool _ | Null | Undefined | Untagged _ ->
None)
with
| Some case -> case
Expand Down
3 changes: 2 additions & 1 deletion jscomp/core/lam.ml
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ let prim ~primitive:(prim : Lam_primitive.t) ~args loc : t =
(* FIXME: could raise? *)
Lift.bool
(Lam_compat.cmp_float cmp (float_of_string a) (float_of_string b))
| Pbigintcomp cmp, Const_bigint _, Const_bigint _ -> default ()
| Pintcomp ((Ceq | Cneq) as op), Const_pointer a, Const_pointer b ->
Lift.bool
(match op with
Expand Down Expand Up @@ -641,7 +642,7 @@ let rec eval_const_as_bool (v : Lam_constant.t) : bool =
| Const_int64 x -> x <> 0L
| Const_js_false | Const_js_null | Const_module_alias | Const_js_undefined _ ->
false
| Const_js_true | Const_string _ | Const_pointer _ | Const_float _
| Const_js_true | Const_string _ | Const_pointer _ | Const_float _ | Const_bigint _
| Const_block _ | Const_float_array _ ->
true
| Const_some b -> eval_const_as_bool b
Expand Down
8 changes: 6 additions & 2 deletions jscomp/core/lam_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ let not_zero_constant (x : Lam_constant.t) =
match x with
| Const_int { i } -> i <> 0l
| Const_int64 i -> i <> 0L
| Const_bigint (_, i) -> i <> "0"
| _ -> false

let rec no_side_effects (lam : Lam.t) : bool =
Expand All @@ -53,7 +54,7 @@ let rec no_side_effects (lam : Lam.t) : bool =
_ ) ->
true
| _, _ -> false)
| Pmodint | Pdivint | Pdivint64 | Pmodint64 -> (
| Pmodint | Pdivint | Pdivint64 | Pmodint64 | Pdivbigint | Pmodbigint -> (
match args with
| [ _; Lconst cst ] -> not_zero_constant cst
| _ -> false)
Expand All @@ -76,6 +77,9 @@ let rec no_side_effects (lam : Lam.t) : bool =
| Pintoffloat | Pfloatofint | Pnegfloat
(* | Pabsfloat *)
| Paddfloat | Psubfloat | Pmulfloat | Pdivfloat | Pfloatcomp _ | Pjscomp _
| Pnegbigint | Paddbigint | Psubbigint | Pmulbigint | Ppowbigint
| Pandbigint | Porbigint | Pxorbigint | Plslbigint | Pasrbigint
| Pbigintcomp _
(* String operations *)
| Pstringlength | Pstringrefu | Pstringrefs | Pbyteslength | Pbytesrefu
| Pbytesrefs | Pmakearray | Parraylength | Parrayrefu | Parrayrefs
Expand Down Expand Up @@ -193,7 +197,7 @@ let rec size (lam : Lam.t) =

and size_constant x =
match x with
| Const_int _ | Const_char _ | Const_float _ | Const_int64 _ | Const_pointer _
| Const_int _ | Const_char _ | Const_float _ | Const_int64 _ | Const_bigint _ | Const_pointer _
| Const_js_null | Const_js_undefined _ | Const_module_alias | Const_js_true
| Const_js_false ->
1
Expand Down
15 changes: 3 additions & 12 deletions jscomp/core/lam_compat.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)

type boxed_integer = Lambda.boxed_integer = Pnativeint | Pint32 | Pint64
type boxed_integer = Lambda.boxed_integer = Pbigint | Pint32 | Pint64

let eq_boxed_integer (p : boxed_integer) (p1 : boxed_integer) =
match p with
| Pnativeint -> p1 = Pnativeint
| Pbigint -> p1 = Pbigint
| Pint32 -> p1 = Pint32
| Pint64 -> p1 = Pint64

Expand Down Expand Up @@ -59,15 +59,6 @@ let cmp_int64 (cmp : comparison) (a : int64) b : bool =
| Clt -> a < b
| Cge -> a >= b

let cmp_nativeint (cmp : comparison) (a : nativeint) b : bool =
match cmp with
| Ceq -> a = b
| Cneq -> a <> b
| Cgt -> a > b
| Cle -> a <= b
| Clt -> a < b
| Cge -> a >= b

let cmp_float (cmp : comparison) (a : float) b : bool =
match cmp with
| Ceq -> a = b
Expand All @@ -76,7 +67,7 @@ let cmp_float (cmp : comparison) (a : float) b : bool =
| Cle -> a <= b
| Clt -> a < b
| Cge -> a >= b

let cmp_int (cmp : comparison) (a : int) b : bool =
match cmp with
| Ceq -> a = b
Expand Down
4 changes: 1 addition & 3 deletions jscomp/core/lam_compat.mli
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)

type boxed_integer = Lambda.boxed_integer = Pnativeint | Pint32 | Pint64
type boxed_integer = Lambda.boxed_integer = Pbigint | Pint32 | Pint64

type comparison = Lambda.comparison = Ceq | Cneq | Clt | Cgt | Cle | Cge

Expand Down Expand Up @@ -59,8 +59,6 @@ val cmp_int32 : comparison -> int32 -> int32 -> bool

val cmp_int64 : comparison -> int64 -> int64 -> bool

val cmp_nativeint : comparison -> nativeint -> nativeint -> bool

val cmp_float : comparison -> float -> float -> bool

val cmp_int : comparison -> int -> int -> bool
Expand Down
1 change: 1 addition & 0 deletions jscomp/core/lam_compile_const.ml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ and translate (x : Lam_constant.t) : J.expression =
(* E.float (Int64.to_string i) *)
Js_long.of_const i
(* https://github.com/google/closure-library/blob/master/closure%2Fgoog%2Fmath%2Flong.js *)
| Const_bigint (sign, i) -> E.bigint sign i
| Const_float f -> E.float f (* TODO: preserve float *)
| Const_string { s; unicode = false } -> E.str s
| Const_string { s; unicode = true } -> E.str ~delim:DStarJ s
Expand Down
Loading