mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Also store f64 for things like pattern comparisons, etc
This commit is contained in:
parent
adabf70132
commit
d69b9173fc
18 changed files with 195 additions and 252 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3017,6 +3017,7 @@ dependencies = [
|
|||
"roc_region",
|
||||
"roc_reporting",
|
||||
"roc_solve",
|
||||
"roc_std",
|
||||
"roc_types",
|
||||
"roc_unify",
|
||||
"serde_json",
|
||||
|
|
|
@ -21,6 +21,7 @@ roc_mono = { path = "../mono" }
|
|||
roc_load = { path = "../load" }
|
||||
roc_gen_llvm = { path = "../gen_llvm", optional = true }
|
||||
roc_reporting = { path = "../reporting" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
|
|
|
@ -285,11 +285,7 @@ fn lowlevel_4(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
|||
fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let int_var = var_store.fresh();
|
||||
let int_precision_var = var_store.fresh();
|
||||
let body = Int(
|
||||
int_var,
|
||||
int_precision_var,
|
||||
i64::MAX.to_string().into_boxed_str(),
|
||||
);
|
||||
let body = int(int_var, int_precision_var, i64::MAX.into());
|
||||
|
||||
Def {
|
||||
annotation: None,
|
||||
|
@ -304,11 +300,7 @@ fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let int_var = var_store.fresh();
|
||||
let int_precision_var = var_store.fresh();
|
||||
let body = Int(
|
||||
int_var,
|
||||
int_precision_var,
|
||||
i64::MIN.to_string().into_boxed_str(),
|
||||
);
|
||||
let body = int(int_var, int_precision_var, i64::MIN.into());
|
||||
|
||||
Def {
|
||||
annotation: None,
|
||||
|
@ -693,10 +685,7 @@ fn num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::Eq,
|
||||
args: vec![
|
||||
(arg_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
arg_var,
|
||||
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
|
||||
),
|
||||
(arg_var, num(unbound_zero_var, 0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
};
|
||||
|
@ -719,10 +708,7 @@ fn num_is_negative(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op: LowLevel::NumGt,
|
||||
args: vec![
|
||||
(
|
||||
arg_var,
|
||||
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
|
||||
),
|
||||
(arg_var, num(unbound_zero_var, 0)),
|
||||
(arg_var, Var(Symbol::ARG_1)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
|
@ -747,10 +733,7 @@ fn num_is_positive(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::NumGt,
|
||||
args: vec![
|
||||
(arg_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
arg_var,
|
||||
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
|
||||
),
|
||||
(arg_var, num(unbound_zero_var, 0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
};
|
||||
|
@ -773,24 +756,14 @@ fn num_is_odd(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op: LowLevel::Eq,
|
||||
args: vec![
|
||||
(
|
||||
arg_var,
|
||||
Int(
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
1.to_string().into_boxed_str(),
|
||||
),
|
||||
),
|
||||
(arg_var, int(var_store.fresh(), var_store.fresh(), 1)),
|
||||
(
|
||||
arg_var,
|
||||
RunLowLevel {
|
||||
op: LowLevel::NumRemUnchecked,
|
||||
args: vec![
|
||||
(arg_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
arg_var,
|
||||
Num(unbound_two_var, "2".to_string().into_boxed_str()),
|
||||
),
|
||||
(arg_var, num(unbound_two_var, 2)),
|
||||
],
|
||||
ret_var: arg_var,
|
||||
},
|
||||
|
@ -817,14 +790,14 @@ fn num_is_even(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op: LowLevel::Eq,
|
||||
args: vec![
|
||||
(arg_var, Num(arg_num_var, "0".to_string().into_boxed_str())),
|
||||
(arg_var, num(arg_num_var, 0)),
|
||||
(
|
||||
arg_var,
|
||||
RunLowLevel {
|
||||
op: LowLevel::NumRemUnchecked,
|
||||
args: vec![
|
||||
(arg_var, Var(Symbol::ARG_1)),
|
||||
(arg_var, Num(arg_num_var, "2".to_string().into_boxed_str())),
|
||||
(arg_var, num(arg_num_var, 2)),
|
||||
],
|
||||
ret_var: arg_var,
|
||||
},
|
||||
|
@ -878,14 +851,7 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::NumGte,
|
||||
args: vec![
|
||||
(float_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
float_var,
|
||||
Float(
|
||||
unbound_zero_var,
|
||||
precision_var,
|
||||
"0.0".to_string().into_boxed_str(),
|
||||
),
|
||||
),
|
||||
(float_var, float(unbound_zero_var, precision_var, 0.0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
}),
|
||||
|
@ -931,14 +897,7 @@ fn num_log(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::NumGt,
|
||||
args: vec![
|
||||
(float_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
float_var,
|
||||
Float(
|
||||
unbound_zero_var,
|
||||
precision_var,
|
||||
"0.0".to_string().into_boxed_str(),
|
||||
),
|
||||
),
|
||||
(float_var, float(unbound_zero_var, precision_var, 0.0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
}),
|
||||
|
@ -1168,11 +1127,7 @@ fn num_int_cast(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let int_var = var_store.fresh();
|
||||
let int_precision_var = var_store.fresh();
|
||||
let body = Int(
|
||||
int_var,
|
||||
int_precision_var,
|
||||
i128::MAX.to_string().into_boxed_str(),
|
||||
);
|
||||
let body = int(int_var, int_precision_var, i128::MAX);
|
||||
|
||||
let std = roc_builtins::std::types();
|
||||
let solved = std.get(&symbol).unwrap();
|
||||
|
@ -1205,10 +1160,7 @@ fn list_is_empty(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op: LowLevel::Eq,
|
||||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
|
||||
),
|
||||
(len_var, num(unbound_zero_var, 0)),
|
||||
(
|
||||
len_var,
|
||||
RunLowLevel {
|
||||
|
@ -2087,10 +2039,7 @@ fn list_sum(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(list_var, Var(Symbol::ARG_1)),
|
||||
(closure_var, list_sum_add(num_var, var_store)),
|
||||
(
|
||||
num_var,
|
||||
Num(var_store.fresh(), "0".to_string().into_boxed_str()),
|
||||
),
|
||||
(num_var, num(var_store.fresh(), 0)),
|
||||
],
|
||||
ret_var,
|
||||
};
|
||||
|
@ -2132,10 +2081,7 @@ fn list_product(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(list_var, Var(Symbol::ARG_1)),
|
||||
(closure_var, list_product_mul(num_var, var_store)),
|
||||
(
|
||||
num_var,
|
||||
Num(var_store.fresh(), "1".to_string().into_boxed_str()),
|
||||
),
|
||||
(num_var, num(var_store.fresh(), 1)),
|
||||
],
|
||||
ret_var,
|
||||
};
|
||||
|
@ -2613,10 +2559,7 @@ fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::NotEq,
|
||||
args: vec![
|
||||
(num_var, Var(Symbol::ARG_2)),
|
||||
(
|
||||
num_var,
|
||||
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
|
||||
),
|
||||
(num_var, num(unbound_zero_var, 0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
},
|
||||
|
@ -2719,14 +2662,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::NotEq,
|
||||
args: vec![
|
||||
(num_var, Var(Symbol::ARG_2)),
|
||||
(
|
||||
num_var,
|
||||
Float(
|
||||
unbound_zero_var,
|
||||
precision_var,
|
||||
"0.0".to_string().into_boxed_str(),
|
||||
),
|
||||
),
|
||||
(num_var, float(unbound_zero_var, precision_var, 0.0)),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
},
|
||||
|
@ -2791,11 +2727,7 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
(num_var, Var(Symbol::ARG_2)),
|
||||
(
|
||||
num_var,
|
||||
Int(
|
||||
unbound_zero_var,
|
||||
unbound_zero_precision_var,
|
||||
0.to_string().into_boxed_str(),
|
||||
),
|
||||
int(unbound_zero_var, unbound_zero_precision_var, 0),
|
||||
),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
|
@ -2865,10 +2797,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
RunLowLevel {
|
||||
op: LowLevel::NotEq,
|
||||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
Int(zero_var, zero_precision_var, 0.to_string().into_boxed_str()),
|
||||
),
|
||||
(len_var, int(zero_var, zero_precision_var, 0)),
|
||||
(
|
||||
len_var,
|
||||
RunLowLevel {
|
||||
|
@ -2892,14 +2821,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
op: LowLevel::ListGetUnsafe,
|
||||
args: vec![
|
||||
(list_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
len_var,
|
||||
Int(
|
||||
zero_var,
|
||||
zero_precision_var,
|
||||
0.to_string().into_boxed_str(),
|
||||
),
|
||||
),
|
||||
(len_var, int(zero_var, zero_precision_var, 0)),
|
||||
],
|
||||
ret_var: list_elem_var,
|
||||
},
|
||||
|
@ -2956,10 +2878,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
RunLowLevel {
|
||||
op: LowLevel::NotEq,
|
||||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
Int(num_var, num_precision_var, 0.to_string().into_boxed_str()),
|
||||
),
|
||||
(len_var, int(num_var, num_precision_var, 0)),
|
||||
(
|
||||
len_var,
|
||||
RunLowLevel {
|
||||
|
@ -2998,14 +2917,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
ret_var: len_var,
|
||||
},
|
||||
),
|
||||
(
|
||||
arg_var,
|
||||
Int(
|
||||
num_var,
|
||||
num_precision_var,
|
||||
1.to_string().into_boxed_str(),
|
||||
),
|
||||
),
|
||||
(arg_var, int(num_var, num_precision_var, 1)),
|
||||
],
|
||||
ret_var: len_var,
|
||||
},
|
||||
|
@ -3474,3 +3386,18 @@ fn defn_help(
|
|||
loc_body: Box::new(no_region(body)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn int(num_var: Variable, precision_var: Variable, i: i128) -> Expr {
|
||||
Int(num_var, precision_var, i.to_string().into_boxed_str(), i)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn float(num_var: Variable, precision_var: Variable, f: f64) -> Expr {
|
||||
Float(num_var, precision_var, f.to_string().into_boxed_str(), f)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn num(num_var: Variable, i: i64) -> Expr {
|
||||
Num(num_var, i.to_string().into_boxed_str(), i)
|
||||
}
|
||||
|
|
|
@ -742,9 +742,9 @@ fn pattern_to_vars_by_symbol(
|
|||
}
|
||||
}
|
||||
|
||||
NumLiteral(_, _)
|
||||
| IntLiteral(_, _)
|
||||
| FloatLiteral(_, _)
|
||||
NumLiteral(_, _, _)
|
||||
| IntLiteral(_, _, _)
|
||||
| FloatLiteral(_, _, _)
|
||||
| StrLiteral(_)
|
||||
| Underscore
|
||||
| MalformedPattern(_, _)
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::builtins::builtin_defs_map;
|
|||
use crate::def::{can_defs_with_return, Def};
|
||||
use crate::env::Env;
|
||||
use crate::num::{
|
||||
finish_parsing_base, finish_parsing_int, float_expr_from_result, int_expr_from_result,
|
||||
num_expr_from_result, validate_float_str,
|
||||
finish_parsing_base, finish_parsing_float, finish_parsing_int, float_expr_from_result,
|
||||
int_expr_from_result, num_expr_from_result,
|
||||
};
|
||||
use crate::pattern::{canonicalize_pattern, Pattern};
|
||||
use crate::procedure::References;
|
||||
|
@ -52,11 +52,11 @@ pub enum Expr {
|
|||
|
||||
// Num stores the `a` variable in `Num a`. Not the same as the variable
|
||||
// stored in Int and Float below, which is strictly for better error messages
|
||||
Num(Variable, Box<str>),
|
||||
Num(Variable, Box<str>, i64),
|
||||
|
||||
// Int and Float store a variable to generate better error messages
|
||||
Int(Variable, Variable, Box<str>),
|
||||
Float(Variable, Variable, Box<str>),
|
||||
Int(Variable, Variable, Box<str>, i128),
|
||||
Float(Variable, Variable, Box<str>, f64),
|
||||
Str(Box<str>),
|
||||
List {
|
||||
elem_var: Variable,
|
||||
|
@ -206,10 +206,10 @@ pub fn canonicalize_expr<'a>(
|
|||
use Expr::*;
|
||||
|
||||
let (expr, output) = match expr {
|
||||
ast::Expr::Num(string) => {
|
||||
ast::Expr::Num(str) => {
|
||||
let answer = num_expr_from_result(
|
||||
var_store,
|
||||
finish_parsing_int(*string).map(|_| *string),
|
||||
finish_parsing_int(*str).map(|int| (*str, int)),
|
||||
region,
|
||||
env,
|
||||
);
|
||||
|
@ -219,7 +219,7 @@ pub fn canonicalize_expr<'a>(
|
|||
ast::Expr::Float(str) => {
|
||||
let answer = float_expr_from_result(
|
||||
var_store,
|
||||
validate_float_str(str).map(|()| *str),
|
||||
finish_parsing_float(str).map(|f| (*str, f)),
|
||||
region,
|
||||
env,
|
||||
);
|
||||
|
@ -810,7 +810,7 @@ pub fn canonicalize_expr<'a>(
|
|||
// to keep borrowed values around and make this compile
|
||||
let int_string = int.to_string();
|
||||
let int_str = int_string.as_str();
|
||||
int_expr_from_result(var_store, Ok(int_str), region, *base, env)
|
||||
int_expr_from_result(var_store, Ok((int_str, int as i128)), region, *base, env)
|
||||
}
|
||||
Err(e) => int_expr_from_result(var_store, Err(e), region, *base, env),
|
||||
};
|
||||
|
@ -1234,9 +1234,9 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
|||
match expr {
|
||||
// Num stores the `a` variable in `Num a`. Not the same as the variable
|
||||
// stored in Int and Float below, which is strictly for better error messages
|
||||
other @ Num(_, _)
|
||||
| other @ Int(_, _, _)
|
||||
| other @ Float(_, _, _)
|
||||
other @ Num(_, _, _)
|
||||
| other @ Int(_, _, _, _)
|
||||
| other @ Float(_, _, _, _)
|
||||
| other @ Str { .. }
|
||||
| other @ RuntimeError(_)
|
||||
| other @ EmptyRecord
|
||||
|
|
|
@ -382,9 +382,9 @@ fn fix_values_captured_in_closure_pattern(
|
|||
}
|
||||
}
|
||||
Identifier(_)
|
||||
| NumLiteral(_, _)
|
||||
| IntLiteral(_, _)
|
||||
| FloatLiteral(_, _)
|
||||
| NumLiteral(_, _, _)
|
||||
| IntLiteral(_, _, _)
|
||||
| FloatLiteral(_, _, _)
|
||||
| StrLiteral(_)
|
||||
| Underscore
|
||||
| Shadowed(_, _)
|
||||
|
@ -438,9 +438,9 @@ fn fix_values_captured_in_closure_expr(
|
|||
fix_values_captured_in_closure_expr(&mut loc_body.value, no_capture_symbols);
|
||||
}
|
||||
|
||||
Num(_, _)
|
||||
| Int(_, _, _)
|
||||
| Float(_, _, _)
|
||||
Num(_, _, _)
|
||||
| Int(_, _, _, _)
|
||||
| Float(_, _, _, _)
|
||||
| Str(_)
|
||||
| Var(_)
|
||||
| EmptyRecord
|
||||
|
|
|
@ -16,12 +16,12 @@ use std::i64;
|
|||
#[inline(always)]
|
||||
pub fn num_expr_from_result(
|
||||
var_store: &mut VarStore,
|
||||
result: Result<&str, (&str, IntErrorKind)>,
|
||||
result: Result<(&str, i64), (&str, IntErrorKind)>,
|
||||
region: Region,
|
||||
env: &mut Env,
|
||||
) -> Expr {
|
||||
match result {
|
||||
Ok(str) => Expr::Num(var_store.fresh(), (*str).into()),
|
||||
Ok((str, num)) => Expr::Num(var_store.fresh(), (*str).into(), num),
|
||||
Err((raw, error)) => {
|
||||
// (Num *) compiles to Int if it doesn't
|
||||
// get specialized to something else first,
|
||||
|
@ -38,14 +38,14 @@ pub fn num_expr_from_result(
|
|||
#[inline(always)]
|
||||
pub fn int_expr_from_result(
|
||||
var_store: &mut VarStore,
|
||||
result: Result<&str, (&str, IntErrorKind)>,
|
||||
result: Result<(&str, i128), (&str, IntErrorKind)>,
|
||||
region: Region,
|
||||
base: Base,
|
||||
env: &mut Env,
|
||||
) -> Expr {
|
||||
// Int stores a variable to generate better error messages
|
||||
match result {
|
||||
Ok(str) => Expr::Int(var_store.fresh(), var_store.fresh(), (*str).into()),
|
||||
Ok((str, int)) => Expr::Int(var_store.fresh(), var_store.fresh(), (*str).into(), int),
|
||||
Err((raw, error)) => {
|
||||
let runtime_error = InvalidInt(error, base, region, raw.into());
|
||||
|
||||
|
@ -59,13 +59,13 @@ pub fn int_expr_from_result(
|
|||
#[inline(always)]
|
||||
pub fn float_expr_from_result(
|
||||
var_store: &mut VarStore,
|
||||
result: Result<&str, (&str, FloatErrorKind)>,
|
||||
result: Result<(&str, f64), (&str, FloatErrorKind)>,
|
||||
region: Region,
|
||||
env: &mut Env,
|
||||
) -> Expr {
|
||||
// Float stores a variable to generate better error messages
|
||||
match result {
|
||||
Ok(str) => Expr::Float(var_store.fresh(), var_store.fresh(), (*str).into()),
|
||||
Ok((str, float)) => Expr::Float(var_store.fresh(), var_store.fresh(), (*str).into(), float),
|
||||
Err((raw, error)) => {
|
||||
let runtime_error = InvalidFloat(error, region, raw.into());
|
||||
|
||||
|
@ -77,12 +77,10 @@ pub fn float_expr_from_result(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn finish_parsing_int(raw: &str) -> Result<&str, (&str, IntErrorKind)> {
|
||||
pub fn finish_parsing_int(raw: &str) -> Result<i64, (&str, IntErrorKind)> {
|
||||
// Ignore underscores.
|
||||
let radix = 10;
|
||||
from_str_radix::<i64>(raw.replace("_", "").as_str(), radix)
|
||||
.map(|_| raw)
|
||||
.map_err(|e| (raw, e.kind))
|
||||
from_str_radix::<i64>(raw.replace("_", "").as_str(), radix).map_err(|e| (raw, e.kind))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -108,10 +106,10 @@ pub fn finish_parsing_base(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn validate_float_str(raw: &str) -> Result<(), (&str, FloatErrorKind)> {
|
||||
pub fn finish_parsing_float(raw: &str) -> Result<f64, (&str, FloatErrorKind)> {
|
||||
// Ignore underscores.
|
||||
match raw.replace("_", "").parse::<f64>() {
|
||||
Ok(float) if float.is_finite() => Ok(()),
|
||||
Ok(float) if float.is_finite() => Ok(float),
|
||||
Ok(float) => {
|
||||
if float.is_sign_positive() {
|
||||
Err((raw, FloatErrorKind::PositiveInfinity))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::env::Env;
|
||||
use crate::expr::{canonicalize_expr, unescape_char, Expr, Output};
|
||||
use crate::num::{finish_parsing_base, finish_parsing_int, validate_float_str};
|
||||
use crate::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
|
||||
use crate::scope::Scope;
|
||||
use roc_module::ident::{Ident, Lowercase, TagName};
|
||||
use roc_module::symbol::Symbol;
|
||||
|
@ -25,9 +25,9 @@ pub enum Pattern {
|
|||
ext_var: Variable,
|
||||
destructs: Vec<Located<RecordDestruct>>,
|
||||
},
|
||||
IntLiteral(Variable, Box<str>),
|
||||
NumLiteral(Variable, Box<str>),
|
||||
FloatLiteral(Variable, Box<str>),
|
||||
IntLiteral(Variable, Box<str>, i64),
|
||||
NumLiteral(Variable, Box<str>, i64),
|
||||
FloatLiteral(Variable, Box<str>, f64),
|
||||
StrLiteral(Box<str>),
|
||||
Underscore,
|
||||
|
||||
|
@ -85,9 +85,9 @@ pub fn symbols_from_pattern_help(pattern: &Pattern, symbols: &mut Vec<Symbol>) {
|
|||
}
|
||||
}
|
||||
|
||||
NumLiteral(_, _)
|
||||
| IntLiteral(_, _)
|
||||
| FloatLiteral(_, _)
|
||||
NumLiteral(_, _, _)
|
||||
| IntLiteral(_, _, _)
|
||||
| FloatLiteral(_, _, _)
|
||||
| StrLiteral(_)
|
||||
| Underscore
|
||||
| MalformedPattern(_, _)
|
||||
|
@ -186,12 +186,12 @@ pub fn canonicalize_pattern<'a>(
|
|||
}
|
||||
|
||||
FloatLiteral(str) => match pattern_type {
|
||||
WhenBranch => match validate_float_str(str) {
|
||||
WhenBranch => match finish_parsing_float(str) {
|
||||
Err(_error) => {
|
||||
let problem = MalformedPatternProblem::MalformedFloat;
|
||||
malformed_pattern(env, problem, region)
|
||||
}
|
||||
Ok(_float) => Pattern::FloatLiteral(var_store.fresh(), (*str).into()),
|
||||
Ok(float) => Pattern::FloatLiteral(var_store.fresh(), (*str).into(), float),
|
||||
},
|
||||
ptype => unsupported_pattern(env, ptype, region),
|
||||
},
|
||||
|
@ -207,7 +207,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
let problem = MalformedPatternProblem::MalformedInt;
|
||||
malformed_pattern(env, problem, region)
|
||||
}
|
||||
Ok(_int) => Pattern::NumLiteral(var_store.fresh(), (*str).into()),
|
||||
Ok(int) => Pattern::NumLiteral(var_store.fresh(), (*str).into(), int),
|
||||
},
|
||||
ptype => unsupported_pattern(env, ptype, region),
|
||||
},
|
||||
|
@ -225,7 +225,8 @@ pub fn canonicalize_pattern<'a>(
|
|||
Ok(int) => {
|
||||
let sign_str = if *is_negative { "-" } else { "" };
|
||||
let int_str = format!("{}{}", sign_str, int.to_string()).into_boxed_str();
|
||||
Pattern::IntLiteral(var_store.fresh(), int_str)
|
||||
let i = if *is_negative { -int } else { int };
|
||||
Pattern::IntLiteral(var_store.fresh(), int_str, i)
|
||||
}
|
||||
},
|
||||
ptype => unsupported_pattern(env, ptype, region),
|
||||
|
@ -471,9 +472,9 @@ fn add_bindings_from_patterns(
|
|||
answer.push((*symbol, *region));
|
||||
}
|
||||
}
|
||||
NumLiteral(_, _)
|
||||
| IntLiteral(_, _)
|
||||
| FloatLiteral(_, _)
|
||||
NumLiteral(_, _, _)
|
||||
| IntLiteral(_, _, _)
|
||||
| FloatLiteral(_, _, _)
|
||||
| StrLiteral(_)
|
||||
| Underscore
|
||||
| Shadowed(_, _)
|
||||
|
|
|
@ -96,8 +96,8 @@ pub fn constrain_expr(
|
|||
expected: Expected<Type>,
|
||||
) -> Constraint {
|
||||
match expr {
|
||||
Int(var, precision, _) => int_literal(*var, *precision, expected, region),
|
||||
Num(var, _) => exists(
|
||||
Int(var, precision, _, _) => int_literal(*var, *precision, expected, region),
|
||||
Num(var, _, _) => exists(
|
||||
vec![*var],
|
||||
Eq(
|
||||
crate::builtins::num_num(Type::Variable(*var)),
|
||||
|
@ -106,7 +106,7 @@ pub fn constrain_expr(
|
|||
region,
|
||||
),
|
||||
),
|
||||
Float(var, precision, _) => float_literal(*var, *precision, expected, region),
|
||||
Float(var, precision, _, _) => float_literal(*var, *precision, expected, region),
|
||||
EmptyRecord => constrain_empty_record(region, expected),
|
||||
Expr::Record { record_var, fields } => {
|
||||
if fields.is_empty() {
|
||||
|
|
|
@ -56,9 +56,9 @@ fn headers_from_annotation_help(
|
|||
| Shadowed(_, _)
|
||||
| MalformedPattern(_, _)
|
||||
| UnsupportedPattern(_)
|
||||
| NumLiteral(_, _)
|
||||
| IntLiteral(_, _)
|
||||
| FloatLiteral(_, _)
|
||||
| NumLiteral(_, _, _)
|
||||
| IntLiteral(_, _, _)
|
||||
| FloatLiteral(_, _, _)
|
||||
| StrLiteral(_) => true,
|
||||
|
||||
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
||||
|
@ -143,7 +143,7 @@ pub fn constrain_pattern(
|
|||
);
|
||||
}
|
||||
|
||||
NumLiteral(var, _) => {
|
||||
NumLiteral(var, _, _) => {
|
||||
state.vars.push(*var);
|
||||
|
||||
state.constraints.push(Constraint::Pattern(
|
||||
|
@ -154,7 +154,7 @@ pub fn constrain_pattern(
|
|||
));
|
||||
}
|
||||
|
||||
IntLiteral(precision_var, _) => {
|
||||
IntLiteral(precision_var, _, _) => {
|
||||
state.constraints.push(Constraint::Pattern(
|
||||
region,
|
||||
PatternCategory::Int,
|
||||
|
@ -163,7 +163,7 @@ pub fn constrain_pattern(
|
|||
));
|
||||
}
|
||||
|
||||
FloatLiteral(precision_var, _) => {
|
||||
FloatLiteral(precision_var, _, _) => {
|
||||
state.constraints.push(Constraint::Pattern(
|
||||
region,
|
||||
PatternCategory::Float,
|
||||
|
|
|
@ -16,6 +16,7 @@ roc_builtins = { path = "../builtins" }
|
|||
roc_unify = { path = "../unify" }
|
||||
roc_solve = { path = "../solve" }
|
||||
roc_mono = { path = "../mono" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
morphic_lib = { path = "../../vendor/morphic_lib" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
|
@ -29,7 +30,6 @@ roc_parse = { path = "../parse" }
|
|||
roc_load = { path = "../load" }
|
||||
roc_reporting = { path = "../reporting" }
|
||||
roc_build = { path = "../build" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
pretty_assertions = "0.5.1"
|
||||
maplit = "1.0.1"
|
||||
indoc = "0.3.3"
|
||||
|
|
|
@ -54,6 +54,7 @@ use roc_mono::ir::{
|
|||
BranchInfo, CallType, EntryPoint, ExceptionId, JoinPointId, ModifyRc, OptLevel, ProcLayout,
|
||||
};
|
||||
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, UnionLayout};
|
||||
use roc_std::RocDec;
|
||||
|
||||
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
|
||||
/// output in debug builds, but we don't want it to print to stdout in release builds!
|
||||
|
@ -620,15 +621,18 @@ pub fn int_with_precision<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn float_with_precision<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
value_str: &str,
|
||||
value: f64,
|
||||
precision: &Builtin,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match precision {
|
||||
Builtin::Decimal => call_bitcode_fn(
|
||||
env,
|
||||
&[env.context.f64_type().const_float(value).into()],
|
||||
bitcode::DEC_FROM_F64,
|
||||
),
|
||||
Builtin::Decimal => {
|
||||
let dec = match RocDec::from_str(value_str) {
|
||||
Some(d) => d.0,
|
||||
None => panic!("Invalid decimal for float literal = {}. TODO: Make this a nice, user-friendly error message", value),
|
||||
};
|
||||
env.context.i128_type().const_int(dec as u64, false).into()
|
||||
}
|
||||
Builtin::Float64 => env.context.f64_type().const_float(value).into(),
|
||||
Builtin::Float32 => env.context.f32_type().const_float(value).into(),
|
||||
_ => panic!("Invalid layout for float literal = {:?}", precision),
|
||||
|
@ -648,8 +652,8 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
|
|||
_ => panic!("Invalid layout for int literal = {:?}", layout),
|
||||
},
|
||||
|
||||
Float(float) => match layout {
|
||||
Layout::Builtin(builtin) => float_with_precision(env, *float, builtin),
|
||||
Float(float_str, float) => match layout {
|
||||
Layout::Builtin(builtin) => float_with_precision(env, *float_str, *float, builtin),
|
||||
_ => panic!("Invalid layout for float literal = {:?}", layout),
|
||||
},
|
||||
|
||||
|
|
|
@ -1207,7 +1207,7 @@ fn literal_spec(
|
|||
|
||||
match literal {
|
||||
Str(_) => new_static_string(builder, block),
|
||||
Int(_) | Float(_) | Bool(_) | Byte(_) => builder.add_make_tuple(block, &[]),
|
||||
Int(_) | Float(_, _) | Bool(_) | Byte(_) => builder.add_make_tuple(block, &[]),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,8 +85,7 @@ enum Test<'a> {
|
|||
arguments: Vec<(Pattern<'a>, Layout<'a>)>,
|
||||
},
|
||||
IsInt(i128),
|
||||
// float patterns are stored as u64 so they are comparable/hashable
|
||||
IsFloat(u64),
|
||||
IsFloat(Box<str>, u64),
|
||||
IsStr(Box<str>),
|
||||
IsBit(bool),
|
||||
IsByte {
|
||||
|
@ -109,7 +108,7 @@ impl<'a> Hash for Test<'a> {
|
|||
state.write_u8(1);
|
||||
v.hash(state);
|
||||
}
|
||||
IsFloat(v) => {
|
||||
IsFloat(_, v) => {
|
||||
state.write_u8(2);
|
||||
v.hash(state);
|
||||
}
|
||||
|
@ -301,7 +300,7 @@ fn tests_are_complete_help(last_test: &Test, number_of_tests: usize) -> bool {
|
|||
Test::IsByte { num_alts, .. } => number_of_tests == *num_alts,
|
||||
Test::IsBit(_) => number_of_tests == 2,
|
||||
Test::IsInt(_) => false,
|
||||
Test::IsFloat(_) => false,
|
||||
Test::IsFloat(_, _) => false,
|
||||
Test::IsStr(_) => false,
|
||||
}
|
||||
}
|
||||
|
@ -555,7 +554,7 @@ fn test_at_path<'a>(
|
|||
num_alts: union.alternatives.len(),
|
||||
},
|
||||
IntLiteral(v) => IsInt(*v),
|
||||
FloatLiteral(v) => IsFloat(*v),
|
||||
FloatLiteral(s, v) => IsFloat(s.clone(), *v),
|
||||
StrLiteral(v) => IsStr(v.clone()),
|
||||
};
|
||||
|
||||
|
@ -811,8 +810,8 @@ fn to_relevant_branch_help<'a>(
|
|||
_ => None,
|
||||
},
|
||||
|
||||
FloatLiteral(float) => match test {
|
||||
IsFloat(test_float) if float == *test_float => {
|
||||
FloatLiteral(_, float) => match test {
|
||||
IsFloat(_, test_float) if float == *test_float => {
|
||||
start.extend(end);
|
||||
Some(Branch {
|
||||
goal: branch.goal,
|
||||
|
@ -909,7 +908,7 @@ fn needs_tests(pattern: &Pattern) -> bool {
|
|||
| BitLiteral { .. }
|
||||
| EnumLiteral { .. }
|
||||
| IntLiteral(_)
|
||||
| FloatLiteral(_)
|
||||
| FloatLiteral(_, _)
|
||||
| StrLiteral(_) => true,
|
||||
}
|
||||
}
|
||||
|
@ -1269,10 +1268,10 @@ fn test_to_equality<'a>(
|
|||
(stores, lhs_symbol, rhs_symbol, None)
|
||||
}
|
||||
|
||||
Test::IsFloat(test_int) => {
|
||||
Test::IsFloat(test_str, test_int) => {
|
||||
// TODO maybe we can actually use i64 comparison here?
|
||||
let test_float = f64::from_bits(test_int as u64);
|
||||
let lhs = Expr::Literal(Literal::Float(test_float));
|
||||
let lhs = Expr::Literal(Literal::Float(env.arena.alloc(test_str), test_float));
|
||||
let lhs_symbol = env.unique_symbol();
|
||||
stores.push((lhs_symbol, Layout::Builtin(Builtin::Float64), lhs));
|
||||
|
||||
|
@ -1709,7 +1708,7 @@ fn decide_to_branching<'a>(
|
|||
|
||||
let tag = match test {
|
||||
Test::IsInt(v) => v as u64,
|
||||
Test::IsFloat(v) => v as u64,
|
||||
Test::IsFloat(_, v) => v as u64,
|
||||
Test::IsBit(v) => v as u64,
|
||||
Test::IsByte { tag_id, .. } => tag_id as u64,
|
||||
Test::IsCtor { tag_id, .. } => tag_id as u64,
|
||||
|
|
|
@ -55,7 +55,7 @@ pub enum Literal {
|
|||
Int(i128),
|
||||
Bit(bool),
|
||||
Byte(u8),
|
||||
Float(u64),
|
||||
Float(Box<str>, u64),
|
||||
Str(Box<str>),
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ fn simplify(pattern: &crate::ir::Pattern) -> Pattern {
|
|||
|
||||
match pattern {
|
||||
IntLiteral(v) => Literal(Literal::Int(*v)),
|
||||
FloatLiteral(v) => Literal(Literal::Float(*v)),
|
||||
FloatLiteral(s, v) => Literal(Literal::Float(s.clone(), *v)),
|
||||
StrLiteral(v) => Literal(Literal::Str(v.clone())),
|
||||
|
||||
// To make sure these are exhaustive, we have to "fake" a union here
|
||||
|
|
|
@ -1016,7 +1016,7 @@ impl ModifyRc {
|
|||
pub enum Literal<'a> {
|
||||
// Literals
|
||||
Int(i128),
|
||||
Float(f64),
|
||||
Float(&'a str, f64),
|
||||
Str(&'a str),
|
||||
/// Closed tag unions containing exactly two (0-arity) tags compile to Expr::Bool,
|
||||
/// so they can (at least potentially) be emitted as 1-bit machine bools.
|
||||
|
@ -1197,7 +1197,7 @@ impl<'a> Literal<'a> {
|
|||
|
||||
match self {
|
||||
Int(lit) => alloc.text(format!("{}i64", lit)),
|
||||
Float(lit) => alloc.text(format!("{}f64", lit)),
|
||||
Float(_, lit) => alloc.text(format!("{}f64", lit)),
|
||||
Bool(lit) => alloc.text(format!("{}", lit)),
|
||||
Byte(lit) => alloc.text(format!("{}u8", lit)),
|
||||
Str(lit) => alloc.text(format!("{:?}", lit)),
|
||||
|
@ -1729,7 +1729,7 @@ fn pattern_to_when<'a>(
|
|||
(symbol, Located::at_zero(wrapped_body))
|
||||
}
|
||||
|
||||
IntLiteral(_, _) | NumLiteral(_, _) | FloatLiteral(_, _) | StrLiteral(_) => {
|
||||
IntLiteral(_, _, _) | NumLiteral(_, _, _) | FloatLiteral(_, _, _) | StrLiteral(_) => {
|
||||
// These patters are refutable, and thus should never occur outside a `when` expression
|
||||
// They should have been replaced with `UnsupportedPattern` during canonicalization
|
||||
unreachable!("refutable pattern {:?} where irrefutable pattern is expected. This should never happen!", pattern.value)
|
||||
|
@ -2707,17 +2707,17 @@ pub fn with_hole<'a>(
|
|||
let arena = env.arena;
|
||||
|
||||
match can_expr {
|
||||
Int(_, precision, num) => {
|
||||
Int(_, precision, _, int) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, false) {
|
||||
IntOrFloat::SignedIntType(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(num)),
|
||||
Expr::Literal(Literal::Int(int)),
|
||||
Layout::Builtin(int_precision_to_builtin(precision)),
|
||||
hole,
|
||||
),
|
||||
IntOrFloat::UnsignedIntType(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(num)),
|
||||
Expr::Literal(Literal::Int(int)),
|
||||
Layout::Builtin(int_precision_to_builtin(precision)),
|
||||
hole,
|
||||
),
|
||||
|
@ -2725,17 +2725,17 @@ pub fn with_hole<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
Float(_, precision, num) => {
|
||||
Float(_, precision, float_str, float) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, true) {
|
||||
IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Float(num as f64)),
|
||||
Expr::Literal(Literal::Float(arena.alloc(float_str), float)),
|
||||
Layout::Builtin(float_precision_to_builtin(precision)),
|
||||
hole,
|
||||
),
|
||||
IntOrFloat::DecimalFloatType => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Float(num as f64)),
|
||||
Expr::Literal(Literal::Float(arena.alloc(float_str), float)),
|
||||
Layout::Builtin(Builtin::Decimal),
|
||||
hole,
|
||||
),
|
||||
|
@ -2750,7 +2750,8 @@ pub fn with_hole<'a>(
|
|||
hole,
|
||||
),
|
||||
|
||||
Num(var, num) => match num_argument_to_int_or_float(env.subs, env.ptr_bytes, var, false) {
|
||||
Num(var, num_str, num) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, var, false) {
|
||||
IntOrFloat::SignedIntType(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(num.into())),
|
||||
|
@ -2765,17 +2766,18 @@ pub fn with_hole<'a>(
|
|||
),
|
||||
IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Float(num as f64)),
|
||||
Expr::Literal(Literal::Float(arena.alloc(num_str), num as f64)),
|
||||
Layout::Builtin(float_precision_to_builtin(precision)),
|
||||
hole,
|
||||
),
|
||||
IntOrFloat::DecimalFloatType => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Float(num as f64)),
|
||||
Expr::Literal(Literal::Float(arena.alloc(num_str), num as f64)),
|
||||
Layout::Builtin(Builtin::Decimal),
|
||||
hole,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
LetNonRec(def, cont, _) => {
|
||||
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
|
||||
if let Closure {
|
||||
|
@ -5523,7 +5525,7 @@ fn store_pattern_help<'a>(
|
|||
return StorePattern::NotProductive(stmt);
|
||||
}
|
||||
IntLiteral(_)
|
||||
| FloatLiteral(_)
|
||||
| FloatLiteral(_, _)
|
||||
| EnumLiteral { .. }
|
||||
| BitLiteral { .. }
|
||||
| StrLiteral(_) => {
|
||||
|
@ -5657,7 +5659,7 @@ fn store_tag_pattern<'a>(
|
|||
// ignore
|
||||
}
|
||||
IntLiteral(_)
|
||||
| FloatLiteral(_)
|
||||
| FloatLiteral(_, _)
|
||||
| EnumLiteral { .. }
|
||||
| BitLiteral { .. }
|
||||
| StrLiteral(_) => {}
|
||||
|
@ -5732,7 +5734,7 @@ fn store_newtype_pattern<'a>(
|
|||
// ignore
|
||||
}
|
||||
IntLiteral(_)
|
||||
| FloatLiteral(_)
|
||||
| FloatLiteral(_, _)
|
||||
| EnumLiteral { .. }
|
||||
| BitLiteral { .. }
|
||||
| StrLiteral(_) => {}
|
||||
|
@ -5807,7 +5809,7 @@ fn store_record_destruct<'a>(
|
|||
return StorePattern::NotProductive(stmt);
|
||||
}
|
||||
IntLiteral(_)
|
||||
| FloatLiteral(_)
|
||||
| FloatLiteral(_, _)
|
||||
| EnumLiteral { .. }
|
||||
| BitLiteral { .. }
|
||||
| StrLiteral(_) => {
|
||||
|
@ -6782,7 +6784,7 @@ pub enum Pattern<'a> {
|
|||
Identifier(Symbol),
|
||||
Underscore,
|
||||
IntLiteral(i128),
|
||||
FloatLiteral(u64),
|
||||
FloatLiteral(Box<str>, u64),
|
||||
BitLiteral {
|
||||
value: bool,
|
||||
tag_name: TagName,
|
||||
|
@ -6859,8 +6861,11 @@ fn from_can_pattern_help<'a>(
|
|||
match can_pattern {
|
||||
Underscore => Ok(Pattern::Underscore),
|
||||
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
||||
IntLiteral(_, int) => Ok(Pattern::IntLiteral(*int as i128)),
|
||||
FloatLiteral(_, float) => Ok(Pattern::FloatLiteral(f64::to_bits(*float))),
|
||||
IntLiteral(_, _, int) => Ok(Pattern::IntLiteral(*int as i128)),
|
||||
FloatLiteral(_, float_str, float) => Ok(Pattern::FloatLiteral(
|
||||
float_str.clone(),
|
||||
f64::to_bits(*float),
|
||||
)),
|
||||
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
||||
Shadowed(region, ident) => Err(RuntimeError::Shadowing {
|
||||
original_region: *region,
|
||||
|
@ -6871,12 +6876,16 @@ fn from_can_pattern_help<'a>(
|
|||
// TODO preserve malformed problem information here?
|
||||
Err(RuntimeError::UnsupportedPattern(*region))
|
||||
}
|
||||
NumLiteral(var, num) => {
|
||||
NumLiteral(var, num_str, num) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
|
||||
IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)),
|
||||
IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)),
|
||||
IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(*num as u64)),
|
||||
IntOrFloat::DecimalFloatType => Ok(Pattern::FloatLiteral(*num as u64)),
|
||||
IntOrFloat::BinaryFloatType(_) => {
|
||||
Ok(Pattern::FloatLiteral(num_str.clone(), *num as u64))
|
||||
}
|
||||
IntOrFloat::DecimalFloatType => {
|
||||
Ok(Pattern::FloatLiteral(num_str.clone(), *num as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ fn pattern_to_doc_help<'b>(
|
|||
Bit(true) => alloc.text("True"),
|
||||
Bit(false) => alloc.text("False"),
|
||||
Byte(b) => alloc.text(b.to_string()),
|
||||
Float(f) => alloc.text(f.to_string()),
|
||||
Float(_, f) => alloc.text(f.to_string()),
|
||||
Str(s) => alloc.string(s.into()),
|
||||
},
|
||||
Ctor(union, tag_id, args) => {
|
||||
|
|
|
@ -731,11 +731,9 @@ impl RocDec {
|
|||
}
|
||||
};
|
||||
|
||||
let after_point = match parts.next() {
|
||||
Some(answer) if answer.len() <= Self::DECIMAL_PLACES as usize => answer,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
let opt_after_point = match parts.next() {
|
||||
Some(answer) if answer.len() <= Self::DECIMAL_PLACES as usize => Some(answer),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// There should have only been one "." in the string!
|
||||
|
@ -744,7 +742,9 @@ impl RocDec {
|
|||
}
|
||||
|
||||
// Calculate the low digits - the ones after the decimal point.
|
||||
let lo = match after_point.parse::<i128>() {
|
||||
let lo = match opt_after_point {
|
||||
Some(after_point) => {
|
||||
match after_point.parse::<i128>() {
|
||||
Ok(answer) => {
|
||||
// Translate e.g. the 1 from 0.1 into 10000000000000000000
|
||||
// by "restoring" the elided trailing zeroes to the number!
|
||||
|
@ -760,6 +760,9 @@ impl RocDec {
|
|||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
// Calculate the high digits - the ones before the decimal point.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue