Also store f64 for things like pattern comparisons, etc

This commit is contained in:
Jared Ramirez 2021-08-18 17:18:13 -07:00
parent adabf70132
commit d69b9173fc
18 changed files with 195 additions and 252 deletions

1
Cargo.lock generated
View file

@ -3017,6 +3017,7 @@ dependencies = [
"roc_region", "roc_region",
"roc_reporting", "roc_reporting",
"roc_solve", "roc_solve",
"roc_std",
"roc_types", "roc_types",
"roc_unify", "roc_unify",
"serde_json", "serde_json",

View file

@ -21,6 +21,7 @@ roc_mono = { path = "../mono" }
roc_load = { path = "../load" } roc_load = { path = "../load" }
roc_gen_llvm = { path = "../gen_llvm", optional = true } roc_gen_llvm = { path = "../gen_llvm", optional = true }
roc_reporting = { path = "../reporting" } roc_reporting = { path = "../reporting" }
roc_std = { path = "../../roc_std" }
im = "14" # im and im-rc should always have the same version! 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! im-rc = "14" # im and im-rc should always have the same version!
bumpalo = { version = "3.6.1", features = ["collections"] } bumpalo = { version = "3.6.1", features = ["collections"] }

View file

@ -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 { fn num_max_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh(); let int_var = var_store.fresh();
let int_precision_var = var_store.fresh(); let int_precision_var = var_store.fresh();
let body = Int( let body = int(int_var, int_precision_var, i64::MAX.into());
int_var,
int_precision_var,
i64::MAX.to_string().into_boxed_str(),
);
Def { Def {
annotation: None, 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 { fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh(); let int_var = var_store.fresh();
let int_precision_var = var_store.fresh(); let int_precision_var = var_store.fresh();
let body = Int( let body = int(int_var, int_precision_var, i64::MIN.into());
int_var,
int_precision_var,
i64::MIN.to_string().into_boxed_str(),
);
Def { Def {
annotation: None, annotation: None,
@ -693,10 +685,7 @@ fn num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::Eq, op: LowLevel::Eq,
args: vec![ args: vec![
(arg_var, Var(Symbol::ARG_1)), (arg_var, Var(Symbol::ARG_1)),
( (arg_var, num(unbound_zero_var, 0)),
arg_var,
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
),
], ],
ret_var: bool_var, ret_var: bool_var,
}; };
@ -719,10 +708,7 @@ fn num_is_negative(symbol: Symbol, var_store: &mut VarStore) -> Def {
let body = RunLowLevel { let body = RunLowLevel {
op: LowLevel::NumGt, op: LowLevel::NumGt,
args: vec![ args: vec![
( (arg_var, num(unbound_zero_var, 0)),
arg_var,
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
),
(arg_var, Var(Symbol::ARG_1)), (arg_var, Var(Symbol::ARG_1)),
], ],
ret_var: bool_var, ret_var: bool_var,
@ -747,10 +733,7 @@ fn num_is_positive(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::NumGt, op: LowLevel::NumGt,
args: vec![ args: vec![
(arg_var, Var(Symbol::ARG_1)), (arg_var, Var(Symbol::ARG_1)),
( (arg_var, num(unbound_zero_var, 0)),
arg_var,
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
),
], ],
ret_var: bool_var, ret_var: bool_var,
}; };
@ -773,24 +756,14 @@ fn num_is_odd(symbol: Symbol, var_store: &mut VarStore) -> Def {
let body = RunLowLevel { let body = RunLowLevel {
op: LowLevel::Eq, op: LowLevel::Eq,
args: vec![ args: vec![
( (arg_var, int(var_store.fresh(), var_store.fresh(), 1)),
arg_var,
Int(
var_store.fresh(),
var_store.fresh(),
1.to_string().into_boxed_str(),
),
),
( (
arg_var, arg_var,
RunLowLevel { RunLowLevel {
op: LowLevel::NumRemUnchecked, op: LowLevel::NumRemUnchecked,
args: vec![ args: vec![
(arg_var, Var(Symbol::ARG_1)), (arg_var, Var(Symbol::ARG_1)),
( (arg_var, num(unbound_two_var, 2)),
arg_var,
Num(unbound_two_var, "2".to_string().into_boxed_str()),
),
], ],
ret_var: arg_var, ret_var: arg_var,
}, },
@ -817,14 +790,14 @@ fn num_is_even(symbol: Symbol, var_store: &mut VarStore) -> Def {
let body = RunLowLevel { let body = RunLowLevel {
op: LowLevel::Eq, op: LowLevel::Eq,
args: vec![ args: vec![
(arg_var, Num(arg_num_var, "0".to_string().into_boxed_str())), (arg_var, num(arg_num_var, 0)),
( (
arg_var, arg_var,
RunLowLevel { RunLowLevel {
op: LowLevel::NumRemUnchecked, op: LowLevel::NumRemUnchecked,
args: vec![ args: vec![
(arg_var, Var(Symbol::ARG_1)), (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, ret_var: arg_var,
}, },
@ -878,14 +851,7 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::NumGte, op: LowLevel::NumGte,
args: vec![ args: vec![
(float_var, Var(Symbol::ARG_1)), (float_var, Var(Symbol::ARG_1)),
( (float_var, float(unbound_zero_var, precision_var, 0.0)),
float_var,
Float(
unbound_zero_var,
precision_var,
"0.0".to_string().into_boxed_str(),
),
),
], ],
ret_var: bool_var, ret_var: bool_var,
}), }),
@ -931,14 +897,7 @@ fn num_log(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::NumGt, op: LowLevel::NumGt,
args: vec![ args: vec![
(float_var, Var(Symbol::ARG_1)), (float_var, Var(Symbol::ARG_1)),
( (float_var, float(unbound_zero_var, precision_var, 0.0)),
float_var,
Float(
unbound_zero_var,
precision_var,
"0.0".to_string().into_boxed_str(),
),
),
], ],
ret_var: bool_var, 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 { fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh(); let int_var = var_store.fresh();
let int_precision_var = var_store.fresh(); let int_precision_var = var_store.fresh();
let body = Int( let body = int(int_var, int_precision_var, i128::MAX);
int_var,
int_precision_var,
i128::MAX.to_string().into_boxed_str(),
);
let std = roc_builtins::std::types(); let std = roc_builtins::std::types();
let solved = std.get(&symbol).unwrap(); let solved = std.get(&symbol).unwrap();
@ -1205,10 +1160,7 @@ fn list_is_empty(symbol: Symbol, var_store: &mut VarStore) -> Def {
let body = RunLowLevel { let body = RunLowLevel {
op: LowLevel::Eq, op: LowLevel::Eq,
args: vec![ args: vec![
( (len_var, num(unbound_zero_var, 0)),
len_var,
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
),
( (
len_var, len_var,
RunLowLevel { RunLowLevel {
@ -2087,10 +2039,7 @@ fn list_sum(symbol: Symbol, var_store: &mut VarStore) -> Def {
args: vec![ args: vec![
(list_var, Var(Symbol::ARG_1)), (list_var, Var(Symbol::ARG_1)),
(closure_var, list_sum_add(num_var, var_store)), (closure_var, list_sum_add(num_var, var_store)),
( (num_var, num(var_store.fresh(), 0)),
num_var,
Num(var_store.fresh(), "0".to_string().into_boxed_str()),
),
], ],
ret_var, ret_var,
}; };
@ -2132,10 +2081,7 @@ fn list_product(symbol: Symbol, var_store: &mut VarStore) -> Def {
args: vec![ args: vec![
(list_var, Var(Symbol::ARG_1)), (list_var, Var(Symbol::ARG_1)),
(closure_var, list_product_mul(num_var, var_store)), (closure_var, list_product_mul(num_var, var_store)),
( (num_var, num(var_store.fresh(), 1)),
num_var,
Num(var_store.fresh(), "1".to_string().into_boxed_str()),
),
], ],
ret_var, ret_var,
}; };
@ -2613,10 +2559,7 @@ fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::NotEq, op: LowLevel::NotEq,
args: vec![ args: vec![
(num_var, Var(Symbol::ARG_2)), (num_var, Var(Symbol::ARG_2)),
( (num_var, num(unbound_zero_var, 0)),
num_var,
Num(unbound_zero_var, "0".to_string().into_boxed_str()),
),
], ],
ret_var: bool_var, ret_var: bool_var,
}, },
@ -2719,14 +2662,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::NotEq, op: LowLevel::NotEq,
args: vec![ args: vec![
(num_var, Var(Symbol::ARG_2)), (num_var, Var(Symbol::ARG_2)),
( (num_var, float(unbound_zero_var, precision_var, 0.0)),
num_var,
Float(
unbound_zero_var,
precision_var,
"0.0".to_string().into_boxed_str(),
),
),
], ],
ret_var: bool_var, 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, Var(Symbol::ARG_2)),
( (
num_var, num_var,
Int( int(unbound_zero_var, unbound_zero_precision_var, 0),
unbound_zero_var,
unbound_zero_precision_var,
0.to_string().into_boxed_str(),
),
), ),
], ],
ret_var: bool_var, ret_var: bool_var,
@ -2865,10 +2797,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
RunLowLevel { RunLowLevel {
op: LowLevel::NotEq, op: LowLevel::NotEq,
args: vec![ args: vec![
( (len_var, int(zero_var, zero_precision_var, 0)),
len_var,
Int(zero_var, zero_precision_var, 0.to_string().into_boxed_str()),
),
( (
len_var, len_var,
RunLowLevel { RunLowLevel {
@ -2892,14 +2821,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
op: LowLevel::ListGetUnsafe, op: LowLevel::ListGetUnsafe,
args: vec![ args: vec![
(list_var, Var(Symbol::ARG_1)), (list_var, Var(Symbol::ARG_1)),
( (len_var, int(zero_var, zero_precision_var, 0)),
len_var,
Int(
zero_var,
zero_precision_var,
0.to_string().into_boxed_str(),
),
),
], ],
ret_var: list_elem_var, ret_var: list_elem_var,
}, },
@ -2956,10 +2878,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
RunLowLevel { RunLowLevel {
op: LowLevel::NotEq, op: LowLevel::NotEq,
args: vec![ args: vec![
( (len_var, int(num_var, num_precision_var, 0)),
len_var,
Int(num_var, num_precision_var, 0.to_string().into_boxed_str()),
),
( (
len_var, len_var,
RunLowLevel { RunLowLevel {
@ -2998,14 +2917,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
ret_var: len_var, ret_var: len_var,
}, },
), ),
( (arg_var, int(num_var, num_precision_var, 1)),
arg_var,
Int(
num_var,
num_precision_var,
1.to_string().into_boxed_str(),
),
),
], ],
ret_var: len_var, ret_var: len_var,
}, },
@ -3474,3 +3386,18 @@ fn defn_help(
loc_body: Box::new(no_region(body)), 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)
}

View file

@ -742,9 +742,9 @@ fn pattern_to_vars_by_symbol(
} }
} }
NumLiteral(_, _) NumLiteral(_, _, _)
| IntLiteral(_, _) | IntLiteral(_, _, _)
| FloatLiteral(_, _) | FloatLiteral(_, _, _)
| StrLiteral(_) | StrLiteral(_)
| Underscore | Underscore
| MalformedPattern(_, _) | MalformedPattern(_, _)

View file

@ -3,8 +3,8 @@ use crate::builtins::builtin_defs_map;
use crate::def::{can_defs_with_return, Def}; use crate::def::{can_defs_with_return, Def};
use crate::env::Env; use crate::env::Env;
use crate::num::{ use crate::num::{
finish_parsing_base, finish_parsing_int, float_expr_from_result, int_expr_from_result, finish_parsing_base, finish_parsing_float, finish_parsing_int, float_expr_from_result,
num_expr_from_result, validate_float_str, int_expr_from_result, num_expr_from_result,
}; };
use crate::pattern::{canonicalize_pattern, Pattern}; use crate::pattern::{canonicalize_pattern, Pattern};
use crate::procedure::References; 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 // 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 // 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 and Float store a variable to generate better error messages
Int(Variable, Variable, Box<str>), Int(Variable, Variable, Box<str>, i128),
Float(Variable, Variable, Box<str>), Float(Variable, Variable, Box<str>, f64),
Str(Box<str>), Str(Box<str>),
List { List {
elem_var: Variable, elem_var: Variable,
@ -206,10 +206,10 @@ pub fn canonicalize_expr<'a>(
use Expr::*; use Expr::*;
let (expr, output) = match expr { let (expr, output) = match expr {
ast::Expr::Num(string) => { ast::Expr::Num(str) => {
let answer = num_expr_from_result( let answer = num_expr_from_result(
var_store, var_store,
finish_parsing_int(*string).map(|_| *string), finish_parsing_int(*str).map(|int| (*str, int)),
region, region,
env, env,
); );
@ -219,7 +219,7 @@ pub fn canonicalize_expr<'a>(
ast::Expr::Float(str) => { ast::Expr::Float(str) => {
let answer = float_expr_from_result( let answer = float_expr_from_result(
var_store, var_store,
validate_float_str(str).map(|()| *str), finish_parsing_float(str).map(|f| (*str, f)),
region, region,
env, env,
); );
@ -810,7 +810,7 @@ pub fn canonicalize_expr<'a>(
// to keep borrowed values around and make this compile // to keep borrowed values around and make this compile
let int_string = int.to_string(); let int_string = int.to_string();
let int_str = int_string.as_str(); 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), 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 { match expr {
// Num stores the `a` variable in `Num a`. Not the same as the variable // 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 // stored in Int and Float below, which is strictly for better error messages
other @ Num(_, _) other @ Num(_, _, _)
| other @ Int(_, _, _) | other @ Int(_, _, _, _)
| other @ Float(_, _, _) | other @ Float(_, _, _, _)
| other @ Str { .. } | other @ Str { .. }
| other @ RuntimeError(_) | other @ RuntimeError(_)
| other @ EmptyRecord | other @ EmptyRecord

View file

@ -382,9 +382,9 @@ fn fix_values_captured_in_closure_pattern(
} }
} }
Identifier(_) Identifier(_)
| NumLiteral(_, _) | NumLiteral(_, _, _)
| IntLiteral(_, _) | IntLiteral(_, _, _)
| FloatLiteral(_, _) | FloatLiteral(_, _, _)
| StrLiteral(_) | StrLiteral(_)
| Underscore | Underscore
| Shadowed(_, _) | 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); fix_values_captured_in_closure_expr(&mut loc_body.value, no_capture_symbols);
} }
Num(_, _) Num(_, _, _)
| Int(_, _, _) | Int(_, _, _, _)
| Float(_, _, _) | Float(_, _, _, _)
| Str(_) | Str(_)
| Var(_) | Var(_)
| EmptyRecord | EmptyRecord

View file

@ -16,12 +16,12 @@ use std::i64;
#[inline(always)] #[inline(always)]
pub fn num_expr_from_result( pub fn num_expr_from_result(
var_store: &mut VarStore, var_store: &mut VarStore,
result: Result<&str, (&str, IntErrorKind)>, result: Result<(&str, i64), (&str, IntErrorKind)>,
region: Region, region: Region,
env: &mut Env, env: &mut Env,
) -> Expr { ) -> Expr {
match result { 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)) => { Err((raw, error)) => {
// (Num *) compiles to Int if it doesn't // (Num *) compiles to Int if it doesn't
// get specialized to something else first, // get specialized to something else first,
@ -38,14 +38,14 @@ pub fn num_expr_from_result(
#[inline(always)] #[inline(always)]
pub fn int_expr_from_result( pub fn int_expr_from_result(
var_store: &mut VarStore, var_store: &mut VarStore,
result: Result<&str, (&str, IntErrorKind)>, result: Result<(&str, i128), (&str, IntErrorKind)>,
region: Region, region: Region,
base: Base, base: Base,
env: &mut Env, env: &mut Env,
) -> Expr { ) -> Expr {
// Int stores a variable to generate better error messages // Int stores a variable to generate better error messages
match result { 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)) => { Err((raw, error)) => {
let runtime_error = InvalidInt(error, base, region, raw.into()); let runtime_error = InvalidInt(error, base, region, raw.into());
@ -59,13 +59,13 @@ pub fn int_expr_from_result(
#[inline(always)] #[inline(always)]
pub fn float_expr_from_result( pub fn float_expr_from_result(
var_store: &mut VarStore, var_store: &mut VarStore,
result: Result<&str, (&str, FloatErrorKind)>, result: Result<(&str, f64), (&str, FloatErrorKind)>,
region: Region, region: Region,
env: &mut Env, env: &mut Env,
) -> Expr { ) -> Expr {
// Float stores a variable to generate better error messages // Float stores a variable to generate better error messages
match result { 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)) => { Err((raw, error)) => {
let runtime_error = InvalidFloat(error, region, raw.into()); let runtime_error = InvalidFloat(error, region, raw.into());
@ -77,12 +77,10 @@ pub fn float_expr_from_result(
} }
#[inline(always)] #[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. // Ignore underscores.
let radix = 10; let radix = 10;
from_str_radix::<i64>(raw.replace("_", "").as_str(), radix) from_str_radix::<i64>(raw.replace("_", "").as_str(), radix).map_err(|e| (raw, e.kind))
.map(|_| raw)
.map_err(|e| (raw, e.kind))
} }
#[inline(always)] #[inline(always)]
@ -108,10 +106,10 @@ pub fn finish_parsing_base(
} }
#[inline(always)] #[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. // Ignore underscores.
match raw.replace("_", "").parse::<f64>() { match raw.replace("_", "").parse::<f64>() {
Ok(float) if float.is_finite() => Ok(()), Ok(float) if float.is_finite() => Ok(float),
Ok(float) => { Ok(float) => {
if float.is_sign_positive() { if float.is_sign_positive() {
Err((raw, FloatErrorKind::PositiveInfinity)) Err((raw, FloatErrorKind::PositiveInfinity))

View file

@ -1,6 +1,6 @@
use crate::env::Env; use crate::env::Env;
use crate::expr::{canonicalize_expr, unescape_char, Expr, Output}; 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 crate::scope::Scope;
use roc_module::ident::{Ident, Lowercase, TagName}; use roc_module::ident::{Ident, Lowercase, TagName};
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
@ -25,9 +25,9 @@ pub enum Pattern {
ext_var: Variable, ext_var: Variable,
destructs: Vec<Located<RecordDestruct>>, destructs: Vec<Located<RecordDestruct>>,
}, },
IntLiteral(Variable, Box<str>), IntLiteral(Variable, Box<str>, i64),
NumLiteral(Variable, Box<str>), NumLiteral(Variable, Box<str>, i64),
FloatLiteral(Variable, Box<str>), FloatLiteral(Variable, Box<str>, f64),
StrLiteral(Box<str>), StrLiteral(Box<str>),
Underscore, Underscore,
@ -85,9 +85,9 @@ pub fn symbols_from_pattern_help(pattern: &Pattern, symbols: &mut Vec<Symbol>) {
} }
} }
NumLiteral(_, _) NumLiteral(_, _, _)
| IntLiteral(_, _) | IntLiteral(_, _, _)
| FloatLiteral(_, _) | FloatLiteral(_, _, _)
| StrLiteral(_) | StrLiteral(_)
| Underscore | Underscore
| MalformedPattern(_, _) | MalformedPattern(_, _)
@ -186,12 +186,12 @@ pub fn canonicalize_pattern<'a>(
} }
FloatLiteral(str) => match pattern_type { FloatLiteral(str) => match pattern_type {
WhenBranch => match validate_float_str(str) { WhenBranch => match finish_parsing_float(str) {
Err(_error) => { Err(_error) => {
let problem = MalformedPatternProblem::MalformedFloat; let problem = MalformedPatternProblem::MalformedFloat;
malformed_pattern(env, problem, region) 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), ptype => unsupported_pattern(env, ptype, region),
}, },
@ -207,7 +207,7 @@ pub fn canonicalize_pattern<'a>(
let problem = MalformedPatternProblem::MalformedInt; let problem = MalformedPatternProblem::MalformedInt;
malformed_pattern(env, problem, region) 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), ptype => unsupported_pattern(env, ptype, region),
}, },
@ -225,7 +225,8 @@ pub fn canonicalize_pattern<'a>(
Ok(int) => { Ok(int) => {
let sign_str = if *is_negative { "-" } else { "" }; let sign_str = if *is_negative { "-" } else { "" };
let int_str = format!("{}{}", sign_str, int.to_string()).into_boxed_str(); 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), ptype => unsupported_pattern(env, ptype, region),
@ -471,9 +472,9 @@ fn add_bindings_from_patterns(
answer.push((*symbol, *region)); answer.push((*symbol, *region));
} }
} }
NumLiteral(_, _) NumLiteral(_, _, _)
| IntLiteral(_, _) | IntLiteral(_, _, _)
| FloatLiteral(_, _) | FloatLiteral(_, _, _)
| StrLiteral(_) | StrLiteral(_)
| Underscore | Underscore
| Shadowed(_, _) | Shadowed(_, _)

View file

@ -96,8 +96,8 @@ pub fn constrain_expr(
expected: Expected<Type>, expected: Expected<Type>,
) -> Constraint { ) -> Constraint {
match expr { match expr {
Int(var, precision, _) => int_literal(*var, *precision, expected, region), Int(var, precision, _, _) => int_literal(*var, *precision, expected, region),
Num(var, _) => exists( Num(var, _, _) => exists(
vec![*var], vec![*var],
Eq( Eq(
crate::builtins::num_num(Type::Variable(*var)), crate::builtins::num_num(Type::Variable(*var)),
@ -106,7 +106,7 @@ pub fn constrain_expr(
region, 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), EmptyRecord => constrain_empty_record(region, expected),
Expr::Record { record_var, fields } => { Expr::Record { record_var, fields } => {
if fields.is_empty() { if fields.is_empty() {

View file

@ -56,9 +56,9 @@ fn headers_from_annotation_help(
| Shadowed(_, _) | Shadowed(_, _)
| MalformedPattern(_, _) | MalformedPattern(_, _)
| UnsupportedPattern(_) | UnsupportedPattern(_)
| NumLiteral(_, _) | NumLiteral(_, _, _)
| IntLiteral(_, _) | IntLiteral(_, _, _)
| FloatLiteral(_, _) | FloatLiteral(_, _, _)
| StrLiteral(_) => true, | StrLiteral(_) => true,
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() { RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
@ -143,7 +143,7 @@ pub fn constrain_pattern(
); );
} }
NumLiteral(var, _) => { NumLiteral(var, _, _) => {
state.vars.push(*var); state.vars.push(*var);
state.constraints.push(Constraint::Pattern( state.constraints.push(Constraint::Pattern(
@ -154,7 +154,7 @@ pub fn constrain_pattern(
)); ));
} }
IntLiteral(precision_var, _) => { IntLiteral(precision_var, _, _) => {
state.constraints.push(Constraint::Pattern( state.constraints.push(Constraint::Pattern(
region, region,
PatternCategory::Int, PatternCategory::Int,
@ -163,7 +163,7 @@ pub fn constrain_pattern(
)); ));
} }
FloatLiteral(precision_var, _) => { FloatLiteral(precision_var, _, _) => {
state.constraints.push(Constraint::Pattern( state.constraints.push(Constraint::Pattern(
region, region,
PatternCategory::Float, PatternCategory::Float,

View file

@ -16,6 +16,7 @@ roc_builtins = { path = "../builtins" }
roc_unify = { path = "../unify" } roc_unify = { path = "../unify" }
roc_solve = { path = "../solve" } roc_solve = { path = "../solve" }
roc_mono = { path = "../mono" } roc_mono = { path = "../mono" }
roc_std = { path = "../../roc_std" }
morphic_lib = { path = "../../vendor/morphic_lib" } morphic_lib = { path = "../../vendor/morphic_lib" }
im = "14" # im and im-rc should always have the same version! 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! 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_load = { path = "../load" }
roc_reporting = { path = "../reporting" } roc_reporting = { path = "../reporting" }
roc_build = { path = "../build" } roc_build = { path = "../build" }
roc_std = { path = "../../roc_std" }
pretty_assertions = "0.5.1" pretty_assertions = "0.5.1"
maplit = "1.0.1" maplit = "1.0.1"
indoc = "0.3.3" indoc = "0.3.3"

View file

@ -54,6 +54,7 @@ use roc_mono::ir::{
BranchInfo, CallType, EntryPoint, ExceptionId, JoinPointId, ModifyRc, OptLevel, ProcLayout, BranchInfo, CallType, EntryPoint, ExceptionId, JoinPointId, ModifyRc, OptLevel, ProcLayout,
}; };
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, UnionLayout}; 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 /// 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! /// 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>( pub fn float_with_precision<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
value_str: &str,
value: f64, value: f64,
precision: &Builtin, precision: &Builtin,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
match precision { match precision {
Builtin::Decimal => call_bitcode_fn( Builtin::Decimal => {
env, let dec = match RocDec::from_str(value_str) {
&[env.context.f64_type().const_float(value).into()], Some(d) => d.0,
bitcode::DEC_FROM_F64, 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::Float64 => env.context.f64_type().const_float(value).into(),
Builtin::Float32 => env.context.f32_type().const_float(value).into(), Builtin::Float32 => env.context.f32_type().const_float(value).into(),
_ => panic!("Invalid layout for float literal = {:?}", precision), _ => 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), _ => panic!("Invalid layout for int literal = {:?}", layout),
}, },
Float(float) => match layout { Float(float_str, float) => match layout {
Layout::Builtin(builtin) => float_with_precision(env, *float, builtin), Layout::Builtin(builtin) => float_with_precision(env, *float_str, *float, builtin),
_ => panic!("Invalid layout for float literal = {:?}", layout), _ => panic!("Invalid layout for float literal = {:?}", layout),
}, },

View file

@ -1207,7 +1207,7 @@ fn literal_spec(
match literal { match literal {
Str(_) => new_static_string(builder, block), Str(_) => new_static_string(builder, block),
Int(_) | Float(_) | Bool(_) | Byte(_) => builder.add_make_tuple(block, &[]), Int(_) | Float(_, _) | Bool(_) | Byte(_) => builder.add_make_tuple(block, &[]),
} }
} }

View file

@ -85,8 +85,7 @@ enum Test<'a> {
arguments: Vec<(Pattern<'a>, Layout<'a>)>, arguments: Vec<(Pattern<'a>, Layout<'a>)>,
}, },
IsInt(i128), IsInt(i128),
// float patterns are stored as u64 so they are comparable/hashable IsFloat(Box<str>, u64),
IsFloat(u64),
IsStr(Box<str>), IsStr(Box<str>),
IsBit(bool), IsBit(bool),
IsByte { IsByte {
@ -109,7 +108,7 @@ impl<'a> Hash for Test<'a> {
state.write_u8(1); state.write_u8(1);
v.hash(state); v.hash(state);
} }
IsFloat(v) => { IsFloat(_, v) => {
state.write_u8(2); state.write_u8(2);
v.hash(state); 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::IsByte { num_alts, .. } => number_of_tests == *num_alts,
Test::IsBit(_) => number_of_tests == 2, Test::IsBit(_) => number_of_tests == 2,
Test::IsInt(_) => false, Test::IsInt(_) => false,
Test::IsFloat(_) => false, Test::IsFloat(_, _) => false,
Test::IsStr(_) => false, Test::IsStr(_) => false,
} }
} }
@ -555,7 +554,7 @@ fn test_at_path<'a>(
num_alts: union.alternatives.len(), num_alts: union.alternatives.len(),
}, },
IntLiteral(v) => IsInt(*v), IntLiteral(v) => IsInt(*v),
FloatLiteral(v) => IsFloat(*v), FloatLiteral(s, v) => IsFloat(s.clone(), *v),
StrLiteral(v) => IsStr(v.clone()), StrLiteral(v) => IsStr(v.clone()),
}; };
@ -811,8 +810,8 @@ fn to_relevant_branch_help<'a>(
_ => None, _ => None,
}, },
FloatLiteral(float) => match test { FloatLiteral(_, float) => match test {
IsFloat(test_float) if float == *test_float => { IsFloat(_, test_float) if float == *test_float => {
start.extend(end); start.extend(end);
Some(Branch { Some(Branch {
goal: branch.goal, goal: branch.goal,
@ -909,7 +908,7 @@ fn needs_tests(pattern: &Pattern) -> bool {
| BitLiteral { .. } | BitLiteral { .. }
| EnumLiteral { .. } | EnumLiteral { .. }
| IntLiteral(_) | IntLiteral(_)
| FloatLiteral(_) | FloatLiteral(_, _)
| StrLiteral(_) => true, | StrLiteral(_) => true,
} }
} }
@ -1269,10 +1268,10 @@ fn test_to_equality<'a>(
(stores, lhs_symbol, rhs_symbol, None) (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? // TODO maybe we can actually use i64 comparison here?
let test_float = f64::from_bits(test_int as u64); 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(); let lhs_symbol = env.unique_symbol();
stores.push((lhs_symbol, Layout::Builtin(Builtin::Float64), lhs)); stores.push((lhs_symbol, Layout::Builtin(Builtin::Float64), lhs));
@ -1709,7 +1708,7 @@ fn decide_to_branching<'a>(
let tag = match test { let tag = match test {
Test::IsInt(v) => v as u64, 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::IsBit(v) => v as u64,
Test::IsByte { tag_id, .. } => tag_id as u64, Test::IsByte { tag_id, .. } => tag_id as u64,
Test::IsCtor { tag_id, .. } => tag_id as u64, Test::IsCtor { tag_id, .. } => tag_id as u64,

View file

@ -55,7 +55,7 @@ pub enum Literal {
Int(i128), Int(i128),
Bit(bool), Bit(bool),
Byte(u8), Byte(u8),
Float(u64), Float(Box<str>, u64),
Str(Box<str>), Str(Box<str>),
} }
@ -64,7 +64,7 @@ fn simplify(pattern: &crate::ir::Pattern) -> Pattern {
match pattern { match pattern {
IntLiteral(v) => Literal(Literal::Int(*v)), 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())), StrLiteral(v) => Literal(Literal::Str(v.clone())),
// To make sure these are exhaustive, we have to "fake" a union here // To make sure these are exhaustive, we have to "fake" a union here

View file

@ -1016,7 +1016,7 @@ impl ModifyRc {
pub enum Literal<'a> { pub enum Literal<'a> {
// Literals // Literals
Int(i128), Int(i128),
Float(f64), Float(&'a str, f64),
Str(&'a str), Str(&'a str),
/// Closed tag unions containing exactly two (0-arity) tags compile to Expr::Bool, /// 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. /// so they can (at least potentially) be emitted as 1-bit machine bools.
@ -1197,7 +1197,7 @@ impl<'a> Literal<'a> {
match self { match self {
Int(lit) => alloc.text(format!("{}i64", lit)), 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)), Bool(lit) => alloc.text(format!("{}", lit)),
Byte(lit) => alloc.text(format!("{}u8", lit)), Byte(lit) => alloc.text(format!("{}u8", lit)),
Str(lit) => alloc.text(format!("{:?}", lit)), Str(lit) => alloc.text(format!("{:?}", lit)),
@ -1729,7 +1729,7 @@ fn pattern_to_when<'a>(
(symbol, Located::at_zero(wrapped_body)) (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 // These patters are refutable, and thus should never occur outside a `when` expression
// They should have been replaced with `UnsupportedPattern` during canonicalization // They should have been replaced with `UnsupportedPattern` during canonicalization
unreachable!("refutable pattern {:?} where irrefutable pattern is expected. This should never happen!", pattern.value) 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; let arena = env.arena;
match can_expr { match can_expr {
Int(_, precision, num) => { Int(_, precision, _, int) => {
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, false) { match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, false) {
IntOrFloat::SignedIntType(precision) => Stmt::Let( IntOrFloat::SignedIntType(precision) => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Int(num)), Expr::Literal(Literal::Int(int)),
Layout::Builtin(int_precision_to_builtin(precision)), Layout::Builtin(int_precision_to_builtin(precision)),
hole, hole,
), ),
IntOrFloat::UnsignedIntType(precision) => Stmt::Let( IntOrFloat::UnsignedIntType(precision) => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Int(num)), Expr::Literal(Literal::Int(int)),
Layout::Builtin(int_precision_to_builtin(precision)), Layout::Builtin(int_precision_to_builtin(precision)),
hole, 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) { match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, true) {
IntOrFloat::BinaryFloatType(precision) => Stmt::Let( IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Float(num as f64)), Expr::Literal(Literal::Float(arena.alloc(float_str), float)),
Layout::Builtin(float_precision_to_builtin(precision)), Layout::Builtin(float_precision_to_builtin(precision)),
hole, hole,
), ),
IntOrFloat::DecimalFloatType => Stmt::Let( IntOrFloat::DecimalFloatType => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Float(num as f64)), Expr::Literal(Literal::Float(arena.alloc(float_str), float)),
Layout::Builtin(Builtin::Decimal), Layout::Builtin(Builtin::Decimal),
hole, hole,
), ),
@ -2750,7 +2750,8 @@ pub fn with_hole<'a>(
hole, 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( IntOrFloat::SignedIntType(precision) => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Int(num.into())), Expr::Literal(Literal::Int(num.into())),
@ -2765,17 +2766,18 @@ pub fn with_hole<'a>(
), ),
IntOrFloat::BinaryFloatType(precision) => Stmt::Let( IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
assigned, 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)), Layout::Builtin(float_precision_to_builtin(precision)),
hole, hole,
), ),
IntOrFloat::DecimalFloatType => Stmt::Let( IntOrFloat::DecimalFloatType => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Float(num as f64)), Expr::Literal(Literal::Float(arena.alloc(num_str), num as f64)),
Layout::Builtin(Builtin::Decimal), Layout::Builtin(Builtin::Decimal),
hole, hole,
), ),
}, }
}
LetNonRec(def, cont, _) => { LetNonRec(def, cont, _) => {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value { if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure { if let Closure {
@ -5523,7 +5525,7 @@ fn store_pattern_help<'a>(
return StorePattern::NotProductive(stmt); return StorePattern::NotProductive(stmt);
} }
IntLiteral(_) IntLiteral(_)
| FloatLiteral(_) | FloatLiteral(_, _)
| EnumLiteral { .. } | EnumLiteral { .. }
| BitLiteral { .. } | BitLiteral { .. }
| StrLiteral(_) => { | StrLiteral(_) => {
@ -5657,7 +5659,7 @@ fn store_tag_pattern<'a>(
// ignore // ignore
} }
IntLiteral(_) IntLiteral(_)
| FloatLiteral(_) | FloatLiteral(_, _)
| EnumLiteral { .. } | EnumLiteral { .. }
| BitLiteral { .. } | BitLiteral { .. }
| StrLiteral(_) => {} | StrLiteral(_) => {}
@ -5732,7 +5734,7 @@ fn store_newtype_pattern<'a>(
// ignore // ignore
} }
IntLiteral(_) IntLiteral(_)
| FloatLiteral(_) | FloatLiteral(_, _)
| EnumLiteral { .. } | EnumLiteral { .. }
| BitLiteral { .. } | BitLiteral { .. }
| StrLiteral(_) => {} | StrLiteral(_) => {}
@ -5807,7 +5809,7 @@ fn store_record_destruct<'a>(
return StorePattern::NotProductive(stmt); return StorePattern::NotProductive(stmt);
} }
IntLiteral(_) IntLiteral(_)
| FloatLiteral(_) | FloatLiteral(_, _)
| EnumLiteral { .. } | EnumLiteral { .. }
| BitLiteral { .. } | BitLiteral { .. }
| StrLiteral(_) => { | StrLiteral(_) => {
@ -6782,7 +6784,7 @@ pub enum Pattern<'a> {
Identifier(Symbol), Identifier(Symbol),
Underscore, Underscore,
IntLiteral(i128), IntLiteral(i128),
FloatLiteral(u64), FloatLiteral(Box<str>, u64),
BitLiteral { BitLiteral {
value: bool, value: bool,
tag_name: TagName, tag_name: TagName,
@ -6859,8 +6861,11 @@ fn from_can_pattern_help<'a>(
match can_pattern { match can_pattern {
Underscore => Ok(Pattern::Underscore), Underscore => Ok(Pattern::Underscore),
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)), Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
IntLiteral(_, int) => Ok(Pattern::IntLiteral(*int as i128)), IntLiteral(_, _, int) => Ok(Pattern::IntLiteral(*int as i128)),
FloatLiteral(_, float) => Ok(Pattern::FloatLiteral(f64::to_bits(*float))), FloatLiteral(_, float_str, float) => Ok(Pattern::FloatLiteral(
float_str.clone(),
f64::to_bits(*float),
)),
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())), StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
Shadowed(region, ident) => Err(RuntimeError::Shadowing { Shadowed(region, ident) => Err(RuntimeError::Shadowing {
original_region: *region, original_region: *region,
@ -6871,12 +6876,16 @@ fn from_can_pattern_help<'a>(
// TODO preserve malformed problem information here? // TODO preserve malformed problem information here?
Err(RuntimeError::UnsupportedPattern(*region)) 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) { match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)), IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)),
IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)), IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)),
IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(*num as u64)), IntOrFloat::BinaryFloatType(_) => {
IntOrFloat::DecimalFloatType => Ok(Pattern::FloatLiteral(*num as u64)), Ok(Pattern::FloatLiteral(num_str.clone(), *num as u64))
}
IntOrFloat::DecimalFloatType => {
Ok(Pattern::FloatLiteral(num_str.clone(), *num as u64))
}
} }
} }

View file

@ -142,7 +142,7 @@ fn pattern_to_doc_help<'b>(
Bit(true) => alloc.text("True"), Bit(true) => alloc.text("True"),
Bit(false) => alloc.text("False"), Bit(false) => alloc.text("False"),
Byte(b) => alloc.text(b.to_string()), 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()), Str(s) => alloc.string(s.into()),
}, },
Ctor(union, tag_id, args) => { Ctor(union, tag_id, args) => {

View file

@ -731,11 +731,9 @@ impl RocDec {
} }
}; };
let after_point = match parts.next() { let opt_after_point = match parts.next() {
Some(answer) if answer.len() <= Self::DECIMAL_PLACES as usize => answer, Some(answer) if answer.len() <= Self::DECIMAL_PLACES as usize => Some(answer),
_ => { _ => None,
return None;
}
}; };
// There should have only been one "." in the string! // 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. // 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) => { Ok(answer) => {
// Translate e.g. the 1 from 0.1 into 10000000000000000000 // Translate e.g. the 1 from 0.1 into 10000000000000000000
// by "restoring" the elided trailing zeroes to the number! // by "restoring" the elided trailing zeroes to the number!
@ -760,6 +760,9 @@ impl RocDec {
Err(_) => { Err(_) => {
return None; return None;
} }
}
}
None => 0,
}; };
// Calculate the high digits - the ones before the decimal point. // Calculate the high digits - the ones before the decimal point.