feat: anonymous functions

This commit is contained in:
rvcas 2022-10-02 15:38:59 -04:00 committed by Lucas
parent 695ac409b7
commit 512431d27f
2 changed files with 138 additions and 2 deletions

View File

@ -176,12 +176,20 @@ pub fn fn_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseEr
.delimited_by(just(Token::LeftParen), just(Token::RightParen)), .delimited_by(just(Token::LeftParen), just(Token::RightParen)),
) )
.then(just(Token::RArrow).ignore_then(type_parser()).or_not()) .then(just(Token::RArrow).ignore_then(type_parser()).or_not())
.then(expr_seq_parser().delimited_by(just(Token::LeftBrace), just(Token::RightBrace))) .then(
expr_seq_parser()
.or_not()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span( .map_with_span(
|((((opt_pub, name), arguments), return_annotation), body), span| { |((((opt_pub, name), arguments), return_annotation), body), span| {
ast::UntypedDefinition::Fn { ast::UntypedDefinition::Fn {
arguments, arguments,
body, body: body.unwrap_or(expr::UntypedExpr::Todo {
kind: TodoKind::EmptyFunction,
location: span,
label: None,
}),
doc: None, doc: None,
location: span, location: span,
name, name,
@ -229,6 +237,29 @@ pub fn fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = ParseErr
}) })
} }
pub fn anon_fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = ParseError> {
// TODO: return a better error when a label is provided `UnexpectedLabel`
choice((
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
ast::ArgName::Discard {
name,
location: span,
}
}),
select! {Token::Name {name} => name}.map_with_span(|name, span| ast::ArgName::Named {
name,
location: span,
}),
))
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
.map_with_span(|(arg_name, annotation), span| ast::Arg {
location: span,
annotation,
tipo: (),
arg_name,
})
}
pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> { pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
recursive(|r| { recursive(|r| {
choice(( choice((
@ -310,6 +341,28 @@ pub fn expr_parser(
tail, tail,
}); });
let anon_fn_parser = just(Token::Fn)
.ignore_then(
anon_fn_param_parser()
.separated_by(just(Token::Comma))
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
)
.then(just(Token::RArrow).ignore_then(type_parser()).or_not())
.then(
seq_r
.clone()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(
|((arguments, return_annotation), body), span| expr::UntypedExpr::Fn {
arguments,
body: Box::new(body),
location: span,
is_capture: false,
return_annotation,
},
);
let block_parser = seq_r.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)); let block_parser = seq_r.delimited_by(just(Token::LeftBrace), just(Token::RightBrace));
// TODO: do guards later // TODO: do guards later
@ -393,6 +446,7 @@ pub fn expr_parser(
var_parser, var_parser,
todo_parser, todo_parser,
list_parser, list_parser,
anon_fn_parser,
block_parser, block_parser,
when_parser, when_parser,
let_parser, let_parser,

View File

@ -69,6 +69,12 @@ fn module() {
_ -> 4 _ -> 4
} }
} }
pub fn such() -> Int {
let add_one = fn (a: Int) -> Int { a + 1 }
2 |> add_one
}
"#; "#;
let len = code.chars().count(); let len = code.chars().count();
@ -627,6 +633,82 @@ fn module() {
return_annotation: None, return_annotation: None,
return_type: (), return_type: (),
}, },
ast::UntypedDefinition::Fn {
arguments: vec![],
body: expr::UntypedExpr::Sequence {
location: Span::new(SrcId::empty(), 1292..1364),
expressions: vec![
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 1292..1334),
value: Box::new(expr::UntypedExpr::Fn {
location: Span::new(SrcId::empty(), 1306..1334),
is_capture: false,
arguments: vec![ast::Arg {
arg_name: ast::ArgName::Named {
name: "a".to_string(),
location: Span::new(SrcId::empty(), 1310..1311),
},
location: Span::new(SrcId::empty(), 1310..1316),
annotation: Some(ast::Annotation::Constructor {
location: Span::new(SrcId::empty(), 1313..1316),
module: None,
name: "Int".to_string(),
arguments: vec![],
},),
tipo: (),
},],
body: Box::new(expr::UntypedExpr::BinOp {
location: Span::new(SrcId::empty(), 1327..1332),
name: ast::BinOp::AddInt,
left: Box::new(expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1327..1328),
name: "a".to_string(),
}),
right: Box::new(expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1331..1332),
value: "1".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new(SrcId::empty(), 1321..1324),
module: None,
name: "Int".to_string(),
arguments: vec![],
},),
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 1296..1303),
name: "add_one".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::PipeLine {
expressions: vec1::vec1![
expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1352..1353),
value: "2".to_string(),
},
expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1357..1364),
name: "add_one".to_string(),
},
],
},
],
},
doc: None,
location: Span::new(SrcId::empty(), 1253..1378),
name: "such".to_string(),
public: true,
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new(SrcId::empty(), 1270..1273),
module: None,
name: "Int".to_string(),
arguments: vec![],
},),
return_type: (),
},
] ]
}, },
); );