Change guard to DestructType

This commit is contained in:
Richard Feldman 2020-07-18 12:42:04 -04:00
parent 85f51ef39d
commit 8b53ec15fe
4 changed files with 69 additions and 16 deletions

View file

@ -941,7 +941,7 @@ fn canonicalize_field<'a>(
match field { match field {
// Both a label and a value, e.g. `{ name: "blah" }` // Both a label and a value, e.g. `{ name: "blah" }`
LabeledValue(label, _, loc_expr) => { RequiredValue(label, _, loc_expr) => {
let field_var = var_store.fresh(); let field_var = var_store.fresh();
let (loc_can_expr, output) = let (loc_can_expr, output) =
canonicalize_expr(env, var_store, scope, loc_expr.region, &loc_expr.value); canonicalize_expr(env, var_store, scope, loc_expr.region, &loc_expr.value);
@ -954,6 +954,10 @@ fn canonicalize_field<'a>(
) )
} }
OptionalValue(_, _, _) => {
todo!("TODO gracefully handle an optional field being used in an Expr");
}
// A label with no value, e.g. `{ name }` (this is sugar for { name: name }) // A label with no value, e.g. `{ name }` (this is sugar for { name: name })
LabelOnly(_) => { LabelOnly(_) => {
panic!("Somehow a LabelOnly record field was not desugared!"); panic!("Somehow a LabelOnly record field was not desugared!");

View file

@ -44,7 +44,14 @@ pub struct RecordDestruct {
pub var: Variable, pub var: Variable,
pub label: Lowercase, pub label: Lowercase,
pub symbol: Symbol, pub symbol: Symbol,
pub guard: Option<(Variable, Located<Pattern>)>, pub typ: DestructType,
}
#[derive(Clone, Debug, PartialEq)]
pub enum DestructType {
Required,
Optional(Variable),
Guard(Variable, Located<Pattern>),
} }
pub fn symbols_from_pattern(pattern: &Pattern) -> Vec<Symbol> { pub fn symbols_from_pattern(pattern: &Pattern) -> Vec<Symbol> {
@ -253,7 +260,7 @@ pub fn canonicalize_pattern<'a>(
var: var_store.fresh(), var: var_store.fresh(),
label: Lowercase::from(label), label: Lowercase::from(label),
symbol, symbol,
guard: None, typ: DestructType::Required,
}, },
}); });
} }
@ -271,7 +278,8 @@ pub fn canonicalize_pattern<'a>(
} }
}; };
} }
RecordField(label, loc_guard) => {
RequiredField(label, loc_guard) => {
// a guard does not introduce the label into scope! // a guard does not introduce the label into scope!
let symbol = scope.ignore(label.into(), &mut env.ident_ids); let symbol = scope.ignore(label.into(), &mut env.ident_ids);
let can_guard = canonicalize_pattern( let can_guard = canonicalize_pattern(
@ -289,7 +297,7 @@ pub fn canonicalize_pattern<'a>(
var: var_store.fresh(), var: var_store.fresh(),
label: Lowercase::from(label), label: Lowercase::from(label),
symbol, symbol,
guard: Some((var_store.fresh(), can_guard)), typ: DestructType::Guard(var_store.fresh(), can_guard),
}, },
}); });
} }
@ -305,7 +313,8 @@ pub fn canonicalize_pattern<'a>(
destructs, destructs,
}) })
} }
RecordField(_name, _loc_pattern) => {
RequiredField(_name, _loc_pattern) | OptionalField(_name, _loc_pattern) => {
unreachable!("should have been handled in RecordDestructure"); unreachable!("should have been handled in RecordDestructure");
} }

View file

