mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Change guard to DestructType
This commit is contained in:
parent
85f51ef39d
commit
8b53ec15fe
4 changed files with 69 additions and 16 deletions
|
@ -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!");
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue