mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
parse default optional expressions in pattern matches
This commit is contained in:
parent
3656257191
commit
29c3eebace
6 changed files with 209 additions and 26 deletions
|
@ -348,10 +348,9 @@ pub fn assigned_expr_field_to_pattern<'a>(
|
|||
}
|
||||
}
|
||||
AssignedField::OptionalValue(name, spaces, value) => {
|
||||
let pattern = expr_to_pattern(arena, &value.value)?;
|
||||
let result = arena.alloc(Located {
|
||||
region: value.region,
|
||||
value: pattern,
|
||||
value: value.value.clone(),
|
||||
});
|
||||
if spaces.is_empty() {
|
||||
Pattern::OptionalField(name.value, result)
|
||||
|
@ -378,13 +377,13 @@ pub fn assigned_expr_field_to_pattern<'a>(
|
|||
/// Used for patterns like { x: Just _ }
|
||||
pub fn assigned_pattern_field_to_pattern<'a>(
|
||||
arena: &'a Bump,
|
||||
assigned_field: &AssignedField<'a, Pattern<'a>>,
|
||||
assigned_field: &AssignedField<'a, Expr<'a>>,
|
||||
backup_region: Region,
|
||||
) -> Result<Located<Pattern<'a>>, Fail> {
|
||||
// the assigned fields always store spaces, but this slice is often empty
|
||||
Ok(match assigned_field {
|
||||
AssignedField::RequiredValue(name, spaces, value) => {
|
||||
let pattern = value.value.clone();
|
||||
let pattern = expr_to_pattern(arena, &value.value)?;
|
||||
let region = Region::span_across(&value.region, &value.region);
|
||||
let result = arena.alloc(Located {
|
||||
region: value.region,
|
||||
|
@ -929,22 +928,72 @@ fn underscore_pattern<'a>() -> impl Parser<'a, Pattern<'a>> {
|
|||
|
||||
fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
||||
then(
|
||||
record_without_update!(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,
|
||||
assigned_field.region,
|
||||
) {
|
||||
Ok(pattern) => patterns.push(pattern),
|
||||
Err(e) => return Err((e, state)),
|
||||
}
|
||||
}
|
||||
collection!(
|
||||
char('{'),
|
||||
move |arena: &'a bumpalo::Bump,
|
||||
state: crate::parser::State<'a>|
|
||||
-> crate::parser::ParseResult<'a, Located<crate::ast::Pattern<'a>>> {
|
||||
use crate::blankspace::{space0, space0_before};
|
||||
use crate::ident::lowercase_ident;
|
||||
use crate::parser::Either::*;
|
||||
use roc_region::all::Region;
|
||||
|
||||
// You must have a field name, e.g. "email"
|
||||
let (loc_label, state) = loc!(lowercase_ident()).parse(arena, state)?;
|
||||
|
||||
let (spaces, state) = space0(min_indent).parse(arena, state)?;
|
||||
|
||||
// Having a value is optional; both `{ email }` and `{ email: blah }` work.
|
||||
// (This is true in both literals and types.)
|
||||
let (opt_loc_val, state) = crate::parser::optional(either!(
|
||||
skip_first!(
|
||||
char(':'),
|
||||
space0_before(loc_pattern(min_indent), min_indent)
|
||||
),
|
||||
skip_first!(char('?'), space0_before(loc!(expr(min_indent)), min_indent))
|
||||
))
|
||||
.parse(arena, state)?;
|
||||
|
||||
let answer = match opt_loc_val {
|
||||
Some(either) => match either {
|
||||
First(loc_val) => Located {
|
||||
region: Region::span_across(&loc_label.region, &loc_val.region),
|
||||
value: Pattern::RequiredField(loc_label.value, arena.alloc(loc_val)),
|
||||
},
|
||||
Second(loc_val) => Located {
|
||||
region: Region::span_across(&loc_label.region, &loc_val.region),
|
||||
value: Pattern::OptionalField(loc_label.value, arena.alloc(loc_val)),
|
||||
},
|
||||
},
|
||||
// If no value was provided, record it as a Var.
|
||||
// Canonicalize will know what to do with a Var later.
|
||||
None => {
|
||||
if !spaces.is_empty() {
|
||||
Located {
|
||||
region: loc_label.region,
|
||||
value: Pattern::SpaceAfter(
|
||||
arena.alloc(Pattern::Identifier(loc_label.value)),
|
||||
spaces,
|
||||
),
|
||||
}
|
||||
} else {
|
||||
Located {
|
||||
region: loc_label.region,
|
||||
value: Pattern::Identifier(loc_label.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok((answer, state))
|
||||
},
|
||||
char(','),
|
||||
char('}'),
|
||||
min_indent
|
||||
),
|
||||
move |_arena, state, loc_patterns| {
|
||||
Ok((
|
||||
Pattern::RecordDestructure(patterns.into_bump_slice()),
|
||||
Pattern::RecordDestructure(loc_patterns.into_bump_slice()),
|
||||
state,
|
||||
))
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue