feat: field access
This commit is contained in:
parent
34492f600c
commit
1b61f4b25b
|
@ -2,12 +2,22 @@ use chumsky::prelude::*;
|
|||
use vec1::Vec1;
|
||||
|
||||
use crate::{
|
||||
ast::{self, BinOp, TodoKind},
|
||||
ast::{self, BinOp, Span, TodoKind},
|
||||
error::ParseError,
|
||||
expr,
|
||||
token::Token,
|
||||
};
|
||||
|
||||
// Parsing a function call into the appropriate structure
|
||||
#[derive(Debug)]
|
||||
pub enum ParserArg {
|
||||
Arg(Box<ast::CallArg<expr::UntypedExpr>>),
|
||||
Hole {
|
||||
location: Span,
|
||||
label: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn module_parser(
|
||||
kind: ast::ModuleKind,
|
||||
) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> {
|
||||
|
@ -453,13 +463,65 @@ pub fn expr_parser(
|
|||
assert_parser,
|
||||
));
|
||||
|
||||
enum Chain {
|
||||
FieldAccess(String, Span),
|
||||
RecordUpdate,
|
||||
Call(Vec<ParserArg>, Span),
|
||||
}
|
||||
|
||||
let field_access_parser = just(Token::Dot)
|
||||
.ignore_then(select! {
|
||||
Token::Name { name } => name,
|
||||
Token::UpName { name } => name
|
||||
})
|
||||
.map_with_span(Chain::FieldAccess);
|
||||
|
||||
let call_parser = choice((
|
||||
select! { Token::Name { name } => name }
|
||||
.then_ignore(just(Token::Colon))
|
||||
.or_not()
|
||||
.then(r.clone())
|
||||
.map_with_span(|(label, value), span| {
|
||||
ParserArg::Arg(Box::new(ast::CallArg {
|
||||
label,
|
||||
location: span,
|
||||
value,
|
||||
}))
|
||||
}),
|
||||
select! { Token::Name { name } => name }
|
||||
.then_ignore(just(Token::Colon))
|
||||
.or_not()
|
||||
.then_ignore(select! {Token::DiscardName {name} => name })
|
||||
.map_with_span(|label, span| ParserArg::Hole {
|
||||
location: span,
|
||||
label,
|
||||
}),
|
||||
))
|
||||
.separated_by(just(Token::Comma))
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.map_with_span(Chain::Call);
|
||||
|
||||
let chain = choice((field_access_parser, call_parser));
|
||||
|
||||
let chained = expr_unit_parser
|
||||
.then(chain.repeated())
|
||||
.foldl(|e, chain| match chain {
|
||||
Chain::FieldAccess(label, span) => expr::UntypedExpr::FieldAccess {
|
||||
location: e.location().union(span),
|
||||
label,
|
||||
container: Box::new(e),
|
||||
},
|
||||
_ => todo!(),
|
||||
});
|
||||
|
||||
// Negate
|
||||
let op = just(Token::Bang);
|
||||
|
||||
let unary = op
|
||||
.ignored()
|
||||
.map_with_span(|_, span| span)
|
||||
.repeated()
|
||||
.then(expr_unit_parser)
|
||||
.then(chained)
|
||||
.foldr(|span, value| expr::UntypedExpr::Negate {
|
||||
location: span.union(value.location()),
|
||||
value: Box::new(value),
|
||||
|
|
|
@ -77,6 +77,10 @@ fn module() {
|
|||
}
|
||||
|
||||
fn run() {}
|
||||
|
||||
fn name(user: User) {
|
||||
user.name
|
||||
}
|
||||
"#;
|
||||
let len = code.chars().count();
|
||||
|
||||
|
@ -725,6 +729,36 @@ fn module() {
|
|||
return_annotation: None,
|
||||
return_type: (),
|
||||
},
|
||||
ast::UntypedDefinition::Fn {
|
||||
arguments: vec![ast::Arg {
|
||||
arg_name: ast::ArgName::Named {
|
||||
name: "user".to_string(),
|
||||
location: Span::new(SrcId::empty(), 1425..1429),
|
||||
},
|
||||
location: Span::new(SrcId::empty(), 1425..1435),
|
||||
annotation: Some(ast::Annotation::Constructor {
|
||||
location: Span::new(SrcId::empty(), 1431..1435),
|
||||
module: None,
|
||||
name: "User".to_string(),
|
||||
arguments: vec![],
|
||||
},),
|
||||
tipo: (),
|
||||
},],
|
||||
body: expr::UntypedExpr::FieldAccess {
|
||||
location: Span::new(SrcId::empty(), 1455..1464),
|
||||
label: "name".to_string(),
|
||||
container: Box::new(expr::UntypedExpr::Var {
|
||||
location: Span::new(SrcId::empty(), 1455..1459),
|
||||
name: "user".to_string(),
|
||||
}),
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new(SrcId::empty(), 1417..1478),
|
||||
name: "name".to_string(),
|
||||
public: false,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
},
|
||||
]
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue