feat: field access
This commit is contained in:
parent
34492f600c
commit
1b61f4b25b
|
@ -2,12 +2,22 @@ use chumsky::prelude::*;
|
||||||
use vec1::Vec1;
|
use vec1::Vec1;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, BinOp, TodoKind},
|
ast::{self, BinOp, Span, TodoKind},
|
||||||
error::ParseError,
|
error::ParseError,
|
||||||
expr,
|
expr,
|
||||||
token::Token,
|
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(
|
pub fn module_parser(
|
||||||
kind: ast::ModuleKind,
|
kind: ast::ModuleKind,
|
||||||
) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> {
|
) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> {
|
||||||
|
@ -453,13 +463,65 @@ pub fn expr_parser(
|
||||||
assert_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 op = just(Token::Bang);
|
||||||
|
|
||||||
let unary = op
|
let unary = op
|
||||||
.ignored()
|
.ignored()
|
||||||
.map_with_span(|_, span| span)
|
.map_with_span(|_, span| span)
|
||||||
.repeated()
|
.repeated()
|
||||||
.then(expr_unit_parser)
|
.then(chained)
|
||||||
.foldr(|span, value| expr::UntypedExpr::Negate {
|
.foldr(|span, value| expr::UntypedExpr::Negate {
|
||||||
location: span.union(value.location()),
|
location: span.union(value.location()),
|
||||||
value: Box::new(value),
|
value: Box::new(value),
|
||||||
|
|
|
@ -77,6 +77,10 @@ fn module() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run() {}
|
fn run() {}
|
||||||
|
|
||||||
|
fn name(user: User) {
|
||||||
|
user.name
|
||||||
|
}
|
||||||
"#;
|
"#;
|
||||||
let len = code.chars().count();
|
let len = code.chars().count();
|
||||||
|
|
||||||
|
@ -725,6 +729,36 @@ fn module() {
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
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