mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +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;
|
let min_indent = *min_indent_ref;
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
enclosed_closure(min_indent),
|
|
||||||
closure(min_indent),
|
closure(min_indent),
|
||||||
parenthetical_expr(min_indent),
|
parenthetical_expr(min_indent),
|
||||||
string("{}").with(value(Expr::EmptyRecord)),
|
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 => expr
|
||||||
///
|
|
||||||
/// 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)
|
|
||||||
pub fn closure<I>(min_indent: u32) -> impl Parser<Input = I, Output = Expr>
|
pub fn closure<I>(min_indent: u32) -> impl Parser<Input = I, Output = Expr>
|
||||||
where I: Stream<Item = char, Position = IndentablePosition>,
|
where I: Stream<Item = char, Position = IndentablePosition>,
|
||||||
I::Error: ParseError<I::Item, I::Range, I::Position>
|
I::Error: ParseError<I::Item, I::Range, I::Position>
|
||||||
{
|
{
|
||||||
attempt(
|
char('\\')
|
||||||
between(char('('), char(')'),
|
.skip(indented_whitespaces(min_indent))
|
||||||
|
.with(
|
||||||
sep_by1(
|
sep_by1(
|
||||||
located(pattern(min_indent)),
|
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(indented_whitespaces1(min_indent))
|
||||||
.skip(string("->"))
|
|
||||||
.skip(indented_whitespaces1(min_indent))
|
|
||||||
)
|
|
||||||
.and(located(expr_body(min_indent)))
|
.and(located(expr_body(min_indent)))
|
||||||
.map(|(patterns, closure_body)| {
|
.map(|(patterns, closure_body)| {
|
||||||
Expr::Closure(patterns, Box::new(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!
|
// all of the above tests except with parens too!
|
||||||
// Also, verify them all with variable paren counts; ((foo)) should work.
|
// 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
|
// FUNC
|
||||||
|
|
||||||
fn expect_parsed_func<'a>(parse_str: &'a str, func_str: &'a str, args: Vec<Located<Expr>>) {
|
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]
|
#[test]
|
||||||
fn regression_on_calling_function_named_c() {
|
fn regression_on_calling_function_named_c() {
|
||||||
// This was broken because case-expressions were greedily consuming 'c' characters for "case"
|
// This was broken because case-expressions were greedily consuming 'c' characters for "case"
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_without_loc("f = (x) -> c 1\n\nf"),
|
parse_without_loc("f = \\x => c 1\n\nf"),
|
||||||
Ok((
|
Ok((
|
||||||
Assign(
|
Assign(
|
||||||
loc(Identifier("f".to_string())),
|
loc(Identifier("f".to_string())),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue