respect int/float precision in pattern matchs

This commit is contained in:
Folkert 2021-09-18 22:55:34 +02:00
parent cde9f97415
commit ada331567a
4 changed files with 153 additions and 66 deletions

View file

@ -2774,13 +2774,13 @@ pub fn with_hole<'a>(
IntOrFloat::SignedIntType(precision) => Stmt::Let(
assigned,
Expr::Literal(Literal::Int(int)),
Layout::Builtin(int_precision_to_builtin(precision)),
precision.as_layout(),
hole,
),
IntOrFloat::UnsignedIntType(precision) => Stmt::Let(
assigned,
Expr::Literal(Literal::Int(int)),
Layout::Builtin(int_precision_to_builtin(precision)),
precision.as_layout(),
hole,
),
_ => unreachable!("unexpected float precision for integer"),
@ -2792,7 +2792,7 @@ pub fn with_hole<'a>(
IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
assigned,
Expr::Literal(Literal::Float(float)),
Layout::Builtin(float_precision_to_builtin(precision)),
precision.as_layout(),
hole,
),
IntOrFloat::DecimalFloatType => {
@ -2824,19 +2824,19 @@ pub fn with_hole<'a>(
IntOrFloat::SignedIntType(precision) => Stmt::Let(
assigned,
Expr::Literal(Literal::Int(num.into())),
Layout::Builtin(int_precision_to_builtin(precision)),
precision.as_layout(),
hole,
),
IntOrFloat::UnsignedIntType(precision) => Stmt::Let(
assigned,
Expr::Literal(Literal::Int(num.into())),
Layout::Builtin(int_precision_to_builtin(precision)),
precision.as_layout(),
hole,
),
IntOrFloat::BinaryFloatType(precision) => Stmt::Let(
assigned,
Expr::Literal(Literal::Float(num as f64)),
Layout::Builtin(float_precision_to_builtin(precision)),
precision.as_layout(),
hole,
),
IntOrFloat::DecimalFloatType => {
@ -5634,8 +5634,8 @@ fn store_pattern_help<'a>(
// do nothing
return StorePattern::NotProductive(stmt);
}
IntLiteral(_)
| FloatLiteral(_)
IntLiteral(_, _)
| FloatLiteral(_, _)
| DecimalLiteral(_)
| EnumLiteral { .. }
| BitLiteral { .. }
@ -5769,8 +5769,8 @@ fn store_tag_pattern<'a>(
Underscore => {
// ignore
}
IntLiteral(_)
| FloatLiteral(_)
IntLiteral(_, _)
| FloatLiteral(_, _)
| DecimalLiteral(_)
| EnumLiteral { .. }
| BitLiteral { .. }
@ -5845,8 +5845,8 @@ fn store_newtype_pattern<'a>(
Underscore => {
// ignore
}
IntLiteral(_)
| FloatLiteral(_)
IntLiteral(_, _)
| FloatLiteral(_, _)
| DecimalLiteral(_)
| EnumLiteral { .. }
| BitLiteral { .. }
@ -5921,8 +5921,8 @@ fn store_record_destruct<'a>(
// internally. But `y` is never used, so we must make sure it't not stored/loaded.
return StorePattern::NotProductive(stmt);
}
IntLiteral(_)
| FloatLiteral(_)
IntLiteral(_, _)
| FloatLiteral(_, _)
| DecimalLiteral(_)
| EnumLiteral { .. }
| BitLiteral { .. }
@ -6892,8 +6892,8 @@ fn call_specialized_proc<'a>(
pub enum Pattern<'a> {
Identifier(Symbol),
Underscore,
IntLiteral(i128),
FloatLiteral(u64),
IntLiteral(i128, IntPrecision),
FloatLiteral(u64, FloatPrecision),
DecimalLiteral(RocDec),
BitLiteral {
value: bool,
@ -6971,7 +6971,22 @@ fn from_can_pattern_help<'a>(
match can_pattern {
Underscore => Ok(Pattern::Underscore),
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
IntLiteral(_, _, int) => Ok(Pattern::IntLiteral(*int as i128)),
IntLiteral(var, _, int) => {
let precision = {
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
IntOrFloat::SignedIntType(precision)
| IntOrFloat::UnsignedIntType(precision) => precision,
other => {
panic!(
"Invalid precision for int pattern: {:?} has {:?}",
can_pattern, other
)
}
}
};
Ok(Pattern::IntLiteral(*int as i128, precision))
}
FloatLiteral(var, float_str, float) => {
// TODO: Can I reuse num_argument_to_int_or_float here if I pass in true?
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, true) {
@ -6981,7 +6996,9 @@ fn from_can_pattern_help<'a>(
IntOrFloat::UnsignedIntType(_) => {
panic!("Invalid percision for float literal = {:?}", var)
}
IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(f64::to_bits(*float))),
IntOrFloat::BinaryFloatType(precision) => {
Ok(Pattern::FloatLiteral(f64::to_bits(*float), precision))
}
IntOrFloat::DecimalFloatType => {
let dec = match RocDec::from_str(float_str) {
Some(d) => d,
@ -7003,9 +7020,15 @@ fn from_can_pattern_help<'a>(
}
NumLiteral(var, num_str, num) => {
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
IntOrFloat::SignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)),
IntOrFloat::UnsignedIntType(_) => Ok(Pattern::IntLiteral(*num as i128)),
IntOrFloat::BinaryFloatType(_) => Ok(Pattern::FloatLiteral(*num as u64)),
IntOrFloat::SignedIntType(precision) => {
Ok(Pattern::IntLiteral(*num as i128, precision))
}
IntOrFloat::UnsignedIntType(precision) => {
Ok(Pattern::IntLiteral(*num as i128, precision))
}
IntOrFloat::BinaryFloatType(precision) => {
Ok(Pattern::FloatLiteral(*num as u64, precision))
}
IntOrFloat::DecimalFloatType => {
let dec = match RocDec::from_str(num_str) {
Some(d) => d,
@ -7587,7 +7610,7 @@ fn from_can_record_destruct<'a>(
})
}
#[derive(Debug)]
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
pub enum IntPrecision {
Usize,
I128,
@ -7597,11 +7620,45 @@ pub enum IntPrecision {
I8,
}
impl IntPrecision {
pub fn as_layout(&self) -> Layout<'static> {
Layout::Builtin(self.as_builtin())
}
pub fn as_builtin(&self) -> Builtin<'static> {
use IntPrecision::*;
match self {
I128 => Builtin::Int128,
I64 => Builtin::Int64,
I32 => Builtin::Int32,
I16 => Builtin::Int16,
I8 => Builtin::Int8,
Usize => Builtin::Usize,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
pub enum FloatPrecision {
F64,
F32,
}
impl FloatPrecision {
pub fn as_layout(&self) -> Layout<'static> {
Layout::Builtin(self.as_builtin())
}
pub fn as_builtin(&self) -> Builtin<'static> {
use FloatPrecision::*;
match self {
F64 => Builtin::Float64,
F32 => Builtin::Float32,
}
}
}
#[derive(Debug)]
pub enum IntOrFloat {
SignedIntType(IntPrecision),
UnsignedIntType(IntPrecision),
@ -7609,26 +7666,6 @@ pub enum IntOrFloat {
DecimalFloatType,
}
fn float_precision_to_builtin(precision: FloatPrecision) -> Builtin<'static> {
use FloatPrecision::*;
match precision {
F64 => Builtin::Float64,
F32 => Builtin::Float32,
}
}
fn int_precision_to_builtin(precision: IntPrecision) -> Builtin<'static> {
use IntPrecision::*;
match precision {
I128 => Builtin::Int128,
I64 => Builtin::Int64,
I32 => Builtin::Int32,
I16 => Builtin::Int16,
I8 => Builtin::Int8,
Usize => Builtin::Usize,
}
}
/// Given the `a` in `Num a`, determines whether it's an int or a float
pub fn num_argument_to_int_or_float(
subs: &Subs,