Add 'Pair' pattern and rework internals to use it.

Currently, pattern-matching on 'Pair' is handled by treating Pair as a
  record, which comes as slightly odd given that it isn't actually a
  record and isn't user-defined. Thus now, every use of a record must
  distinguish between Pairs and other kind of records -- which screams
  for another variant constructor instead.

  We cannot use `Tuple` either for this, because then we have no ways to
  tell 2-tuples apart from pairs, which is the whole point here. So the
  most sensical thing to do is to define a new pattern `Pair` which is
  akin to tuples, but simpler since we know the number of elements and
  it's always 2.
This commit is contained in:
KtorZ
2024-04-04 10:36:13 +02:00
committed by Kasey
parent 897b5d1d7e
commit 91a7e77ab4
7 changed files with 143 additions and 120 deletions

View File

@@ -679,24 +679,19 @@ pub fn pattern_has_conditions(
Pattern::Tuple { elems, .. } => elems
.iter()
.any(|elem| pattern_has_conditions(elem, data_types)),
Pattern::Pair { fst, snd, .. } => {
pattern_has_conditions(fst, data_types) || pattern_has_conditions(snd, data_types)
}
Pattern::Constructor {
arguments, tipo, ..
} => {
if tipo.is_pair()
|| (tipo.is_function() && tipo.return_type().map(|t| t.is_pair()).unwrap_or(false))
{
arguments
let data_type = lookup_data_type_by_tipo(data_types, tipo)
.unwrap_or_else(|| panic!("Data type not found: {:#?}", tipo));
data_type.constructors.len() > 1
|| arguments
.iter()
.any(|arg| pattern_has_conditions(&arg.value, data_types))
} else {
let data_type = lookup_data_type_by_tipo(data_types, tipo)
.unwrap_or_else(|| panic!("Data type not found: {:#?}", tipo));
data_type.constructors.len() > 1
|| arguments
.iter()
.any(|arg| pattern_has_conditions(&arg.value, data_types))
}
}
Pattern::Assign { pattern, .. } => pattern_has_conditions(pattern, data_types),
Pattern::Var { .. } | Pattern::Discard { .. } => false,