generate callers based on layout traversal

This commit is contained in:
Folkert 2023-02-20 22:05:35 +01:00
parent 8a443ba8bb
commit 68524ef07e
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
4 changed files with 562 additions and 44 deletions

View file

@ -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() {