mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
don't use a tuple to ensure non-emptiness
This commit is contained in:
parent
64a562ebc6
commit
a98113c88d
6 changed files with 46 additions and 67 deletions
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue