Merge pull request #2354 from rtfeldman/add_builtin_Num.minI128

Add `Num.minI128` builtin
This commit is contained in:
Richard Feldman 2022-01-16 22:38:27 -05:00 committed by GitHub
commit 2ade76b373
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 0 deletions

View file

@ -65,6 +65,7 @@ interface Num
maxI128,
maxInt,
minFloat,
minI128,
minInt,
modInt,
modFloat,
@ -822,6 +823,25 @@ maxU32 : U32
## and zero is the lowest unsigned number. Unsigned numbers cannot be negative.
minU32 : U32
## The highest number that can be stored in an #I128 without overflowing its
## available memory and crashing.
##
## For reference, this number is `170_141_183_460_469_231_731_687_303_715_884_105_727`,
## which is over 2 million.
##
## Note that this is smaller than the positive version of #Int.minI128,
## which means if you call #Num.abs on #Int.minI128, it will overflow and crash!
maxI128 : I128
## The min number that can be stored in an #I128 without underflowing its
## available memory and crashing.
##
## For reference, this number is `-170_141_183_460_469_231_731_687_303_715_884_105_728`.
##
## Note that the positive version of this number is larger than #Int.maxI128,
## which means if you call #Num.abs on #Int.minI128, it will overflow and crash!
minI128 : I128
## The highest supported #F64 value you can have, which is approximately 1.8 × 10^308.
##
## If you go higher than this, your running Roc code will crash - so be careful not to!

View file

@ -397,6 +397,9 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(bool_type()),
);
// minI128 : I128
add_type!(Symbol::NUM_MIN_I128, i128_type());
// maxI128 : I128
add_type!(Symbol::NUM_MAX_I128, i128_type());

View file

@ -206,6 +206,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_SHIFT_RIGHT => num_shift_right_by,
NUM_SHIFT_RIGHT_ZERO_FILL => num_shift_right_zf_by,
NUM_INT_CAST=> num_int_cast,
NUM_MIN_I128=> num_min_i128,
NUM_MAX_I128=> num_max_i128,
NUM_TO_STR => num_to_str,
RESULT_MAP => result_map,
@ -1237,6 +1238,35 @@ fn num_int_cast(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_1(symbol, LowLevel::NumIntCast, var_store)
}
/// Num.minI128: I128
fn num_min_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh();
let int_precision_var = var_store.fresh();
// TODO: or `i128::MIN.into()` ?
let body = int(int_var, int_precision_var, i128::MIN);
let std = roc_builtins::std::types();
let solved = std.get(&symbol).unwrap();
let mut free_vars = roc_types::solved_types::FreeVars::default();
let signature = roc_types::solved_types::to_type(&solved.0, &mut free_vars, var_store);
let annotation = crate::def::Annotation {
signature,
introduced_variables: Default::default(),
region: Region::zero(),
aliases: Default::default(),
};
Def {
// TODO: or `None` ?
annotation: Some(annotation),
expr_var: int_var,
loc_expr: Loc::at_zero(body),
loc_pattern: Loc::at_zero(Pattern::Identifier(symbol)),
pattern_vars: SendMap::default(),
}
}
/// Num.maxI128: I128
fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh();

View file

@ -995,6 +995,7 @@ define_builtins! {
107 NUM_CAST_TO_NAT: "#castToNat"
108 NUM_DIV_CEIL: "divCeil"
109 NUM_TO_STR: "toStr"
110 NUM_MIN_I128: "minI128"
}
2 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias

View file

@ -3341,6 +3341,18 @@ mod solve_expr {
);
}
#[test]
fn min_i128() {
infer_eq_without_problem(
indoc!(
r#"
Num.minI128
"#
),
"I128",
);
}
#[test]
fn max_i128() {
infer_eq_without_problem(

View file

@ -1829,6 +1829,20 @@ fn shift_right_zf_by() {
assert_evals_to!("Num.shiftRightBy 3 0b0000_1100u8", 0b0000_0011, i64);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn min_i128() {
assert_evals_to!(
indoc!(
r#"
Num.minI128
"#
),
i128::MIN,
i128
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn max_i128() {