mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
parse records with type signatures
{ x, y } : { x : Int, y : Float }
This commit is contained in:
parent
97f2c57a39
commit
9d7ce6ff15
2 changed files with 53 additions and 2 deletions
|
@ -1235,7 +1235,10 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
Attempting::Record,
|
||||
loc!(record!(loc!(expr(min_indent)), min_indent))
|
||||
),
|
||||
optional(and!(space0(min_indent), equals_with_indent()))
|
||||
optional(and!(
|
||||
space0(min_indent),
|
||||
either!(equals_with_indent(), colon_with_indent())
|
||||
))
|
||||
),
|
||||
move |arena, state, (loc_assigned_fields, opt_def)| match opt_def {
|
||||
None => {
|
||||
|
@ -1258,7 +1261,7 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
|
||||
Ok((value, state))
|
||||
}
|
||||
Some((spaces_before_equals, equals_indent)) => {
|
||||
Some((spaces_before_equals, Either::First(equals_indent))) => {
|
||||
// This is a record destructure def.
|
||||
let region = loc_assigned_fields.region;
|
||||
let assigned_fields = loc_assigned_fields.value;
|
||||
|
@ -1291,6 +1294,40 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
Expr::SpaceBefore(arena.alloc(parsed_expr), spaces_after_equals)
|
||||
};
|
||||
|
||||
Ok((answer, state))
|
||||
}
|
||||
Some((spaces_before_colon, Either::Second(colon_indent))) => {
|
||||
// This is a record type annotation
|
||||
let region = loc_assigned_fields.region;
|
||||
let assigned_fields = loc_assigned_fields.value;
|
||||
let mut loc_patterns = Vec::with_capacity_in(assigned_fields.len(), arena);
|
||||
|
||||
for loc_assigned_field in assigned_fields {
|
||||
let region = loc_assigned_field.region;
|
||||
match assigned_field_to_pattern(arena, &loc_assigned_field.value) {
|
||||
Ok(value) => loc_patterns.push(Located { region, value }),
|
||||
// an Expr became a pattern that should not be.
|
||||
Err(e) => return Err((e, state)),
|
||||
}
|
||||
}
|
||||
|
||||
let pattern = Pattern::RecordDestructure(loc_patterns);
|
||||
let value = if spaces_before_colon.is_empty() {
|
||||
pattern
|
||||
} else {
|
||||
Pattern::SpaceAfter(arena.alloc(pattern), spaces_before_colon)
|
||||
};
|
||||
let loc_pattern = Located { region, value };
|
||||
let (spaces_after_equals, state) = space0(min_indent).parse(arena, state)?;
|
||||
let (parsed_expr, state) =
|
||||
parse_def_signature(min_indent, colon_indent, arena, state, loc_pattern)?;
|
||||
|
||||
let answer = if spaces_after_equals.is_empty() {
|
||||
parsed_expr
|
||||
} else {
|
||||
Expr::SpaceBefore(arena.alloc(parsed_expr), spaces_after_equals)
|
||||
};
|
||||
|
||||
Ok((answer, state))
|
||||
}
|
||||
},
|
||||
|
|
|
@ -902,4 +902,18 @@ mod test_infer {
|
|||
fn accessor_function() {
|
||||
infer_eq(".foo", "{ foo : a }* -> a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_signature_without_body_record() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
{ x, y } : { x : (Int -> custom) , y : Int }
|
||||
|
||||
x
|
||||
"#
|
||||
),
|
||||
"Int -> custom",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue