Skip to content

Commit 9652115

Browse files
committed
change bigint model to sign * string
1 parent 84eecd7 commit 9652115

24 files changed

+72
-52
lines changed

jscomp/core/js_analyzer.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ let rec eq_expression ({ expression_desc = x0 } : J.expression)
158158
| Undefined x -> y0 = Undefined x
159159
| Number (Int { i }) -> (
160160
match y0 with Number (Int { i = j }) -> i = j | _ -> false)
161-
| Number (Bigint { i }) -> (
162-
match y0 with Number (Bigint { i = j }) -> i = j | _ -> false)
161+
| Number (Bigint (s0, i )) -> (
162+
match y0 with Number (Bigint (s1, j)) -> s0 = s1 && i = j | _ -> false)
163163
| Number (Float _) -> false
164164
(* begin match y0 with
165165
| Number (Float j) ->

jscomp/core/js_dump.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ and expression_desc cxt ~(level : int) f x : cxt =
664664
Int32.to_string i
665665
(* check , js convention with ocaml lexical convention *)
666666
| Uint i -> Format.asprintf "%lu" i
667-
| Bigint { i } -> Format.asprintf "%sn" i
667+
| Bigint (sign, i) -> Format.asprintf "%sn" (Bigint_utils.to_string sign i)
668668
in
669669
let need_paren =
670670
if s.[0] = '-' then level > 13

jscomp/core/js_exp_make.ml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,9 @@ let obj_int_tag_literal : t =
312312

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

315-
let bigint ?comment i : t = { expression_desc = Number (Bigint { i }); comment}
315+
let bigint ?comment sign i : t = { expression_desc = Number (Bigint (sign, i)); comment}
316316

317-
let zero_bigint_literal : t = {expression_desc = Number (Bigint {i = "0"}); comment = None}
317+
let zero_bigint_literal : t = {expression_desc = Number (Bigint (true, "0")); comment = None}
318318

319319
let small_int i : t =
320320
match i with
@@ -807,7 +807,11 @@ let tag_type = function
807807
| Ast_untagged_variants.String s -> str s ~delim:DStarJ
808808
| Int i -> small_int i
809809
| Float f -> float f
810-
| Bigint i -> bigint i
810+
| Bigint i ->
811+
let open Bigint_utils in
812+
let sign, i = i |> remove_leading_sign in
813+
let i = remove_leading_zeros i in
814+
bigint sign i
811815
| Bool b -> bool b
812816
| Null -> nil
813817
| Undefined -> undefined

jscomp/core/js_exp_make.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ val uint32 : ?comment:string -> int32 -> t
111111

112112
val small_int : int -> t
113113

114-
val bigint : ?comment:string -> string -> t
114+
val bigint : ?comment:string -> bool -> string -> t
115115

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

jscomp/core/js_op.ml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,11 @@ type 'a access = Getter | Setter
126126
(* literal char *)
127127
type float_lit = { f : string } [@@unboxed]
128128

129-
type bigint_lit = { i: string } [@@unboxed]
130-
131129
type number =
132130
| Float of float_lit
133131
| Int of { i : int32; c : int option }
134132
| Uint of int32
135-
| Bigint of bigint_lit
133+
| Bigint of bool * string
136134

137135
(* becareful when constant folding +/-,
138136
since we treat it as js nativeint, bitwise operators:

jscomp/core/lam.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ let prim ~primitive:(prim : Lam_primitive.t) ~args loc : t =
506506
(* FIXME: could raise? *)
507507
Lift.bool
508508
(Lam_compat.cmp_float cmp (float_of_string a) (float_of_string b))
509-
| Pbigintcomp cmp, Const_bigint a, Const_bigint b -> default ()
509+
| Pbigintcomp cmp, Const_bigint (_, a), Const_bigint (_, b) -> default ()
510510
| Pintcomp ((Ceq | Cneq) as op), Const_pointer a, Const_pointer b ->
511511
Lift.bool
512512
(match op with

jscomp/core/lam_analysis.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ let not_zero_constant (x : Lam_constant.t) =
2727
match x with
2828
| Const_int { i } -> i <> 0l
2929
| Const_int64 i -> i <> 0L
30-
| Const_bigint i -> i <> "0"
30+
| Const_bigint (_, i) -> i <> "0"
3131
| _ -> false
3232

3333
let rec no_side_effects (lam : Lam.t) : bool =

jscomp/core/lam_compile_const.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ and translate (x : Lam_constant.t) : J.expression =
7474
(* E.float (Int64.to_string i) *)
7575
Js_long.of_const i
7676
(* https://github.com/google/closure-library/blob/master/closure%2Fgoog%2Fmath%2Flong.js *)
77-
| Const_bigint i -> E.bigint i
77+
| Const_bigint (sign, i) -> E.bigint sign i
7878
| Const_float f -> E.float f (* TODO: preserve float *)
7979
| Const_string { s; unicode = false } -> E.str s
8080
| Const_string { s; unicode = true } -> E.str ~delim:DStarJ s

jscomp/core/lam_constant_convert.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ let rec convert_constant (const : Lambda.structured_constant) : Lam_constant.t =
3636
| Const_base (Const_float i) -> Const_float i
3737
| Const_base (Const_int32 i) -> Const_int { i; comment = None }
3838
| Const_base (Const_int64 i) -> Const_int64 i
39-
| Const_base (Const_bigint i) -> Const_bigint i
39+
| Const_base (Const_bigint (sign, i)) -> Const_bigint (sign, i)
4040
| Const_pointer (0, Pt_constructor { name = "()"; const = 1; non_const = 0 })
4141
->
4242
Const_js_undefined {isUnit = true}

jscomp/core/lam_print.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ let rec struct_const ppf (cst : Lam_constant.t) =
2525
| Const_string { s } -> fprintf ppf "%S" s
2626
| Const_float f -> fprintf ppf "%s" f
2727
| Const_int64 n -> fprintf ppf "%LiL" n
28-
| Const_bigint i -> fprintf ppf "%sn" i
28+
| Const_bigint (sign, i) -> fprintf ppf "%sn" (Bigint_utils.to_string sign i)
2929
| Const_pointer name -> fprintf ppf "`%s" name
3030
| Const_some n -> fprintf ppf "[some-c]%a" struct_const n
3131
| Const_block (tag, _, []) -> fprintf ppf "[%i]" tag

jscomp/frontend/external_ffi_types.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,9 @@ let inline_int64_primitive (i : int64) : string list =
301301
[""; to_string (Ffi_inline_const (Const_int64 i))]
302302

303303
let inline_bigint_primitive (i : string) : string list =
304-
[""; to_string (Ffi_inline_const (Const_bigint i))]
304+
let sign, i = i |> Bigint_utils.remove_leading_sign in
305+
let i = Bigint_utils.remove_leading_zeros i in
306+
[""; to_string (Ffi_inline_const (Const_bigint (sign, i)))]
305307

306308
let inline_float_primitive (i : string) : string list =
307309
[""; to_string (Ffi_inline_const (Const_float i))]

jscomp/frontend/lam_constant.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type t =
5050
| Const_string of {s: string; unicode: bool}
5151
| Const_float of string
5252
| Const_int64 of int64
53-
| Const_bigint of string
53+
| Const_bigint of bool * string
5454
| Const_pointer of string
5555
| Const_block of int * Lambda.tag_info * t list
5656
| Const_float_array of string list
@@ -87,9 +87,9 @@ let rec eq_approx (x : t) (y : t) =
8787
match y with
8888
| Const_int64 iy -> ix = iy
8989
| _ -> false)
90-
| Const_bigint ix -> (
90+
| Const_bigint (sx, ix) -> (
9191
match y with
92-
| Const_bigint iy -> ix = iy
92+
| Const_bigint (sy, iy) -> sx = sy && ix = iy
9393
| _ -> false)
9494
| Const_pointer ix -> (
9595
match y with

jscomp/frontend/lam_constant.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type t =
4646
| Const_string of {s: string; unicode: bool}
4747
| Const_float of string
4848
| Const_int64 of int64
49-
| Const_bigint of string
49+
| Const_bigint of bool * string
5050
| Const_pointer of string
5151
| Const_block of int * Lambda.tag_info * t list
5252
| Const_float_array of string list

jscomp/ml/asttypes.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type constant =
2222
| Const_float of string
2323
| Const_int32 of int32
2424
| Const_int64 of int64
25-
| Const_bigint of string
25+
| Const_bigint of bool * string
2626

2727
type rec_flag = Nonrecursive | Recursive
2828

jscomp/ml/bigint_utils.ml

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
let is_neg s = String.length s > 0 && s.[0] = '-'
2+
let is_pos s = String.length s > 0 && s.[0] = '+'
3+
4+
let to_string sign s = (if sign then "" else "-") ^ s
5+
6+
let remove_leading_sign str : bool * string =
7+
let len = String.length str in
8+
if len = 0 then (false, str)
9+
else
10+
if is_neg str || is_pos str then (not (is_neg str), String.sub str 1 (len -1))
11+
else (not (is_neg str), str)
12+
113
(*
214
Removes leading zeros from the string only if the first non-zero character
315
encountered is a digit. Unlike int and float, bigint cannot be of_string, so
@@ -32,7 +44,7 @@ let remove_leading_zeros str =
3244
let str = String.concat "" (String.split_on_char '_' str) in
3345
(* Check if negative *)
3446
let starts_with_minus = str <> "" && str.[0] = '-' in
35-
let str = if starts_with_minus then String.sub str 1 (String.length str - 1) else str in
47+
let str = if is_neg str || is_pos str then String.sub str 1 (String.length str - 1) else str in
3648
let processed_str = aux str in
3749
if starts_with_minus then "-" ^ processed_str else processed_str
3850

@@ -42,7 +54,7 @@ let is_numeric s =
4254
else
4355
let is_digit c = (c >= '0' && c <= '9') || c = '_' in
4456
let first_char = s.[0] in
45-
if first_char <> '-' && not (is_digit first_char) then false
57+
if first_char <> '-' && first_char <> '+' && not (is_digit first_char) then false
4658
else
4759
let rec check idx =
4860
if idx >= len then true
@@ -53,18 +65,16 @@ let is_numeric s =
5365
in
5466
check 1
5567

56-
let compare s0 s1 =
57-
(* check if negative *)
58-
let is_neg s = String.length s > 0 && s.[0] = '-' in
59-
match (is_neg s0, is_neg s1) with
60-
| (true, false) -> -1 (* If only s0 is negative, it's smaller. *)
61-
| (false, true) -> 1 (* If only s1 is negative, s0 is larger. *)
68+
let compare (p0, s0) (p1, s1) =
69+
match (p0, p1) with
70+
| (false, true) -> -1 (* If only s1 is positive, s0 is smaller. *)
71+
| (true, false) -> 1 (* If only s0 is positive, s0 is larger. *)
6272
| _ ->
6373
(* If both numbers are either negative or positive, compare their lengths. *)
6474
let len0, len1 = (String.length s0, String.length s1) in
6575
if len0 = len1 then
66-
if is_neg s0 then String.compare s1 s0 else String.compare s0 s1 (* If lengths are equal, compare the strings directly. *)
76+
if p0 then String.compare s0 s1 else String.compare s1 s0 (* If lengths are equal, compare the strings directly. *)
6777
else if len0 > len1 then
68-
if is_neg s0 then -1 else 1 (* A longer s0 means it's larger unless it's negative. *)
78+
if p0 then 1 else -1 (* A longer s0 means it's larger unless it's negative. *)
6979
else (* len0 < len1 *)
70-
if is_neg s1 then 1 else -1 (* A longer s1 means s0 is smaller unless s1 is negative. *)
80+
if p0 then -1 else 1 (* A longer s1 means s0 is smaller unless s1 is negative. *)

jscomp/ml/bigint_utils.mli

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
val is_neg: string -> bool
2+
val is_pos: string -> bool
3+
val to_string: bool -> string -> string
4+
val remove_leading_sign : string -> bool * string
15
val remove_leading_zeros : string -> string
26
val is_numeric : string -> bool
3-
val compare : string -> string -> int
7+
val compare : bool * string -> bool * string -> int

jscomp/ml/parmatch.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ let const_compare x y =
264264
match x,y with
265265
| Const_float f1, Const_float f2 ->
266266
compare (float_of_string f1) (float_of_string f2)
267-
| Const_bigint b1, Const_bigint b2 ->
268-
Bigint_utils.compare b1 b2
267+
| Const_bigint (s1, b1), Const_bigint (s2, b2) ->
268+
Bigint_utils.compare (s1, b1) (s2, b2)
269269
| Const_string (s1, _), Const_string (s2, _) ->
270270
String.compare s1 s2
271271
| _, _ -> compare x y
@@ -386,7 +386,7 @@ let pretty_const c = match c with
386386
| Const_float f -> Printf.sprintf "%s" f
387387
| Const_int32 i -> Printf.sprintf "%ldl" i
388388
| Const_int64 i -> Printf.sprintf "%LdL" i
389-
| Const_bigint i -> Printf.sprintf "%s" i
389+
| Const_bigint (sign, i) -> Printf.sprintf "%s" (Bigint_utils.to_string sign i)
390390

391391
let rec pretty_val ppf v =
392392
match v.pat_extra with
@@ -1106,8 +1106,8 @@ let build_other ext env : Typedtree.pattern = match env with
11061106
0L Int64.succ p env
11071107
| ({pat_desc=(Tpat_constant (Const_bigint _))} as p,_) :: _ ->
11081108
build_other_constant
1109-
(function Tpat_constant(Const_bigint i) -> String.length i | _ -> assert false)
1110-
(function i -> Tpat_constant(Const_bigint (String.make i '*')))
1109+
(function Tpat_constant(Const_bigint (sign, i)) -> String.length (Bigint_utils.to_string sign i) | _ -> assert false)
1110+
(function i -> Tpat_constant(Const_bigint (true, (String.make i '*'))))
11111111
0 succ p env
11121112
| ({pat_desc=(Tpat_constant (Const_string _))} as p,_) :: _ ->
11131113
build_other_constant

jscomp/ml/printlambda.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ let rec struct_const ppf = function
2727
| Const_base(Const_float f) -> fprintf ppf "%s" f
2828
| Const_base(Const_int32 n) -> fprintf ppf "%lil" n
2929
| Const_base(Const_int64 n) -> fprintf ppf "%LiL" n
30-
| Const_base(Const_bigint n) -> fprintf ppf "%sn" n
30+
| Const_base(Const_bigint (sign, n)) -> fprintf ppf "%sn" (Bigint_utils.to_string sign n)
3131
| Const_pointer (n,_) -> fprintf ppf "%ia" n
3232
| Const_block(tag_info, []) ->
3333
let tag = Lambda.tag_of_tag_info tag_info in

jscomp/ml/printtyped.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ let fmt_constant f x =
6565
| Const_float (s) -> fprintf f "Const_float %s" s;
6666
| Const_int32 (i) -> fprintf f "Const_int32 %ld" i;
6767
| Const_int64 (i) -> fprintf f "Const_int64 %Ld" i;
68-
| Const_bigint (i) -> fprintf f "Const_bigint %s" i;
68+
| Const_bigint (sign, i) -> fprintf f "Const_bigint %s" (Bigint_utils.to_string sign i);
6969
;;
7070

7171
let fmt_mutable_flag f x =

jscomp/ml/typecore.ml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ type error =
7676
| Empty_record_literal
7777
| Uncurried_arity_mismatch of type_expr * int * int
7878
| Field_not_optional of string * type_expr
79-
| Invalid_decimal of string
8079
exception Error of Location.t * Env.t * error
8180
exception Error_forward of Location.error
8281

@@ -261,9 +260,9 @@ let constant : Parsetree.constant -> (Asttypes.constant, error) result =
261260
with Failure _ -> Error (Literal_overflow "int64")
262261
end
263262
| Pconst_integer (i,Some 'n') ->
264-
if Bigint_utils.is_numeric i then
265-
Ok (Const_bigint (Bigint_utils.remove_leading_zeros i))
266-
else Error (Invalid_decimal i)
263+
let sign, i = i |> Bigint_utils.remove_leading_sign in
264+
let i = Bigint_utils.remove_leading_zeros i in
265+
Ok (Const_bigint (sign, i))
267266
| Pconst_integer (i,Some c) -> Error (Unknown_literal (i, c))
268267
| Pconst_char c -> Ok (Const_char c)
269268
| Pconst_string (s,d) -> Ok (Const_string (s,d))
@@ -4079,9 +4078,6 @@ let report_error env ppf = function
40794078
fprintf ppf
40804079
"Field @{<info>%s@} is not optional in type %a. Use without ?" name
40814080
type_expr typ
4082-
| Invalid_decimal s ->
4083-
fprintf ppf
4084-
"Invalid decimal literal '%sn'. Only decimal literal is allowed for bigint" s
40854081
40864082
40874083
let super_report_error_no_wrap_printing_env = report_error

jscomp/ml/typecore.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ type error =
111111
| Empty_record_literal
112112
| Uncurried_arity_mismatch of type_expr * int * int
113113
| Field_not_optional of string * type_expr
114-
| Invalid_decimal of string
115114
exception Error of Location.t * Env.t * error
116115
exception Error_forward of Location.error
117116

jscomp/ml/untypeast.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ let constant = function
114114
| Const_int i -> Pconst_integer (string_of_int i, None)
115115
| Const_int32 i -> Pconst_integer (Int32.to_string i, Some 'l')
116116
| Const_int64 i -> Pconst_integer (Int64.to_string i, Some 'L')
117-
| Const_bigint i -> Pconst_integer (i, Some 'n')
117+
| Const_bigint (sign, i) ->
118+
Pconst_integer (Bigint_utils.to_string sign i, Some 'n')
118119
| Const_float f -> Pconst_float (f,None)
119120

120121
let attribute sub (s, p) = (map_loc sub s, p)

jscomp/syntax/src/res_core.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,12 @@ let parseConstant p =
812812
let constant =
813813
match p.Parser.token with
814814
| Int {i; suffix} ->
815+
(* Only decimal literal is allowed for bigint *)
816+
if suffix = Some 'n' && not (Bigint_utils.is_numeric i) then
817+
Parser.err p
818+
(Diagnostics.message
819+
"Invalid decimal literal. Only decimal literal is allowed for \
820+
bigint.");
815821
let intTxt = if isNegative then "-" ^ i else i in
816822
Parsetree.Pconst_integer (intTxt, suffix)
817823
| Float {f; suffix} ->

jscomp/test/bigint_test.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)