mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
optimize initial tag union creation
This commit is contained in:
parent
26da66d73f
commit
4cbb1c9b25
3 changed files with 106 additions and 76 deletions
|
@ -1,12 +1,13 @@
|
|||
use roc_can::constraint::Constraint::{self, *};
|
||||
use roc_can::expected::{Expected, PExpected};
|
||||
use roc_collections::all::{default_hasher, MutMap};
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_module::ident::TagName;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_types::solved_types::Solved;
|
||||
use roc_types::subs::{
|
||||
AliasVariables, Content, Descriptor, FlatType, Mark, OptVariable, Rank, RecordFields, Subs,
|
||||
SubsIndex, Variable, VariableSubsSlice,
|
||||
SubsIndex, SubsSlice, UnionTags, Variable, VariableSubsSlice,
|
||||
};
|
||||
use roc_types::types::Type::{self, *};
|
||||
use roc_types::types::{gather_fields_unsorted_iter, Alias, Category, ErrorType, PatternCategory};
|
||||
|
@ -706,32 +707,8 @@ fn type_to_variable(
|
|||
register(subs, rank, pools, content)
|
||||
}
|
||||
TagUnion(tags, ext) => {
|
||||
let mut tag_vars = MutMap::with_capacity_and_hasher(tags.len(), default_hasher());
|
||||
|
||||
for (tag, tag_argument_types) in tags {
|
||||
let mut tag_argument_vars = Vec::with_capacity(tag_argument_types.len());
|
||||
|
||||
for arg_type in tag_argument_types {
|
||||
tag_argument_vars.push(type_to_variable(subs, rank, pools, cached, arg_type));
|
||||
}
|
||||
|
||||
tag_vars.insert(tag.clone(), tag_argument_vars);
|
||||
}
|
||||
|
||||
let temp_ext_var = type_to_variable(subs, rank, pools, cached, ext);
|
||||
let mut ext_tag_vec = Vec::new();
|
||||
let new_ext_var = match roc_types::pretty_print::chase_ext_tag_union(
|
||||
subs,
|
||||
temp_ext_var,
|
||||
&mut ext_tag_vec,
|
||||
) {
|
||||
Ok(()) => Variable::EMPTY_TAG_UNION,
|
||||
Err((new, _)) => new,
|
||||
};
|
||||
tag_vars.extend(ext_tag_vec.into_iter());
|
||||
|
||||
let content =
|
||||
Content::Structure(roc_unify::unify::from_mutmap(subs, tag_vars, new_ext_var));
|
||||
let (union_tags, ext) = type_to_union_tags(subs, rank, pools, cached, tags, ext);
|
||||
let content = Content::Structure(FlatType::TagUnion(union_tags, ext));
|
||||
|
||||
register(subs, rank, pools, content)
|
||||
}
|
||||
|
@ -758,36 +735,9 @@ fn type_to_variable(
|
|||
register(subs, rank, pools, content)
|
||||
}
|
||||
RecursiveTagUnion(rec_var, tags, ext) => {
|
||||
let mut tag_vars = MutMap::with_capacity_and_hasher(tags.len(), default_hasher());
|
||||
|
||||
for (tag, tag_argument_types) in tags {
|
||||
let mut tag_argument_vars = Vec::with_capacity(tag_argument_types.len());
|
||||
|
||||
for arg_type in tag_argument_types {
|
||||
tag_argument_vars.push(type_to_variable(subs, rank, pools, cached, arg_type));
|
||||
}
|
||||
|
||||
tag_vars.insert(tag.clone(), tag_argument_vars);
|
||||
}
|
||||
|
||||
let temp_ext_var = type_to_variable(subs, rank, pools, cached, ext);
|
||||
let mut ext_tag_vec = Vec::new();
|
||||
let new_ext_var = match roc_types::pretty_print::chase_ext_tag_union(
|
||||
subs,
|
||||
temp_ext_var,
|
||||
&mut ext_tag_vec,
|
||||
) {
|
||||
Ok(()) => Variable::EMPTY_TAG_UNION,
|
||||
Err((new, _)) => new,
|
||||
};
|
||||
tag_vars.extend(ext_tag_vec.into_iter());
|
||||
|
||||
let content = Content::Structure(roc_unify::unify::from_mutmap_rec(
|
||||
subs,
|
||||
*rec_var,
|
||||
tag_vars,
|
||||
new_ext_var,
|
||||
));
|
||||
let (union_tags, ext) = type_to_union_tags(subs, rank, pools, cached, tags, ext);
|
||||
let content =
|
||||
Content::Structure(FlatType::RecursiveTagUnion(*rec_var, union_tags, ext));
|
||||
|
||||
let tag_union_var = register(subs, rank, pools, content);
|
||||
|
||||
|
@ -903,6 +853,59 @@ fn type_to_variable(
|
|||
}
|
||||
}
|
||||
|
||||
fn type_to_union_tags(
|
||||
subs: &mut Subs,
|
||||
rank: Rank,
|
||||
pools: &mut Pools,
|
||||
cached: &mut MutMap<Symbol, Variable>,
|
||||
tags: &[(TagName, Vec<Type>)],
|
||||
ext: &Type,
|
||||
) -> (UnionTags, Variable) {
|
||||
let mut tag_vars = Vec::with_capacity(tags.len());
|
||||
|
||||
let mut tag_argument_vars = Vec::new();
|
||||
for (tag, tag_argument_types) in tags {
|
||||
for arg_type in tag_argument_types {
|
||||
let new_var = type_to_variable(subs, rank, pools, cached, arg_type);
|
||||
tag_argument_vars.push(new_var);
|
||||
}
|
||||
|
||||
let new_slice = VariableSubsSlice::insert_into_subs(subs, tag_argument_vars.drain(..));
|
||||
|
||||
tag_vars.push((tag.clone(), new_slice));
|
||||
}
|
||||
|
||||
let temp_ext_var = type_to_variable(subs, rank, pools, cached, ext);
|
||||
|
||||
let ext = {
|
||||
let (it, ext) =
|
||||
roc_types::types::gather_tags_unsorted_iter(subs, UnionTags::default(), temp_ext_var);
|
||||
|
||||
tag_vars.extend(it.map(|(n, v)| (n.clone(), v)));
|
||||
tag_vars.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
|
||||
|
||||
// deduplicate, keeping the right-most occurence of a tag name
|
||||
let mut i = 0;
|
||||
|
||||
while i < tag_vars.len() {
|
||||
match (tag_vars.get(i), tag_vars.get(i + 1)) {
|
||||
(Some((t1, _)), Some((t2, _))) => {
|
||||
if t1 == t2 {
|
||||
tag_vars.remove(i);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
ext
|
||||
};
|
||||
|
||||
(UnionTags::insert_slices_into_subs(subs, tag_vars), ext)
|
||||
}
|
||||
|
||||
fn check_for_infinite_type(
|
||||
subs: &mut Subs,
|
||||
problems: &mut Vec<TypeError>,
|
||||
|
@ -1509,23 +1512,35 @@ fn deep_copy_var_help(
|
|||
}
|
||||
|
||||
TagUnion(tags, ext_var) => {
|
||||
let mut new_tags = MutMap::default();
|
||||
let mut new_variable_slices = Vec::with_capacity(tags.len());
|
||||
|
||||
for (tag_index, index) in tags.iter_all() {
|
||||
let tag = subs[tag_index].clone();
|
||||
let mut new_variables = Vec::new();
|
||||
for index in tags.variables() {
|
||||
let slice = subs[index];
|
||||
let mut new_vars = Vec::new();
|
||||
for var_index in slice {
|
||||
let var = subs[var_index];
|
||||
let new_var = deep_copy_var_help(subs, max_rank, pools, var);
|
||||
new_vars.push(new_var);
|
||||
new_variables.push(new_var);
|
||||
}
|
||||
|
||||
new_tags.insert(tag, new_vars);
|
||||
let new_slice =
|
||||
VariableSubsSlice::insert_into_subs(subs, new_variables.drain(..));
|
||||
|
||||
new_variable_slices.push(new_slice);
|
||||
}
|
||||
|
||||
let new_variables = {
|
||||
let start = subs.variable_slices.len() as u32;
|
||||
let length = new_variable_slices.len() as u16;
|
||||
subs.variable_slices.extend(new_variable_slices);
|
||||
|
||||
SubsSlice::new(start, length)
|
||||
};
|
||||
|
||||
let union_tags = UnionTags::from_slices(tags.tag_names(), new_variables);
|
||||
|
||||
let new_ext = deep_copy_var_help(subs, max_rank, pools, ext_var);
|
||||
roc_unify::unify::from_mutmap(subs, new_tags, new_ext)
|
||||
TagUnion(union_tags, new_ext)
|
||||
}
|
||||
|
||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => FunctionOrTagUnion(
|
||||
|
@ -1535,25 +1550,37 @@ fn deep_copy_var_help(
|
|||
),
|
||||
|
||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||
let mut new_tags = MutMap::default();
|
||||
let mut new_variable_slices = Vec::with_capacity(tags.len());
|
||||
|
||||
let new_rec_var = deep_copy_var_help(subs, max_rank, pools, rec_var);
|
||||
|
||||
for (tag_index, index) in tags.iter_all() {
|
||||
let tag = subs[tag_index].clone();
|
||||
let mut new_variables = Vec::new();
|
||||
for index in tags.variables() {
|
||||
let slice = subs[index];
|
||||
let mut new_vars = Vec::new();
|
||||
for var_index in slice {
|
||||
let var = subs[var_index];
|
||||
let new_var = deep_copy_var_help(subs, max_rank, pools, var);
|
||||
new_vars.push(new_var);
|
||||
new_variables.push(new_var);
|
||||
}
|
||||
|
||||
new_tags.insert(tag, new_vars);
|
||||
let new_slice =
|
||||
VariableSubsSlice::insert_into_subs(subs, new_variables.drain(..));
|
||||
|
||||
new_variable_slices.push(new_slice);
|
||||
}
|
||||
|
||||
let new_variables = {
|
||||
let start = subs.variable_slices.len() as u32;
|
||||
let length = new_variable_slices.len() as u16;
|
||||
subs.variable_slices.extend(new_variable_slices);
|
||||
|
||||
SubsSlice::new(start, length)
|
||||
};
|
||||
|
||||
let union_tags = UnionTags::from_slices(tags.tag_names(), new_variables);
|
||||
|
||||
let new_ext = deep_copy_var_help(subs, max_rank, pools, ext_var);
|
||||
roc_unify::unify::from_mutmap_rec(subs, new_rec_var, new_tags, new_ext)
|
||||
let new_rec_var = deep_copy_var_help(subs, max_rank, pools, rec_var);
|
||||
|
||||
RecursiveTagUnion(new_rec_var, union_tags, new_ext)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue