remove Shadowed variant from mono pattern

This commit is contained in:
Folkert 2020-12-28 23:14:04 +01:00
parent 4cdde12823
commit 794f8c4d41
4 changed files with 90 additions and 52 deletions

View file

@ -1750,7 +1750,9 @@ mod gen_primitives {
} }
#[test] #[test]
#[should_panic(expected = "shadowed")] #[should_panic(
expected = "Roc failed with message: \"Shadowing { original_region: |L 3-3, C 4-5|, shadow: |L 6-6, C 8-9| Ident(\\\"x\\\") }\""
)]
fn pattern_shadowing() { fn pattern_shadowing() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1768,7 +1770,7 @@ mod gen_primitives {
#[test] #[test]
#[ignore] #[ignore]
#[should_panic(expected = "shadowed")] #[should_panic(expected = "foo")]
fn unsupported_pattern_tag() { fn unsupported_pattern_tag() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(

View file

@ -379,7 +379,7 @@ fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut V
match pattern { match pattern {
// TODO use guard! // TODO use guard!
Identifier(_) | Underscore | Shadowed(_, _) | UnsupportedPattern(_) => { Identifier(_) | Underscore | UnsupportedPattern(_) => {
if let Guard::Guard { symbol, id, stmt } = guard { if let Guard::Guard { symbol, id, stmt } = guard {
all_tests.push(Guarded { all_tests.push(Guarded {
opt_test: None, opt_test: None,
@ -531,7 +531,7 @@ fn to_relevant_branch_help<'a>(
use Test::*; use Test::*;
match pattern { match pattern {
Identifier(_) | Underscore | Shadowed(_, _) | UnsupportedPattern(_) => Some(branch.clone()), Identifier(_) | Underscore | UnsupportedPattern(_) => Some(branch.clone()),
RecordDestructure(destructs, _) => match test { RecordDestructure(destructs, _) => match test {
IsCtor { IsCtor {
@ -742,7 +742,7 @@ fn needs_tests<'a>(pattern: &Pattern<'a>) -> bool {
use Pattern::*; use Pattern::*;
match pattern { match pattern {
Identifier(_) | Underscore | Shadowed(_, _) | UnsupportedPattern(_) => false, Identifier(_) | Underscore | UnsupportedPattern(_) => false,
RecordDestructure(_, _) RecordDestructure(_, _)
| AppliedTag { .. } | AppliedTag { .. }

View file

@ -84,11 +84,6 @@ fn simplify<'a>(pattern: &crate::ir::Pattern<'a>) -> Pattern {
Ctor(union, tag_id, patterns) Ctor(union, tag_id, patterns)
} }
Shadowed(_region, _ident) => {
// Treat as an Anything
// code-gen will make a runtime error out of the branch
Anything
}
UnsupportedPattern(_region) => { UnsupportedPattern(_region) => {
// Treat as an Anything // Treat as an Anything
// code-gen will make a runtime error out of the branch // code-gen will make a runtime error out of the branch

View file

@ -4,7 +4,7 @@ use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem};
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_collections::all::{default_hasher, MutMap, MutSet}; use roc_collections::all::{default_hasher, MutMap, MutSet};
use roc_module::ident::{ForeignSymbol, Ident, Lowercase, TagName}; use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
use roc_module::low_level::LowLevel; use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_problem::can::RuntimeError; use roc_problem::can::RuntimeError;
@ -1264,7 +1264,22 @@ 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 = from_can_pattern(env, layout_cache, &pattern.value); let mono_pattern = match from_can_pattern(env, layout_cache, &pattern.value) {
Ok(v) => v,
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
// RuntimeError we encountered remains the first.
body = body.and({
Err(Located {
region: pattern.region,
value: runtime_error,
})
});
continue;
}
};
match crate::exhaustive::check( match crate::exhaustive::check(
pattern.region, pattern.region,
@ -2392,7 +2407,14 @@ pub fn with_hole<'a>(
} }
} else { } else {
// this may be a destructure pattern // this may be a destructure pattern
let mono_pattern = from_can_pattern(env, layout_cache, &def.loc_pattern.value); let mono_pattern = match from_can_pattern(env, layout_cache, &def.loc_pattern.value)
{
Ok(v) => v,
Err(_runtime_error) => {
// todo
panic!();
}
};
let context = crate::exhaustive::Context::BadDestruct; let context = crate::exhaustive::Context::BadDestruct;
match crate::exhaustive::check( match crate::exhaustive::check(
@ -3923,7 +3945,10 @@ pub fn from_can<'a>(
} }
// this may be a destructure pattern // this may be a destructure pattern
let mono_pattern = from_can_pattern(env, layout_cache, &def.loc_pattern.value); let mono_pattern = match from_can_pattern(env, layout_cache, &def.loc_pattern.value) {
Ok(v) => v,
Err(_) => todo!(),
};
if let Pattern::Identifier(symbol) = mono_pattern { if let Pattern::Identifier(symbol) = mono_pattern {
let hole = let hole =
@ -4015,19 +4040,34 @@ fn to_opt_branches<'a>(
}; };
for loc_pattern in when_branch.patterns { for loc_pattern in when_branch.patterns {
let mono_pattern = from_can_pattern(env, layout_cache, &loc_pattern.value); match from_can_pattern(env, layout_cache, &loc_pattern.value) {
Ok(mono_pattern) => {
loc_branches.push((
Located::at(loc_pattern.region, mono_pattern.clone()),
exhaustive_guard.clone(),
));
loc_branches.push(( // TODO remove clone?
Located::at(loc_pattern.region, mono_pattern.clone()), opt_branches.push((
exhaustive_guard.clone(), mono_pattern,
)); when_branch.guard.clone(),
when_branch.value.value.clone(),
));
}
Err(runtime_error) => {
loc_branches.push((
Located::at(loc_pattern.region, Pattern::Underscore),
exhaustive_guard.clone(),
));
// TODO remove clone? // TODO remove clone?
opt_branches.push(( opt_branches.push((
mono_pattern, Pattern::Underscore,
when_branch.guard.clone(), when_branch.guard.clone(),
when_branch.value.value.clone(), roc_can::expr::Expr::RuntimeError(runtime_error),
)); ));
}
}
} }
} }
@ -4659,10 +4699,6 @@ fn store_pattern<'a>(
unreachable!("a record destructure must always occur on a struct layout"); unreachable!("a record destructure must always occur on a struct layout");
} }
Shadowed(_region, _ident) => {
return Err(&"shadowed");
}
UnsupportedPattern(_region) => { UnsupportedPattern(_region) => {
return Err(&"unsupported pattern"); return Err(&"unsupported pattern");
} }
@ -5431,7 +5467,7 @@ pub enum Pattern<'a> {
}, },
// Runtime Exceptions // Runtime Exceptions
Shadowed(Region, Located<Ident>), // Shadowed(Region, Located<Ident>),
// Example: (5 = 1 + 2) is an unsupported pattern in an assignment; Int patterns aren't allowed in assignments! // Example: (5 = 1 + 2) is an unsupported pattern in an assignment; Int patterns aren't allowed in assignments!
UnsupportedPattern(Region), UnsupportedPattern(Region),
} }
@ -5463,23 +5499,26 @@ pub 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,
) -> Pattern<'a> { ) -> Result<Pattern<'a>, RuntimeError> {
use roc_can::pattern::Pattern::*; use roc_can::pattern::Pattern::*;
match can_pattern { match can_pattern {
Underscore => Pattern::Underscore, Underscore => Ok(Pattern::Underscore),
Identifier(symbol) => Pattern::Identifier(*symbol), Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
IntLiteral(v) => Pattern::IntLiteral(*v), IntLiteral(v) => Ok(Pattern::IntLiteral(*v)),
FloatLiteral(v) => Pattern::FloatLiteral(f64::to_bits(*v)), FloatLiteral(v) => Ok(Pattern::FloatLiteral(f64::to_bits(*v))),
StrLiteral(v) => Pattern::StrLiteral(v.clone()), StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
Shadowed(region, ident) => Pattern::Shadowed(*region, ident.clone()), Shadowed(region, ident) => Err(RuntimeError::Shadowing {
UnsupportedPattern(region) => Pattern::UnsupportedPattern(*region), original_region: *region,
shadow: ident.clone(),
}),
UnsupportedPattern(region) => Ok(Pattern::UnsupportedPattern(*region)),
MalformedPattern(_problem, region) => { MalformedPattern(_problem, region) => {
// TODO preserve malformed problem information here? // TODO preserve malformed problem information here?
Pattern::UnsupportedPattern(*region) Ok(Pattern::UnsupportedPattern(*region))
} }
NumLiteral(var, num) => match num_argument_to_int_or_float(env.subs, *var) { NumLiteral(var, num) => match num_argument_to_int_or_float(env.subs, *var) {
IntOrFloat::IntType => Pattern::IntLiteral(*num), IntOrFloat::IntType => Ok(Pattern::IntLiteral(*num)),
IntOrFloat::FloatType => Pattern::FloatLiteral(*num as u64), IntOrFloat::FloatType => Ok(Pattern::FloatLiteral(*num as u64)),
}, },
AppliedTag { AppliedTag {
@ -5493,7 +5532,7 @@ pub fn from_can_pattern<'a>(
let variant = crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs); let variant = crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs);
match variant { let result = match variant {
Never => unreachable!( Never => unreachable!(
"there is no pattern of type `[]`, union var {:?}", "there is no pattern of type `[]`, union var {:?}",
*whole_var *whole_var
@ -5582,7 +5621,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(env, layout_cache, &loc_pat.value)?,
layout.clone(), layout.clone(),
)); ));
} }
@ -5642,7 +5681,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(env, layout_cache, &loc_pat.value)?,
layout.clone(), layout.clone(),
)); ));
} }
@ -5664,7 +5703,9 @@ pub fn from_can_pattern<'a>(
layout, layout,
} }
} }
} };
Ok(result)
} }
RecordDestructure { RecordDestructure {
@ -5704,7 +5745,7 @@ pub fn from_can_pattern<'a>(
layout_cache, layout_cache,
&destruct.value, &destruct.value,
field_layout.clone(), field_layout.clone(),
)); )?);
} }
None => { None => {
// this field is not destructured by the pattern // this field is not destructured by the pattern
@ -5783,10 +5824,10 @@ pub fn from_can_pattern<'a>(
} }
} }
Pattern::RecordDestructure( Ok(Pattern::RecordDestructure(
mono_destructs, mono_destructs,
Layout::Struct(field_layouts.into_bump_slice()), Layout::Struct(field_layouts.into_bump_slice()),
) ))
} }
} }
} }
@ -5796,8 +5837,8 @@ 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>,
) -> RecordDestruct<'a> { ) -> Result<RecordDestruct<'a>, RuntimeError> {
RecordDestruct { Ok(RecordDestruct {
label: can_rd.label.clone(), label: can_rd.label.clone(),
symbol: can_rd.symbol, symbol: can_rd.symbol,
variable: can_rd.var, variable: can_rd.var,
@ -5810,10 +5851,10 @@ fn from_can_record_destruct<'a>(
DestructType::Required DestructType::Required
} }
roc_can::pattern::DestructType::Guard(_, loc_pattern) => { roc_can::pattern::DestructType::Guard(_, loc_pattern) => {
DestructType::Guard(from_can_pattern(env, layout_cache, &loc_pattern.value)) DestructType::Guard(from_can_pattern(env, layout_cache, &loc_pattern.value)?)
} }
}, },
} })
} }
/// Potentially translate LowLevel operations into more efficient ones based on /// Potentially translate LowLevel operations into more efficient ones based on