mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
exit early from range checking
This commit is contained in:
parent
e3b6a38394
commit
b46721e43b
2 changed files with 80 additions and 37 deletions
|
@ -267,47 +267,53 @@ pub trait TypedNumericBound {
|
|||
fn bounded_range(&self) -> Vec<Variable>;
|
||||
}
|
||||
|
||||
const fn int_width_to_variable(w: IntWidth) -> Variable {
|
||||
match w {
|
||||
IntWidth::U8 => Variable::U8,
|
||||
IntWidth::U16 => Variable::U16,
|
||||
IntWidth::U32 => Variable::U32,
|
||||
IntWidth::U64 => Variable::U64,
|
||||
IntWidth::U128 => Variable::U128,
|
||||
IntWidth::I8 => Variable::I8,
|
||||
IntWidth::I16 => Variable::I16,
|
||||
IntWidth::I32 => Variable::I32,
|
||||
IntWidth::I64 => Variable::I64,
|
||||
IntWidth::I128 => Variable::I128,
|
||||
IntWidth::Nat => Variable::NAT,
|
||||
}
|
||||
}
|
||||
|
||||
const NO_DEMAND_INT_VARIABLES: &[(IntWidth, Variable)] = &[
|
||||
(IntWidth::I8, Variable::I8),
|
||||
(IntWidth::U8, Variable::U8),
|
||||
(IntWidth::I16, Variable::I16),
|
||||
(IntWidth::U16, Variable::U16),
|
||||
(IntWidth::I32, Variable::I32),
|
||||
(IntWidth::U32, Variable::U32),
|
||||
(IntWidth::I64, Variable::I64),
|
||||
(IntWidth::Nat, Variable::NAT), // FIXME: Nat's order here depends on the platform!
|
||||
(IntWidth::U64, Variable::U64),
|
||||
(IntWidth::I128, Variable::I128),
|
||||
(IntWidth::U128, Variable::U128),
|
||||
];
|
||||
|
||||
const SIGNED_INT_VARIABLES: &[(IntWidth, Variable)] = &[
|
||||
(IntWidth::I8, Variable::I8),
|
||||
(IntWidth::I16, Variable::I16),
|
||||
(IntWidth::I32, Variable::I32),
|
||||
(IntWidth::I64, Variable::I64),
|
||||
(IntWidth::I128, Variable::I128),
|
||||
];
|
||||
|
||||
impl TypedNumericBound for IntBound {
|
||||
fn bounded_range(&self) -> Vec<Variable> {
|
||||
match self {
|
||||
IntBound::None => vec![],
|
||||
IntBound::Exact(w) => vec![match w {
|
||||
IntWidth::U8 => Variable::U8,
|
||||
IntWidth::U16 => Variable::U16,
|
||||
IntWidth::U32 => Variable::U32,
|
||||
IntWidth::U64 => Variable::U64,
|
||||
IntWidth::U128 => Variable::U128,
|
||||
IntWidth::I8 => Variable::I8,
|
||||
IntWidth::I16 => Variable::I16,
|
||||
IntWidth::I32 => Variable::I32,
|
||||
IntWidth::I64 => Variable::I64,
|
||||
IntWidth::I128 => Variable::I128,
|
||||
IntWidth::Nat => Variable::NAT,
|
||||
}],
|
||||
IntBound::Exact(w) => vec![int_width_to_variable(*w)],
|
||||
IntBound::AtLeast { sign, width } => {
|
||||
let whole_range: &[(IntWidth, Variable)] = match sign {
|
||||
SignDemand::NoDemand => {
|
||||
&[
|
||||
(IntWidth::I8, Variable::I8),
|
||||
(IntWidth::U8, Variable::U8),
|
||||
(IntWidth::I16, Variable::I16),
|
||||
(IntWidth::U16, Variable::U16),
|
||||
(IntWidth::I32, Variable::I32),
|
||||
(IntWidth::U32, Variable::U32),
|
||||
(IntWidth::I64, Variable::I64),
|
||||
(IntWidth::Nat, Variable::NAT), // FIXME: Nat's order here depends on the platform!
|
||||
(IntWidth::U64, Variable::U64),
|
||||
(IntWidth::I128, Variable::I128),
|
||||
(IntWidth::U128, Variable::U128),
|
||||
]
|
||||
}
|
||||
SignDemand::Signed => &[
|
||||
(IntWidth::I8, Variable::I8),
|
||||
(IntWidth::I16, Variable::I16),
|
||||
(IntWidth::I32, Variable::I32),
|
||||
(IntWidth::I64, Variable::I64),
|
||||
(IntWidth::I128, Variable::I128),
|
||||
],
|
||||
SignDemand::NoDemand => NO_DEMAND_INT_VARIABLES,
|
||||
SignDemand::Signed => SIGNED_INT_VARIABLES,
|
||||
};
|
||||
whole_range
|
||||
.iter()
|
||||
|
|
|
@ -454,9 +454,46 @@ fn check_valid_range(
|
|||
range: VariableSubsSlice,
|
||||
mode: Mode,
|
||||
) -> Outcome {
|
||||
let slice = subs.get_subs_slice(range).to_vec();
|
||||
let slice = subs.get_subs_slice(range);
|
||||
let content = subs.get_content_without_compacting(var);
|
||||
|
||||
let mut it = slice.iter().peekable();
|
||||
macro_rules! is_in_range {
|
||||
($var:expr) => {
|
||||
if slice.contains(&$var) {
|
||||
return Outcome::default();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if let Content::Alias(symbol, _, _, _) = content {
|
||||
match *symbol {
|
||||
Symbol::NUM_I8 => is_in_range!(Variable::I8),
|
||||
Symbol::NUM_U8 => is_in_range!(Variable::U8),
|
||||
Symbol::NUM_I16 => is_in_range!(Variable::I16),
|
||||
Symbol::NUM_U16 => is_in_range!(Variable::U16),
|
||||
Symbol::NUM_I32 => is_in_range!(Variable::I32),
|
||||
Symbol::NUM_U32 => is_in_range!(Variable::U32),
|
||||
Symbol::NUM_I64 => is_in_range!(Variable::I64),
|
||||
Symbol::NUM_NAT => is_in_range!(Variable::NAT),
|
||||
Symbol::NUM_U64 => is_in_range!(Variable::U64),
|
||||
Symbol::NUM_I128 => is_in_range!(Variable::I128),
|
||||
Symbol::NUM_U128 => is_in_range!(Variable::U128),
|
||||
|
||||
Symbol::NUM_DEC => is_in_range!(Variable::DEC),
|
||||
Symbol::NUM_F32 => is_in_range!(Variable::F32),
|
||||
Symbol::NUM_F64 => is_in_range!(Variable::F64),
|
||||
|
||||
Symbol::NUM_NUM | Symbol::NUM_INT | Symbol::NUM_FRAC => {
|
||||
// these satisfy any range that they are given
|
||||
return Outcome::default();
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let vec = slice.to_vec();
|
||||
let mut it = vec.iter().peekable();
|
||||
while let Some(&possible_var) = it.next() {
|
||||
let snapshot = subs.snapshot();
|
||||
let old_pool = pool.clone();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue