mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
First pass
This commit is contained in:
parent
d25e891fb0
commit
5e0d90ac53
8 changed files with 391 additions and 263 deletions
|
@ -1,7 +1,7 @@
|
|||
use crate::def::Def;
|
||||
use crate::expr::{self, ClosureData, Expr::*, IntValue};
|
||||
use crate::expr::{Expr, Field, Recursive};
|
||||
use crate::num::{FloatWidth, IntWidth, NumWidth, NumericBound};
|
||||
use crate::num::{FloatBound, IntBound, IntWidth, NumericBound};
|
||||
use crate::pattern::Pattern;
|
||||
use roc_collections::all::SendMap;
|
||||
use roc_module::called_via::CalledVia;
|
||||
|
@ -867,7 +867,7 @@ fn num_is_odd(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(
|
||||
arg_var,
|
||||
int::<i128>(var_store.fresh(), var_store.fresh(), 1, num_no_bound()),
|
||||
int::<i128>(var_store.fresh(), var_store.fresh(), 1, int_no_bound()),
|
||||
),
|
||||
(
|
||||
arg_var,
|
||||
|
@ -965,7 +965,7 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
(float_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
float_var,
|
||||
float(unbound_zero_var, precision_var, 0.0, num_no_bound()),
|
||||
float(unbound_zero_var, precision_var, 0.0, float_no_bound()),
|
||||
),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
|
@ -1014,7 +1014,7 @@ fn num_log(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
(float_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
float_var,
|
||||
float(unbound_zero_var, precision_var, 0.0, num_no_bound()),
|
||||
float(unbound_zero_var, precision_var, 0.0, float_no_bound()),
|
||||
),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
|
@ -1253,162 +1253,82 @@ fn num_int_cast(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
|
||||
/// Num.minI8: I8
|
||||
fn num_min_i8(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i8>(
|
||||
symbol,
|
||||
var_store,
|
||||
i8::MIN,
|
||||
NumericBound::Exact(IntWidth::I8),
|
||||
)
|
||||
int_min_or_max::<i8>(symbol, var_store, i8::MIN, IntBound::Exact(IntWidth::I8))
|
||||
}
|
||||
|
||||
/// Num.maxI8: I8
|
||||
fn num_max_i8(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i8>(
|
||||
symbol,
|
||||
var_store,
|
||||
i8::MAX,
|
||||
NumericBound::Exact(IntWidth::I8),
|
||||
)
|
||||
int_min_or_max::<i8>(symbol, var_store, i8::MAX, IntBound::Exact(IntWidth::I8))
|
||||
}
|
||||
|
||||
/// Num.minU8: U8
|
||||
fn num_min_u8(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u8>(
|
||||
symbol,
|
||||
var_store,
|
||||
u8::MIN,
|
||||
NumericBound::Exact(IntWidth::U8),
|
||||
)
|
||||
int_min_or_max::<u8>(symbol, var_store, u8::MIN, IntBound::Exact(IntWidth::U8))
|
||||
}
|
||||
|
||||
/// Num.maxU8: U8
|
||||
fn num_max_u8(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u8>(
|
||||
symbol,
|
||||
var_store,
|
||||
u8::MAX,
|
||||
NumericBound::Exact(IntWidth::U8),
|
||||
)
|
||||
int_min_or_max::<u8>(symbol, var_store, u8::MAX, IntBound::Exact(IntWidth::U8))
|
||||
}
|
||||
|
||||
/// Num.minI16: I16
|
||||
fn num_min_i16(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i16>(
|
||||
symbol,
|
||||
var_store,
|
||||
i16::MIN,
|
||||
NumericBound::Exact(IntWidth::I16),
|
||||
)
|
||||
int_min_or_max::<i16>(symbol, var_store, i16::MIN, IntBound::Exact(IntWidth::I16))
|
||||
}
|
||||
|
||||
/// Num.maxI16: I16
|
||||
fn num_max_i16(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i16>(
|
||||
symbol,
|
||||
var_store,
|
||||
i16::MAX,
|
||||
NumericBound::Exact(IntWidth::I16),
|
||||
)
|
||||
int_min_or_max::<i16>(symbol, var_store, i16::MAX, IntBound::Exact(IntWidth::I16))
|
||||
}
|
||||
|
||||
/// Num.minU16: U16
|
||||
fn num_min_u16(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u16>(
|
||||
symbol,
|
||||
var_store,
|
||||
u16::MIN,
|
||||
NumericBound::Exact(IntWidth::U16),
|
||||
)
|
||||
int_min_or_max::<u16>(symbol, var_store, u16::MIN, IntBound::Exact(IntWidth::U16))
|
||||
}
|
||||
|
||||
/// Num.maxU16: U16
|
||||
fn num_max_u16(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u16>(
|
||||
symbol,
|
||||
var_store,
|
||||
u16::MAX,
|
||||
NumericBound::Exact(IntWidth::U16),
|
||||
)
|
||||
int_min_or_max::<u16>(symbol, var_store, u16::MAX, IntBound::Exact(IntWidth::U16))
|
||||
}
|
||||
|
||||
/// Num.minI32: I32
|
||||
fn num_min_i32(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i32>(
|
||||
symbol,
|
||||
var_store,
|
||||
i32::MIN,
|
||||
NumericBound::Exact(IntWidth::I32),
|
||||
)
|
||||
int_min_or_max::<i32>(symbol, var_store, i32::MIN, IntBound::Exact(IntWidth::I32))
|
||||
}
|
||||
|
||||
/// Num.maxI32: I32
|
||||
fn num_max_i32(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i32>(
|
||||
symbol,
|
||||
var_store,
|
||||
i32::MAX,
|
||||
NumericBound::Exact(IntWidth::I32),
|
||||
)
|
||||
int_min_or_max::<i32>(symbol, var_store, i32::MAX, IntBound::Exact(IntWidth::I32))
|
||||
}
|
||||
|
||||
/// Num.minU32: U32
|
||||
fn num_min_u32(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u32>(
|
||||
symbol,
|
||||
var_store,
|
||||
u32::MIN,
|
||||
NumericBound::Exact(IntWidth::U32),
|
||||
)
|
||||
int_min_or_max::<u32>(symbol, var_store, u32::MIN, IntBound::Exact(IntWidth::U32))
|
||||
}
|
||||
|
||||
/// Num.maxU32: U32
|
||||
fn num_max_u32(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u32>(
|
||||
symbol,
|
||||
var_store,
|
||||
u32::MAX,
|
||||
NumericBound::Exact(IntWidth::U32),
|
||||
)
|
||||
int_min_or_max::<u32>(symbol, var_store, u32::MAX, IntBound::Exact(IntWidth::U32))
|
||||
}
|
||||
|
||||
/// Num.minI64: I64
|
||||
fn num_min_i64(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i64>(
|
||||
symbol,
|
||||
var_store,
|
||||
i64::MIN,
|
||||
NumericBound::Exact(IntWidth::I64),
|
||||
)
|
||||
int_min_or_max::<i64>(symbol, var_store, i64::MIN, IntBound::Exact(IntWidth::I64))
|
||||
}
|
||||
|
||||
/// Num.maxI64: I64
|
||||
fn num_max_i64(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<i64>(
|
||||
symbol,
|
||||
var_store,
|
||||
i64::MAX,
|
||||
NumericBound::Exact(IntWidth::I64),
|
||||
)
|
||||
int_min_or_max::<i64>(symbol, var_store, i64::MAX, IntBound::Exact(IntWidth::I64))
|
||||
}
|
||||
|
||||
/// Num.minU64: U64
|
||||
fn num_min_u64(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u64>(
|
||||
symbol,
|
||||
var_store,
|
||||
u64::MIN,
|
||||
NumericBound::Exact(IntWidth::U64),
|
||||
)
|
||||
int_min_or_max::<u64>(symbol, var_store, u64::MIN, IntBound::Exact(IntWidth::U64))
|
||||
}
|
||||
|
||||
/// Num.maxU64: U64
|
||||
fn num_max_u64(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
int_min_or_max::<u64>(
|
||||
symbol,
|
||||
var_store,
|
||||
u64::MAX,
|
||||
NumericBound::Exact(IntWidth::U64),
|
||||
)
|
||||
int_min_or_max::<u64>(symbol, var_store, u64::MAX, IntBound::Exact(IntWidth::U64))
|
||||
}
|
||||
|
||||
/// Num.minI128: I128
|
||||
|
@ -1417,7 +1337,7 @@ fn num_min_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
symbol,
|
||||
var_store,
|
||||
i128::MIN,
|
||||
NumericBound::Exact(IntWidth::I128),
|
||||
IntBound::Exact(IntWidth::I128),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1427,7 +1347,7 @@ fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
symbol,
|
||||
var_store,
|
||||
i128::MAX,
|
||||
NumericBound::Exact(IntWidth::I128),
|
||||
IntBound::Exact(IntWidth::I128),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1559,7 +1479,7 @@ fn str_to_num(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
errorcode_var,
|
||||
Variable::UNSIGNED8,
|
||||
0,
|
||||
NumericBound::Exact(IntWidth::U8),
|
||||
IntBound::Exact(IntWidth::U8),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -2307,7 +2227,7 @@ fn list_take_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
len_var,
|
||||
Variable::NATURAL,
|
||||
0,
|
||||
NumericBound::Exact(IntWidth::Nat),
|
||||
IntBound::Exact(IntWidth::Nat),
|
||||
);
|
||||
|
||||
let body = RunLowLevel {
|
||||
|
@ -2338,7 +2258,7 @@ fn list_take_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
len_var,
|
||||
Variable::NATURAL,
|
||||
0,
|
||||
NumericBound::Exact(IntWidth::Nat),
|
||||
IntBound::Exact(IntWidth::Nat),
|
||||
);
|
||||
let bool_var = var_store.fresh();
|
||||
|
||||
|
@ -2453,7 +2373,7 @@ fn list_intersperse(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
int_var,
|
||||
Variable::NATURAL,
|
||||
0,
|
||||
NumericBound::Exact(IntWidth::Nat),
|
||||
IntBound::Exact(IntWidth::Nat),
|
||||
);
|
||||
|
||||
// \acc, elem -> acc |> List.append sep |> List.append elem
|
||||
|
@ -2538,7 +2458,7 @@ fn list_split(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
index_var,
|
||||
Variable::NATURAL,
|
||||
0,
|
||||
NumericBound::Exact(IntWidth::Nat),
|
||||
IntBound::Exact(IntWidth::Nat),
|
||||
);
|
||||
|
||||
let clos = Closure(ClosureData {
|
||||
|
@ -2703,7 +2623,7 @@ fn list_drop_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
(list_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
index_var,
|
||||
int::<i128>(num_var, num_precision_var, 0, num_no_bound()),
|
||||
int::<i128>(num_var, num_precision_var, 0, int_no_bound()),
|
||||
),
|
||||
],
|
||||
ret_var: list_var,
|
||||
|
@ -2803,7 +2723,7 @@ fn list_drop_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
),
|
||||
(
|
||||
arg_var,
|
||||
int::<i128>(num_var, num_precision_var, 1, num_no_bound()),
|
||||
int::<i128>(num_var, num_precision_var, 1, int_no_bound()),
|
||||
),
|
||||
],
|
||||
ret_var: len_var,
|
||||
|
@ -3004,7 +2924,7 @@ fn list_min(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
int::<i128>(num_var, num_precision_var, 0, num_no_bound()),
|
||||
int::<i128>(num_var, num_precision_var, 0, int_no_bound()),
|
||||
),
|
||||
(
|
||||
len_var,
|
||||
|
@ -3042,7 +2962,7 @@ fn list_min(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
num_var,
|
||||
num_precision_var,
|
||||
0,
|
||||
num_no_bound(),
|
||||
int_no_bound(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -3145,7 +3065,7 @@ fn list_max(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
int::<i128>(num_var, num_precision_var, 0, num_no_bound()),
|
||||
int::<i128>(num_var, num_precision_var, 0, int_no_bound()),
|
||||
),
|
||||
(
|
||||
len_var,
|
||||
|
@ -3183,7 +3103,7 @@ fn list_max(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
num_var,
|
||||
num_precision_var,
|
||||
0,
|
||||
num_no_bound(),
|
||||
int_no_bound(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -4076,7 +3996,7 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
(num_var, Var(Symbol::ARG_2)),
|
||||
(
|
||||
num_var,
|
||||
float(unbound_zero_var, precision_var, 0.0, num_no_bound()),
|
||||
float(unbound_zero_var, precision_var, 0.0, float_no_bound()),
|
||||
),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
|
@ -4146,7 +4066,7 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
unbound_zero_var,
|
||||
unbound_zero_precision_var,
|
||||
0,
|
||||
num_no_bound(),
|
||||
int_no_bound(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -4217,7 +4137,7 @@ fn num_div_ceil(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
unbound_zero_var,
|
||||
unbound_zero_precision_var,
|
||||
0,
|
||||
num_no_bound(),
|
||||
int_no_bound(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -4290,7 +4210,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
int::<i128>(zero_var, zero_precision_var, 0, num_no_bound()),
|
||||
int::<i128>(zero_var, zero_precision_var, 0, int_no_bound()),
|
||||
),
|
||||
(
|
||||
len_var,
|
||||
|
@ -4317,7 +4237,7 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
(list_var, Var(Symbol::ARG_1)),
|
||||
(
|
||||
len_var,
|
||||
int::<i128>(zero_var, zero_precision_var, 0, num_no_bound()),
|
||||
int::<i128>(zero_var, zero_precision_var, 0, int_no_bound()),
|
||||
),
|
||||
],
|
||||
ret_var: list_elem_var,
|
||||
|
@ -4377,7 +4297,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
args: vec![
|
||||
(
|
||||
len_var,
|
||||
int::<i128>(num_var, num_precision_var, 0, num_no_bound()),
|
||||
int::<i128>(num_var, num_precision_var, 0, int_no_bound()),
|
||||
),
|
||||
(
|
||||
len_var,
|
||||
|
@ -4423,7 +4343,7 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
num_var,
|
||||
num_precision_var,
|
||||
1,
|
||||
num_no_bound(),
|
||||
int_no_bound(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -5144,12 +5064,7 @@ fn defn_help(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn int_min_or_max<I128>(
|
||||
symbol: Symbol,
|
||||
var_store: &mut VarStore,
|
||||
i: I128,
|
||||
bound: NumericBound<IntWidth>,
|
||||
) -> Def
|
||||
fn int_min_or_max<I128>(symbol: Symbol, var_store: &mut VarStore, i: I128, bound: IntBound) -> Def
|
||||
where
|
||||
I128: Into<i128>,
|
||||
{
|
||||
|
@ -5178,17 +5093,20 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn num_no_bound<W: Copy>() -> NumericBound<W> {
|
||||
fn num_no_bound() -> NumericBound {
|
||||
NumericBound::None
|
||||
}
|
||||
|
||||
fn int_no_bound() -> IntBound {
|
||||
IntBound::None
|
||||
}
|
||||
|
||||
fn float_no_bound() -> FloatBound {
|
||||
FloatBound::None
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn int<I128>(
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
i: I128,
|
||||
bound: NumericBound<IntWidth>,
|
||||
) -> Expr
|
||||
fn int<I128>(num_var: Variable, precision_var: Variable, i: I128, bound: IntBound) -> Expr
|
||||
where
|
||||
I128: Into<i128>,
|
||||
{
|
||||
|
@ -5203,12 +5121,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn float(
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
f: f64,
|
||||
bound: NumericBound<FloatWidth>,
|
||||
) -> Expr {
|
||||
fn float(num_var: Variable, precision_var: Variable, f: f64, bound: FloatBound) -> Expr {
|
||||
Float(
|
||||
num_var,
|
||||
precision_var,
|
||||
|
@ -5219,7 +5132,7 @@ fn float(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn num<I: Into<i128>>(num_var: Variable, i: I, bound: NumericBound<NumWidth>) -> Expr {
|
||||
fn num<I: Into<i128>>(num_var: Variable, i: I, bound: NumericBound) -> Expr {
|
||||
let i = i.into();
|
||||
Num(
|
||||
num_var,
|
||||
|
|
|
@ -27,6 +27,14 @@ pub enum Constraint {
|
|||
Let(Box<LetConstraint>),
|
||||
And(Vec<Constraint>),
|
||||
Present(Type, PresenceConstraint),
|
||||
|
||||
/// `EqBoundedRange(Ts, U, ...)` means there must be at least one `T` in the *ordered* range `Ts`
|
||||
/// that unifies (via `Eq`) with `U`.
|
||||
///
|
||||
/// This is only used for integers, where we may see e.g. the number literal `-1` and know it
|
||||
/// has the bounded range `[I8, I16, I32, I64, I128]`, at least one of which must unify with
|
||||
/// the type the number literal is used as.
|
||||
EqBoundedRange(Type, Expected<Vec<Type>>, Category, Region),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -87,6 +95,7 @@ impl Constraint {
|
|||
}
|
||||
Constraint::And(cs) => cs.iter().any(|c| c.contains_save_the_environment()),
|
||||
Constraint::Present(_, _) => false,
|
||||
Constraint::EqBoundedRange(_, _, _, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,5 +180,11 @@ fn validate_help(constraint: &Constraint, declared: &Declared, accum: &mut Varia
|
|||
}
|
||||
}
|
||||
}
|
||||
Constraint::EqBoundedRange(typ, one_of, _, _) => {
|
||||
subtract(declared, &typ.variables_detail(), accum);
|
||||
for typ in one_of.get_type_ref() {
|
||||
subtract(declared, &typ.variables_detail(), accum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::def::{can_defs_with_return, Def};
|
|||
use crate::env::Env;
|
||||
use crate::num::{
|
||||
finish_parsing_base, finish_parsing_float, finish_parsing_num, float_expr_from_result,
|
||||
int_expr_from_result, num_expr_from_result, FloatWidth, IntWidth, NumWidth, NumericBound,
|
||||
int_expr_from_result, num_expr_from_result, FloatBound, IntBound, NumericBound,
|
||||
};
|
||||
use crate::pattern::{canonicalize_pattern, Pattern};
|
||||
use crate::procedure::References;
|
||||
|
@ -67,17 +67,11 @@ pub enum Expr {
|
|||
|
||||
// Num stores the `a` variable in `Num a`. Not the same as the variable
|
||||
// stored in Int and Float below, which is strictly for better error messages
|
||||
Num(Variable, Box<str>, IntValue, NumericBound<NumWidth>),
|
||||
Num(Variable, Box<str>, IntValue, NumericBound),
|
||||
|
||||
// Int and Float store a variable to generate better error messages
|
||||
Int(
|
||||
Variable,
|
||||
Variable,
|
||||
Box<str>,
|
||||
IntValue,
|
||||
NumericBound<IntWidth>,
|
||||
),
|
||||
Float(Variable, Variable, Box<str>, f64, NumericBound<FloatWidth>),
|
||||
Int(Variable, Variable, Box<str>, IntValue, IntBound),
|
||||
Float(Variable, Variable, Box<str>, f64, FloatBound),
|
||||
Str(Box<str>),
|
||||
List {
|
||||
elem_var: Variable,
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn num_expr_from_result(
|
|||
#[inline(always)]
|
||||
pub fn int_expr_from_result(
|
||||
var_store: &mut VarStore,
|
||||
result: Result<(&str, IntValue, NumericBound<IntWidth>), (&str, IntErrorKind)>,
|
||||
result: Result<(&str, IntValue, IntBound), (&str, IntErrorKind)>,
|
||||
region: Region,
|
||||
base: Base,
|
||||
env: &mut Env,
|
||||
|
@ -77,7 +77,7 @@ pub fn int_expr_from_result(
|
|||
#[inline(always)]
|
||||
pub fn float_expr_from_result(
|
||||
var_store: &mut VarStore,
|
||||
result: Result<(&str, f64, NumericBound<FloatWidth>), (&str, FloatErrorKind)>,
|
||||
result: Result<(&str, f64, FloatBound), (&str, FloatErrorKind)>,
|
||||
region: Region,
|
||||
env: &mut Env,
|
||||
) -> Expr {
|
||||
|
@ -101,8 +101,8 @@ pub fn float_expr_from_result(
|
|||
}
|
||||
|
||||
pub enum ParsedNumResult {
|
||||
Int(IntValue, NumericBound<IntWidth>),
|
||||
Float(f64, NumericBound<FloatWidth>),
|
||||
Int(IntValue, IntBound),
|
||||
Float(f64, FloatBound),
|
||||
UnknownNum(IntValue),
|
||||
}
|
||||
|
||||
|
@ -115,15 +115,13 @@ pub fn finish_parsing_num(raw: &str) -> Result<ParsedNumResult, (&str, IntErrorK
|
|||
// Let's try to specialize the number
|
||||
Ok(match bound {
|
||||
NumericBound::None => ParsedNumResult::UnknownNum(num),
|
||||
NumericBound::Exact(NumWidth::Int(iw)) => {
|
||||
ParsedNumResult::Int(num, NumericBound::Exact(iw))
|
||||
}
|
||||
NumericBound::Exact(NumWidth::Float(fw)) => {
|
||||
NumericBound::Int(ib) => ParsedNumResult::Int(num, ib),
|
||||
NumericBound::Float(fb) => {
|
||||
let num = match num {
|
||||
IntValue::I128(n) => n as f64,
|
||||
IntValue::U128(n) => n as f64,
|
||||
};
|
||||
ParsedNumResult::Float(num, NumericBound::Exact(fw))
|
||||
ParsedNumResult::Float(num, fb)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -133,7 +131,7 @@ pub fn finish_parsing_base(
|
|||
raw: &str,
|
||||
base: Base,
|
||||
is_negative: bool,
|
||||
) -> Result<(IntValue, NumericBound<IntWidth>), (&str, IntErrorKind)> {
|
||||
) -> Result<(IntValue, IntBound), (&str, IntErrorKind)> {
|
||||
let radix = match base {
|
||||
Base::Hex => 16,
|
||||
Base::Decimal => 10,
|
||||
|
@ -149,9 +147,9 @@ pub fn finish_parsing_base(
|
|||
})
|
||||
.and_then(|(n, bound)| {
|
||||
let bound = match bound {
|
||||
NumericBound::None => NumericBound::None,
|
||||
NumericBound::Exact(NumWidth::Int(iw)) => NumericBound::Exact(iw),
|
||||
NumericBound::Exact(NumWidth::Float(_)) => return Err(IntErrorKind::FloatSuffix),
|
||||
NumericBound::None => IntBound::None,
|
||||
NumericBound::Int(ib) => ib,
|
||||
NumericBound::Float(_) => return Err(IntErrorKind::FloatSuffix),
|
||||
};
|
||||
Ok((n, bound))
|
||||
})
|
||||
|
@ -159,15 +157,13 @@ pub fn finish_parsing_base(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn finish_parsing_float(
|
||||
raw: &str,
|
||||
) -> Result<(f64, NumericBound<FloatWidth>), (&str, FloatErrorKind)> {
|
||||
pub fn finish_parsing_float(raw: &str) -> Result<(f64, FloatBound), (&str, FloatErrorKind)> {
|
||||
let (opt_bound, raw_without_suffix) = parse_literal_suffix(raw);
|
||||
|
||||
let bound = match opt_bound {
|
||||
None => NumericBound::None,
|
||||
Some(NumWidth::Float(fw)) => NumericBound::Exact(fw),
|
||||
Some(NumWidth::Int(_)) => return Err((raw, FloatErrorKind::IntSuffix)),
|
||||
None => FloatBound::None,
|
||||
Some(ParsedWidth::Float(fw)) => FloatBound::Exact(fw),
|
||||
Some(ParsedWidth::Int(_)) => return Err((raw, FloatErrorKind::IntSuffix)),
|
||||
};
|
||||
|
||||
// Ignore underscores.
|
||||
|
@ -184,7 +180,13 @@ pub fn finish_parsing_float(
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_literal_suffix(num_str: &str) -> (Option<NumWidth>, &str) {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
enum ParsedWidth {
|
||||
Int(IntWidth),
|
||||
Float(FloatWidth),
|
||||
}
|
||||
|
||||
fn parse_literal_suffix(num_str: &str) -> (Option<ParsedWidth>, &str) {
|
||||
macro_rules! parse_num_suffix {
|
||||
($($suffix:expr, $width:expr)*) => {$(
|
||||
if num_str.ends_with($suffix) {
|
||||
|
@ -194,20 +196,20 @@ fn parse_literal_suffix(num_str: &str) -> (Option<NumWidth>, &str) {
|
|||
}
|
||||
|
||||
parse_num_suffix! {
|
||||
"u8", NumWidth::Int(IntWidth::U8)
|
||||
"u16", NumWidth::Int(IntWidth::U16)
|
||||
"u32", NumWidth::Int(IntWidth::U32)
|
||||
"u64", NumWidth::Int(IntWidth::U64)
|
||||
"u128", NumWidth::Int(IntWidth::U128)
|
||||
"i8", NumWidth::Int(IntWidth::I8)
|
||||
"i16", NumWidth::Int(IntWidth::I16)
|
||||
"i32", NumWidth::Int(IntWidth::I32)
|
||||
"i64", NumWidth::Int(IntWidth::I64)
|
||||
"i128", NumWidth::Int(IntWidth::I128)
|
||||
"nat", NumWidth::Int(IntWidth::Nat)
|
||||
"dec", NumWidth::Float(FloatWidth::Dec)
|
||||
"f32", NumWidth::Float(FloatWidth::F32)
|
||||
"f64", NumWidth::Float(FloatWidth::F64)
|
||||
"u8", ParsedWidth::Int(IntWidth::U8)
|
||||
"u16", ParsedWidth::Int(IntWidth::U16)
|
||||
"u32", ParsedWidth::Int(IntWidth::U32)
|
||||
"u64", ParsedWidth::Int(IntWidth::U64)
|
||||
"u128", ParsedWidth::Int(IntWidth::U128)
|
||||
"i8", ParsedWidth::Int(IntWidth::I8)
|
||||
"i16", ParsedWidth::Int(IntWidth::I16)
|
||||
"i32", ParsedWidth::Int(IntWidth::I32)
|
||||
"i64", ParsedWidth::Int(IntWidth::I64)
|
||||
"i128", ParsedWidth::Int(IntWidth::I128)
|
||||
"nat", ParsedWidth::Int(IntWidth::Nat)
|
||||
"dec", ParsedWidth::Float(FloatWidth::Dec)
|
||||
"f32", ParsedWidth::Float(FloatWidth::F32)
|
||||
"f64", ParsedWidth::Float(FloatWidth::F64)
|
||||
}
|
||||
|
||||
(None, num_str)
|
||||
|
@ -221,10 +223,7 @@ fn parse_literal_suffix(num_str: &str) -> (Option<NumWidth>, &str) {
|
|||
/// the LEGAL_DETAILS file in the root directory of this distribution.
|
||||
///
|
||||
/// Thanks to the Rust project and its contributors!
|
||||
fn from_str_radix(
|
||||
src: &str,
|
||||
radix: u32,
|
||||
) -> Result<(IntValue, NumericBound<NumWidth>), IntErrorKind> {
|
||||
fn from_str_radix(src: &str, radix: u32) -> Result<(IntValue, NumericBound), IntErrorKind> {
|
||||
use self::IntErrorKind::*;
|
||||
|
||||
assert!(
|
||||
|
@ -268,19 +267,31 @@ fn from_str_radix(
|
|||
|
||||
match opt_exact_bound {
|
||||
None => {
|
||||
// TODO: use the lower bound
|
||||
Ok((result, NumericBound::None))
|
||||
// There's no exact bound, but we do have a lower bound.
|
||||
let sign_demand = if is_negative {
|
||||
SignDemand::Signed
|
||||
} else {
|
||||
SignDemand::NoDemand
|
||||
};
|
||||
Ok((
|
||||
result,
|
||||
IntBound::AtLeast {
|
||||
sign: sign_demand,
|
||||
width: lower_bound,
|
||||
}
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
Some(bound @ NumWidth::Float(_)) => {
|
||||
Some(ParsedWidth::Float(fw)) => {
|
||||
// For now, assume floats can represent all integers
|
||||
// TODO: this is somewhat incorrect, revisit
|
||||
Ok((result, NumericBound::Exact(bound)))
|
||||
Ok((result, FloatBound::Exact(fw).into()))
|
||||
}
|
||||
Some(NumWidth::Int(exact_width)) => {
|
||||
Some(ParsedWidth::Int(exact_width)) => {
|
||||
// We need to check if the exact bound >= lower bound.
|
||||
if exact_width.is_superset(&lower_bound, is_negative) {
|
||||
// Great! Use the exact bound.
|
||||
Ok((result, NumericBound::Exact(NumWidth::Int(exact_width))))
|
||||
Ok((result, IntBound::Exact(exact_width).into()))
|
||||
} else {
|
||||
// This is something like 200i8; the lower bound is u8, which holds strictly more
|
||||
// ints on the positive side than i8 does. Report an error depending on which side
|
||||
|
@ -474,19 +485,47 @@ pub enum FloatWidth {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum NumWidth {
|
||||
Int(IntWidth),
|
||||
Float(FloatWidth),
|
||||
pub enum SignDemand {
|
||||
/// Can be signed or unsigned.
|
||||
NoDemand,
|
||||
/// Must be signed.
|
||||
Signed,
|
||||
}
|
||||
|
||||
/// Describes a bound on the width of a numeric literal.
|
||||
/// Describes a bound on the width of an integer.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum NumericBound<W>
|
||||
where
|
||||
W: Copy,
|
||||
{
|
||||
pub enum IntBound {
|
||||
/// There is no bound on the width.
|
||||
None,
|
||||
/// Must have exactly the width `W`.
|
||||
Exact(W),
|
||||
/// Must have an exact width.
|
||||
Exact(IntWidth),
|
||||
/// Must have a certain sign and a minimum width.
|
||||
AtLeast { sign: SignDemand, width: IntWidth },
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum FloatBound {
|
||||
None,
|
||||
Exact(FloatWidth),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum NumericBound {
|
||||
None,
|
||||
Int(IntBound),
|
||||
Float(FloatBound),
|
||||
}
|
||||
|
||||
impl From<IntBound> for NumericBound {
|
||||
#[inline(always)]
|
||||
fn from(ib: IntBound) -> Self {
|
||||
Self::Int(ib)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FloatBound> for NumericBound {
|
||||
#[inline(always)]
|
||||
fn from(fb: FloatBound) -> Self {
|
||||
Self::Float(fb)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::env::Env;
|
||||
use crate::expr::{canonicalize_expr, unescape_char, Expr, IntValue, Output};
|
||||
use crate::num::{
|
||||
finish_parsing_base, finish_parsing_float, finish_parsing_num, FloatWidth, IntWidth, NumWidth,
|
||||
finish_parsing_base, finish_parsing_float, finish_parsing_num, FloatBound, IntBound,
|
||||
NumericBound, ParsedNumResult,
|
||||
};
|
||||
use crate::scope::Scope;
|
||||
|
@ -29,15 +29,9 @@ pub enum Pattern {
|
|||
ext_var: Variable,
|
||||
destructs: Vec<Loc<RecordDestruct>>,
|
||||
},
|
||||
NumLiteral(Variable, Box<str>, IntValue, NumericBound<NumWidth>),
|
||||
IntLiteral(
|
||||
Variable,
|
||||
Variable,
|
||||
Box<str>,
|
||||
IntValue,
|
||||
NumericBound<IntWidth>,
|
||||
),
|
||||
FloatLiteral(Variable, Variable, Box<str>, f64, NumericBound<FloatWidth>),
|
||||
NumLiteral(Variable, Box<str>, IntValue, NumericBound),
|
||||
IntLiteral(Variable, Variable, Box<str>, IntValue, IntBound),
|
||||
FloatLiteral(Variable, Variable, Box<str>, f64, FloatBound),
|
||||
StrLiteral(Box<str>),
|
||||
Underscore,
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue