implement layout for Tag

This commit is contained in:
Folkert 2020-03-16 13:09:01 +01:00
parent 8c7124aba6
commit d875f8bfce
5 changed files with 28 additions and 11 deletions

View file

@ -10,7 +10,7 @@ use roc_types::subs::{Content, FlatType, Subs, Variable};
pub enum Layout<'a> {
Builtin(Builtin<'a>),
Struct(&'a [(Lowercase, Layout<'a>)]),
Tag(&'a [Layout<'a>]),
Union(&'a MutMap<TagName, &'a [Layout<'a>]>),
Pointer(&'a Layout<'a>),
/// A function. The types of its arguments, then the type of its return value.
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
@ -93,12 +93,15 @@ impl<'a> Layout<'a> {
sum
}
Tag(fields) => {
// the symbol is a 64-bit value, so 8 bytes
let mut sum = 8;
Union(fields) => {
// the tag gets converted to a u8, so 1 byte.
// But for one-tag unions, we don't store the tag, so 0 bytes
let mut sum = (fields.len() > 1) as u32;
for field_layout in *fields {
sum += field_layout.stack_size(pointer_size);
for (_, tag_layout) in *fields {
for field_layout in *tag_layout {
sum += field_layout.stack_size(pointer_size);
}
}
sum
@ -344,8 +347,18 @@ fn layout_from_flat_type<'a>(
Ok(Layout::Builtin(Builtin::Byte(tag_to_u8)))
}
} else {
// panic!("TODO handle a tag union with mutliple tags: {:?}", tags);
Ok(Layout::Tag(&[]))
let mut layouts = MutMap::default();
for (tag_name, arguments) in tags {
let mut arg_layouts = Vec::with_capacity_in(arguments.len(), arena);
for arg in arguments {
arg_layouts.push(Layout::from_var(arena, arg, subs, pointer_size)?);
}
layouts.insert(tag_name, arg_layouts.into_bump_slice());
}
Ok(Layout::Union(arena.alloc(layouts)))
}
}
}