extract optional record field default assignments

This commit is contained in:
Folkert 2020-12-29 01:04:55 +01:00
parent f8e04619b8
commit 40b514a26d

View file

@ -5487,12 +5487,27 @@ pub struct WhenBranch<'a> {
pub guard: Option<Stmt<'a>>, pub guard: Option<Stmt<'a>>,
} }
pub fn from_can_pattern<'a>( fn from_can_pattern<'a>(
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
layout_cache: &mut LayoutCache<'a>, layout_cache: &mut LayoutCache<'a>,
can_pattern: &roc_can::pattern::Pattern, can_pattern: &roc_can::pattern::Pattern,
// ) -> Result<(Pattern<'a>, &'a [(Symbol, Layout<'a>, roc_can::expr::Expr)]), RuntimeError> {
) -> Result<Pattern<'a>, RuntimeError> {
let mut assignments = Vec::new_in(env.arena);
let pattern = from_can_pattern_help(env, layout_cache, can_pattern, &mut assignments)?;
// Ok((pattern, assignments.into_bump_slice()))
Ok(pattern)
}
fn from_can_pattern_help<'a>(
env: &mut Env<'a, '_>,
layout_cache: &mut LayoutCache<'a>,
can_pattern: &roc_can::pattern::Pattern,
assignments: &mut Vec<'a, (Symbol, Layout<'a>, roc_can::expr::Expr)>,
) -> Result<Pattern<'a>, RuntimeError> { ) -> Result<Pattern<'a>, RuntimeError> {
use roc_can::pattern::Pattern::*; use roc_can::pattern::Pattern::*;
match can_pattern { match can_pattern {
Underscore => Ok(Pattern::Underscore), Underscore => Ok(Pattern::Underscore),
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)), Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
@ -5614,7 +5629,7 @@ pub fn from_can_pattern<'a>(
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena); let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
for ((_, loc_pat), layout) in arguments.iter().zip(field_layouts.iter()) { for ((_, loc_pat), layout) in arguments.iter().zip(field_layouts.iter()) {
mono_args.push(( mono_args.push((
from_can_pattern(env, layout_cache, &loc_pat.value)?, from_can_pattern_help(env, layout_cache, &loc_pat.value, assignments)?,
layout.clone(), layout.clone(),
)); ));
} }
@ -5674,7 +5689,7 @@ pub fn from_can_pattern<'a>(
let it = argument_layouts[1..].iter(); let it = argument_layouts[1..].iter();
for ((_, loc_pat), layout) in arguments.iter().zip(it) { for ((_, loc_pat), layout) in arguments.iter().zip(it) {
mono_args.push(( mono_args.push((
from_can_pattern(env, layout_cache, &loc_pat.value)?, from_can_pattern_help(env, layout_cache, &loc_pat.value, assignments)?,
layout.clone(), layout.clone(),
)); ));
} }
@ -5738,6 +5753,7 @@ pub fn from_can_pattern<'a>(
layout_cache, layout_cache,
&destruct.value, &destruct.value,
field_layout.clone(), field_layout.clone(),
assignments,
)?); )?);
} }
None => { None => {
@ -5761,22 +5777,20 @@ pub fn from_can_pattern<'a>(
match destructs_by_label.remove(&label) { match destructs_by_label.remove(&label) {
Some(destruct) => { Some(destruct) => {
// this field is destructured by the pattern // this field is destructured by the pattern
mono_destructs.push(RecordDestruct { match &destruct.value.typ {
label: destruct.value.label.clone(), roc_can::pattern::DestructType::Optional(_, loc_expr) => {
symbol: destruct.value.symbol, // if we reach this stage, the optional field is not present
layout: field_layout, // so we push the default assignment into the branch
variable, assignments.push((
typ: match &destruct.value.typ { destruct.value.symbol,
roc_can::pattern::DestructType::Optional(_, loc_expr) => { field_layout,
// if we reach this stage, the optional field is not present loc_expr.value.clone(),
// so use the default ));
DestructType::Optional(loc_expr.value.clone()) }
} _ => unreachable!(
_ => unreachable!( "only optional destructs can be optional fields"
"only optional destructs can be optional fields" ),
), };
},
});
} }
None => { None => {
// this field is not destructured by the pattern // this field is not destructured by the pattern
@ -5830,6 +5844,7 @@ fn from_can_record_destruct<'a>(
layout_cache: &mut LayoutCache<'a>, layout_cache: &mut LayoutCache<'a>,
can_rd: &roc_can::pattern::RecordDestruct, can_rd: &roc_can::pattern::RecordDestruct,
field_layout: Layout<'a>, field_layout: Layout<'a>,
assignments: &mut Vec<'a, (Symbol, Layout<'a>, roc_can::expr::Expr)>,
) -> Result<RecordDestruct<'a>, RuntimeError> { ) -> Result<RecordDestruct<'a>, RuntimeError> {
Ok(RecordDestruct { Ok(RecordDestruct {
label: can_rd.label.clone(), label: can_rd.label.clone(),
@ -5843,9 +5858,9 @@ fn from_can_record_destruct<'a>(
// DestructType::Optional(loc_expr.value.clone()) // DestructType::Optional(loc_expr.value.clone())
DestructType::Required DestructType::Required
} }
roc_can::pattern::DestructType::Guard(_, loc_pattern) => { roc_can::pattern::DestructType::Guard(_, loc_pattern) => DestructType::Guard(
DestructType::Guard(from_can_pattern(env, layout_cache, &loc_pattern.value)?) from_can_pattern_help(env, layout_cache, &loc_pattern.value, assignments)?,
} ),
}, },
}) })
} }