mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Specialize polymorphic lists against non-polymorphic ones
This commit is contained in:
parent
37a8bbd87c
commit
f72b8c2c30
1 changed files with 43 additions and 27 deletions
|
@ -399,34 +399,19 @@ pub fn is_useful(mut old_matrix: PatternMatrix, mut vector: Row) -> bool {
|
||||||
&mut spec_matrix,
|
&mut spec_matrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add Anythings for the missing elements.
|
let mut vector = vector.clone();
|
||||||
let full_args = if let ListArity::Slice(before, _) = arity {
|
specialize_row_with_polymorphic_list(
|
||||||
if arity.min_len() < list_ctor.min_len() {
|
&mut vector,
|
||||||
let (before, after) = args.split_at(before);
|
&args,
|
||||||
let num_extra_wildcards =
|
arity,
|
||||||
list_ctor.min_len() - arity.min_len();
|
list_ctor,
|
||||||
let extra_wildcards =
|
);
|
||||||
std::iter::repeat(&Anything).take(num_extra_wildcards);
|
|
||||||
|
|
||||||
before
|
if is_useful(spec_matrix, vector) {
|
||||||
.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) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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).
|
// 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
|
// 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());
|
debug_assert!(spec_arity.min_len() > this_arity.min_len());
|
||||||
match this_arity {
|
match this_arity {
|
||||||
ListArity::Exact(_) => internal_error!("exact-sized lists cannot cover lists of other minimum length"),
|
ListArity::Exact(_) => internal_error!("exact-sized lists cannot cover lists of other minimum length"),
|
||||||
ListArity::Slice(before, _) => {
|
ListArity::Slice(before, after) => {
|
||||||
let (before, after) = args.split_at(before);
|
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 num_extra_wildcards = spec_arity.min_len() - this_arity.min_len();
|
||||||
let extra_wildcards = std::iter::repeat(&Anything).take(num_extra_wildcards);
|
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)
|
(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
|
let exact_size_lists = (min_len..l) // exclusive
|
||||||
.map(ListArity::Exact);
|
.map(ListArity::Exact);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue