mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
Merge branch 'trunk' into list-comment-formatting
This commit is contained in:
commit
6763f2500f
8 changed files with 139 additions and 32 deletions
|
@ -486,14 +486,14 @@ pub fn canonicalize_expr(
|
|||
for (loc_pattern, loc_expr) in branches {
|
||||
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(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
region,
|
||||
loc_pattern,
|
||||
loc_pattern.first().unwrap(),
|
||||
loc_expr,
|
||||
&mut output,
|
||||
);
|
||||
|
|
|
@ -170,10 +170,10 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
|
|||
let desugared = desugar_expr(arena, &loc_branch_expr);
|
||||
|
||||
desugared_branches.push(&*arena.alloc((
|
||||
Located {
|
||||
region: loc_pattern.region,
|
||||
value: Pattern::Nested(&loc_pattern.value),
|
||||
},
|
||||
bumpalo::vec![in arena; Located {
|
||||
region: loc_pattern.first().unwrap().region,
|
||||
value: Pattern::Nested(&loc_pattern.first().unwrap().value),
|
||||
}],
|
||||
Located {
|
||||
region: desugared.region,
|
||||
value: Nested(&desugared.value),
|
||||
|
@ -251,10 +251,10 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
|
|||
let pattern_region = condition.region;
|
||||
|
||||
branches.push(&*arena.alloc((
|
||||
Located {
|
||||
bumpalo::vec![in arena; Located {
|
||||
value: Pattern::GlobalTag("False"),
|
||||
region: pattern_region,
|
||||
},
|
||||
}],
|
||||
Located {
|
||||
value: Nested(&else_branch.value),
|
||||
region: else_branch.region,
|
||||
|
@ -262,10 +262,10 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
|
|||
)));
|
||||
|
||||
branches.push(&*arena.alloc((
|
||||
Located {
|
||||
bumpalo::vec![in arena; Located {
|
||||
value: Pattern::Underscore,
|
||||
region: pattern_region,
|
||||
},
|
||||
}],
|
||||
Located {
|
||||
value: Nested(&then_branch.value),
|
||||
region: then_branch.region,
|
||||
|
|
|
@ -144,16 +144,29 @@ pub fn fmt_expr<'a>(
|
|||
buf.push_str(" is\n");
|
||||
|
||||
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);
|
||||
let (first, rest) = patterns.split_first().unwrap();
|
||||
|
||||
match pattern.value {
|
||||
match first.value {
|
||||
Pattern::SpaceBefore(nested, spaces) => {
|
||||
fmt_comments_only(buf, spaces.iter(), indent + INDENT);
|
||||
fmt_pattern(buf, nested, indent + INDENT, false);
|
||||
}
|
||||
_ => {
|
||||
fmt_pattern(buf, &pattern.value, indent + INDENT, false);
|
||||
fmt_pattern(buf, &first.value, indent + INDENT, false);
|
||||
}
|
||||
};
|
||||
for pattern in rest {
|
||||
buf.push_str(" | ");
|
||||
match pattern.value {
|
||||
Pattern::SpaceBefore(nested, spaces) => {
|
||||
fmt_comments_only(buf, spaces.iter(), indent + INDENT);
|
||||
fmt_pattern(buf, nested, indent + INDENT, false);
|
||||
}
|
||||
_ => {
|
||||
fmt_pattern(buf, &pattern.value, indent + INDENT, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ pub enum Expr<'a> {
|
|||
If(&'a (Loc<Expr<'a>>, Loc<Expr<'a>>, Loc<Expr<'a>>)),
|
||||
When(
|
||||
&'a Loc<Expr<'a>>,
|
||||
Vec<'a, &'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.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
pub static IF: &str = "if";
|
||||
pub static THEN: &str = "then";
|
||||
pub static ELSE: &str = "else";
|
||||
pub static CASE: &str = "case";
|
||||
pub static WHEN: &str = "when";
|
||||
pub static AS: &str = "as";
|
||||
pub static IS: &str = "is";
|
||||
|
|
|
@ -687,7 +687,6 @@ fn reserved_keyword<'a>() -> impl Parser<'a, ()> {
|
|||
string(keyword::IF),
|
||||
string(keyword::THEN),
|
||||
string(keyword::ELSE),
|
||||
string(keyword::CASE),
|
||||
string(keyword::WHEN),
|
||||
string(keyword::IS),
|
||||
string(keyword::AS)
|
||||
|
@ -887,27 +886,29 @@ pub fn when_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
|
||||
pub fn case_branches<'a>(
|
||||
min_indent: u16,
|
||||
) -> impl Parser<'a, Vec<'a, &'a (Located<Pattern<'a>>, Located<Expr<'a>>)>> {
|
||||
) -> impl Parser<'a, Vec<'a, &'a (Vec<'a, Located<Pattern<'a>>>, Located<Expr<'a>>)>> {
|
||||
move |arena, state| {
|
||||
let mut branches: Vec<'a, &'a (Located<Pattern<'a>>, Located<Expr<'a>>)> =
|
||||
let mut branches: Vec<'a, &'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.)
|
||||
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
||||
|
||||
let (mut loc_first_pattern, state) =
|
||||
space1_before(loc_pattern(min_indent), min_indent).parse(arena, state)?;
|
||||
let (mut loc_first_pattern, state) = sep_by1(
|
||||
map!(and!(space0(min_indent), char('|')), |_| ()),
|
||||
space0_before(loc_pattern(min_indent), min_indent),
|
||||
)
|
||||
.parse(arena, state)?;
|
||||
let original_indent = state.indent_col;
|
||||
let indented_more = original_indent + 1;
|
||||
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
|
||||
|
||||
// Record the spaces before the first "->", if any.
|
||||
if !spaces_before_arrow.is_empty() {
|
||||
let region = loc_first_pattern.region;
|
||||
let value =
|
||||
Pattern::SpaceAfter(arena.alloc(loc_first_pattern.value), spaces_before_arrow);
|
||||
|
||||
loc_first_pattern = Located { region, value };
|
||||
let last = loc_first_pattern.pop().unwrap();
|
||||
let region = last.region;
|
||||
let value = Pattern::SpaceAfter(arena.alloc(last.value), spaces_before_arrow);
|
||||
loc_first_pattern.push(Located { region, value });
|
||||
};
|
||||
|
||||
// Parse the first "->" and the expression after it.
|
||||
|
@ -926,7 +927,10 @@ pub fn case_branches<'a>(
|
|||
|
||||
let branch_parser = and!(
|
||||
then(
|
||||
space1_around(loc_pattern(min_indent), min_indent),
|
||||
sep_by1(
|
||||
char('|'),
|
||||
space0_around(loc_pattern(min_indent), min_indent),
|
||||
),
|
||||
move |_arena, state, loc_pattern| {
|
||||
if state.indent_col == original_indent {
|
||||
Ok((loc_pattern, state))
|
||||
|
|
|
@ -1289,6 +1289,50 @@ mod test_format {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn when_with_alternatives() {
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
when b is
|
||||
1 | 2 ->
|
||||
when c is
|
||||
6 | 7 ->
|
||||
8
|
||||
|
||||
3 | 4 ->
|
||||
5
|
||||
"#
|
||||
));
|
||||
expr_formats_same(indoc!(
|
||||
r#"
|
||||
when b is
|
||||
# a comment here
|
||||
1 | 2 ->
|
||||
# a comment there
|
||||
1
|
||||
"#
|
||||
));
|
||||
expr_formats_to(
|
||||
indoc!(
|
||||
r#"
|
||||
when b is
|
||||
1 | 2 |3
|
||||
->
|
||||
|
||||
1
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
when b is
|
||||
1 | 2 | 3
|
||||
->
|
||||
1
|
||||
"#
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn when_with_moving_comments() {
|
||||
expr_formats_to(
|
||||
|
|
|
@ -1589,14 +1589,14 @@ mod test_parse {
|
|||
let loc_pattern1 = Located::new(1, 1, 1, 7, pattern1);
|
||||
let expr1 = Int("1");
|
||||
let loc_expr1 = Located::new(1, 1, 11, 12, expr1);
|
||||
let branch1 = &*arena.alloc((loc_pattern1, loc_expr1));
|
||||
let branch1 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern1], loc_expr1));
|
||||
let newlines = bumpalo::vec![in &arena; Newline];
|
||||
let pattern2 =
|
||||
Pattern::SpaceBefore(arena.alloc(StrLiteral("mise")), newlines.into_bump_slice());
|
||||
let loc_pattern2 = Located::new(2, 2, 1, 7, pattern2);
|
||||
let expr2 = Int("2");
|
||||
let loc_expr2 = Located::new(2, 2, 11, 12, expr2);
|
||||
let branch2 = &*arena.alloc((loc_pattern2, loc_expr2));
|
||||
let branch2 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern2 ], loc_expr2));
|
||||
let branches = bumpalo::vec![in &arena; branch1, branch2];
|
||||
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
|
||||
let expected = Expr::When(arena.alloc(loc_cond), branches);
|
||||
|
@ -1623,14 +1623,14 @@ mod test_parse {
|
|||
let loc_pattern1 = Located::new(1, 1, 1, 2, pattern1);
|
||||
let expr1 = Int("2");
|
||||
let loc_expr1 = Located::new(1, 1, 6, 7, expr1);
|
||||
let branch1 = &*arena.alloc((loc_pattern1, loc_expr1));
|
||||
let branch1 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern1], loc_expr1));
|
||||
let newlines = bumpalo::vec![in &arena; Newline];
|
||||
let pattern2 =
|
||||
Pattern::SpaceBefore(arena.alloc(IntLiteral("3")), newlines.into_bump_slice());
|
||||
let loc_pattern2 = Located::new(2, 2, 1, 2, pattern2);
|
||||
let expr2 = Int("4");
|
||||
let loc_expr2 = Located::new(2, 2, 6, 7, expr2);
|
||||
let branch2 = &*arena.alloc((loc_pattern2, loc_expr2));
|
||||
let branch2 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern2], loc_expr2));
|
||||
let branches = bumpalo::vec![in &arena; branch1, branch2];
|
||||
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
|
||||
let expected = Expr::When(arena.alloc(loc_cond), branches);
|
||||
|
@ -1660,7 +1660,7 @@ mod test_parse {
|
|||
let loc_pattern1 = Located::new(1, 1, 1, 6, pattern1);
|
||||
let expr1 = Int("2");
|
||||
let loc_expr1 = Located::new(1, 1, 10, 11, expr1);
|
||||
let branch1 = &*arena.alloc((loc_pattern1, loc_expr1));
|
||||
let branch1 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern1 ], loc_expr1));
|
||||
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 pattern2 = Pattern::SpaceBefore(
|
||||
|
@ -1670,7 +1670,7 @@ mod test_parse {
|
|||
let loc_pattern2 = Located::new(2, 2, 1, 9, pattern2);
|
||||
let expr2 = Int("4");
|
||||
let loc_expr2 = Located::new(2, 2, 13, 14, expr2);
|
||||
let branch2 = &*arena.alloc((loc_pattern2, loc_expr2));
|
||||
let branch2 = &*arena.alloc((bumpalo::vec![in &arena;loc_pattern2 ], loc_expr2));
|
||||
let branches = bumpalo::vec![in &arena; branch1, branch2];
|
||||
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
|
||||
let expected = Expr::When(arena.alloc(loc_cond), branches);
|
||||
|
@ -1688,6 +1688,53 @@ mod test_parse {
|
|||
assert_eq!(Ok(expected), actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn when_with_alternative_patterns() {
|
||||
let arena = Bump::new();
|
||||
let newlines = bumpalo::vec![in &arena; Newline];
|
||||
let pattern1 =
|
||||
Pattern::SpaceBefore(arena.alloc(StrLiteral("blah")), newlines.into_bump_slice());
|
||||
let pattern1_alt = StrLiteral("blop");
|
||||
let loc_pattern1 = Located::new(1, 1, 1, 7, pattern1);
|
||||
let loc_pattern1_alt = Located::new(1, 1, 10, 16, pattern1_alt);
|
||||
let expr1 = Int("1");
|
||||
let loc_expr1 = Located::new(1, 1, 20, 21, expr1);
|
||||
let branch1 = &*arena.alloc((
|
||||
bumpalo::vec![in &arena;loc_pattern1, loc_pattern1_alt],
|
||||
loc_expr1,
|
||||
));
|
||||
let newlines = bumpalo::vec![in &arena; Newline];
|
||||
let pattern2 =
|
||||
Pattern::SpaceBefore(arena.alloc(StrLiteral("foo")), newlines.into_bump_slice());
|
||||
let newlines = bumpalo::vec![in &arena; Newline];
|
||||
let pattern2_alt =
|
||||
Pattern::SpaceBefore(arena.alloc(StrLiteral("bar")), newlines.into_bump_slice());
|
||||
let loc_pattern2 = Located::new(2, 2, 1, 6, pattern2);
|
||||
let loc_pattern2_alt = Located::new(3, 3, 1, 6, pattern2_alt);
|
||||
let expr2 = Int("2");
|
||||
let loc_expr2 = Located::new(3, 3, 10, 11, expr2);
|
||||
let branch2 = &*arena.alloc((
|
||||
bumpalo::vec![in &arena;loc_pattern2, loc_pattern2_alt],
|
||||
loc_expr2,
|
||||
));
|
||||
let branches = bumpalo::vec![in &arena; branch1, branch2];
|
||||
let loc_cond = Located::new(0, 0, 5, 6, Var(&[], "x"));
|
||||
let expected = Expr::When(arena.alloc(loc_cond), branches);
|
||||
let actual = parse_with(
|
||||
&arena,
|
||||
indoc!(
|
||||
r#"
|
||||
when x is
|
||||
"blah" | "blop" -> 1
|
||||
"foo" |
|
||||
"bar" -> 2
|
||||
"#
|
||||
),
|
||||
);
|
||||
|
||||
assert_eq!(Ok(expected), actual);
|
||||
}
|
||||
|
||||
// MODULE
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue