feat: record update syntax
This commit is contained in:
parent
3ad915cafd
commit
dba82d544d
|
@ -447,7 +447,7 @@ pub struct TypedRecordUpdateArg {
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct UntypedRecordUpdateArg {
|
||||
pub label: String,
|
||||
// pub location: SrcSpan,
|
||||
pub location: Span,
|
||||
pub value: UntypedExpr,
|
||||
}
|
||||
|
||||
|
|
|
@ -467,9 +467,12 @@ pub fn expr_parser(
|
|||
}
|
||||
|
||||
enum Chain {
|
||||
FieldAccess(String, Span),
|
||||
RecordUpdate,
|
||||
Call(Vec<ParserArg>, Span),
|
||||
FieldAccess(String, Span),
|
||||
RecordUpdate(
|
||||
Box<(expr::UntypedExpr, Vec<ast::UntypedRecordUpdateArg>)>,
|
||||
Span,
|
||||
),
|
||||
}
|
||||
|
||||
let field_access_parser = just(Token::Dot)
|
||||
|
@ -479,6 +482,29 @@ pub fn expr_parser(
|
|||
})
|
||||
.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((
|
||||
select! { Token::Name { name } => name }
|
||||
.then_ignore(just(Token::Colon))
|
||||
|
@ -504,16 +530,11 @@ pub fn expr_parser(
|
|||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.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
|
||||
.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),
|
||||
},
|
||||
Chain::Call(args, span) => {
|
||||
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
|
||||
|
|
|
@ -89,6 +89,10 @@ fn module() {
|
|||
|
||||
map_add_x([ 1, 2, 3 ])
|
||||
}
|
||||
|
||||
fn update_name(user: User, name: String) -> User {
|
||||
User { ..user, name: "Aiken", }
|
||||
}
|
||||
"#;
|
||||
let len = code.chars().count();
|
||||
|
||||
|
@ -923,6 +927,71 @@ 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(), 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