@ -248,7 +248,7 @@ impl<'a> Formattable<'a> for AssignedField<'a, TypeAnnotation<'a>> {
indent: u16, indent: u16,
) { ) {
// we abuse the `Newlines` type to decide between multiline or single-line layout // we abuse the `Newlines` type to decide between multiline or single-line layout
format_assigned_field_help(self, buf, parens, indent, " : ", newlines == Newlines::Yes); format_assigned_field_help(self, buf, parens, indent, " ", newlines == Newlines::Yes);
} }
} }
@ -265,7 +265,7 @@ impl<'a> Formattable<'a> for AssignedField<'a, Expr<'a>> {
indent: u16, indent: u16,
) { ) {
// we abuse the `Newlines` type to decide between multiline or single-line layout // we abuse the `Newlines` type to decide between multiline or single-line layout
format_assigned_field_help(self, buf, parens, indent, ": ", newlines == Newlines::Yes); format_assigned_field_help(self, buf, parens, indent, "", newlines == Newlines::Yes);
} }
} }
@ -273,7 +273,9 @@ fn is_multiline_assigned_field_help<'a, T: Formattable<'a>>(afield: &AssignedFie
use self::AssignedField::*; use self::AssignedField::*;
match afield { match afield {
LabeledValue(_, spaces, ann) => !spaces.is_empty() || ann.value.is_multiline(), RequiredValue(_, spaces, ann) | OptionalValue(_, spaces, ann) => {
!spaces.is_empty() || ann.value.is_multiline()
}
LabelOnly(_) => false, LabelOnly(_) => false,
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => true, AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => true,
Malformed(text) => text.chars().any(|c| c == '\n'), Malformed(text) => text.chars().any(|c| c == '\n'),
@ -285,7 +287,7 @@ fn format_assigned_field_help<'a, T>(
buf: &mut String<'a>, buf: &mut String<'a>,
parens: Parens, parens: Parens,
indent: u16, indent: u16,
separator: &str, separator_prefix: &str,
is_multiline: bool, is_multiline: bool,
) where ) where
T: Formattable<'a>, T: Formattable<'a>,
@ -293,7 +295,7 @@ fn format_assigned_field_help<'a, T>(
use self::AssignedField::*; use self::AssignedField::*;
match zelf { match zelf {
LabeledValue(name, spaces, ann) => { RequiredValue(name, spaces, ann) => {
if is_multiline { if is_multiline {
newline(buf, indent); newline(buf, indent);
} }
@ -304,7 +306,23 @@ fn format_assigned_field_help<'a, T>(
fmt_spaces(buf, spaces.iter(), indent); fmt_spaces(buf, spaces.iter(), indent);
} }
buf.push_str(separator); buf.push_str(separator_prefix);
buf.push(':');
ann.value.format(buf, indent);
}
OptionalValue(name, spaces, ann) => {
if is_multiline {
newline(buf, indent);
}
buf.push_str(name.value);
if !spaces.is_empty() {
fmt_spaces(buf, spaces.iter(), indent);
}
buf.push_str(separator_prefix);
buf.push('?');
ann.value.format(buf, indent); ann.value.format(buf, indent);
} }
LabelOnly(name) => { LabelOnly(name) => {
@ -316,10 +334,24 @@ fn format_assigned_field_help<'a, T>(
} }
AssignedField::SpaceBefore(sub_field, spaces) => { AssignedField::SpaceBefore(sub_field, spaces) => {
fmt_comments_only(buf, spaces.iter(), indent); fmt_comments_only(buf, spaces.iter(), indent);
format_assigned_field_help(sub_field, buf, parens, indent, separator, is_multiline); format_assigned_field_help(
sub_field,
buf,
parens,
indent,
separator_prefix,
is_multiline,
);
} }
AssignedField::SpaceAfter(sub_field, spaces) => { AssignedField::SpaceAfter(sub_field, spaces) => {
format_assigned_field_help(sub_field, buf, parens, indent, separator, is_multiline); format_assigned_field_help(
sub_field,
buf,
parens,
indent,
separator_prefix,
is_multiline,
);
fmt_comments_only(buf, spaces.iter(), indent); fmt_comments_only(buf, spaces.iter(), indent);
} }
Malformed(raw) => { Malformed(raw) => {

View file

@ -25,7 +25,9 @@ impl<'a> Formattable<'a> for Pattern<'a> {
Pattern::Nested(nested_pat) => nested_pat.is_multiline(), Pattern::Nested(nested_pat) => nested_pat.is_multiline(),
Pattern::RecordDestructure(fields) => fields.iter().any(|f| f.is_multiline()), Pattern::RecordDestructure(fields) => fields.iter().any(|f| f.is_multiline()),
Pattern::RecordField(_, subpattern) => subpattern.is_multiline(), Pattern::RequiredField(_, subpattern) | Pattern::OptionalField(_, subpattern) => {
subpattern.is_multiline()
}
Pattern::Identifier(_) Pattern::Identifier(_)
| Pattern::GlobalTag(_) | Pattern::GlobalTag(_)
@ -92,12 +94,18 @@ impl<'a> Formattable<'a> for Pattern<'a> {
buf.push_str(" }"); buf.push_str(" }");
} }
RecordField(name, loc_pattern) => { RequiredField(name, loc_pattern) => {
buf.push_str(name); buf.push_str(name);
buf.push_str(": "); buf.push_str(": ");
loc_pattern.format(buf, indent); loc_pattern.format(buf, indent);
} }
OptionalField(name, loc_pattern) => {
buf.push_str(name);
buf.push_str(" ? ");
loc_pattern.format(buf, indent);
}
NumLiteral(string) => buf.push_str(string), NumLiteral(string) => buf.push_str(string),
NonBase10Literal { NonBase10Literal {
base, base,