Extract some common wrapper logic

This commit is contained in:
Richard Feldman 2022-08-05 13:49:00 -04:00
parent efa31ae747
commit e9966e6551
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798

View file

@ -534,7 +534,10 @@ pub enum RocTagUnion {
/// 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))]`
NonNullableUnwrapped { name: String, content: TypeId }, NonNullableUnwrapped {
name: String,
content: TypeId,
},
/// A recursive tag union that has an empty variant /// A recursive tag union that has an empty variant
/// Optimization: Represent the empty variant as null pointer => no memory usage & fast comparison /// Optimization: Represent the empty variant as null pointer => no memory usage & fast comparison
@ -1016,7 +1019,7 @@ fn add_tag_union<'a>(
}) })
.collect(); .collect();
let typ = match layout { let tag_union_type = match layout {
Layout::Union(union_layout) => { Layout::Union(union_layout) => {
use UnionLayout::*; use UnionLayout::*;
@ -1030,12 +1033,12 @@ fn add_tag_union<'a>(
.max(1); .max(1);
let discriminant_offset = union_layout.tag_id_offset(env.target).unwrap(); let discriminant_offset = union_layout.tag_id_offset(env.target).unwrap();
RocType::TagUnion(RocTagUnion::NonRecursive { RocTagUnion::NonRecursive {
name: name.clone(), name: name.clone(),
tags, tags,
discriminant_size, discriminant_size,
discriminant_offset, discriminant_offset,
}) }
} }
// A recursive tag union (general case) // A recursive tag union (general case)
// e.g. `Expr : [Sym Str, Add Expr Expr]` // e.g. `Expr : [Sym Str, Add Expr Expr]`
@ -1044,12 +1047,12 @@ fn add_tag_union<'a>(
Discriminant::from_number_of_tags(tags.len()).stack_size(); Discriminant::from_number_of_tags(tags.len()).stack_size();
let discriminant_offset = union_layout.tag_id_offset(env.target).unwrap(); let discriminant_offset = union_layout.tag_id_offset(env.target).unwrap();
RocType::TagUnion(RocTagUnion::Recursive { RocTagUnion::Recursive {
name: name.clone(), name: name.clone(),
tags, tags,
discriminant_size, discriminant_size,
discriminant_offset, discriminant_offset,
}) }
} }
// 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")
@ -1091,41 +1094,42 @@ fn add_tag_union<'a>(
let (non_null_tag, non_null_payload) = non_null; let (non_null_tag, non_null_payload) = non_null;
RocType::TagUnion(RocTagUnion::NullableUnwrapped { RocTagUnion::NullableUnwrapped {
name: name.clone(), name: name.clone(),
null_tag, null_tag,
non_null_tag, non_null_tag,
non_null_payload: non_null_payload.unwrap(), non_null_payload: non_null_payload.unwrap(),
null_represents_first_tag, null_represents_first_tag,
}) }
} }
} }
} }
Layout::Builtin(Builtin::Int(int_width)) => RocType::TagUnion(RocTagUnion::Enumeration { Layout::Builtin(Builtin::Int(int_width)) => RocTagUnion::Enumeration {
name: name.clone(), name: name.clone(),
tags: tags.into_iter().map(|(tag_name, _)| tag_name).collect(), tags: tags.into_iter().map(|(tag_name, _)| tag_name).collect(),
size: int_width.stack_size(), size: int_width.stack_size(),
}), },
Layout::Builtin(_) Layout::Builtin(_)
| Layout::Struct { .. } | Layout::Struct { .. }
| Layout::Boxed(_) | Layout::Boxed(_)
| Layout::LambdaSet(_) | Layout::LambdaSet(_)
| Layout::RecursivePointer => { | Layout::RecursivePointer => {
// These must be single-tag unions. Generate ordinary nonrecursive // These must be single-tag wrappers. Generate ordinary nonrecursive
// tag unions for them, and let Rust do the unwrapping. // tag unions for them, and let the generator do any unwrapping.
// //
// This should be a very rare use case, and it's not worth overcomplicating // This should be a very rare use case, and it's not worth overcomplicating
// the rest of glue to make it do something different. // the rest of glue to make it do something different.
RocType::TagUnion(RocTagUnion::NonRecursive { RocTagUnion::NonRecursive {
name: name.clone(), name: name.clone(),
tags, tags,
// These actually have no discriminant, since there's only one tag. // These actually have no discriminant, since there's only one tag.
discriminant_size: 1, discriminant_size: 1,
discriminant_offset: 0, discriminant_offset: 0,
}) }
} }
}; };
let typ = RocType::TagUnion(tag_union_type);
let type_id = types.add_named(name, typ, layout); let type_id = types.add_named(name, typ, layout);
if is_recursive { if is_recursive {