Merge branch 'trunk' into ct/case-when-to-when-is

This commit is contained in:
Richard Feldman 2019-12-23 23:29:43 -08:00 committed by GitHub
commit fd36e153ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 353 additions and 192 deletions

View file

@ -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,17 +355,63 @@ 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>>,
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::LabeledValue(name, spaces, value) => {
let pattern = value.value.clone();
let region = Region::span_across(&value.region, &value.region);
let result = arena.alloc(Located {
region: value.region,
value: pattern,
});
if spaces.is_empty() {
Located::at(region, Pattern::RecordField(name.value, result))
} else {
Located::at(
region,
Pattern::SpaceAfter(
arena.alloc(Pattern::RecordField(name.value, result)),
spaces,
),
)
}
}
AssignedField::LabelOnly(name) => Located::at(name.region, Pattern::Identifier(name.value)),
AssignedField::SpaceBefore(nested, spaces) => {
let can_nested = assigned_pattern_field_to_pattern(arena, nested, backup_region)?;
Located::at(
can_nested.region,
Pattern::SpaceBefore(arena.alloc(can_nested.value), spaces),
)
}
AssignedField::SpaceAfter(nested, spaces) => {
let can_nested = assigned_pattern_field_to_pattern(arena, nested, backup_region)?;
Located::at(
can_nested.region,
Pattern::SpaceAfter(arena.alloc(can_nested.value), spaces),
)
}
AssignedField::Malformed(string) => Located::at(backup_region, Pattern::Malformed(string)),
})
}
/// A def beginning with a parenthetical pattern, for example:
///
/// (UserId userId) = ...
@ -745,15 +792,23 @@ 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,
assigned_field.region,
) {
Ok(pattern) => patterns.push(pattern),
Err(e) => return Err((e, state)),
}
}
Ok((Pattern::RecordDestructure(patterns), state))
},
)
}
@ -1270,7 +1325,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)),
@ -1305,7 +1360,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)),