-
Notifications
You must be signed in to change notification settings - Fork 464
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
Introducing the bigint #6670
Changes from 1 commit
1441f59
db001fa
20410da
2f6217b
0b14c33
4f40575
6020820
8d95ccd
83070a0
128aa20
c1d39b2
8835276
51e2ab2
84cf107
0f21844
6b01997
d386c4a
bc22261
3b34a01
d3032e1
d3090ff
5683ca2
da60074
41ba70b
3e9a471
fee14cc
fc1ea04
ec90078
b8a5efd
79df62c
dd6b0cf
9852ad0
00d741a
379dc31
990e5ac
0d40dd9
79c7013
5748e83
4a43e39
e7e41c4
e8e8050
5e963cd
84eecd7
9652115
d82b4bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -126,13 +126,11 @@ type 'a access = Getter | Setter | |
(* literal char *) | ||
type float_lit = { f : string } [@@unboxed] | ||
|
||
type bigint_lit = { i: string } [@@unboxed] | ||
|
||
type number = | ||
| Float of float_lit | ||
| Int of { i : int32; c : int option } | ||
| Uint of int32 | ||
| Bigint of bigint_lit | ||
| Bigint of bool * string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small style suggestion keep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good, it seems not going to be unboxed, still okay? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The difference is going to be tiny in practice. |
||
|
||
(* becareful when constant folding +/-, | ||
since we treat it as js nativeint, bitwise operators: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -506,7 +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 a, Const_bigint b -> default () | ||
| Pbigintcomp cmp, Const_bigint (_, a), Const_bigint (_, b) -> default () | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: here |
||
| Pintcomp ((Ceq | Cneq) as op), Const_pointer a, Const_pointer b -> | ||
Lift.bool | ||
(match op with | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,15 @@ | ||
let is_neg s = String.length s > 0 && s.[0] = '-' | ||
let is_pos s = String.length s > 0 && s.[0] = '+' | ||
|
||
let to_string sign s = (if sign then "" else "-") ^ s | ||
|
||
let remove_leading_sign str : bool * string = | ||
let len = String.length str in | ||
if len = 0 then (false, str) | ||
else | ||
if is_neg str || is_pos str then (not (is_neg str), String.sub str 1 (len -1)) | ||
else (not (is_neg str), str) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: in this branch |
||
|
||
(* | ||
Removes leading zeros from the string only if the first non-zero character | ||
encountered is a digit. Unlike int and float, bigint cannot be of_string, so | ||
|
@@ -32,7 +44,7 @@ let remove_leading_zeros str = | |
let str = String.concat "" (String.split_on_char '_' str) in | ||
(* Check if negative *) | ||
let starts_with_minus = str <> "" && str.[0] = '-' in | ||
let str = if starts_with_minus then String.sub str 1 (String.length str - 1) else str in | ||
let str = if is_neg str || is_pos str then String.sub str 1 (String.length str - 1) else str in | ||
let processed_str = aux str in | ||
if starts_with_minus then "-" ^ processed_str else processed_str | ||
|
||
|
@@ -42,7 +54,7 @@ let is_numeric s = | |
else | ||
let is_digit c = (c >= '0' && c <= '9') || c = '_' in | ||
let first_char = s.[0] in | ||
if first_char <> '-' && not (is_digit first_char) then false | ||
if first_char <> '-' && first_char <> '+' && not (is_digit first_char) then false | ||
else | ||
let rec check idx = | ||
if idx >= len then true | ||
|
@@ -53,18 +65,16 @@ let is_numeric s = | |
in | ||
check 1 | ||
|
||
let compare s0 s1 = | ||
(* check if negative *) | ||
let is_neg s = String.length s > 0 && s.[0] = '-' in | ||
match (is_neg s0, is_neg s1) with | ||
| (true, false) -> -1 (* If only s0 is negative, it's smaller. *) | ||
| (false, true) -> 1 (* If only s1 is negative, s0 is larger. *) | ||
let compare (p0, s0) (p1, s1) = | ||
match (p0, p1) with | ||
| (false, true) -> -1 (* If only s1 is positive, s0 is smaller. *) | ||
| (true, false) -> 1 (* If only s0 is positive, s0 is larger. *) | ||
| _ -> | ||
(* If both numbers are either negative or positive, compare their lengths. *) | ||
let len0, len1 = (String.length s0, String.length s1) in | ||
if len0 = len1 then | ||
if is_neg s0 then String.compare s1 s0 else String.compare s0 s1 (* If lengths are equal, compare the strings directly. *) | ||
if p0 then String.compare s0 s1 else String.compare s1 s0 (* If lengths are equal, compare the strings directly. *) | ||
else if len0 > len1 then | ||
if is_neg s0 then -1 else 1 (* A longer s0 means it's larger unless it's negative. *) | ||
if p0 then 1 else -1 (* A longer s0 means it's larger unless it's negative. *) | ||
else (* len0 < len1 *) | ||
if is_neg s1 then 1 else -1 (* A longer s1 means s0 is smaller unless s1 is negative. *) | ||
if p0 then -1 else 1 (* A longer s1 means s0 is smaller unless s1 is negative. *) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
val is_neg: string -> bool | ||
val is_pos: string -> bool | ||
val to_string: bool -> string -> string | ||
val remove_leading_sign : string -> bool * string | ||
val remove_leading_zeros : string -> string | ||
val is_numeric : string -> bool | ||
val compare : string -> string -> int | ||
val compare : bool * string -> bool * string -> int |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -264,8 +264,8 @@ let const_compare x y = | |
match x,y with | ||
| Const_float f1, Const_float f2 -> | ||
compare (float_of_string f1) (float_of_string f2) | ||
| Const_bigint b1, Const_bigint b2 -> | ||
Bigint_utils.compare b1 b2 | ||
| Const_bigint (s1, b1), Const_bigint (s2, b2) -> | ||
Bigint_utils.compare (s1, b1) (s2, b2) | ||
| Const_string (s1, _), Const_string (s2, _) -> | ||
String.compare s1 s2 | ||
| _, _ -> compare x y | ||
|
@@ -386,7 +386,7 @@ let pretty_const c = match c with | |
| Const_float f -> Printf.sprintf "%s" f | ||
| Const_int32 i -> Printf.sprintf "%ldl" i | ||
| Const_int64 i -> Printf.sprintf "%LdL" i | ||
| Const_bigint i -> Printf.sprintf "%s" i | ||
| Const_bigint (sign, i) -> Printf.sprintf "%s" (Bigint_utils.to_string sign i) | ||
|
||
let rec pretty_val ppf v = | ||
match v.pat_extra with | ||
|
@@ -1106,8 +1106,8 @@ let build_other ext env : Typedtree.pattern = match env with | |
0L Int64.succ p env | ||
| ({pat_desc=(Tpat_constant (Const_bigint _))} as p,_) :: _ -> | ||
build_other_constant | ||
(function Tpat_constant(Const_bigint i) -> String.length i | _ -> assert false) | ||
(function i -> Tpat_constant(Const_bigint (String.make i '*'))) | ||
(function Tpat_constant(Const_bigint (sign, i)) -> String.length (Bigint_utils.to_string sign i) | _ -> assert false) | ||
(function i -> Tpat_constant(Const_bigint (true, (String.make i '*')))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure what There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure. I guess this function is used in pattern matching for gadt partially. But logically I think we can change |
||
0 succ p env | ||
| ({pat_desc=(Tpat_constant (Const_string _))} as p,_) :: _ -> | ||
build_other_constant | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -812,6 +812,12 @@ let parseConstant p = | |
let constant = | ||
match p.Parser.token with | ||
| Int {i; suffix} -> | ||
(* Only decimal literal is allowed for bigint *) | ||
if suffix = Some 'n' && not (Bigint_utils.is_numeric i) then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: perhaps |
||
Parser.err p | ||
(Diagnostics.message | ||
"Invalid decimal literal. Only decimal literal is allowed for \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perhaps "Invalid bigint literal. Only decimal...". |
||
bigint."); | ||
let intTxt = if isNegative then "-" ^ i else i in | ||
Parsetree.Pconst_integer (intTxt, suffix) | ||
| Float {f; suffix} -> | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style/naming: perhaps:
let {positive, value} = parse_bigint i
where
parse_bigint
also removes the leading zeros, so there's no way one can forget to do that