mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Merge pull request #4616 from roc-lang/fix-pattern-equivalent
Fix missing cases in Pattern::equivalent
This commit is contained in:
commit
a0bc105ca8
1 changed files with 158 additions and 54 deletions
|
@ -773,69 +773,173 @@ impl<'a> Pattern<'a> {
|
||||||
pub fn equivalent(&self, other: &Self) -> bool {
|
pub fn equivalent(&self, other: &Self) -> bool {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
|
|
||||||
match (self, other) {
|
match other {
|
||||||
(Identifier(x), Identifier(y)) => x == y,
|
SpaceBefore(y, _) | SpaceAfter(y, _) => {
|
||||||
(Tag(x), Tag(y)) => x == y,
|
return self.equivalent(y);
|
||||||
(Apply(constructor_x, args_x), Apply(constructor_y, args_y)) => {
|
}
|
||||||
let equivalent_args = args_x
|
_ => {}
|
||||||
.iter()
|
}
|
||||||
.zip(args_y.iter())
|
|
||||||
.all(|(p, q)| p.value.equivalent(&q.value));
|
|
||||||
|
|
||||||
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
match self {
|
||||||
|
Tag(x) => {
|
||||||
|
if let Tag(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(RecordDestructure(fields_x), RecordDestructure(fields_y)) => fields_x
|
Apply(constructor_x, args_x) => {
|
||||||
.iter()
|
if let Apply(constructor_y, args_y) = other {
|
||||||
.zip(fields_y.iter())
|
let equivalent_args = args_x
|
||||||
.all(|(p, q)| p.value.equivalent(&q.value)),
|
.iter()
|
||||||
(RequiredField(x, inner_x), RequiredField(y, inner_y)) => {
|
.zip(args_y.iter())
|
||||||
x == y && inner_x.value.equivalent(&inner_y.value)
|
.all(|(p, q)| p.value.equivalent(&q.value));
|
||||||
|
|
||||||
|
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(OptionalField(x, _), OptionalField(y, _))
|
RecordDestructure(fields_x) => {
|
||||||
| (OptionalField(x, _), Identifier(y))
|
if let RecordDestructure(fields_y) = other {
|
||||||
| (Identifier(x), OptionalField(y, _)) => {
|
fields_x
|
||||||
// optional record fields can be annotated as:
|
.iter()
|
||||||
// { x, y } : { x : Int, y ? Bool }
|
.zip(fields_y.iter())
|
||||||
// { x, y ? False } = rec
|
.all(|(p, q)| p.value.equivalent(&q.value))
|
||||||
x == y
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Literal
|
RequiredField(x, inner_x) => {
|
||||||
(NumLiteral(x), NumLiteral(y)) => x == y,
|
if let RequiredField(y, inner_y) = other {
|
||||||
(
|
x == y && inner_x.value.equivalent(&inner_y.value)
|
||||||
NonBase10Literal {
|
} else {
|
||||||
string: string_x,
|
false
|
||||||
base: base_x,
|
}
|
||||||
is_negative: is_negative_x,
|
}
|
||||||
},
|
|
||||||
NonBase10Literal {
|
// optional record fields can be annotated as:
|
||||||
|
// { x, y } : { x : Int, y ? Bool }
|
||||||
|
// { x, y ? False } = rec
|
||||||
|
OptionalField(x, _) => match other {
|
||||||
|
Identifier(y) | OptionalField(y, _) => x == y,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
Identifier(x) => match other {
|
||||||
|
Identifier(y) | OptionalField(y, _) => x == y,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
NumLiteral(x) => {
|
||||||
|
if let NumLiteral(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NonBase10Literal {
|
||||||
|
string: string_x,
|
||||||
|
base: base_x,
|
||||||
|
is_negative: is_negative_x,
|
||||||
|
} => {
|
||||||
|
if let NonBase10Literal {
|
||||||
string: string_y,
|
string: string_y,
|
||||||
base: base_y,
|
base: base_y,
|
||||||
is_negative: is_negative_y,
|
is_negative: is_negative_y,
|
||||||
},
|
} = other
|
||||||
) => string_x == string_y && base_x == base_y && is_negative_x == is_negative_y,
|
{
|
||||||
(FloatLiteral(x), FloatLiteral(y)) => x == y,
|
string_x == string_y && base_x == base_y && is_negative_x == is_negative_y
|
||||||
(StrLiteral(x), StrLiteral(y)) => x == y,
|
} else {
|
||||||
(Underscore(x), Underscore(y)) => x == y,
|
false
|
||||||
|
}
|
||||||
// Space
|
}
|
||||||
(SpaceBefore(x, _), SpaceBefore(y, _)) => x.equivalent(y),
|
FloatLiteral(x) => {
|
||||||
(SpaceAfter(x, _), SpaceAfter(y, _)) => x.equivalent(y),
|
if let FloatLiteral(y) = other {
|
||||||
|
x == y
|
||||||
// Malformed
|
} else {
|
||||||
(Malformed(x), Malformed(y)) => x == y,
|
false
|
||||||
(
|
}
|
||||||
QualifiedIdentifier {
|
}
|
||||||
module_name: a,
|
StrLiteral(x) => {
|
||||||
ident: x,
|
if let StrLiteral(y) = other {
|
||||||
},
|
x == y
|
||||||
QualifiedIdentifier {
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Underscore(x) => {
|
||||||
|
if let Underscore(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SpaceBefore(x, _) | SpaceAfter(x, _) => match other {
|
||||||
|
SpaceBefore(y, _) | SpaceAfter(y, _) => x.equivalent(y),
|
||||||
|
y => x.equivalent(y),
|
||||||
|
},
|
||||||
|
Malformed(x) => {
|
||||||
|
if let Malformed(y) = other {
|
||||||
|
x == y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QualifiedIdentifier {
|
||||||
|
module_name: a,
|
||||||
|
ident: x,
|
||||||
|
} => {
|
||||||
|
if let QualifiedIdentifier {
|
||||||
module_name: b,
|
module_name: b,
|
||||||
ident: y,
|
ident: y,
|
||||||
},
|
} = other
|
||||||
) => (a == b) && (x == y),
|
{
|
||||||
|
a == b && x == y
|
||||||
// Different constructors
|
} else {
|
||||||
_ => false,
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpaqueRef(a) => {
|
||||||
|
if let OpaqueRef(b) = other {
|
||||||
|
a == b
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SingleQuote(a) => {
|
||||||
|
if let SingleQuote(b) = other {
|
||||||
|
a == b
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tuple(items_x) => {
|
||||||
|
if let Tuple(items_y) = other {
|
||||||
|
items_x
|
||||||
|
.iter()
|
||||||
|
.zip(items_y.iter())
|
||||||
|
.all(|(p, q)| p.value.equivalent(&q.value))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List(items_x) => {
|
||||||
|
if let List(items_y) = other {
|
||||||
|
items_x
|
||||||
|
.iter()
|
||||||
|
.zip(items_y.iter())
|
||||||
|
.all(|(p, q)| p.value.equivalent(&q.value))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListRest => matches!(other, ListRest),
|
||||||
|
MalformedIdent(str_x, _) => {
|
||||||
|
if let MalformedIdent(str_y, _) = other {
|
||||||
|
str_x == str_y
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue