mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +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
|
// this must be fixed when moving exhaustiveness checking to the new canonical AST
|
||||||
for (pattern_var, pattern) in patterns.into_iter() {
|
for (pattern_var, pattern) in patterns.into_iter() {
|
||||||
let context = crate::exhaustive::Context::BadArg;
|
let context = crate::exhaustive::Context::BadArg;
|
||||||
let (mono_pattern, assignments) = match from_can_pattern(env, layout_cache, &pattern.value)
|
let mono_pattern = match from_can_pattern(env, layout_cache, &pattern.value) {
|
||||||
{
|
Ok((pat, assignments)) => {
|
||||||
Ok(v) => v,
|
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) => {
|
Err(runtime_error) => {
|
||||||
// Even if the body was Ok, replace it with this Err.
|
// 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
|
// 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");
|
// 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
|
// convert the continuation
|
||||||
let mut stmt = with_hole(
|
let mut stmt = with_hole(
|
||||||
env,
|
env,
|
||||||
|
@ -3953,10 +3988,16 @@ pub fn from_can<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Pattern::Identifier(symbol) = mono_pattern {
|
if let Pattern::Identifier(symbol) = mono_pattern {
|
||||||
let hole =
|
let mut hole =
|
||||||
env.arena
|
env.arena
|
||||||
.alloc(from_can(env, variable, cont.value, procs, layout_cache));
|
.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(
|
with_hole(
|
||||||
env,
|
env,
|
||||||
def.loc_expr.value,
|
def.loc_expr.value,
|
||||||
|
@ -3989,6 +4030,12 @@ pub fn from_can<'a>(
|
||||||
// convert the continuation
|
// convert the continuation
|
||||||
let mut stmt = from_can(env, variable, cont.value, procs, layout_cache);
|
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 {
|
if let roc_can::expr::Expr::Var(outer_symbol) = def.loc_expr.value {
|
||||||
store_pattern(env, procs, layout_cache, &mono_pattern, outer_symbol, stmt)
|
store_pattern(env, procs, layout_cache, &mono_pattern, outer_symbol, stmt)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -4050,12 +4097,29 @@ fn to_opt_branches<'a>(
|
||||||
exhaustive_guard.clone(),
|
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?
|
// TODO remove clone?
|
||||||
opt_branches.push((
|
opt_branches.push((mono_pattern, when_branch.guard.clone(), loc_expr.value));
|
||||||
mono_pattern,
|
|
||||||
when_branch.guard.clone(),
|
|
||||||
when_branch.value.value.clone(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Err(runtime_error) => {
|
Err(runtime_error) => {
|
||||||
loc_branches.push((
|
loc_branches.push((
|
||||||
|
@ -5493,18 +5557,24 @@ 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>,
|
||||||
|
Vec<'a, (Symbol, Variable, roc_can::expr::Expr)>,
|
||||||
|
),
|
||||||
|
RuntimeError,
|
||||||
|
> {
|
||||||
let mut assignments = Vec::new_in(env.arena);
|
let mut assignments = Vec::new_in(env.arena);
|
||||||
let pattern = from_can_pattern_help(env, layout_cache, can_pattern, &mut assignments)?;
|
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>(
|
fn from_can_pattern_help<'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,
|
||||||
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> {
|
) -> Result<Pattern<'a>, RuntimeError> {
|
||||||
use roc_can::pattern::Pattern::*;
|
use roc_can::pattern::Pattern::*;
|
||||||
|
|
||||||
|
@ -5783,7 +5853,7 @@ fn from_can_pattern_help<'a>(
|
||||||
// so we push the default assignment into the branch
|
// so we push the default assignment into the branch
|
||||||
assignments.push((
|
assignments.push((
|
||||||
destruct.value.symbol,
|
destruct.value.symbol,
|
||||||
field_layout,
|
variable,
|
||||||
loc_expr.value.clone(),
|
loc_expr.value.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -5844,7 +5914,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)>,
|
assignments: &mut Vec<'a, (Symbol, Variable, 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(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue