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 @@ pub fn type_from_layout(cfg: TargetFrontendConfig, layout: &Layout<'_>) -> Type
use roc_mono::layout::Layout::*;
match layout {
Pointer(_) | FunctionPointer(_, _) | Struct(_) | Tag(_) => cfg.pointer_type(),
Pointer(_) | FunctionPointer(_, _) | Struct(_) | Union(_) => cfg.pointer_type(),
Builtin(builtin) => match builtin {
Int64 => types::I64,
Float64 => types::F64,

View File

@ -68,7 +68,7 @@ pub fn basic_type_from_layout<'ctx>(
.struct_type(field_types.into_bump_slice(), false)
.as_basic_type_enum()
}
Tag(_fields) => {
Union(_fields) => {
panic!("TODO layout_to_basic_type for Tag");
}
Pointer(_layout) => {

View File

@ -124,7 +124,9 @@ fn flatten_patterns<'a>(branch: Branch<'a>) -> Branch<'a> {
fn flatten<'a>(path_pattern: (Path, Pattern<'a>), path_patterns: &mut Vec<(Path, Pattern<'a>)>) {
match &path_pattern.1 {
Pattern::AppliedTag { union, .. } => {
Pattern::AppliedTag {
union, arguments, ..
} => {
if union.alternatives.len() == 1 {
// case map dearg ctorArgs of
// [arg] ->

View File

@ -104,6 +104,7 @@ pub struct Env<'a, 'i> {
pub ident_ids: &'i mut IdentIds,
pub pointer_size: u32,
symbol_counter: usize,
pub jump_counter: &'a mut u64,
}
impl<'a, 'i> Env<'a, 'i> {
@ -217,6 +218,7 @@ impl<'a> Expr<'a> {
ident_ids,
pointer_size,
symbol_counter: 0,
jump_counter: arena.alloc(0),
};
from_can(&mut env, can_expr, procs, None)

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)))
}
}
}