mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
parse guarded record patterns
e.g. case foo when { x: 4 } -> ... { x, y } -> ...
This commit is contained in:
parent
f47c2677ee
commit
1b2636bee6
3 changed files with 75 additions and 18 deletions
|
@ -290,7 +290,7 @@ fn expr_to_pattern<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<'a>,
|
|||
|
||||
for loc_assigned_field in loc_assigned_fields {
|
||||
let region = loc_assigned_field.region;
|
||||
let value = assigned_field_to_pattern(arena, &loc_assigned_field.value)?;
|
||||
let value = assigned_expr_field_to_pattern(arena, &loc_assigned_field.value)?;
|
||||
|
||||
loc_patterns.push(Located { region, value });
|
||||
}
|
||||
|
@ -331,7 +331,8 @@ fn expr_to_pattern<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<'a>,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn assigned_field_to_pattern<'a>(
|
||||
/// use for expressions like { x: a + b }
|
||||
pub fn assigned_expr_field_to_pattern<'a>(
|
||||
arena: &'a Bump,
|
||||
assigned_field: &AssignedField<'a, Expr<'a>>,
|
||||
) -> Result<Pattern<'a>, Fail> {
|
||||
|
@ -354,11 +355,46 @@ pub fn assigned_field_to_pattern<'a>(
|
|||
}
|
||||
AssignedField::LabelOnly(name) => Pattern::Identifier(name.value),
|
||||
AssignedField::SpaceBefore(nested, spaces) => Pattern::SpaceBefore(
|
||||
arena.alloc(assigned_field_to_pattern(arena, nested)?),
|
||||
arena.alloc(assigned_expr_field_to_pattern(arena, nested)?),
|
||||
spaces,
|
||||
),
|
||||
AssignedField::SpaceAfter(nested, spaces) => Pattern::SpaceAfter(
|
||||
arena.alloc(assigned_field_to_pattern(arena, nested)?),
|
||||
arena.alloc(assigned_expr_field_to_pattern(arena, nested)?),
|
||||
spaces,
|
||||
),
|
||||
AssignedField::Malformed(string) => Pattern::Malformed(string),
|
||||
})
|
||||
}
|
||||
|
||||
/// Used for patterns like { x: Just _ }
|
||||
pub fn assigned_pattern_field_to_pattern<'a>(
|
||||
arena: &'a Bump,
|
||||
assigned_field: &AssignedField<'a, Pattern<'a>>,
|
||||
) -> Result<Pattern<'a>, Fail> {
|
||||
// the assigned fields always store spaces, but this slice is often empty
|
||||
Ok(match assigned_field {
|
||||
AssignedField::LabeledValue(name, spaces, value) => {
|
||||
let pattern = value.value.clone();
|
||||
let result = arena.alloc(Located {
|
||||
region: value.region,
|
||||
value: pattern,
|
||||
});
|
||||
if spaces.is_empty() {
|
||||
Pattern::RecordField(name.value, result)
|
||||
} else {
|
||||
Pattern::SpaceAfter(
|
||||
arena.alloc(Pattern::RecordField(name.value, result)),
|
||||
spaces,
|
||||
)
|
||||
}
|
||||
}
|
||||
AssignedField::LabelOnly(name) => Pattern::Identifier(name.value),
|
||||
AssignedField::SpaceBefore(nested, spaces) => Pattern::SpaceBefore(
|
||||
arena.alloc(assigned_pattern_field_to_pattern(arena, nested)?),
|
||||
spaces,
|
||||
),
|
||||
AssignedField::SpaceAfter(nested, spaces) => Pattern::SpaceAfter(
|
||||
arena.alloc(assigned_pattern_field_to_pattern(arena, nested)?),
|
||||
spaces,
|
||||
),
|
||||
AssignedField::Malformed(string) => Pattern::Malformed(string),
|
||||
|
@ -744,15 +780,19 @@ fn underscore_pattern<'a>() -> impl Parser<'a, Pattern<'a>> {
|
|||
}
|
||||
|
||||
fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
||||
map!(
|
||||
collection!(
|
||||
char('{'),
|
||||
loc!(ident_pattern()),
|
||||
char(','),
|
||||
char('}'),
|
||||
min_indent
|
||||
),
|
||||
Pattern::RecordDestructure
|
||||
then(
|
||||
record!(loc!(pattern(min_indent)), min_indent),
|
||||
move |arena, state, assigned_fields| {
|
||||
let mut patterns = Vec::with_capacity_in(assigned_fields.len(), arena);
|
||||
for assigned_field in assigned_fields {
|
||||
match assigned_pattern_field_to_pattern(arena, &assigned_field.value) {
|
||||
Ok(pattern) => patterns.push(Located::at(assigned_field.region, pattern)),
|
||||
Err(e) => return Err((e, state)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Pattern::RecordDestructure(patterns), state))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1269,7 +1309,7 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
|
||||
for loc_assigned_field in assigned_fields {
|
||||
let region = loc_assigned_field.region;
|
||||
match assigned_field_to_pattern(arena, &loc_assigned_field.value) {
|
||||
match assigned_expr_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)),
|
||||
|
@ -1304,7 +1344,7 @@ pub fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
|||
|
||||
for loc_assigned_field in assigned_fields {
|
||||
let region = loc_assigned_field.region;
|
||||
match assigned_field_to_pattern(arena, &loc_assigned_field.value) {
|
||||
match assigned_expr_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)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue