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