Relax argument indentation requirements in closures

This commit is contained in:
Joshua Warner 2025-01-13 21:34:06 -08:00
parent ede015517a
commit 51f2cdccf7
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
7 changed files with 70 additions and 21 deletions

View file

@ -6692,17 +6692,20 @@ All branches in an `if` must have the same type!
)
"
),
@r"
UNFINISHED FUNCTION in tmp/unfinished_closure_pattern_in_parens/Test.roc
@r###"
MISSING ARROW in tmp/unfinished_closure_pattern_in_parens/Test.roc
I was partway through parsing a function, but I got stuck here:
I am partway through parsing a function argument list, but I got stuck
here:
4 x = \( a
5 )
^
6
7
^
I just saw a pattern, so I was expecting to see a -> next.
"
I was expecting a -> next.
"###
);
test_report!(

View file

@ -2340,16 +2340,18 @@ pub fn parse_top_level_defs<'a>(
fn closure_help<'a>(check_for_arrow: CheckForArrow) -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
one_of!(
closure_new_syntax_help(),
closure_new_syntax_help(check_for_arrow),
closure_old_syntax_help(check_for_arrow),
)
}
fn closure_new_syntax_help<'a>() -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
fn closure_new_syntax_help<'a>(
check_for_arrow: CheckForArrow,
) -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
map_with_arena(
indented_seq_skip_first(
skip_first(
error_on_pizza(byte_indent(b'|', EClosure::Bar), EClosure::Start),
and(
reset_min_indent(and(
sep_by1_e(
byte_indent(b',', EClosure::Comma),
space0_around_ee(
@ -2363,14 +2365,9 @@ fn closure_new_syntax_help<'a>() -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
// Parse the -> which separates params from body
byte(b'|', EClosure::Bar),
// Parse the body
block(
CheckForArrow(false),
true,
EClosure::IndentBody,
EClosure::Body,
),
block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body),
),
),
)),
),
|arena: &'a Bump, (params, body)| {
let params: Vec<'a, Loc<Pattern<'a>>> = params;
@ -2386,12 +2383,12 @@ fn closure_old_syntax_help<'a>(
// closure_help_help(options)
map_with_arena(
// After the first token, all other tokens must be indented past the start of the line
indented_seq_skip_first(
skip_first(
// All closures start with a '\' - e.g. (\x -> x + 1)
byte_indent(b'\\', EClosure::Start),
// Once we see the '\', we're committed to parsing this as a closure.
// It may turn out to be malformed, but it is definitely a closure.
and(
reset_min_indent(and(
// Parse the params
// Params are comma-separated
sep_by1_e(
@ -2409,7 +2406,7 @@ fn closure_old_syntax_help<'a>(
// Parse the body
block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body),
),
),
)),
),
|arena: &'a Bump, (params, body)| {
let params: Vec<'a, Loc<Pattern<'a>>> = params;

View file

@ -1 +1 @@
Expr(Closure(IndentArrow(@10), @4), @0)
Expr(Closure(Arrow(@11), @4), @0)

View file

@ -0,0 +1,41 @@
@0-14 SpaceAfter(
Apply(
@0-6 RecordUpdate {
update: @3-4 SpaceBefore(
Var {
module_name: "",
ident: "h",
},
[
LineComment(
"",
),
],
),
fields: [],
},
[
@6-14 Closure(
[
@10-11 SpaceBefore(
Identifier {
ident: "i",
},
[
LineComment(
"",
),
],
),
],
@13-14 Num(
"0",
),
),
],
Space,
),
[
Newline,
],
)

View file

@ -672,6 +672,7 @@ mod test_snapshots {
pass/record_literal_field_bang.expr,
pass/record_type_with_function.expr,
pass/record_update.expr,
pass/record_update_apply_closure_comments.expr,
pass/record_update_comment_before_ampersand.expr,
pass/record_updater_closure_weirdness.expr,
pass/record_updater_literal_apply.expr,