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,
|
Attempting::Record,
|
||||||
loc!(record!(loc!(expr(min_indent)), min_indent))
|
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 {
|
move |arena, state, (loc_assigned_fields, opt_def)| match opt_def {
|
||||||
None => {
|
None => {
|
||||||
|
@ -1258,7 +1261,7 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||||
|
|
||||||
Ok((value, state))
|
Ok((value, state))
|
||||||
}
|
}
|
||||||
Some((spaces_before_equals, equals_indent)) => {
|
Some((spaces_before_equals, Either::First(equals_indent))) => {
|
||||||
// This is a record destructure def.
|
// This is a record destructure def.
|
||||||
let region = loc_assigned_fields.region;
|
let region = loc_assigned_fields.region;
|
||||||
let assigned_fields = loc_assigned_fields.value;
|
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)
|
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))
|
Ok((answer, state))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -902,4 +902,18 @@ mod test_infer {
|
||||||
fn accessor_function() {
|
fn accessor_function() {
|
||||||
infer_eq(".foo", "{ foo : a }* -> a");
|
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