feat: type aliases and some fn parsing

This commit is contained in:
rvcas 2022-08-15 15:02:03 -04:00
parent fbc9b27efe
commit d87bb17a27
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
2 changed files with 182 additions and 32 deletions

View File

@ -32,7 +32,7 @@ pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Definition<T, Expr, ConstantRecordTag, PackageName> { pub enum Definition<T, Expr, ConstantRecordTag, PackageName> {
Fn { Fn {
arguments: Vec<Vec<Arg<T>>>, arguments: Vec<Arg<T>>,
body: Expr, body: Expr,
doc: Option<String>, doc: Option<String>,
location: Span, location: Span,
@ -164,9 +164,11 @@ pub struct RecordConstructorArg<T> {
pub doc: Option<String>, pub doc: Option<String>,
} }
pub type UntypedArg = Arg<()>;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Arg<T> { pub struct Arg<T> {
pub names: ArgName, pub arg_name: ArgName,
pub location: Span, pub location: Span,
pub annotation: Option<Annotation>, pub annotation: Option<Annotation>,
pub tipo: T, pub tipo: T,
@ -174,10 +176,22 @@ pub struct Arg<T> {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum ArgName { pub enum ArgName {
Discard { name: String }, Discard {
LabeledDiscard { label: String, name: String }, name: String,
Named { name: String }, location: Span,
NamedLabeled { name: String, label: String }, },
LabeledDiscard {
label: String,
name: String,
location: Span,
},
Named {
name: String,
},
NamedLabeled {
name: String,
label: String,
},
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]

View File

@ -1,20 +1,25 @@
use chumsky::prelude::*; use chumsky::prelude::*;
use crate::{ast, error::ParseError, token::Token}; use crate::{ast, error::ParseError, expr, token::Token};
pub fn module_parser( pub fn module_parser(
kind: ast::ModuleKind, kind: ast::ModuleKind,
) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> { ) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> {
choice((import_parser(), data_parser())) choice((
.repeated() import_parser(),
.then_ignore(end()) data_parser(),
.map(move |definitions| ast::UntypedModule { type_alias_parser(),
kind, fn_parser(),
definitions, ))
docs: vec![], .repeated()
name: vec![], .then_ignore(end())
type_info: (), .map(move |definitions| ast::UntypedModule {
}) kind,
definitions,
docs: vec![],
name: vec![],
type_info: (),
})
} }
pub fn import_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> { pub fn import_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
@ -105,20 +110,10 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
}] }]
}); });
just(Token::Pub) pub_parser()
.ignored()
.then(just(Token::Opaque).ignored().or_not()) .then(just(Token::Opaque).ignored().or_not())
.or_not() .or_not()
.then( .then(type_name_with_args())
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(),
),
),
)
.then(choice((constructors, record_sugar))) .then(choice((constructors, record_sugar)))
.map_with_span(|((pub_opaque, (name, parameters)), constructors), span| { .map_with_span(|((pub_opaque, (name, parameters)), constructors), span| {
ast::UntypedDefinition::DataType { ast::UntypedDefinition::DataType {
@ -145,6 +140,82 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
}) })
} }
pub fn type_alias_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
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<Token, ast::UntypedDefinition, Error = ParseError> {
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<Token, ast::UntypedArg, Error = ParseError> {
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<Token, expr::UntypedExpr, Error = ParseError> {}
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> { pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
recursive(|r| { recursive(|r| {
choice(( choice((
@ -226,6 +297,22 @@ pub fn labeled_constructor_type_args(
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)) .delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
} }
pub fn type_name_with_args() -> impl Parser<Token, (String, Option<Vec<String>>), 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<Token, (), Error = ParseError> {
just(Token::Pub).ignored()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use chumsky::prelude::*; use chumsky::prelude::*;
@ -252,6 +339,19 @@ mod tests {
pub opaque type User { pub opaque type User {
name: _w 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(); let len = code.chars().count();
@ -264,8 +364,6 @@ mod tests {
)) ))
.unwrap(); .unwrap();
dbg!(tokens.clone());
let res = module_parser(ast::ModuleKind::Script) let res = module_parser(ast::ModuleKind::Script)
.parse(chumsky::Stream::from_iter(span(len), tokens.into_iter())) .parse(chumsky::Stream::from_iter(span(len), tokens.into_iter()))
.unwrap(); .unwrap();
@ -416,7 +514,45 @@ mod tests {
parameters: vec![], parameters: vec![],
public: true, public: true,
typed_parameters: vec![], 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: (),
},
] ]
}, },
"{:#?}", "{:#?}",