From 512431d27fba8f9febf99c789ea45811d2a81337 Mon Sep 17 00:00:00 2001 From: rvcas Date: Sun, 2 Oct 2022 15:38:59 -0400 Subject: [PATCH] feat: anonymous functions --- crates/lang/src/parser.rs | 58 ++++++++++++++++++++++- crates/lang/src/tests/parser.rs | 82 +++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/parser.rs b/crates/lang/src/parser.rs index dac7103a..a5b9663f 100644 --- a/crates/lang/src/parser.rs +++ b/crates/lang/src/parser.rs @@ -176,12 +176,20 @@ pub fn fn_parser() -> impl Parser impl Parser impl Parser { + // 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 { recursive(|r| { choice(( @@ -310,6 +341,28 @@ pub fn expr_parser( 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)); // TODO: do guards later @@ -393,6 +446,7 @@ pub fn expr_parser( var_parser, todo_parser, list_parser, + anon_fn_parser, block_parser, when_parser, let_parser, diff --git a/crates/lang/src/tests/parser.rs b/crates/lang/src/tests/parser.rs index af4412de..5c3ba104 100644 --- a/crates/lang/src/tests/parser.rs +++ b/crates/lang/src/tests/parser.rs @@ -69,6 +69,12 @@ fn module() { _ -> 4 } } + + pub fn such() -> Int { + let add_one = fn (a: Int) -> Int { a + 1 } + + 2 |> add_one + } "#; let len = code.chars().count(); @@ -627,6 +633,82 @@ fn module() { return_annotation: None, 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: (), + }, ] }, );