mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
generate callers based on layout traversal
This commit is contained in:
parent
8a443ba8bb
commit
68524ef07e
4 changed files with 562 additions and 44 deletions
|
@ -2717,6 +2717,60 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_varying_stack_size<I>(self, interner: &I, arena: &bumpalo::Bump) -> bool
|
||||
where
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let mut stack: Vec<Layout> = bumpalo::collections::Vec::new_in(arena);
|
||||
|
||||
stack.push(self);
|
||||
|
||||
while let Some(layout) = stack.pop() {
|
||||
match layout {
|
||||
Layout::Builtin(builtin) => match builtin {
|
||||
Builtin::Int(_)
|
||||
| Builtin::Float(_)
|
||||
| Builtin::Bool
|
||||
| Builtin::Decimal
|
||||
| Builtin::Str
|
||||
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
|
||||
| Builtin::List(_) => { /* do nothing */ }
|
||||
},
|
||||
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
|
||||
Layout::Struct { field_layouts, .. } => {
|
||||
stack.extend(field_layouts.iter().map(|interned| interner.get(*interned)))
|
||||
}
|
||||
Layout::Union(tag_union) => match tag_union {
|
||||
UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => {
|
||||
for tag in tags {
|
||||
stack.extend(tag.iter().map(|interned| interner.get(*interned)));
|
||||
}
|
||||
}
|
||||
UnionLayout::NonNullableUnwrapped(fields) => {
|
||||
stack.extend(fields.iter().map(|interned| interner.get(*interned)));
|
||||
}
|
||||
UnionLayout::NullableWrapped { other_tags, .. } => {
|
||||
for tag in other_tags {
|
||||
stack.extend(tag.iter().map(|interned| interner.get(*interned)));
|
||||
}
|
||||
}
|
||||
UnionLayout::NullableUnwrapped { other_fields, .. } => {
|
||||
stack.extend(other_fields.iter().map(|interned| interner.get(*interned)));
|
||||
}
|
||||
},
|
||||
Layout::LambdaSet(_) => return true,
|
||||
Layout::Boxed(_) => {
|
||||
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
|
||||
}
|
||||
Layout::RecursivePointer(_) => {
|
||||
/* do nothing, we've already generated for this type through the Union(_) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Used to build a `Layout::Struct` where the field name order is irrelevant.
|
||||
pub fn struct_no_name_order(field_layouts: &'a [InLayout]) -> Self {
|
||||
if field_layouts.is_empty() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue