Specialize polymorphic lists against non-polymorphic ones

This commit is contained in:
Ayaz Hafiz 2023-11-20 20:56:02 -06:00 committed by Brendan Hansknecht
parent 37a8bbd87c
commit f72b8c2c30
No known key found for this signature in database
GPG key ID: 0EA784685083E75B

View file

@ -399,34 +399,19 @@ pub fn is_useful(mut old_matrix: PatternMatrix, mut vector: Row) -> bool {
&mut spec_matrix,
);
// Add Anythings for the missing elements.
let full_args = if let ListArity::Slice(before, _) = arity {
if arity.min_len() < list_ctor.min_len() {
let (before, after) = args.split_at(before);
let num_extra_wildcards =
list_ctor.min_len() - arity.min_len();
let extra_wildcards =
std::iter::repeat(&Anything).take(num_extra_wildcards);
let mut vector = vector.clone();
specialize_row_with_polymorphic_list(
&mut vector,
&args,
arity,
list_ctor,
);
before
.iter()
.chain(extra_wildcards)
.chain(after)
.cloned()
.collect()
} else {
args.clone()
}
} else {
args.clone()
};
let mut nested_vector = vector.clone();
nested_vector.extend(full_args);
if is_useful(spec_matrix, nested_vector) {
if is_useful(spec_matrix, vector) {
return true;
}
}
return false;
}
}
@ -527,6 +512,36 @@ fn specialize_matrix_by_list(
}
}
fn specialize_row_with_polymorphic_list(
row: &mut Vec<Pattern>,
list_element_patterns: &[Pattern],
polymorphic_list_ctor: ListArity,
specialized_list_ctor: ListArity,
) {
let min_len = specialized_list_ctor.min_len();
if list_element_patterns.len() > min_len {
row.extend(list_element_patterns.iter().cloned());
}
let (patterns_before, patterns_after) = match polymorphic_list_ctor {
ListArity::Slice(before, after) => (
&list_element_patterns[..before],
&list_element_patterns[after..],
),
ListArity::Exact(_) => (list_element_patterns, &[] as &[Pattern]),
};
let middle_any_patterns_needed =
specialized_list_ctor.min_len() - polymorphic_list_ctor.min_len();
let middle_patterns = std::iter::repeat(Anything).take(middle_any_patterns_needed);
row.extend(
(patterns_before.iter().cloned())
.chain(middle_patterns)
.chain(patterns_after.iter().cloned()),
);
}
// Specialize a row that matches a list's constructor(s).
//
// See the docs on [build_list_ctors_covering_patterns] for more information on how list
@ -550,8 +565,9 @@ fn specialize_row_by_list(spec_arity: ListArity, mut row: Row) -> Option<Row> {
debug_assert!(spec_arity.min_len() > this_arity.min_len());
match this_arity {
ListArity::Exact(_) => internal_error!("exact-sized lists cannot cover lists of other minimum length"),
ListArity::Slice(before, _) => {
let (before, after) = args.split_at(before);
ListArity::Slice(before, after) => {
let before = &args[..before];
let after = &args[this_arity.min_len() - after..];
let num_extra_wildcards = spec_arity.min_len() - this_arity.min_len();
let extra_wildcards = std::iter::repeat(&Anything).take(num_extra_wildcards);
@ -869,7 +885,7 @@ fn build_list_ctors_covering_patterns(
}
(max_prefix_len, max_suffix_len)
};
let l = inf_cover_prefix + inf_cover_suffix + 1;
let l = inf_cover_prefix + inf_cover_suffix;
let exact_size_lists = (min_len..l) // exclusive
.map(ListArity::Exact);