mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
Reduce some allocations in glue
This commit is contained in:
parent
31eb03ab22
commit
a1f3036fc8
1 changed files with 58 additions and 52 deletions
|
@ -1222,19 +1222,16 @@ fn add_tag_union<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NonNullableUnwrapped(_) => {
|
NonNullableUnwrapped(_) => {
|
||||||
let mut tags =
|
let (tag_name, payload_vars) = single_tag_payload(union_tags, subs);
|
||||||
union_tags_to_types(&name, union_tags, subs, env, types, layout, true);
|
let (tag_name, opt_payload) =
|
||||||
|
tag_to_type(&name, env, tag_name, payload_vars, types, layout, true);
|
||||||
debug_assert_eq!(tags.len(), 1);
|
|
||||||
|
|
||||||
let (tag_name, opt_payload) = tags.pop().unwrap();
|
|
||||||
|
|
||||||
// A recursive tag union with just one constructor
|
// A recursive tag union with just one constructor
|
||||||
// Optimization: No need to store a tag ID (the payload is "unwrapped")
|
// Optimization: No need to store a tag ID (the payload is "unwrapped")
|
||||||
// e.g. `RoseTree a : [Tree a (List (RoseTree a))]`
|
// e.g. `RoseTree a : [Tree a (List (RoseTree a))]`
|
||||||
RocTagUnion::NonNullableUnwrapped {
|
RocTagUnion::NonNullableUnwrapped {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
tag_name,
|
tag_name: tag_name.to_string(),
|
||||||
payload: opt_payload.unwrap(),
|
payload: opt_payload.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1318,7 +1315,7 @@ fn add_tag_union<'a>(
|
||||||
// e.g. `RoseTree a : [Tree a (List (RoseTree a))]`
|
// e.g. `RoseTree a : [Tree a (List (RoseTree a))]`
|
||||||
RocTagUnion::SingleTagStruct {
|
RocTagUnion::SingleTagStruct {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
tag_name,
|
tag_name: tag_name.to_string(),
|
||||||
payload_fields,
|
payload_fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1334,7 +1331,7 @@ fn add_tag_union<'a>(
|
||||||
|
|
||||||
RocTagUnion::SingleTagStruct {
|
RocTagUnion::SingleTagStruct {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
tag_name,
|
tag_name: tag_name.to_string(),
|
||||||
payload_fields: vec![type_id],
|
payload_fields: vec![type_id],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1341,7 @@ fn add_tag_union<'a>(
|
||||||
|
|
||||||
RocTagUnion::SingleTagStruct {
|
RocTagUnion::SingleTagStruct {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
tag_name,
|
tag_name: tag_name.to_string(),
|
||||||
payload_fields,
|
payload_fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1402,31 +1399,44 @@ fn union_tags_to_types<'a>(
|
||||||
(name_str, payload_vars.to_vec())
|
(name_str, payload_vars.to_vec())
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Sort tags alphabetically by tag name
|
// Sort tags alphabetically by tag name
|
||||||
tags.sort_by(|(name1, _), (name2, _)| name1.cmp(name2));
|
tags.sort_by(|(name1, _), (name2, _)| name1.cmp(name2));
|
||||||
|
|
||||||
tags_to_types(name, tags, env, types, layout, is_recursive)
|
tags.into_iter()
|
||||||
|
.map(|(tag_name, payload_vars)| {
|
||||||
|
tag_to_type(
|
||||||
|
name,
|
||||||
|
env,
|
||||||
|
tag_name,
|
||||||
|
&payload_vars,
|
||||||
|
types,
|
||||||
|
layout,
|
||||||
|
is_recursive,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn single_tag_payload<'a>(
|
fn single_tag_payload<'a>(
|
||||||
union_tags: &'a UnionLabels<TagName>,
|
union_tags: &'a UnionLabels<TagName>,
|
||||||
subs: &'a Subs,
|
subs: &'a Subs,
|
||||||
) -> (String, &'a [Variable]) {
|
) -> (&'a str, &'a [Variable]) {
|
||||||
let mut iter = union_tags.iter_from_subs(subs);
|
let mut iter = union_tags.iter_from_subs(subs);
|
||||||
let (tag_name, payload_vars) = iter.next().unwrap();
|
let (tag_name, payload_vars) = iter.next().unwrap();
|
||||||
// This should be a single-tag union.
|
// This should be a single-tag union.
|
||||||
debug_assert_eq!(iter.next(), None);
|
debug_assert_eq!(iter.next(), None);
|
||||||
|
|
||||||
(tag_name.0.as_str().to_string(), payload_vars)
|
(tag_name.0.as_str(), payload_vars)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn single_tag_payload_fields<'a>(
|
fn single_tag_payload_fields<'a, 'b>(
|
||||||
union_tags: &UnionLabels<TagName>,
|
union_tags: &'b UnionLabels<TagName>,
|
||||||
subs: &Subs,
|
subs: &'b Subs,
|
||||||
field_layouts: &[Layout<'a>],
|
field_layouts: &[Layout<'a>],
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
types: &mut Types,
|
types: &mut Types,
|
||||||
) -> (String, Vec<TypeId>) {
|
) -> (&'b str, Vec<TypeId>) {
|
||||||
let (tag_name, payload_vars) = single_tag_payload(union_tags, subs);
|
let (tag_name, payload_vars) = single_tag_payload(union_tags, subs);
|
||||||
|
|
||||||
let payload_fields: Vec<TypeId> = payload_vars
|
let payload_fields: Vec<TypeId> = payload_vars
|
||||||
|
@ -1438,16 +1448,15 @@ fn single_tag_payload_fields<'a>(
|
||||||
(tag_name, payload_fields)
|
(tag_name, payload_fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tags_to_types<'a>(
|
fn tag_to_type<'a, D: Display>(
|
||||||
name: &str,
|
name: &str,
|
||||||
tags: Vec<(String, Vec<Variable>)>,
|
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
|
tag_name: D,
|
||||||
|
payload_vars: &[Variable],
|
||||||
types: &mut Types,
|
types: &mut Types,
|
||||||
layout: Layout<'a>,
|
layout: Layout<'a>,
|
||||||
is_recursive: bool,
|
is_recursive: bool,
|
||||||
) -> Vec<(String, Option<TypeId>)> {
|
) -> (D, Option<TypeId>) {
|
||||||
tags.into_iter()
|
|
||||||
.map(|(tag_name, payload_vars)| {
|
|
||||||
match struct_fields_needed(env, payload_vars.iter().copied()) {
|
match struct_fields_needed(env, payload_vars.iter().copied()) {
|
||||||
0 => {
|
0 => {
|
||||||
// no payload
|
// no payload
|
||||||
|
@ -1470,16 +1479,13 @@ fn tags_to_types<'a>(
|
||||||
// create a RocType for the payload and save it
|
// create a RocType for the payload and save it
|
||||||
let struct_name = format!("{}_{}", &name, tag_name); // e.g. "MyUnion_MyVariant"
|
let struct_name = format!("{}_{}", &name, tag_name); // e.g. "MyUnion_MyVariant"
|
||||||
let fields = payload_vars.iter().copied().enumerate();
|
let fields = payload_vars.iter().copied().enumerate();
|
||||||
let struct_id =
|
let struct_id = add_struct(env, struct_name, fields, types, layout, |name, fields| {
|
||||||
add_struct(env, struct_name, fields, types, layout, |name, fields| {
|
|
||||||
RocType::TagUnionPayload { name, fields }
|
RocType::TagUnionPayload { name, fields }
|
||||||
});
|
});
|
||||||
|
|
||||||
(tag_name, Some(struct_id))
|
(tag_name, Some(struct_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_fields_needed<I: IntoIterator<Item = Variable>>(env: &mut Env<'_>, vars: I) -> usize {
|
fn struct_fields_needed<I: IntoIterator<Item = Variable>>(env: &mut Env<'_>, vars: I) -> usize {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue