mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
optimize alias to var conversion
This commit is contained in:
parent
e6bec46898
commit
27269faa0b
2 changed files with 89 additions and 21 deletions
|
@ -837,25 +837,13 @@ fn type_to_variable<'a>(
|
||||||
actual,
|
actual,
|
||||||
lambda_set_variables,
|
lambda_set_variables,
|
||||||
} => {
|
} => {
|
||||||
// the rank of these variables is NONE (encoded as 0 in practice)
|
if let Some(reserved) = Variable::get_reserved(*symbol) {
|
||||||
// using them for other ranks causes issues
|
|
||||||
if rank.is_none() {
|
if rank.is_none() {
|
||||||
// TODO replace by arithmetic?
|
// reserved variables are stored with rank NONE
|
||||||
match *symbol {
|
return reserved;
|
||||||
Symbol::NUM_I128 => return Variable::I128,
|
} else {
|
||||||
Symbol::NUM_I64 => return Variable::I64,
|
// for any other rank, we need to copy; it takes care of adjusting the rank
|
||||||
Symbol::NUM_I32 => return Variable::I32,
|
return deep_copy_var(subs, rank, pools, reserved);
|
||||||
Symbol::NUM_I16 => return Variable::I16,
|
|
||||||
Symbol::NUM_I8 => return Variable::I8,
|
|
||||||
|
|
||||||
Symbol::NUM_U128 => return Variable::U128,
|
|
||||||
Symbol::NUM_U64 => return Variable::U64,
|
|
||||||
Symbol::NUM_U32 => return Variable::U32,
|
|
||||||
Symbol::NUM_U16 => return Variable::U16,
|
|
||||||
Symbol::NUM_U8 => return Variable::U8,
|
|
||||||
|
|
||||||
Symbol::NUM_NAT => return Variable::NAT,
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +856,11 @@ fn type_to_variable<'a>(
|
||||||
lambda_set_variables,
|
lambda_set_variables,
|
||||||
);
|
);
|
||||||
|
|
||||||
let alias_variable = type_to_variable(subs, rank, pools, arena, actual);
|
let alias_variable = if let Symbol::RESULT_RESULT = *symbol {
|
||||||
|
roc_result_to_var(subs, rank, pools, arena, actual)
|
||||||
|
} else {
|
||||||
|
type_to_variable(subs, rank, pools, arena, actual)
|
||||||
|
};
|
||||||
let content = Content::Alias(*symbol, alias_variables, alias_variable);
|
let content = Content::Alias(*symbol, alias_variables, alias_variable);
|
||||||
|
|
||||||
register(subs, rank, pools, content)
|
register(subs, rank, pools, content)
|
||||||
|
@ -941,6 +933,52 @@ fn alias_to_var<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn roc_result_to_var<'a>(
|
||||||
|
subs: &mut Subs,
|
||||||
|
rank: Rank,
|
||||||
|
pools: &mut Pools,
|
||||||
|
arena: &'a bumpalo::Bump,
|
||||||
|
result_type: &Type,
|
||||||
|
) -> Variable {
|
||||||
|
match result_type {
|
||||||
|
Type::TagUnion(tags, ext) => {
|
||||||
|
debug_assert!(ext.is_empty_tag_union());
|
||||||
|
debug_assert!(tags.len() == 2);
|
||||||
|
|
||||||
|
if let [(err, err_args), (ok, ok_args)] = &tags[..] {
|
||||||
|
debug_assert_eq!(err, &subs.tag_names[0]);
|
||||||
|
debug_assert_eq!(ok, &subs.tag_names[1]);
|
||||||
|
|
||||||
|
if let ([err_type], [ok_type]) = (err_args.as_slice(), ok_args.as_slice()) {
|
||||||
|
let err_var = type_to_variable(subs, rank, pools, arena, err_type);
|
||||||
|
let ok_var = type_to_variable(subs, rank, pools, arena, ok_type);
|
||||||
|
|
||||||
|
let start = subs.variables.len() as u32;
|
||||||
|
let err_slice = SubsSlice::new(start, 1);
|
||||||
|
let ok_slice = SubsSlice::new(start + 1, 1);
|
||||||
|
|
||||||
|
subs.variables.push(err_var);
|
||||||
|
subs.variables.push(ok_var);
|
||||||
|
|
||||||
|
let variables = SubsSlice::new(subs.variable_slices.len() as _, 2);
|
||||||
|
subs.variable_slices.push(err_slice);
|
||||||
|
subs.variable_slices.push(ok_slice);
|
||||||
|
|
||||||
|
let union_tags = UnionTags::from_slices(Subs::RESULT_TAG_NAMES, variables);
|
||||||
|
let ext = Variable::EMPTY_TAG_UNION;
|
||||||
|
|
||||||
|
let content = Content::Structure(FlatType::TagUnion(union_tags, ext));
|
||||||
|
|
||||||
|
return register(subs, rank, pools, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("invalid arguments to Result.Result; canonicalization should catch this!")
|
||||||
|
}
|
||||||
|
_ => unreachable!("not a valid type inside a Result.Result alias"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn insertion_sort_by<T, F>(arr: &mut [T], mut compare: F)
|
fn insertion_sort_by<T, F>(arr: &mut [T], mut compare: F)
|
||||||
where
|
where
|
||||||
F: FnMut(&T, &T) -> std::cmp::Ordering,
|
F: FnMut(&T, &T) -> std::cmp::Ordering,
|
||||||
|
|
|
@ -708,6 +708,29 @@ impl Variable {
|
||||||
pub const fn index(&self) -> u32 {
|
pub const fn index(&self) -> u32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn get_reserved(symbol: Symbol) -> Option<Variable> {
|
||||||
|
// Must be carefule here: the variables must in fact be in Subs
|
||||||
|
match symbol {
|
||||||
|
Symbol::NUM_I128 => Some(Variable::I128),
|
||||||
|
Symbol::NUM_I64 => Some(Variable::I64),
|
||||||
|
Symbol::NUM_I32 => Some(Variable::I32),
|
||||||
|
Symbol::NUM_I16 => Some(Variable::I16),
|
||||||
|
Symbol::NUM_I8 => Some(Variable::I8),
|
||||||
|
|
||||||
|
Symbol::NUM_U128 => Some(Variable::U128),
|
||||||
|
Symbol::NUM_U64 => Some(Variable::U64),
|
||||||
|
Symbol::NUM_U32 => Some(Variable::U32),
|
||||||
|
Symbol::NUM_U16 => Some(Variable::U16),
|
||||||
|
Symbol::NUM_U8 => Some(Variable::U8),
|
||||||
|
|
||||||
|
Symbol::NUM_NAT => Some(Variable::NAT),
|
||||||
|
|
||||||
|
Symbol::BOOL_BOOL => Some(Variable::BOOL),
|
||||||
|
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Variable> for OptVariable {
|
impl From<Variable> for OptVariable {
|
||||||
|
@ -1012,6 +1035,8 @@ fn define_integer_types(subs: &mut Subs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Subs {
|
impl Subs {
|
||||||
|
pub const RESULT_TAG_NAMES: SubsSlice<TagName> = SubsSlice::new(0, 2);
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::with_capacity(0)
|
Self::with_capacity(0)
|
||||||
}
|
}
|
||||||
|
@ -1019,10 +1044,15 @@ impl Subs {
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
let capacity = capacity.max(Variable::NUM_RESERVED_VARS);
|
let capacity = capacity.max(Variable::NUM_RESERVED_VARS);
|
||||||
|
|
||||||
|
let mut tag_names = Vec::with_capacity(32);
|
||||||
|
|
||||||
|
tag_names.push(TagName::Global("Err".into()));
|
||||||
|
tag_names.push(TagName::Global("Ok".into()));
|
||||||
|
|
||||||
let mut subs = Subs {
|
let mut subs = Subs {
|
||||||
utable: UnificationTable::default(),
|
utable: UnificationTable::default(),
|
||||||
variables: Default::default(),
|
variables: Default::default(),
|
||||||
tag_names: Default::default(),
|
tag_names,
|
||||||
field_names: Default::default(),
|
field_names: Default::default(),
|
||||||
record_fields: Default::default(),
|
record_fields: Default::default(),
|
||||||
// store an empty slice at the first position
|
// store an empty slice at the first position
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue