Skip to content

Commit

Permalink
chore: Support Rational and Bigint
Browse files Browse the repository at this point in the history
  • Loading branch information
spotandjake committed Mar 3, 2024
1 parent b742052 commit 470f823
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 34 deletions.
19 changes: 15 additions & 4 deletions compiler/src/typed/typed_well_formedness.re
Expand Up @@ -294,7 +294,11 @@ module WellFormednessArg: TypedtreeIter.IteratorArgument = {
exp_desc:
TExpConstant(
Const_number(
(Const_number_int(_) | Const_number_float(_)) as n,
(
Const_number_int(_) | Const_number_float(_) |
Const_number_rational(_) |
Const_number_bigint(_)
) as n,
),
),
},
Expand All @@ -311,13 +315,17 @@ module WellFormednessArg: TypedtreeIter.IteratorArgument = {
|| modname == "Uint32"
|| modname == "Uint64"
|| modname == "Float32"
|| modname == "Float64" =>
|| modname == "Float64"
|| modname == "Rational"
|| modname == "BigInt" =>
// NOTE: Due to type-checking, we shouldn't need to worry about ending up with a FloatXX value and a Const_number_float
let n_str =
switch (n) {
| Const_number_int(nint) => Int64.to_string(nint)
| Const_number_float(nfloat) => Float.to_string(nfloat)
| _ => failwith("Impossible")
| Const_number_rational({rational_num_rep, rational_den_rep}) =>
Printf.sprintf("%s/%s", rational_num_rep, rational_den_rep)
| Const_number_bigint({bigint_rep}) => bigint_rep
};
let mod_type =
switch (modname) {
Expand All @@ -331,9 +339,12 @@ module WellFormednessArg: TypedtreeIter.IteratorArgument = {
| "Uint64" => Grain_utils.Warnings.Uint64
| "Float32" => Grain_utils.Warnings.Float32
| "Float64" => Grain_utils.Warnings.Float64
| "Rational" => Grain_utils.Warnings.Rational
| "BigInt" => Grain_utils.Warnings.BigInt
| _ => failwith("Impossible")
};
let warning = Grain_utils.Warnings.FromNumberLiteral(mod_type, n_str);
let warning =
Grain_utils.Warnings.FromNumberLiteral(mod_type, modname, n_str);
if (Grain_utils.Warnings.is_active(warning)) {
Grain_parsing.Location.prerr_warning(exp_loc, warning);
};
Expand Down
46 changes: 24 additions & 22 deletions compiler/src/utils/warnings.re
Expand Up @@ -16,7 +16,9 @@ type number_type =
| Uint32
| Uint64
| Float32
| Float64;
| Float64
| Rational
| BigInt;

type t =
| LetRecNonFunction(string)
Expand All @@ -36,7 +38,7 @@ type t =
| ShadowConstructor(string)
| NoCmiFile(string, option(string))
| FuncWasmUnsafe(string, string, string)
| FromNumberLiteral(number_type, string)
| FromNumberLiteral(number_type, string, string)
| UselessRecordSpread;

let last_warning_number = 19;
Expand All @@ -60,7 +62,7 @@ let number =
| NonClosedRecordPattern(_) => 15
| UnusedExtension => 16
| FuncWasmUnsafe(_, _, _) => 17
| FromNumberLiteral(_, _) => 18
| FromNumberLiteral(_, _, _) => 18
| UselessRecordSpread => last_warning_number;

let message =
Expand Down Expand Up @@ -129,25 +131,25 @@ let message =
++ " from the `"
++ m
++ "` module the instead."
| FromNumberLiteral(mod_type, n) => {
let (mod_name, literal) =
| FromNumberLiteral(mod_type, mod_name, n) => {
let literal =
switch (mod_type) {
| Int8 => ("Int8", Printf.sprintf("%ss", n))
| Int16 => ("Int16", Printf.sprintf("%sS", n))
| Int32 => ("Int32", Printf.sprintf("%sl", n))
| Int64 => ("Int64", Printf.sprintf("%sL", n))
| Uint8 => ("Uint8", Printf.sprintf("%sus", n))
| Uint16 => ("Uint16", Printf.sprintf("%suS", n))
| Uint32 => ("Uint32", Printf.sprintf("%sul", n))
| Uint64 => ("Uint64", Printf.sprintf("%suL", n))
| Float32 => (
"Float32",
Printf.sprintf("%sf", String.contains(n, '.') ? n : n ++ "."),
)
| Float64 => (
"Float64",
Printf.sprintf("%sd", String.contains(n, '.') ? n : n ++ "."),
)
| Int8 => Printf.sprintf("%ss", n)
| Int16 => Printf.sprintf("%sS", n)
| Int32 => Printf.sprintf("%sl", n)
| Int64 => Printf.sprintf("%sL", n)
| Uint8 => Printf.sprintf("%sus", n)
| Uint16 => Printf.sprintf("%suS", n)
| Uint32 => Printf.sprintf("%sul", n)
| Uint64 => Printf.sprintf("%suL", n)
| Float32 =>
Printf.sprintf("%sf", String.contains(n, '.') ? n : n ++ ".")

| Float64 =>
Printf.sprintf("%sd", String.contains(n, '.') ? n : n ++ ".")
| Rational =>
Printf.sprintf("%sr", String.contains(n, '/') ? n : n ++ "/1")
| BigInt => Printf.sprintf("%st", n)
};
Printf.sprintf(
"it looks like you are calling %s.fromNumber() with a constant number. Try using the literal syntax (e.g. `%s`) instead.",
Expand Down Expand Up @@ -198,7 +200,7 @@ let defaults = [
ShadowConstructor(""),
NoCmiFile("", None),
FuncWasmUnsafe("", "", ""),
FromNumberLiteral(Int8, ""),
FromNumberLiteral(Int8, "", ""),
UselessRecordSpread,
];

Expand Down
6 changes: 4 additions & 2 deletions compiler/src/utils/warnings.rei
Expand Up @@ -30,7 +30,9 @@ type number_type =
| Uint32
| Uint64
| Float32
| Float64;
| Float64
| Rational
| BigInt;

type t =
| LetRecNonFunction(string)
Expand All @@ -50,7 +52,7 @@ type t =
| ShadowConstructor(string)
| NoCmiFile(string, option(string))
| FuncWasmUnsafe(string, string, string)
| FromNumberLiteral(number_type, string)
| FromNumberLiteral(number_type, string, string)
| UselessRecordSpread;

let is_active: t => bool;
Expand Down
26 changes: 20 additions & 6 deletions compiler/test/suites/numbers.re
Expand Up @@ -200,35 +200,49 @@ describe("numbers", ({test, testSkip}) => {

// well-formedness warnings
test("float32_fromNumber_warn1", ({expect}) => {
expect.string(Warnings.message(FromNumberLiteral(Float32, "5"))).toMatch(
expect.string(
Warnings.message(FromNumberLiteral(Float32, "Float32", "5")),
).
toMatch(
"5.f",
)
});
test("float32_fromNumber_warn2", ({expect}) => {
expect.string(Warnings.message(FromNumberLiteral(Float32, "5."))).
expect.string(
Warnings.message(FromNumberLiteral(Float32, "Float32", "5.")),
).
toMatch(
"5.f",
)
});
test("float32_fromNumber_warn3", ({expect}) => {
expect.string(Warnings.message(FromNumberLiteral(Float32, "5.5"))).
expect.string(
Warnings.message(FromNumberLiteral(Float32, "Float32", "5.5")),
).
toMatch(
"5.5f",
)
});
test("float64_fromNumber_warn1", ({expect}) => {
expect.string(Warnings.message(FromNumberLiteral(Float64, "5"))).toMatch(
expect.string(
Warnings.message(FromNumberLiteral(Float64, "Float64", "5")),
).
toMatch(
"5.d",
)
});
test("float64_fromNumber_warn2", ({expect}) => {
expect.string(Warnings.message(FromNumberLiteral(Float64, "5."))).
expect.string(
Warnings.message(FromNumberLiteral(Float64, "Float64", "5.")),
).
toMatch(
"5.d",
)
});
test("float64_fromNumber_warn3", ({expect}) => {
expect.string(Warnings.message(FromNumberLiteral(Float64, "5.5"))).
expect.string(
Warnings.message(FromNumberLiteral(Float64, "Float64", "5.5")),
).
toMatch(
"5.5d",
)
Expand Down

0 comments on commit 470f823

Please sign in to comment.