feat: record update syntax
This commit is contained in:
		
							parent
							
								
									3ad915cafd
								
							
						
					
					
						commit
						dba82d544d
					
				| 
						 | 
					@ -447,7 +447,7 @@ pub struct TypedRecordUpdateArg {
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
pub struct UntypedRecordUpdateArg {
 | 
					pub struct UntypedRecordUpdateArg {
 | 
				
			||||||
    pub label: String,
 | 
					    pub label: String,
 | 
				
			||||||
    // pub location: SrcSpan,
 | 
					    pub location: Span,
 | 
				
			||||||
    pub value: UntypedExpr,
 | 
					    pub value: UntypedExpr,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -467,9 +467,12 @@ pub fn expr_parser(
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        enum Chain {
 | 
					        enum Chain {
 | 
				
			||||||
            FieldAccess(String, Span),
 | 
					 | 
				
			||||||
            RecordUpdate,
 | 
					 | 
				
			||||||
            Call(Vec<ParserArg>, Span),
 | 
					            Call(Vec<ParserArg>, Span),
 | 
				
			||||||
 | 
					            FieldAccess(String, Span),
 | 
				
			||||||
 | 
					            RecordUpdate(
 | 
				
			||||||
 | 
					                Box<(expr::UntypedExpr, Vec<ast::UntypedRecordUpdateArg>)>,
 | 
				
			||||||
 | 
					                Span,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let field_access_parser = just(Token::Dot)
 | 
					        let field_access_parser = just(Token::Dot)
 | 
				
			||||||
| 
						 | 
					@ -479,6 +482,29 @@ pub fn expr_parser(
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .map_with_span(Chain::FieldAccess);
 | 
					            .map_with_span(Chain::FieldAccess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let record_update_parser = just(Token::DotDot)
 | 
				
			||||||
 | 
					            .ignore_then(r.clone())
 | 
				
			||||||
 | 
					            .then(
 | 
				
			||||||
 | 
					                just(Token::Comma)
 | 
				
			||||||
 | 
					                    .ignore_then(
 | 
				
			||||||
 | 
					                        select! { Token::Name {name} => name }
 | 
				
			||||||
 | 
					                            .then_ignore(just(Token::Colon))
 | 
				
			||||||
 | 
					                            .then(r.clone())
 | 
				
			||||||
 | 
					                            .map_with_span(|(label, value), span| ast::UntypedRecordUpdateArg {
 | 
				
			||||||
 | 
					                                label,
 | 
				
			||||||
 | 
					                                value,
 | 
				
			||||||
 | 
					                                location: span,
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                            .separated_by(just(Token::Comma))
 | 
				
			||||||
 | 
					                            .allow_trailing(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .or_not(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
 | 
				
			||||||
 | 
					            .map_with_span(|(spread, args_opt), span| {
 | 
				
			||||||
 | 
					                Chain::RecordUpdate(Box::new((spread, args_opt.unwrap_or_default())), span)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let call_parser = choice((
 | 
					        let call_parser = choice((
 | 
				
			||||||
            select! { Token::Name { name } => name }
 | 
					            select! { Token::Name { name } => name }
 | 
				
			||||||
                .then_ignore(just(Token::Colon))
 | 
					                .then_ignore(just(Token::Colon))
 | 
				
			||||||
| 
						 | 
					@ -504,16 +530,11 @@ pub fn expr_parser(
 | 
				
			||||||
        .delimited_by(just(Token::LeftParen), just(Token::RightParen))
 | 
					        .delimited_by(just(Token::LeftParen), just(Token::RightParen))
 | 
				
			||||||
        .map_with_span(Chain::Call);
 | 
					        .map_with_span(Chain::Call);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let chain = choice((field_access_parser, call_parser));
 | 
					        let chain = choice((field_access_parser, record_update_parser, call_parser));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let chained = expr_unit_parser
 | 
					        let chained = expr_unit_parser
 | 
				
			||||||
            .then(chain.repeated())
 | 
					            .then(chain.repeated())
 | 
				
			||||||
            .foldl(|e, chain| match chain {
 | 
					            .foldl(|e, chain| match chain {
 | 
				
			||||||
                Chain::FieldAccess(label, span) => expr::UntypedExpr::FieldAccess {
 | 
					 | 
				
			||||||
                    location: e.location().union(span),
 | 
					 | 
				
			||||||
                    label,
 | 
					 | 
				
			||||||
                    container: Box::new(e),
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                Chain::Call(args, span) => {
 | 
					                Chain::Call(args, span) => {
 | 
				
			||||||
                    let mut holes = Vec::new();
 | 
					                    let mut holes = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -563,7 +584,30 @@ pub fn expr_parser(
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => todo!(),
 | 
					
 | 
				
			||||||
 | 
					                Chain::FieldAccess(label, span) => expr::UntypedExpr::FieldAccess {
 | 
				
			||||||
 | 
					                    location: e.location().union(span),
 | 
				
			||||||
 | 
					                    label,
 | 
				
			||||||
 | 
					                    container: Box::new(e),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Chain::RecordUpdate(data, span) => {
 | 
				
			||||||
 | 
					                    let (spread, arguments) = *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let location = span.union(spread.location());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let spread = ast::RecordUpdateSpread {
 | 
				
			||||||
 | 
					                        base: Box::new(spread),
 | 
				
			||||||
 | 
					                        location,
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    expr::UntypedExpr::RecordUpdate {
 | 
				
			||||||
 | 
					                        location: e.location().union(span),
 | 
				
			||||||
 | 
					                        constructor: Box::new(e),
 | 
				
			||||||
 | 
					                        spread,
 | 
				
			||||||
 | 
					                        arguments,
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Negate
 | 
					        // Negate
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,6 +89,10 @@ fn module() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                map_add_x([ 1, 2, 3 ])
 | 
					                map_add_x([ 1, 2, 3 ])
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fn update_name(user: User, name: String) -> User {
 | 
				
			||||||
 | 
					                User { ..user, name: "Aiken", }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        "#;
 | 
					        "#;
 | 
				
			||||||
    let len = code.chars().count();
 | 
					    let len = code.chars().count();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -923,6 +927,71 @@ 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(), 1685..1689),
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            location: Span::new(SrcId::empty(), 1685..1695),
 | 
				
			||||||
 | 
					                            annotation: Some(ast::Annotation::Constructor {
 | 
				
			||||||
 | 
					                                location: Span::new(SrcId::empty(), 1691..1695),
 | 
				
			||||||
 | 
					                                module: None,
 | 
				
			||||||
 | 
					                                name: "User".to_string(),
 | 
				
			||||||
 | 
					                                arguments: vec![],
 | 
				
			||||||
 | 
					                            },),
 | 
				
			||||||
 | 
					                            tipo: (),
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        ast::Arg {
 | 
				
			||||||
 | 
					                            arg_name: ast::ArgName::Named {
 | 
				
			||||||
 | 
					                                name: "name".to_string(),
 | 
				
			||||||
 | 
					                                location: Span::new(SrcId::empty(), 1697..1701),
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            location: Span::new(SrcId::empty(), 1697..1709),
 | 
				
			||||||
 | 
					                            annotation: Some(ast::Annotation::Constructor {
 | 
				
			||||||
 | 
					                                location: Span::new(SrcId::empty(), 1703..1709),
 | 
				
			||||||
 | 
					                                module: None,
 | 
				
			||||||
 | 
					                                name: "String".to_string(),
 | 
				
			||||||
 | 
					                                arguments: vec![],
 | 
				
			||||||
 | 
					                            },),
 | 
				
			||||||
 | 
					                            tipo: (),
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    body: expr::UntypedExpr::RecordUpdate {
 | 
				
			||||||
 | 
					                        location: Span::new(SrcId::empty(), 1737..1768),
 | 
				
			||||||
 | 
					                        constructor: Box::new(expr::UntypedExpr::Var {
 | 
				
			||||||
 | 
					                            location: Span::new(SrcId::empty(), 1737..1741),
 | 
				
			||||||
 | 
					                            name: "User".to_string(),
 | 
				
			||||||
 | 
					                        }),
 | 
				
			||||||
 | 
					                        spread: ast::RecordUpdateSpread {
 | 
				
			||||||
 | 
					                            base: Box::new(expr::UntypedExpr::Var {
 | 
				
			||||||
 | 
					                                location: Span::new(SrcId::empty(), 1746..1750),
 | 
				
			||||||
 | 
					                                name: "user".to_string(),
 | 
				
			||||||
 | 
					                            }),
 | 
				
			||||||
 | 
					                            location: Span::new(SrcId::empty(), 1742..1768),
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        arguments: vec![ast::UntypedRecordUpdateArg {
 | 
				
			||||||
 | 
					                            label: "name".to_string(),
 | 
				
			||||||
 | 
					                            location: Span::new(SrcId::empty(), 1752..1765),
 | 
				
			||||||
 | 
					                            value: expr::UntypedExpr::String {
 | 
				
			||||||
 | 
					                                location: Span::new(SrcId::empty(), 1758..1765),
 | 
				
			||||||
 | 
					                                value: "Aiken".to_string(),
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                        },],
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    doc: None,
 | 
				
			||||||
 | 
					                    location: Span::new(SrcId::empty(), 1670..1782),
 | 
				
			||||||
 | 
					                    name: "update_name".to_string(),
 | 
				
			||||||
 | 
					                    public: false,
 | 
				
			||||||
 | 
					                    return_annotation: Some(ast::Annotation::Constructor {
 | 
				
			||||||
 | 
					                        location: Span::new(SrcId::empty(), 1714..1718),
 | 
				
			||||||
 | 
					                        module: None,
 | 
				
			||||||
 | 
					                        name: "User".to_string(),
 | 
				
			||||||
 | 
					                        arguments: vec![],
 | 
				
			||||||
 | 
					                    },),
 | 
				
			||||||
 | 
					                    return_type: (),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue