From bc8bd95b3df13ea3547ef70d98c0debf3f68b104 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 20 Jun 2021 18:12:18 +0200 Subject: [PATCH] use union layout in mono patterns --- compiler/mono/src/decision_tree.rs | 104 ++++++++++++++--------------- compiler/mono/src/ir.rs | 51 +++++++------- 2 files changed, 77 insertions(+), 78 deletions(-) diff --git a/compiler/mono/src/decision_tree.rs b/compiler/mono/src/decision_tree.rs index b26fd9e134..055281f7dc 100644 --- a/compiler/mono/src/decision_tree.rs +++ b/compiler/mono/src/decision_tree.rs @@ -220,8 +220,7 @@ fn flatten<'a>( } if union.alternatives.len() == 1 && !matches!( layout, - Layout::Union(UnionLayout::NullableWrapped { .. }) - | Layout::Union(UnionLayout::NullableUnwrapped { .. }) + UnionLayout::NullableWrapped { .. } | UnionLayout::NullableUnwrapped { .. } ) => { // TODO ^ do we need to check that guard.is_none() here? @@ -633,59 +632,60 @@ fn to_relevant_branch_help<'a>( debug_assert_eq!(tag_id, *test_id); // the test matches the constructor of this pattern - - match Wrapped::opt_from_layout(&layout) { - None => todo!(), - Some(wrapped) => { - match wrapped { - Wrapped::SingleElementRecord => { - // Theory: Unbox doesn't have any value for us - debug_assert_eq!(arguments.len(), 1); - let arg = arguments[0].clone(); - { - // NOTE here elm unboxes, but we ignore that - // Path::Unbox(Box::new(path.clone())) - start.push((path.to_vec(), guard, arg.0)); - start.extend(end); - } - } - Wrapped::RecordOrSingleTagUnion | Wrapped::LikeARoseTree => { - let sub_positions = arguments.into_iter().enumerate().map( - |(index, (pattern, _))| { - let mut new_path = path.to_vec(); - new_path.push(PathInstruction { - index: index as u64, - tag_id, - }); - (new_path, Guard::NoGuard, pattern) - }, - ); - start.extend(sub_positions); - start.extend(end); - } - Wrapped::MultiTagUnion => { - let sub_positions = arguments.into_iter().enumerate().map( - |(index, (pattern, _))| { - let mut new_path = path.to_vec(); - new_path.push(PathInstruction { - index: 1 + index as u64, - tag_id, - }); - (new_path, Guard::NoGuard, pattern) - }, - ); - start.extend(sub_positions); - start.extend(end); - } - Wrapped::EmptyRecord => todo!(), + match layout { + UnionLayout::NonRecursive([[Layout::Struct([_])]]) => { + // a one-element record equivalent + // Theory: Unbox doesn't have any value for us + debug_assert_eq!(arguments.len(), 1); + let arg = arguments[0].clone(); + { + // NOTE here elm unboxes, but we ignore that + // Path::Unbox(Box::new(path.clone())) + start.push((path.to_vec(), guard, arg.0)); + start.extend(end); } - - Some(Branch { - goal: branch.goal, - patterns: start, - }) + } + UnionLayout::NonRecursive([_]) | UnionLayout::NonNullableUnwrapped(_) => { + let sub_positions = + arguments + .into_iter() + .enumerate() + .map(|(index, (pattern, _))| { + let mut new_path = path.to_vec(); + new_path.push(PathInstruction { + index: index as u64, + tag_id, + }); + (new_path, Guard::NoGuard, pattern) + }); + start.extend(sub_positions); + start.extend(end); + } + UnionLayout::NonRecursive(_) + | UnionLayout::Recursive(_) + | UnionLayout::NullableWrapped { .. } + | UnionLayout::NullableUnwrapped { .. } => { + let sub_positions = + arguments + .into_iter() + .enumerate() + .map(|(index, (pattern, _))| { + let mut new_path = path.to_vec(); + new_path.push(PathInstruction { + index: 1 + index as u64, + tag_id, + }); + (new_path, Guard::NoGuard, pattern) + }); + start.extend(sub_positions); + start.extend(end); } } + + Some(Branch { + goal: branch.goal, + patterns: start, + }) } _ => None, } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 7df6ccf403..33b8af43e7 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -5586,22 +5586,6 @@ fn store_pattern_help<'a>( | StrLiteral(_) => { return StorePattern::NotProductive(stmt); } - AppliedTag { - arguments, layout, .. - } => { - let wrapped = Wrapped::from_layout(layout); - - return store_tag_pattern( - env, - procs, - layout_cache, - outer_symbol, - layout, - &arguments, - wrapped, - stmt, - ); - } NewtypeDestructure { arguments, .. } => { let mut fields = Vec::with_capacity_in(arguments.len(), env.arena); fields.extend(arguments.iter().map(|x| x.1)); @@ -5621,6 +5605,23 @@ fn store_pattern_help<'a>( stmt, ); } + AppliedTag { + arguments, layout, .. + } => { + let union_layout = Layout::Union(*layout); + let wrapped = Wrapped::from_layout(&union_layout); + + return store_tag_pattern( + env, + procs, + layout_cache, + outer_symbol, + &union_layout, + &arguments, + wrapped, + stmt, + ); + } RecordDestructure(destructs, sorted_fields) => { let mut is_productive = false; for (index, destruct) in destructs.iter().enumerate().rev() { @@ -6781,7 +6782,7 @@ pub enum Pattern<'a> { tag_name: TagName, tag_id: u8, arguments: Vec<'a, (Pattern<'a>, Layout<'a>)>, - layout: Layout<'a>, + layout: UnionLayout<'a>, union: crate::exhaustive::Union, }, } @@ -7049,8 +7050,7 @@ fn from_can_pattern_help<'a>( temp }; - let layout = - Layout::Union(UnionLayout::NonRecursive(layouts.into_bump_slice())); + let layout = UnionLayout::NonRecursive(layouts.into_bump_slice()); Pattern::AppliedTag { tag_name: tag_name.clone(), @@ -7108,8 +7108,7 @@ fn from_can_pattern_help<'a>( }; debug_assert!(layouts.len() > 1); - let layout = - Layout::Union(UnionLayout::Recursive(layouts.into_bump_slice())); + let layout = UnionLayout::Recursive(layouts.into_bump_slice()); Pattern::AppliedTag { tag_name: tag_name.clone(), @@ -7154,7 +7153,7 @@ fn from_can_pattern_help<'a>( )); } - let layout = Layout::Union(UnionLayout::NonNullableUnwrapped(fields)); + let layout = UnionLayout::NonNullableUnwrapped(fields); Pattern::AppliedTag { tag_name: tag_name.clone(), @@ -7239,10 +7238,10 @@ fn from_can_pattern_help<'a>( temp }; - let layout = Layout::Union(UnionLayout::NullableWrapped { + let layout = UnionLayout::NullableWrapped { nullable_id, other_tags: layouts.into_bump_slice(), - }); + }; Pattern::AppliedTag { tag_name: tag_name.clone(), @@ -7300,10 +7299,10 @@ fn from_can_pattern_help<'a>( )); } - let layout = Layout::Union(UnionLayout::NullableUnwrapped { + let layout = UnionLayout::NullableUnwrapped { nullable_id, other_fields, - }); + }; Pattern::AppliedTag { tag_name: tag_name.clone(),