mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
Permit binding variables multiple itmes in when branches
This commit is contained in:
parent
c48c4f3183
commit
bf8fc0d0de
6 changed files with 78 additions and 31 deletions
|
@ -227,10 +227,25 @@ pub fn canonicalize_def_header_pattern<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
_ => canonicalize_pattern(env, var_store, scope, output, pattern_type, pattern, region),
|
||||
_ => canonicalize_pattern(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
output,
|
||||
pattern_type,
|
||||
pattern,
|
||||
region,
|
||||
PermitShadows(false),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow binding of symbols that appear shadowed.
|
||||
///
|
||||
/// For example, in the branch `A x | B x -> ...`, both pattern bind `x`; that's not a shadow!
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub struct PermitShadows(pub bool);
|
||||
|
||||
pub fn canonicalize_pattern<'a>(
|
||||
env: &mut Env<'a>,
|
||||
var_store: &mut VarStore,
|
||||
|
@ -239,6 +254,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
pattern_type: PatternType,
|
||||
pattern: &ast::Pattern<'a>,
|
||||
region: Region,
|
||||
permit_shadows: PermitShadows,
|
||||
) -> Loc<Pattern> {
|
||||
use roc_parse::ast::Pattern::*;
|
||||
use PatternType::*;
|
||||
|
@ -250,15 +266,21 @@ pub fn canonicalize_pattern<'a>(
|
|||
|
||||
Pattern::Identifier(symbol)
|
||||
}
|
||||
Err((original_region, shadow, new_symbol)) => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region,
|
||||
shadow: shadow.clone(),
|
||||
kind: ShadowKind::Variable,
|
||||
}));
|
||||
output.references.insert_bound(new_symbol);
|
||||
Err((shadowed_symbol, shadow, new_symbol)) => {
|
||||
if permit_shadows.0 {
|
||||
output.references.insert_bound(shadowed_symbol.value);
|
||||
|
||||
Pattern::Shadowed(original_region, shadow, new_symbol)
|
||||
Pattern::Identifier(shadowed_symbol.value)
|
||||
} else {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region: shadowed_symbol.region,
|
||||
shadow: shadow.clone(),
|
||||
kind: ShadowKind::Variable,
|
||||
}));
|
||||
output.references.insert_bound(new_symbol);
|
||||
|
||||
Pattern::Shadowed(shadowed_symbol.region, shadow, new_symbol)
|
||||
}
|
||||
}
|
||||
},
|
||||
Tag(name) => {
|
||||
|
@ -289,6 +311,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
pattern_type,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
permit_shadows,
|
||||
);
|
||||
|
||||
can_patterns.push((var_store.fresh(), can_pattern));
|
||||
|
@ -457,6 +480,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
pattern_type,
|
||||
sub_pattern,
|
||||
region,
|
||||
permit_shadows,
|
||||
)
|
||||
}
|
||||
RecordDestructure(patterns) => {
|
||||
|
@ -482,9 +506,9 @@ pub fn canonicalize_pattern<'a>(
|
|||
},
|
||||
});
|
||||
}
|
||||
Err((original_region, shadow, new_symbol)) => {
|
||||
Err((shadowed_symbol, shadow, new_symbol)) => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region,
|
||||
original_region: shadowed_symbol.region,
|
||||
shadow: shadow.clone(),
|
||||
kind: ShadowKind::Variable,
|
||||
}));
|
||||
|
@ -493,8 +517,11 @@ pub fn canonicalize_pattern<'a>(
|
|||
// are, we're definitely shadowed and will
|
||||
// get a runtime exception as soon as we
|
||||
// encounter the first bad pattern.
|
||||
opt_erroneous =
|
||||
Some(Pattern::Shadowed(original_region, shadow, new_symbol));
|
||||
opt_erroneous = Some(Pattern::Shadowed(
|
||||
shadowed_symbol.region,
|
||||
shadow,
|
||||
new_symbol,
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -511,6 +538,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
pattern_type,
|
||||
&loc_guard.value,
|
||||
loc_guard.region,
|
||||
permit_shadows,
|
||||
);
|
||||
|
||||
destructs.push(Loc {
|
||||
|
@ -550,9 +578,9 @@ pub fn canonicalize_pattern<'a>(
|
|||
},
|
||||
});
|
||||
}
|
||||
Err((original_region, shadow, new_symbol)) => {
|
||||
Err((shadowed_symbol, shadow, new_symbol)) => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region,
|
||||
original_region: shadowed_symbol.region,
|
||||
shadow: shadow.clone(),
|
||||
kind: ShadowKind::Variable,
|
||||
}));
|
||||
|
@ -561,8 +589,11 @@ pub fn canonicalize_pattern<'a>(
|
|||
// are, we're definitely shadowed and will
|
||||
// get a runtime exception as soon as we
|
||||
// encounter the first bad pattern.
|
||||
opt_erroneous =
|
||||
Some(Pattern::Shadowed(original_region, shadow, new_symbol));
|
||||
opt_erroneous = Some(Pattern::Shadowed(
|
||||
shadowed_symbol.region,
|
||||
shadow,
|
||||
new_symbol,
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue