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