don't use a tuple to ensure non-emptiness

This commit is contained in:
Stoeffel 2020-01-08 11:05:53 +01:00
parent 64a562ebc6
commit a98113c88d
6 changed files with 46 additions and 67 deletions

View file

@ -462,17 +462,17 @@ pub fn canonicalize_expr(
let mut can_branches = Vec::with_capacity(branches.len()); let mut can_branches = Vec::with_capacity(branches.len());
for ((loc_pattern, _), loc_expr) in branches { for (loc_pattern, loc_expr) in branches {
let mut shadowable_idents = scope.idents.clone(); let mut shadowable_idents = scope.idents.clone();
remove_idents(&loc_pattern.value, &mut shadowable_idents); remove_idents(&loc_pattern.first().unwrap().value, &mut shadowable_idents);
let (can_pattern, loc_can_expr, branch_references) = canonicalize_when_branch( let (can_pattern, loc_can_expr, branch_references) = canonicalize_when_branch(
env, env,
var_store, var_store,
scope, scope,
region, region,
loc_pattern, loc_pattern.first().unwrap(),
loc_expr, loc_expr,
&mut output, &mut output,
); );

View file

@ -166,17 +166,14 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
let loc_desugared_cond = &*arena.alloc(desugar_expr(arena, &loc_cond_expr)); let loc_desugared_cond = &*arena.alloc(desugar_expr(arena, &loc_cond_expr));
let mut desugared_branches = Vec::with_capacity_in(branches.len(), arena); let mut desugared_branches = Vec::with_capacity_in(branches.len(), arena);
for ((loc_pattern, _), loc_branch_expr) in branches.into_iter() { for (loc_pattern, loc_branch_expr) in branches.into_iter() {
let desugared = desugar_expr(arena, &loc_branch_expr); let desugared = desugar_expr(arena, &loc_branch_expr);
desugared_branches.push(&*arena.alloc(( desugared_branches.push(&*arena.alloc((
( bumpalo::vec![in arena; Located {
Located { region: loc_pattern.first().unwrap().region,
region: loc_pattern.region, value: Pattern::Nested(&loc_pattern.first().unwrap().value),
value: Pattern::Nested(&loc_pattern.value), }],
},
Vec::with_capacity_in(0, arena),
),
Located { Located {
region: desugared.region, region: desugared.region,
value: Nested(&desugared.value), value: Nested(&desugared.value),
@ -254,13 +251,10 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
let pattern_region = condition.region; let pattern_region = condition.region;
branches.push(&*arena.alloc(( branches.push(&*arena.alloc((
( bumpalo::vec![in arena; Located {
Located {
value: Pattern::GlobalTag("False"), value: Pattern::GlobalTag("False"),
region: pattern_region, region: pattern_region,
}, }],
Vec::new_in(arena),
),
Located { Located {
value: Nested(&else_branch.value), value: Nested(&else_branch.value),
region: else_branch.region, region: else_branch.region,
@ -268,13 +262,10 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
))); )));
branches.push(&*arena.alloc(( branches.push(&*arena.alloc((
( bumpalo::vec![in arena; Located {
Located {
value: Pattern::Underscore, value: Pattern::Underscore,
region: pattern_region, region: pattern_region,
}, }],
Vec::new_in(arena),
),
Located { Located {
value: Nested(&then_branch.value), value: Nested(&then_branch.value),
region: then_branch.region, region: then_branch.region,

View file

@ -141,16 +141,21 @@ pub fn fmt_expr<'a>(
buf.push_str(" is\n"); buf.push_str(" is\n");
let mut it = branches.iter().peekable(); let mut it = branches.iter().peekable();
while let Some(((pattern, _), expr)) = it.next() { while let Some((patterns, expr)) = it.next() {
add_spaces(buf, indent + INDENT); add_spaces(buf, indent + INDENT);
match pattern.value { match patterns.first().unwrap().value {
Pattern::SpaceBefore(nested, spaces) => { Pattern::SpaceBefore(nested, spaces) => {
fmt_comments_only(buf, spaces.iter(), indent + INDENT); fmt_comments_only(buf, spaces.iter(), indent + INDENT);
fmt_pattern(buf, nested, indent + INDENT, false); fmt_pattern(buf, nested, indent + INDENT, false);
} }
_ => { _ => {
fmt_pattern(buf, &pattern.value, indent + INDENT, false); fmt_pattern(
buf,
&patterns.first().unwrap().value,
indent + INDENT,
false,
);
} }
} }

View file

@ -158,7 +158,7 @@ pub enum Expr<'a> {
If(&'a (Loc<Expr<'a>>, Loc<Expr<'a>>, Loc<Expr<'a>>)), If(&'a (Loc<Expr<'a>>, Loc<Expr<'a>>, Loc<Expr<'a>>)),
When( When(
&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>,
Vec<'a, &'a ((Loc<Pattern<'a>>, Vec<'a, Loc<Pattern<'a>>>), Loc<Expr<'a>>)>, Vec<'a, &'a (Vec<'a, Loc<Pattern<'a>>>, Loc<Expr<'a>>)>,
), ),
// Blank Space (e.g. comments, spaces, newlines) before or after an expression. // Blank Space (e.g. comments, spaces, newlines) before or after an expression.

View file

@ -863,46 +863,29 @@ pub fn when_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
pub fn case_branches<'a>( pub fn case_branches<'a>(
min_indent: u16, min_indent: u16,
) -> impl Parser< ) -> impl Parser<'a, Vec<'a, &'a (Vec<'a, Located<Pattern<'a>>>, Located<Expr<'a>>)>> {
'a,
Vec<
'a,
&'a (
(Located<Pattern<'a>>, Vec<'a, Located<Pattern<'a>>>),
Located<Expr<'a>>,
),
>,
> {
move |arena, state| { move |arena, state| {
let mut branches: Vec< let mut branches: Vec<'a, &'a (Vec<'a, Located<Pattern<'a>>>, Located<Expr<'a>>)> =
'a, Vec::with_capacity_in(2, arena);
&'a (
(Located<Pattern<'a>>, Vec<'a, Located<Pattern<'a>>>),
Located<Expr<'a>>,
),
> = Vec::with_capacity_in(2, arena);
// 1. Parse the first branch and get its indentation level. (It must be >= min_indent.) // 1. Parse the first branch and get its indentation level. (It must be >= min_indent.)
// 2. Parse the other branches. Their indentation levels must be == the first branch's. // 2. Parse the other branches. Their indentation levels must be == the first branch's.
let (mut loc_first_pattern, state) = let (mut loc_first_pattern, state) = sep_by1(
space1_before(loc!(pattern(min_indent)), min_indent).parse(arena, state)?; map!(and!(space1(min_indent), char('|')), |_| ()),
space1_before(loc!(pattern(min_indent)), min_indent),
)
.parse(arena, state)?;
let original_indent = state.indent_col; let original_indent = state.indent_col;
let indented_more = original_indent + 1; let indented_more = original_indent + 1;
let (loc_first_pattern_alt, state) = zero_or_more!(skip_first!(
and!(space0(min_indent), char('|')),
space0_before(loc!(pattern(min_indent)), min_indent)
))
.parse(arena, state)?;
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?; let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
// Record the spaces before the first "->", if any. // Record the spaces before the first "->", if any.
if !spaces_before_arrow.is_empty() { if !spaces_before_arrow.is_empty() {
let region = loc_first_pattern.region; let last = loc_first_pattern.pop().unwrap();
let value = let region = last.region;
Pattern::SpaceAfter(arena.alloc(loc_first_pattern.value), spaces_before_arrow); let value = Pattern::SpaceAfter(arena.alloc(last.value), spaces_before_arrow);
loc_first_pattern.push(Located { region, value });
loc_first_pattern = Located { region, value };
}; };
// Parse the first "->" and the expression after it. // Parse the first "->" and the expression after it.
@ -917,14 +900,14 @@ pub fn case_branches<'a>(
.parse(arena, state)?; .parse(arena, state)?;
// Record this as the first branch, then optionally parse additional branches. // Record this as the first branch, then optionally parse additional branches.
branches.push(arena.alloc(((loc_first_pattern, loc_first_pattern_alt), loc_first_expr))); branches.push(arena.alloc((loc_first_pattern, loc_first_expr)));
let branch_parser = and!( let branch_parser = and!(
then( then(
space1_around(loc!(pattern(min_indent)), min_indent), space1_around(loc!(pattern(min_indent)), min_indent),
move |_arena, state, loc_pattern| { move |_arena, state, loc_pattern| {
if state.indent_col == original_indent { if state.indent_col == original_indent {
Ok(((loc_pattern, Vec::with_capacity_in(0, arena)), state)) Ok((bumpalo::vec![in arena; loc_pattern ], state))
} else { } else {
panic!( panic!(
"TODO additional branch didn't have same indentation as first branch" "TODO additional branch didn't have same indentation as first branch"

View file

@ -1364,14 +1364,14 @@ mod test_parse {
let loc_pattern1 = Located::new(1, 1, 1, 7, pattern1); let loc_pattern1 = Located::new(1, 1, 1, 7, pattern1);
let expr1 = Int("1"); let expr1 = Int("1");
let loc_expr1 = Located::new(1, 1, 11, 12, expr1); let loc_expr1 = Located::new(1, 1, 11, 12, expr1);
let branch1 = &*arena.alloc(((loc_pattern1, bumpalo::vec![in &arena;]), loc_expr1)); let branch1 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern1], loc_expr1));
let newlines = bumpalo::vec![in &arena; Newline]; let newlines = bumpalo::vec![in &arena; Newline];
let pattern2 = let pattern2 =
Pattern::SpaceBefore(arena.alloc(StrLiteral("mise")), newlines.into_bump_slice()); Pattern::SpaceBefore(arena.alloc(StrLiteral("mise")), newlines.into_bump_slice());
let loc_pattern2 = Located::new(2, 2, 1, 7, pattern2); let loc_pattern2 = Located::new(2, 2, 1, 7, pattern2);
let expr2 = Int("2"); let expr2 = Int("2");
let loc_expr2 = Located::new(2, 2, 11, 12, expr2); let loc_expr2 = Located::new(2, 2, 11, 12, expr2);
let branch2 = &*arena.alloc(((loc_pattern2, bumpalo::vec![in &arena;]), loc_expr2)); let branch2 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern2 ], loc_expr2));
let branches = bumpalo::vec![in &arena; branch1, branch2]; let branches = bumpalo::vec![in &arena; branch1, branch2];
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x")); let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
let expected = Expr::When(arena.alloc(loc_cond), branches); let expected = Expr::When(arena.alloc(loc_cond), branches);
@ -1398,14 +1398,14 @@ mod test_parse {
let loc_pattern1 = Located::new(1, 1, 1, 2, pattern1); let loc_pattern1 = Located::new(1, 1, 1, 2, pattern1);
let expr1 = Int("2"); let expr1 = Int("2");
let loc_expr1 = Located::new(1, 1, 6, 7, expr1); let loc_expr1 = Located::new(1, 1, 6, 7, expr1);
let branch1 = &*arena.alloc(((loc_pattern1, bumpalo::vec![in &arena;]), loc_expr1)); let branch1 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern1], loc_expr1));
let newlines = bumpalo::vec![in &arena; Newline]; let newlines = bumpalo::vec![in &arena; Newline];
let pattern2 = let pattern2 =
Pattern::SpaceBefore(arena.alloc(IntLiteral("3")), newlines.into_bump_slice()); Pattern::SpaceBefore(arena.alloc(IntLiteral("3")), newlines.into_bump_slice());
let loc_pattern2 = Located::new(2, 2, 1, 2, pattern2); let loc_pattern2 = Located::new(2, 2, 1, 2, pattern2);
let expr2 = Int("4"); let expr2 = Int("4");
let loc_expr2 = Located::new(2, 2, 6, 7, expr2); let loc_expr2 = Located::new(2, 2, 6, 7, expr2);
let branch2 = &*arena.alloc(((loc_pattern2, bumpalo::vec![in &arena;]), loc_expr2)); let branch2 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern2], loc_expr2));
let branches = bumpalo::vec![in &arena; branch1, branch2]; let branches = bumpalo::vec![in &arena; branch1, branch2];
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x")); let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
let expected = Expr::When(arena.alloc(loc_cond), branches); let expected = Expr::When(arena.alloc(loc_cond), branches);
@ -1435,7 +1435,7 @@ mod test_parse {
let loc_pattern1 = Located::new(1, 1, 1, 6, pattern1); let loc_pattern1 = Located::new(1, 1, 1, 6, pattern1);
let expr1 = Int("2"); let expr1 = Int("2");
let loc_expr1 = Located::new(1, 1, 10, 11, expr1); let loc_expr1 = Located::new(1, 1, 10, 11, expr1);
let branch1 = &*arena.alloc(((loc_pattern1, bumpalo::vec![in &arena;]), loc_expr1)); let branch1 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern1 ], loc_expr1));
let newlines = bumpalo::vec![in &arena; Newline]; let newlines = bumpalo::vec![in &arena; Newline];
let identifiers2 = bumpalo::vec![in &arena; Located::new(2, 2, 3, 4, Identifier("z")), Located::new(2, 2, 6, 7, Identifier("w")) ]; let identifiers2 = bumpalo::vec![in &arena; Located::new(2, 2, 3, 4, Identifier("z")), Located::new(2, 2, 6, 7, Identifier("w")) ];
let pattern2 = Pattern::SpaceBefore( let pattern2 = Pattern::SpaceBefore(
@ -1445,7 +1445,7 @@ mod test_parse {
let loc_pattern2 = Located::new(2, 2, 1, 9, pattern2); let loc_pattern2 = Located::new(2, 2, 1, 9, pattern2);
let expr2 = Int("4"); let expr2 = Int("4");
let loc_expr2 = Located::new(2, 2, 13, 14, expr2); let loc_expr2 = Located::new(2, 2, 13, 14, expr2);
let branch2 = &*arena.alloc(((loc_pattern2, bumpalo::vec![in &arena;]), loc_expr2)); let branch2 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern2 ], loc_expr2));
let branches = bumpalo::vec![in &arena; branch1, branch2]; let branches = bumpalo::vec![in &arena; branch1, branch2];
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x")); let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
let expected = Expr::When(arena.alloc(loc_cond), branches); let expected = Expr::When(arena.alloc(loc_cond), branches);
@ -1475,7 +1475,7 @@ mod test_parse {
let expr1 = Int("1"); let expr1 = Int("1");
let loc_expr1 = Located::new(1, 1, 20, 21, expr1); let loc_expr1 = Located::new(1, 1, 20, 21, expr1);
let branch1 = &*arena.alloc(( let branch1 = &*arena.alloc((
(loc_pattern1, bumpalo::vec![in &arena;loc_pattern1_alt]), bumpalo::vec![in &arena;loc_pattern1, loc_pattern1_alt],
loc_expr1, loc_expr1,
)); ));
let branches = bumpalo::vec![in &arena; branch1]; let branches = bumpalo::vec![in &arena; branch1];