From 43b147a9e0995cc23f2713465d22ec3c7d22d6c0 Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 29 Sep 2022 23:28:20 -0400 Subject: [PATCH] feat: lists and flatten sequences --- crates/lang/src/expr.rs | 39 ++++++++-- crates/lang/src/parser.rs | 153 +++++++++++++++++++++++++++----------- 2 files changed, 141 insertions(+), 51 deletions(-) diff --git a/crates/lang/src/expr.rs b/crates/lang/src/expr.rs index 2cd2247b..1fb24b8d 100644 --- a/crates/lang/src/expr.rs +++ b/crates/lang/src/expr.rs @@ -277,17 +277,42 @@ impl UntypedExpr { ..self.location() }; - match self { - Self::Sequence { - mut expressions, .. - } => { - expressions.push(next); + match (self.clone(), next.clone()) { + ( + Self::Sequence { + expressions: mut current_expressions, + .. + }, + Self::Sequence { + expressions: mut next_expressions, + .. + }, + ) => { + current_expressions.append(&mut next_expressions); + Self::Sequence { location, - expressions, + expressions: current_expressions, } } - _ => Self::Sequence { + ( + _, + Self::Sequence { + expressions: mut next_expressions, + .. + }, + ) => { + let mut current_expressions = vec![self]; + + current_expressions.append(&mut next_expressions); + + Self::Sequence { + location, + expressions: current_expressions, + } + } + + (_, _) => Self::Sequence { location, expressions: vec![self, next], }, diff --git a/crates/lang/src/parser.rs b/crates/lang/src/parser.rs index 31a44c78..f2a5be1a 100644 --- a/crates/lang/src/parser.rs +++ b/crates/lang/src/parser.rs @@ -249,18 +249,67 @@ pub fn expr_seq_parser() -> impl Parser impl Parser { recursive(|r| { - let assignment_parser = pattern_parser() + let string_parser = + select! {Token::String {value} => value}.map_with_span(|value, span| { + expr::UntypedExpr::String { + location: span, + value, + } + }); + + let int_parser = select! { Token::Int {value} => value}.map_with_span(|value, span| { + expr::UntypedExpr::Int { + location: span, + value, + } + }); + + let var_parser = select! { + Token::Name { name } => name, + Token::UpName { name } => name, + } + .map_with_span(|name, span| expr::UntypedExpr::Var { + location: span, + name, + }); + + let todo_parser = just(Token::Todo) + .ignore_then( + select! {Token::String {value} => value} + .delimited_by(just(Token::LeftParen), just(Token::RightParen)) + .or_not(), + ) + .map_with_span(|label, span| expr::UntypedExpr::Todo { + kind: TodoKind::Keyword, + location: span, + label, + }); + + let list_parser = just(Token::LeftSquare) + .ignore_then(r.clone().separated_by(just(Token::Comma)).allow_trailing()) + .then( + just(Token::DotDot) + .ignore_then(r.clone()) + .map(Box::new) + .or_not(), + ) + .then_ignore(just(Token::RightSquare)) + // TODO: check if tail.is_some and elements.is_empty then return ListSpreadWithoutElements error + .map_with_span(|(elements, tail), span| expr::UntypedExpr::List { + location: span, + elements, + tail, + }); + + let assignment_parser = just(Token::Let) + .ignore_then(pattern_parser()) .then(just(Token::Colon).ignore_then(type_parser()).or_not()) .then_ignore(just(Token::Equal)) .then(r) @@ -275,40 +324,12 @@ pub fn expr_parser() -> impl Parser value}.map_with_span(|value, span| { - expr::UntypedExpr::String { - location: span, - value, - } - }), - select! { Token::Int {value} => value}.map_with_span(|value, span| { - expr::UntypedExpr::Int { - location: span, - value, - } - }), - select! { - Token::Name { name } => name, - Token::UpName { name } => name, - } - .map_with_span(|name, span| expr::UntypedExpr::Var { - location: span, - name, - }), - just(Token::Todo) - .ignore_then( - select! {Token::String {value} => value} - .delimited_by(just(Token::LeftParen), just(Token::RightParen)) - .or_not(), - ) - .map_with_span(|label, span| expr::UntypedExpr::Todo { - kind: TodoKind::Keyword, - location: span, - label, - }), - just(Token::Let) - .then(assignment_parser) - .map(|(_, assign)| assign), + string_parser, + int_parser, + var_parser, + todo_parser, + list_parser, + assignment_parser, )) .boxed(); @@ -658,6 +679,10 @@ mod tests { a + 2 |> add_one |> add_one + + let thing = [ 1, 2, a ] + + let idk = thing y } @@ -954,10 +979,10 @@ mod tests { tipo: (), },], body: expr::UntypedExpr::Sequence { - location: Span::new(SrcId::empty(), 645..741), + location: Span::new(SrcId::empty(), 641..819), expressions: vec![ expr::UntypedExpr::Assignment { - location: Span::new(SrcId::empty(), 645..724), + location: Span::new(SrcId::empty(), 641..724), value: Box::new(expr::UntypedExpr::PipeLine { expressions: vec1::vec1![ expr::UntypedExpr::BinOp { @@ -989,14 +1014,54 @@ mod tests { kind: ast::AssignmentKind::Let, annotation: None, }, + expr::UntypedExpr::Assignment { + location: Span::new(SrcId::empty(), 748..771), + value: Box::new(expr::UntypedExpr::List { + location: Span::new(SrcId::empty(), 760..771), + elements: vec![ + expr::UntypedExpr::Int { + location: Span::new(SrcId::empty(), 762..763), + value: "1".to_string(), + }, + expr::UntypedExpr::Int { + location: Span::new(SrcId::empty(), 765..766), + value: "2".to_string(), + }, + expr::UntypedExpr::Var { + location: Span::new(SrcId::empty(), 768..769), + name: "a".to_string(), + }, + ], + tail: None, + }), + pattern: ast::Pattern::Var { + location: Span::new(SrcId::empty(), 752..757), + name: "thing".to_string(), + }, + kind: ast::AssignmentKind::Let, + annotation: None, + }, + expr::UntypedExpr::Assignment { + location: Span::new(SrcId::empty(), 787..802), + value: Box::new(expr::UntypedExpr::Var { + location: Span::new(SrcId::empty(), 797..802), + name: "thing".to_string(), + }), + pattern: ast::Pattern::Var { + location: Span::new(SrcId::empty(), 791..794), + name: "idk".to_string(), + }, + kind: ast::AssignmentKind::Let, + annotation: None, + }, expr::UntypedExpr::Var { - location: Span::new(SrcId::empty(), 740..741), + location: Span::new(SrcId::empty(), 818..819), name: "y".to_string(), }, ], }, doc: None, - location: Span::new(SrcId::empty(), 606..755), + location: Span::new(SrcId::empty(), 606..833), name: "wow".to_string(), public: true, return_annotation: None,