mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Change closure syntax to \a b => c
This commit is contained in:
parent
3651151f12
commit
36bea3a13f
2 changed files with 39 additions and 37 deletions
42
src/parse.rs
42
src/parse.rs
|
@ -195,7 +195,6 @@ parser! {
|
|||
let min_indent = *min_indent_ref;
|
||||
|
||||
choice((
|
||||
enclosed_closure(min_indent),
|
||||
closure(min_indent),
|
||||
parenthetical_expr(min_indent),
|
||||
string("{}").with(value(Expr::EmptyRecord)),
|
||||
|
@ -434,48 +433,21 @@ where I: Stream<Item = char, Position = IndentablePosition>,
|
|||
})
|
||||
}
|
||||
|
||||
/// Closure *without* parens around the args
|
||||
///
|
||||
/// e.g. (x, y -> stuff) as opposed to (x, y) -> stuff
|
||||
pub fn enclosed_closure<I>(min_indent: u32) -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char, Position = IndentablePosition>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
attempt(
|
||||
char('(')
|
||||
.with(
|
||||
sep_by1(
|
||||
located(pattern(min_indent)),
|
||||
char(',').skip(indented_whitespaces(min_indent))
|
||||
))
|
||||
.skip(indented_whitespaces1(min_indent))
|
||||
.skip(string("->"))
|
||||
.skip(indented_whitespaces1(min_indent))
|
||||
)
|
||||
.and(located(expr_body(min_indent)))
|
||||
.skip(char(')'))
|
||||
.map(|(patterns, closure_body)| {
|
||||
Expr::Closure(patterns, Box::new(closure_body))
|
||||
})
|
||||
}
|
||||
|
||||
/// Closure with parens around the args
|
||||
///
|
||||
/// e.g. (x, y) -> stuff as opposde to (x, y -> stuff)
|
||||
/// e.g. \x y => expr
|
||||
pub fn closure<I>(min_indent: u32) -> impl Parser<Input = I, Output = Expr>
|
||||
where I: Stream<Item = char, Position = IndentablePosition>,
|
||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||
{
|
||||
attempt(
|
||||
between(char('('), char(')'),
|
||||
char('\\')
|
||||
.skip(indented_whitespaces(min_indent))
|
||||
.with(
|
||||
sep_by1(
|
||||
located(pattern(min_indent)),
|
||||
char(',').skip(indented_whitespaces(min_indent))
|
||||
attempt(many1::<Vec<_>, _>(skipped_indented_whitespace_char(min_indent).skip(not_followed_by(string("=>")))))
|
||||
))
|
||||
.skip(indented_whitespaces(min_indent))
|
||||
.skip(string("=>"))
|
||||
.skip(indented_whitespaces1(min_indent))
|
||||
.skip(string("->"))
|
||||
.skip(indented_whitespaces1(min_indent))
|
||||
)
|
||||
.and(located(expr_body(min_indent)))
|
||||
.map(|(patterns, closure_body)| {
|
||||
Expr::Closure(patterns, Box::new(closure_body))
|
||||
|
|
|
@ -512,6 +512,37 @@ mod test_parse {
|
|||
// all of the above tests except with parens too!
|
||||
// Also, verify them all with variable paren counts; ((foo)) should work.
|
||||
|
||||
// CLOSURE
|
||||
|
||||
#[test]
|
||||
fn single_arg_closure() {
|
||||
assert_eq!(
|
||||
parse_without_loc("\\a => b"),
|
||||
Ok((
|
||||
Closure(
|
||||
vec![loc(Identifier("a".to_string()))],
|
||||
loc_box(Var("b".to_string()))
|
||||
),
|
||||
""
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_arg_closure() {
|
||||
assert_eq!(
|
||||
parse_without_loc("\\a b => c"),
|
||||
Ok((
|
||||
Closure(
|
||||
vec![loc(Identifier("a".to_string())), loc(Identifier("b".to_string()))],
|
||||
loc_box(Var("c".to_string()))
|
||||
),
|
||||
""
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// FUNC
|
||||
|
||||
fn expect_parsed_func<'a>(parse_str: &'a str, func_str: &'a str, args: Vec<Located<Expr>>) {
|
||||
|
@ -1235,12 +1266,11 @@ mod test_parse {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn regression_on_calling_function_named_c() {
|
||||
// This was broken because case-expressions were greedily consuming 'c' characters for "case"
|
||||
assert_eq!(
|
||||
parse_without_loc("f = (x) -> c 1\n\nf"),
|
||||
parse_without_loc("f = \\x => c 1\n\nf"),
|
||||
Ok((
|
||||
Assign(
|
||||
loc(Identifier("f".to_string())),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue