From d87bb17a27c918421f881afab4fad5a001fd2083 Mon Sep 17 00:00:00 2001 From: rvcas Date: Mon, 15 Aug 2022 15:02:03 -0400 Subject: [PATCH] feat: type aliases and some fn parsing --- crates/lang/src/ast.rs | 26 ++++-- crates/lang/src/parser.rs | 188 ++++++++++++++++++++++++++++++++------ 2 files changed, 182 insertions(+), 32 deletions(-) diff --git a/crates/lang/src/ast.rs b/crates/lang/src/ast.rs index 914478c8..75ea3398 100644 --- a/crates/lang/src/ast.rs +++ b/crates/lang/src/ast.rs @@ -32,7 +32,7 @@ pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>; #[derive(Debug, Clone, PartialEq)] pub enum Definition { Fn { - arguments: Vec>>, + arguments: Vec>, body: Expr, doc: Option, location: Span, @@ -164,9 +164,11 @@ pub struct RecordConstructorArg { pub doc: Option, } +pub type UntypedArg = Arg<()>; + #[derive(Debug, Clone, PartialEq)] pub struct Arg { - pub names: ArgName, + pub arg_name: ArgName, pub location: Span, pub annotation: Option, pub tipo: T, @@ -174,10 +176,22 @@ pub struct Arg { #[derive(Debug, Clone, PartialEq, Eq)] pub enum ArgName { - Discard { name: String }, - LabeledDiscard { label: String, name: String }, - Named { name: String }, - NamedLabeled { name: String, label: String }, + Discard { + name: String, + location: Span, + }, + LabeledDiscard { + label: String, + name: String, + location: Span, + }, + Named { + name: String, + }, + NamedLabeled { + name: String, + label: String, + }, } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/lang/src/parser.rs b/crates/lang/src/parser.rs index cf645e5e..a994c8fe 100644 --- a/crates/lang/src/parser.rs +++ b/crates/lang/src/parser.rs @@ -1,20 +1,25 @@ use chumsky::prelude::*; -use crate::{ast, error::ParseError, token::Token}; +use crate::{ast, error::ParseError, expr, token::Token}; pub fn module_parser( kind: ast::ModuleKind, ) -> impl Parser { - choice((import_parser(), data_parser())) - .repeated() - .then_ignore(end()) - .map(move |definitions| ast::UntypedModule { - kind, - definitions, - docs: vec![], - name: vec![], - type_info: (), - }) + choice(( + import_parser(), + data_parser(), + type_alias_parser(), + fn_parser(), + )) + .repeated() + .then_ignore(end()) + .map(move |definitions| ast::UntypedModule { + kind, + definitions, + docs: vec![], + name: vec![], + type_info: (), + }) } pub fn import_parser() -> impl Parser { @@ -105,20 +110,10 @@ pub fn data_parser() -> impl Parser name}.then( - select! {Token::Name { name } => name} - .separated_by(just(Token::Comma)) - .delimited_by(just(Token::LeftParen), just(Token::RightParen)) - .or_not(), - ), - ), - ) + .then(type_name_with_args()) .then(choice((constructors, record_sugar))) .map_with_span(|((pub_opaque, (name, parameters)), constructors), span| { ast::UntypedDefinition::DataType { @@ -145,6 +140,82 @@ pub fn data_parser() -> impl Parser impl Parser { + pub_parser() + .or_not() + .then(type_name_with_args()) + .then_ignore(just(Token::Equal)) + .then(type_parser()) + .map_with_span(|((opt_pub, (alias, parameters)), annotation), span| { + ast::UntypedDefinition::TypeAlias { + alias, + annotation, + doc: None, + location: span, + parameters: parameters.unwrap_or_default(), + public: opt_pub.is_some(), + tipo: (), + } + }) +} + +pub fn fn_parser() -> impl Parser { + pub_parser() + .or_not() + .then_ignore(just(Token::Fn)) + .then(select! {Token::Name {name} => name}) + .then( + 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_ignore(just(Token::LeftBrace)) + .then(expr_seq_parser()) + .then_ignore(just(Token::RightBrace)) + .map_with_span( + |((((opt_pub, name), arguments), return_annotation), body), span| { + ast::UntypedDefinition::Fn { + arguments, + body, + doc: None, + location: span, + name, + public: opt_pub.is_some(), + return_annotation, + return_type: (), + } + }, + ) +} + +pub fn fn_param_parser() -> impl Parser { + choice(( + select! {Token::Name {name} => name} + .then(select! {Token::DiscardName {name} => name}) + .map_with_span(|(label, name), span| ast::ArgName::LabeledDiscard { + label, + name, + location: span, + }), + select! {Token::DiscardName {name} => name}.map_with_span(|name, span| { + ast::ArgName::Discard { + 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 {} + pub fn type_parser() -> impl Parser { recursive(|r| { choice(( @@ -226,6 +297,22 @@ pub fn labeled_constructor_type_args( .delimited_by(just(Token::LeftBrace), just(Token::RightBrace)) } +pub fn type_name_with_args() -> impl Parser>), Error = ParseError> +{ + just(Token::Type).ignore_then( + select! {Token::UpName { name } => name}.then( + select! {Token::Name { name } => name} + .separated_by(just(Token::Comma)) + .delimited_by(just(Token::LeftParen), just(Token::RightParen)) + .or_not(), + ), + ) +} + +pub fn pub_parser() -> impl Parser { + just(Token::Pub).ignored() +} + #[cfg(test)] mod tests { use chumsky::prelude::*; @@ -252,6 +339,19 @@ mod tests { pub opaque type User { name: _w } + + type Thing = Option(Int) + + pub type Me = Option(String) + + pub fn add_one(a) { + a + 1 + } + + pub fn add_one(a: Int) -> Int { + [1, 2, 3] + |> list.map(fn(x) { x + a }) + } "#; let len = code.chars().count(); @@ -264,8 +364,6 @@ mod tests { )) .unwrap(); - dbg!(tokens.clone()); - let res = module_parser(ast::ModuleKind::Script) .parse(chumsky::Stream::from_iter(span(len), tokens.into_iter())) .unwrap(); @@ -416,7 +514,45 @@ mod tests { parameters: vec![], public: true, typed_parameters: vec![], - } + }, + ast::UntypedDefinition::TypeAlias { + alias: "Thing".to_string(), + annotation: ast::Annotation::Constructor { + location: Span::new(SrcId::empty(), 348..359), + module: None, + name: "Option".to_string(), + arguments: vec![ast::Annotation::Constructor { + location: Span::new(SrcId::empty(), 355..358), + module: None, + name: "Int".to_string(), + arguments: vec![], + },], + }, + doc: None, + location: Span::new(SrcId::empty(), 335..359), + parameters: vec![], + public: false, + tipo: (), + }, + ast::UntypedDefinition::TypeAlias { + alias: "Me".to_string(), + annotation: ast::Annotation::Constructor { + location: Span::new(SrcId::empty(), 387..401), + module: None, + name: "Option".to_string(), + arguments: vec![ast::Annotation::Constructor { + location: Span::new(SrcId::empty(), 394..400), + module: None, + name: "String".to_string(), + arguments: vec![], + },], + }, + doc: None, + location: Span::new(SrcId::empty(), 373..401), + parameters: vec![], + public: true, + tipo: (), + }, ] }, "{:#?}",