mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
do exhaustiveness on mono patterns
This commit is contained in:
parent
2e3f21b1ce
commit
58fd1d64ff
2 changed files with 99 additions and 94 deletions
|
@ -335,7 +335,7 @@ fn pattern_to_when<'a>(
|
||||||
(env.fresh_symbol(), body)
|
(env.fresh_symbol(), body)
|
||||||
}
|
}
|
||||||
|
|
||||||
Shadowed(_, _) | UnsupportedPattern(_) => {
|
Shadowed(_, _) | UnsupportedPattern(_) => {
|
||||||
// create the runtime error here, instead of delegating to When.
|
// create the runtime error here, instead of delegating to When.
|
||||||
// UnsupportedPattern should then never occcur in When
|
// UnsupportedPattern should then never occcur in When
|
||||||
panic!("TODO generate runtime error here");
|
panic!("TODO generate runtime error here");
|
||||||
|
@ -411,7 +411,7 @@ fn from_can<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it wasn't specifically an Identifier & Closure, proceed as normal.
|
// If it wasn't specifically an Identifier & Closure, proceed as normal.
|
||||||
let mono_pattern = from_can_pattern(env, loc_pattern.value);
|
let mono_pattern = from_can_pattern(env, &loc_pattern.value);
|
||||||
store_pattern(
|
store_pattern(
|
||||||
env,
|
env,
|
||||||
mono_pattern,
|
mono_pattern,
|
||||||
|
@ -829,7 +829,7 @@ fn from_can_when<'a>(
|
||||||
let mut stored = Vec::with_capacity_in(1, arena);
|
let mut stored = Vec::with_capacity_in(1, arena);
|
||||||
let (loc_when_pattern, loc_branch) = branches.into_iter().next().unwrap();
|
let (loc_when_pattern, loc_branch) = branches.into_iter().next().unwrap();
|
||||||
|
|
||||||
let mono_pattern = from_can_pattern(env, loc_when_pattern.value);
|
let mono_pattern = from_can_pattern(env, &loc_when_pattern.value);
|
||||||
store_pattern(
|
store_pattern(
|
||||||
env,
|
env,
|
||||||
mono_pattern,
|
mono_pattern,
|
||||||
|
@ -844,7 +844,12 @@ fn from_can_when<'a>(
|
||||||
Expr::Store(stored.into_bump_slice(), arena.alloc(ret))
|
Expr::Store(stored.into_bump_slice(), arena.alloc(ret))
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let loc_branches: std::vec::Vec<_> = branches.iter().map(|v| v.0.clone()).collect();
|
let loc_branches: std::vec::Vec<_> = branches
|
||||||
|
.iter()
|
||||||
|
.map(|(loc_branch, _)| {
|
||||||
|
Located::at(loc_branch.region, from_can_pattern(env, &loc_branch.value))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
match crate::pattern::check(Region::zero(), &loc_branches) {
|
match crate::pattern::check(Region::zero(), &loc_branches) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
@ -857,8 +862,8 @@ fn from_can_when<'a>(
|
||||||
let (can_loc_when_pat1, loc_then) = iter.next().unwrap();
|
let (can_loc_when_pat1, loc_then) = iter.next().unwrap();
|
||||||
let (can_loc_when_pat2, loc_else) = iter.next().unwrap();
|
let (can_loc_when_pat2, loc_else) = iter.next().unwrap();
|
||||||
|
|
||||||
let when_pat1 = from_can_pattern(env, can_loc_when_pat1.value);
|
let when_pat1 = from_can_pattern(env, &can_loc_when_pat1.value);
|
||||||
let when_pat2 = from_can_pattern(env, can_loc_when_pat2.value);
|
let when_pat2 = from_can_pattern(env, &can_loc_when_pat2.value);
|
||||||
|
|
||||||
let cond_layout = Layout::Builtin(Builtin::Bool(
|
let cond_layout = Layout::Builtin(Builtin::Bool(
|
||||||
TagName::Global("False".into()),
|
TagName::Global("False".into()),
|
||||||
|
@ -926,7 +931,12 @@ fn from_can_when<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let loc_branches: std::vec::Vec<_> = branches.iter().map(|v| v.0.clone()).collect();
|
let loc_branches: std::vec::Vec<_> = branches
|
||||||
|
.iter()
|
||||||
|
.map(|(loc_branch, _)| {
|
||||||
|
Located::at(loc_branch.region, from_can_pattern(env, &loc_branch.value))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
match crate::pattern::check(Region::zero(), &loc_branches) {
|
match crate::pattern::check(Region::zero(), &loc_branches) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
@ -965,7 +975,7 @@ fn from_can_when<'a>(
|
||||||
let mut is_last = true;
|
let mut is_last = true;
|
||||||
for (loc_when_pat, loc_expr) in branches.into_iter().rev() {
|
for (loc_when_pat, loc_expr) in branches.into_iter().rev() {
|
||||||
let mono_expr = from_can(env, loc_expr.value, procs, None);
|
let mono_expr = from_can(env, loc_expr.value, procs, None);
|
||||||
let when_pat = from_can_pattern(env, loc_when_pat.value);
|
let when_pat = from_can_pattern(env, &loc_when_pat.value);
|
||||||
|
|
||||||
if is_last {
|
if is_last {
|
||||||
opt_default_branch = match &when_pat {
|
opt_default_branch = match &when_pat {
|
||||||
|
@ -976,7 +986,7 @@ fn from_can_when<'a>(
|
||||||
arena.alloc(mono_expr.clone()),
|
arena.alloc(mono_expr.clone()),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
Shadowed(_region, _ident) => {
|
Shadowed(_region, _ident) => {
|
||||||
panic!("TODO make runtime exception out of the branch");
|
panic!("TODO make runtime exception out of the branch");
|
||||||
}
|
}
|
||||||
_ => Some(arena.alloc(mono_expr.clone())),
|
_ => Some(arena.alloc(mono_expr.clone())),
|
||||||
|
@ -992,7 +1002,9 @@ fn from_can_when<'a>(
|
||||||
jumpable_branches.push((*int as u64, mono_expr));
|
jumpable_branches.push((*int as u64, mono_expr));
|
||||||
}
|
}
|
||||||
BitLiteral(v) => jumpable_branches.push((*v as u64, mono_expr)),
|
BitLiteral(v) => jumpable_branches.push((*v as u64, mono_expr)),
|
||||||
EnumLiteral { tag_id , .. } => jumpable_branches.push((*tag_id as u64, mono_expr)),
|
EnumLiteral { tag_id, .. } => {
|
||||||
|
jumpable_branches.push((*tag_id as u64, mono_expr))
|
||||||
|
}
|
||||||
Identifier(_) => {
|
Identifier(_) => {
|
||||||
// store is handled above
|
// store is handled above
|
||||||
}
|
}
|
||||||
|
@ -1198,9 +1210,13 @@ pub enum Pattern<'a> {
|
||||||
tag_name: TagName,
|
tag_name: TagName,
|
||||||
arguments: Vec<'a, Pattern<'a>>,
|
arguments: Vec<'a, Pattern<'a>>,
|
||||||
layout: Layout<'a>,
|
layout: Layout<'a>,
|
||||||
|
union: crate::pattern::Union,
|
||||||
},
|
},
|
||||||
BitLiteral(bool),
|
BitLiteral(bool),
|
||||||
EnumLiteral {tag_id: u8, enum_size: u8 },
|
EnumLiteral {
|
||||||
|
tag_id: u8,
|
||||||
|
enum_size: u8,
|
||||||
|
},
|
||||||
IntLiteral(i64),
|
IntLiteral(i64),
|
||||||
FloatLiteral(f64),
|
FloatLiteral(f64),
|
||||||
StrLiteral(Box<str>),
|
StrLiteral(Box<str>),
|
||||||
|
@ -1222,21 +1238,21 @@ pub struct RecordDestruct<'a> {
|
||||||
|
|
||||||
fn from_can_pattern<'a>(
|
fn from_can_pattern<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
can_pattern: roc_can::pattern::Pattern,
|
can_pattern: &roc_can::pattern::Pattern,
|
||||||
) -> Pattern<'a> {
|
) -> Pattern<'a> {
|
||||||
use roc_can::pattern::Pattern::*;
|
use roc_can::pattern::Pattern::*;
|
||||||
match can_pattern {
|
match can_pattern {
|
||||||
Underscore => Pattern::Underscore,
|
Underscore => Pattern::Underscore,
|
||||||
Identifier(symbol) => Pattern::Identifier(symbol),
|
Identifier(symbol) => Pattern::Identifier(*symbol),
|
||||||
IntLiteral(v) => Pattern::IntLiteral(v),
|
IntLiteral(v) => Pattern::IntLiteral(*v),
|
||||||
FloatLiteral(v) => Pattern::FloatLiteral(v),
|
FloatLiteral(v) => Pattern::FloatLiteral(*v),
|
||||||
StrLiteral(v) => Pattern::StrLiteral(v),
|
StrLiteral(v) => Pattern::StrLiteral(v.clone()),
|
||||||
Shadowed(region, ident) => Pattern::Shadowed(region, ident),
|
Shadowed(region, ident) => Pattern::Shadowed(*region, ident.clone()),
|
||||||
UnsupportedPattern(region) => Pattern::UnsupportedPattern(region),
|
UnsupportedPattern(region) => Pattern::UnsupportedPattern(*region),
|
||||||
|
|
||||||
NumLiteral(var, num) => match to_int_or_float(env.subs, var) {
|
NumLiteral(var, num) => match to_int_or_float(env.subs, *var) {
|
||||||
IntOrFloat::IntType => Pattern::IntLiteral(num),
|
IntOrFloat::IntType => Pattern::IntLiteral(*num),
|
||||||
IntOrFloat::FloatType => Pattern::FloatLiteral(num as f64),
|
IntOrFloat::FloatType => Pattern::FloatLiteral(*num as f64),
|
||||||
},
|
},
|
||||||
|
|
||||||
AppliedTag {
|
AppliedTag {
|
||||||
|
@ -1244,23 +1260,49 @@ fn from_can_pattern<'a>(
|
||||||
tag_name,
|
tag_name,
|
||||||
arguments,
|
arguments,
|
||||||
..
|
..
|
||||||
} => match Layout::from_var(env.arena, whole_var, env.subs, env.pointer_size) {
|
} => match Layout::from_var(env.arena, *whole_var, env.subs, env.pointer_size) {
|
||||||
Ok(Layout::Builtin(Builtin::Bool(_bottom, top))) => {
|
Ok(Layout::Builtin(Builtin::Bool(_bottom, top))) => {
|
||||||
Pattern::BitLiteral(tag_name == top)
|
Pattern::BitLiteral(tag_name == &top)
|
||||||
}
|
}
|
||||||
Ok(Layout::Builtin(Builtin::Byte(conversion))) => match conversion.get(&tag_name) {
|
Ok(Layout::Builtin(Builtin::Byte(conversion))) => match conversion.get(&tag_name) {
|
||||||
Some(index) => Pattern::EnumLiteral{ tag_id : *index, enum_size: conversion.len() as u8 },
|
Some(index) => Pattern::EnumLiteral {
|
||||||
|
tag_id: *index,
|
||||||
|
enum_size: conversion.len() as u8,
|
||||||
|
},
|
||||||
None => unreachable!("Tag must be in its own type"),
|
None => unreachable!("Tag must be in its own type"),
|
||||||
},
|
},
|
||||||
Ok(layout) => {
|
Ok(layout) => {
|
||||||
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) in arguments {
|
for (_, loc_pat) in arguments {
|
||||||
mono_args.push(from_can_pattern(env, loc_pat.value));
|
mono_args.push(from_can_pattern(env, &loc_pat.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut fields = std::vec::Vec::new();
|
||||||
|
let union = match roc_types::pretty_print::chase_ext_tag_union(
|
||||||
|
env.subs,
|
||||||
|
*whole_var,
|
||||||
|
&mut fields,
|
||||||
|
) {
|
||||||
|
Ok(()) | Err((_, Content::FlexVar(_))) => {
|
||||||
|
let mut ctors = std::vec::Vec::with_capacity(fields.len());
|
||||||
|
for (tag_name, args) in fields {
|
||||||
|
ctors.push(crate::pattern::Ctor {
|
||||||
|
name: tag_name.clone(),
|
||||||
|
arity: args.len(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::pattern::Union {
|
||||||
|
alternatives: ctors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(content) => panic!("invalid content in ext_var: {:?}", content),
|
||||||
|
};
|
||||||
|
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
tag_name,
|
tag_name: tag_name.clone(),
|
||||||
arguments: mono_args,
|
arguments: mono_args,
|
||||||
|
union,
|
||||||
layout,
|
layout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1271,11 +1313,11 @@ fn from_can_pattern<'a>(
|
||||||
whole_var,
|
whole_var,
|
||||||
destructs,
|
destructs,
|
||||||
..
|
..
|
||||||
} => match Layout::from_var(env.arena, whole_var, env.subs, env.pointer_size) {
|
} => match Layout::from_var(env.arena, *whole_var, env.subs, env.pointer_size) {
|
||||||
Ok(layout) => {
|
Ok(layout) => {
|
||||||
let mut mono_destructs = Vec::with_capacity_in(destructs.len(), env.arena);
|
let mut mono_destructs = Vec::with_capacity_in(destructs.len(), env.arena);
|
||||||
for loc_rec_des in destructs {
|
for loc_rec_des in destructs {
|
||||||
mono_destructs.push(from_can_record_destruct(env, loc_rec_des.value));
|
mono_destructs.push(from_can_record_destruct(env, &loc_rec_des.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::RecordDestructure(mono_destructs, layout)
|
Pattern::RecordDestructure(mono_destructs, layout)
|
||||||
|
@ -1287,14 +1329,14 @@ fn from_can_pattern<'a>(
|
||||||
|
|
||||||
fn from_can_record_destruct<'a>(
|
fn from_can_record_destruct<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
can_rd: roc_can::pattern::RecordDestruct,
|
can_rd: &roc_can::pattern::RecordDestruct,
|
||||||
) -> RecordDestruct<'a> {
|
) -> RecordDestruct<'a> {
|
||||||
RecordDestruct {
|
RecordDestruct {
|
||||||
label: can_rd.label,
|
label: can_rd.label.clone(),
|
||||||
symbol: can_rd.symbol,
|
symbol: can_rd.symbol,
|
||||||
guard: match can_rd.guard {
|
guard: match &can_rd.guard {
|
||||||
None => None,
|
None => None,
|
||||||
Some((_, loc_pattern)) => Some(from_can_pattern(env, loc_pattern.value)),
|
Some((_, loc_pattern)) => Some(from_can_pattern(env, &loc_pattern.value)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,13 @@ use self::Pattern::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Union {
|
pub struct Union {
|
||||||
alternatives: Vec<Ctor>,
|
pub alternatives: Vec<Ctor>,
|
||||||
num_alts: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Ctor {
|
pub struct Ctor {
|
||||||
name: TagName,
|
pub name: TagName,
|
||||||
arity: usize,
|
pub arity: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -25,27 +24,31 @@ pub enum Pattern {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
Num(i64),
|
|
||||||
Int(i64),
|
Int(i64),
|
||||||
|
Bit(bool),
|
||||||
|
Byte(u8),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Str(Box<str>),
|
Str(Box<str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simplify(pattern: &roc_can::pattern::Pattern) -> Pattern {
|
fn simplify<'a>(pattern: &crate::expr::Pattern<'a>) -> Pattern {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
|
|
||||||
simplify_help(pattern, &mut errors)
|
simplify_help(pattern, &mut errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simplify_help(pattern: &roc_can::pattern::Pattern, errors: &mut Vec<Error>) -> Pattern {
|
fn simplify_help<'a>(pattern: &crate::expr::Pattern<'a>, errors: &mut Vec<Error>) -> Pattern {
|
||||||
use roc_can::pattern::Pattern::*;
|
use crate::expr::Pattern::*;
|
||||||
|
|
||||||
match pattern {
|
match pattern {
|
||||||
IntLiteral(v) => Literal(Literal::Int(*v)),
|
IntLiteral(v) => Literal(Literal::Int(*v)),
|
||||||
NumLiteral(_, v) => Literal(Literal::Int(*v)),
|
|
||||||
FloatLiteral(v) => Literal(Literal::Float(*v)),
|
FloatLiteral(v) => Literal(Literal::Float(*v)),
|
||||||
StrLiteral(v) => Literal(Literal::Str(v.clone())),
|
StrLiteral(v) => Literal(Literal::Str(v.clone())),
|
||||||
|
|
||||||
|
// TODO make sure these are exhaustive
|
||||||
|
BitLiteral(b) => Literal(Literal::Bit(*b)),
|
||||||
|
EnumLiteral { tag_id, .. } => Literal(Literal::Byte(*tag_id)),
|
||||||
|
|
||||||
Underscore => Anything,
|
Underscore => Anything,
|
||||||
Identifier(_) => Anything,
|
Identifier(_) => Anything,
|
||||||
RecordDestructure { .. } => {
|
RecordDestructure { .. } => {
|
||||||
|
@ -67,17 +70,14 @@ fn simplify_help(pattern: &roc_can::pattern::Pattern, errors: &mut Vec<Error>) -
|
||||||
AppliedTag {
|
AppliedTag {
|
||||||
tag_name,
|
tag_name,
|
||||||
arguments,
|
arguments,
|
||||||
|
union,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let union = Union {
|
|
||||||
alternatives: Vec::new(),
|
|
||||||
num_alts: 0,
|
|
||||||
};
|
|
||||||
let simplified_args: std::vec::Vec<_> = arguments
|
let simplified_args: std::vec::Vec<_> = arguments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| simplify_help(&v.1.value, errors))
|
.map(|v| simplify_help(&v, errors))
|
||||||
.collect();
|
.collect();
|
||||||
Ctor(union, tag_name.clone(), simplified_args)
|
Ctor(union.clone(), tag_name.clone(), simplified_args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,9 @@ pub enum Context {
|
||||||
|
|
||||||
/// Check
|
/// Check
|
||||||
|
|
||||||
pub fn check(
|
pub fn check<'a>(
|
||||||
region: Region,
|
region: Region,
|
||||||
patterns: &[Located<roc_can::pattern::Pattern>],
|
patterns: &[Located<crate::expr::Pattern<'a>>],
|
||||||
) -> Result<(), Vec<Error>> {
|
) -> Result<(), Vec<Error>> {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
check_patterns(region, Context::BadArg, patterns, &mut errors);
|
check_patterns(region, Context::BadArg, patterns, &mut errors);
|
||||||
|
@ -113,43 +113,10 @@ pub fn check(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn check(module: roc_can::module::ModuleOutput) -> Result<(), Vec<Error>> {
|
pub fn check_patterns<'a>(
|
||||||
// let mut errors = Vec::new();
|
|
||||||
// check_declarations(&module.declarations, &mut errors);
|
|
||||||
//
|
|
||||||
// if errors.is_empty() {
|
|
||||||
// Ok(())
|
|
||||||
// } else {
|
|
||||||
// Err(errors)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// CHECK DECLS
|
|
||||||
//
|
|
||||||
// fn check_declarations(decls: &[roc_can::def::Declaration], errors: &mut Vec<Error>) {
|
|
||||||
// use roc_can::def::Declaration;
|
|
||||||
//
|
|
||||||
// for decl in decls {
|
|
||||||
// Declaration::Declare(def) => check_def(def, errors),
|
|
||||||
// Declaration::DeclareRef(defs) => {
|
|
||||||
// for def in defs {
|
|
||||||
// check_def(def, errors);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Declaration::InvalidCycle(_) => {}
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn check_def(def: &roc_can::def::Def, errors: &mut Vec<Error>) {
|
|
||||||
// check_patttern
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn check_patterns(
|
|
||||||
region: Region,
|
region: Region,
|
||||||
context: Context,
|
context: Context,
|
||||||
patterns: &[Located<roc_can::pattern::Pattern>],
|
patterns: &[Located<crate::expr::Pattern<'a>>],
|
||||||
errors: &mut Vec<Error>,
|
errors: &mut Vec<Error>,
|
||||||
) {
|
) {
|
||||||
match to_nonredundant_rows(region, patterns) {
|
match to_nonredundant_rows(region, patterns) {
|
||||||
|
@ -197,7 +164,7 @@ fn is_exhaustive(matrix: &PatternMatrix, n: usize) -> PatternMatrix {
|
||||||
let alts = ctors.iter().next().unwrap().1;
|
let alts = ctors.iter().next().unwrap().1;
|
||||||
|
|
||||||
let alt_list = &alts.alternatives;
|
let alt_list = &alts.alternatives;
|
||||||
let num_alts = alts.num_alts;
|
let num_alts = alt_list.len();
|
||||||
|
|
||||||
if num_seen < num_alts {
|
if num_seen < num_alts {
|
||||||
let new_matrix = matrix
|
let new_matrix = matrix
|
||||||
|
@ -277,9 +244,9 @@ fn recover_ctor(
|
||||||
/// REDUNDANT PATTERNS
|
/// REDUNDANT PATTERNS
|
||||||
|
|
||||||
/// INVARIANT: Produces a list of rows where (forall row. length row == 1)
|
/// INVARIANT: Produces a list of rows where (forall row. length row == 1)
|
||||||
fn to_nonredundant_rows(
|
fn to_nonredundant_rows<'a>(
|
||||||
overall_region: Region,
|
overall_region: Region,
|
||||||
patterns: &[Located<roc_can::pattern::Pattern>],
|
patterns: &[Located<crate::expr::Pattern<'a>>],
|
||||||
) -> Result<Vec<Vec<Pattern>>, Error> {
|
) -> Result<Vec<Vec<Pattern>>, Error> {
|
||||||
let mut checked_rows = Vec::with_capacity(patterns.len());
|
let mut checked_rows = Vec::with_capacity(patterns.len());
|
||||||
|
|
||||||
|
@ -449,12 +416,8 @@ fn is_complete(matrix: &PatternMatrix) -> Complete {
|
||||||
|
|
||||||
match it.next() {
|
match it.next() {
|
||||||
None => Complete::No,
|
None => Complete::No,
|
||||||
Some(Union {
|
Some(Union { alternatives, .. }) => {
|
||||||
alternatives,
|
if ctors.len() == alternatives.len() {
|
||||||
num_alts,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if ctors.len() == *num_alts {
|
|
||||||
Complete::Yes(alternatives.to_vec())
|
Complete::Yes(alternatives.to_vec())
|
||||||
} else {
|
} else {
|
||||||
Complete::No
|
Complete::No
|
||||||
|
@ -473,7 +436,7 @@ fn collect_ctors(matrix: &RefPatternMatrix) -> MutMap<TagName, Union> {
|
||||||
let mut ctors = MutMap::default();
|
let mut ctors = MutMap::default();
|
||||||
|
|
||||||
for row in matrix {
|
for row in matrix {
|
||||||
if let Some(Ctor(union, name, _)) = row.get(0) {
|
if let Some(Ctor(union, name, _)) = row.get(row.len() - 1) {
|
||||||
ctors.insert(name.clone(), union.clone());
|
ctors.insert(name.clone(), union.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue