mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
push optional field assignments into the branch
This commit is contained in:
parent
a7efffa542
commit
eb501f90a2
1 changed files with 84 additions and 14 deletions
|
@ -1264,9 +1264,36 @@ fn patterns_to_when<'a>(
|
|||
// this must be fixed when moving exhaustiveness checking to the new canonical AST
|
||||
for (pattern_var, pattern) in patterns.into_iter() {
|
||||
let context = crate::exhaustive::Context::BadArg;
|
||||
let (mono_pattern, assignments) = match from_can_pattern(env, layout_cache, &pattern.value)
|
||||
{
|
||||
Ok(v) => v,
|
||||
let mono_pattern = match from_can_pattern(env, layout_cache, &pattern.value) {
|
||||
Ok((pat, assignments)) => {
|
||||
for (symbol, variable, expr) in assignments.into_iter().rev() {
|
||||
if let Ok(old_body) = body {
|
||||
let def = roc_can::def::Def {
|
||||
annotation: None,
|
||||
expr_var: variable,
|
||||
loc_expr: Located::at(pattern.region, expr),
|
||||
loc_pattern: Located::at(
|
||||
pattern.region,
|
||||
roc_can::pattern::Pattern::Identifier(symbol),
|
||||
),
|
||||
pattern_vars: std::iter::once((symbol, variable)).collect(),
|
||||
};
|
||||
let new_expr = roc_can::expr::Expr::LetNonRec(
|
||||
Box::new(def),
|
||||
Box::new(old_body),
|
||||
variable,
|
||||
);
|
||||
let new_body = Located {
|
||||
region: pattern.region,
|
||||
value: new_expr,
|
||||
};
|
||||
|
||||
body = Ok(new_body);
|
||||
}
|
||||
}
|
||||
|
||||
pat
|
||||
}
|
||||
Err(runtime_error) => {
|
||||
// Even if the body was Ok, replace it with this Err.
|
||||
// If it was already an Err, leave it at that Err, so the first
|
||||
|
@ -2435,6 +2462,14 @@ pub fn with_hole<'a>(
|
|||
// return Stmt::RuntimeError("TODO non-exhaustive pattern");
|
||||
}
|
||||
|
||||
let mut hole = hole;
|
||||
|
||||
for (symbol, variable, expr) in assignments {
|
||||
let stmt = with_hole(env, expr, variable, procs, layout_cache, symbol, hole);
|
||||
|
||||
hole = env.arena.alloc(stmt);
|
||||
}
|
||||
|
||||
// convert the continuation
|
||||
let mut stmt = with_hole(
|
||||
env,
|
||||
|
@ -3953,10 +3988,16 @@ pub fn from_can<'a>(
|
|||
};
|
||||
|
||||
if let Pattern::Identifier(symbol) = mono_pattern {
|
||||
let hole =
|
||||
let mut hole =
|
||||
env.arena
|
||||
.alloc(from_can(env, variable, cont.value, procs, layout_cache));
|
||||
|
||||
for (symbol, variable, expr) in assignments {
|
||||
let stmt = with_hole(env, expr, variable, procs, layout_cache, symbol, hole);
|
||||
|
||||
hole = env.arena.alloc(stmt);
|
||||
}
|
||||
|
||||
with_hole(
|
||||
env,
|
||||
def.loc_expr.value,
|
||||
|
@ -3989,6 +4030,12 @@ pub fn from_can<'a>(
|
|||
// convert the continuation
|
||||
let mut stmt = from_can(env, variable, cont.value, procs, layout_cache);
|
||||
|
||||
// layer on any default record fields
|
||||
for (symbol, variable, expr) in assignments {
|
||||
let hole = env.arena.alloc(stmt);
|
||||
stmt = with_hole(env, expr, variable, procs, layout_cache, symbol, hole);
|
||||
}
|
||||
|
||||
if let roc_can::expr::Expr::Var(outer_symbol) = def.loc_expr.value {
|
||||
store_pattern(env, procs, layout_cache, &mono_pattern, outer_symbol, stmt)
|
||||
.unwrap()
|
||||
|
@ -4050,12 +4097,29 @@ fn to_opt_branches<'a>(
|
|||
exhaustive_guard.clone(),
|
||||
));
|
||||
|
||||
let mut loc_expr = when_branch.value.clone();
|
||||
let region = loc_pattern.region;
|
||||
for (symbol, variable, expr) in assignments.into_iter().rev() {
|
||||
let def = roc_can::def::Def {
|
||||
annotation: None,
|
||||
expr_var: variable,
|
||||
loc_expr: Located::at(region, expr),
|
||||
loc_pattern: Located::at(
|
||||
region,
|
||||
roc_can::pattern::Pattern::Identifier(symbol),
|
||||
),
|
||||
pattern_vars: std::iter::once((symbol, variable)).collect(),
|
||||
};
|
||||
let new_expr = roc_can::expr::Expr::LetNonRec(
|
||||
Box::new(def),
|
||||
Box::new(loc_expr),
|
||||
variable,
|
||||
);
|
||||
loc_expr = Located::at(region, new_expr);
|
||||
}
|
||||
|
||||
// TODO remove clone?
|
||||
opt_branches.push((
|
||||
mono_pattern,
|
||||
when_branch.guard.clone(),
|
||||
when_branch.value.value.clone(),
|
||||
));
|
||||
opt_branches.push((mono_pattern, when_branch.guard.clone(), loc_expr.value));
|
||||
}
|
||||
Err(runtime_error) => {
|
||||
loc_branches.push((
|
||||
|
@ -5493,18 +5557,24 @@ fn from_can_pattern<'a>(
|
|||
env: &mut Env<'a, '_>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
can_pattern: &roc_can::pattern::Pattern,
|
||||
) -> Result<(Pattern<'a>, &'a [(Symbol, Layout<'a>, roc_can::expr::Expr)]), RuntimeError> {
|
||||
) -> Result<
|
||||
(
|
||||
Pattern<'a>,
|
||||
Vec<'a, (Symbol, Variable, roc_can::expr::Expr)>,
|
||||
),
|
||||
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, assignments))
|
||||
}
|
||||
|
||||
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)>,
|
||||
assignments: &mut Vec<'a, (Symbol, Variable, roc_can::expr::Expr)>,
|
||||
) -> Result<Pattern<'a>, RuntimeError> {
|
||||
use roc_can::pattern::Pattern::*;
|
||||
|
||||
|
@ -5783,7 +5853,7 @@ fn from_can_pattern_help<'a>(
|
|||
// so we push the default assignment into the branch
|
||||
assignments.push((
|
||||
destruct.value.symbol,
|
||||
field_layout,
|
||||
variable,
|
||||
loc_expr.value.clone(),
|
||||
));
|
||||
}
|
||||
|
@ -5844,7 +5914,7 @@ fn from_can_record_destruct<'a>(
|
|||
layout_cache: &mut LayoutCache<'a>,
|
||||
can_rd: &roc_can::pattern::RecordDestruct,
|
||||
field_layout: Layout<'a>,
|
||||
assignments: &mut Vec<'a, (Symbol, Layout<'a>, roc_can::expr::Expr)>,
|
||||
assignments: &mut Vec<'a, (Symbol, Variable, roc_can::expr::Expr)>,
|
||||
) -> Result<RecordDestruct<'a>, RuntimeError> {
|
||||
Ok(RecordDestruct {
|
||||
label: can_rd.label.clone(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue