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_region",
|
||||||
"roc_reporting",
|
"roc_reporting",
|
||||||
"roc_solve",
|
"roc_solve",
|
||||||
|
"roc_std",
|
||||||
"roc_types",
|
"roc_types",
|
||||||
"roc_unify",
|
"roc_unify",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -742,9 +742,9 @@ fn pattern_to_vars_by_symbol(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NumLiteral(_, _)
|
NumLiteral(_, _, _)
|
||||||
| IntLiteral(_, _)
|
| IntLiteral(_, _, _)
|
||||||
| FloatLiteral(_, _)
|
| FloatLiteral(_, _, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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(_, _)
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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, &[]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue