46 lines
1.0 KiB
Rust
46 lines
1.0 KiB
Rust
use std::collections::LinkedList;
|
|
|
|
use crate::{token::Literal, join};
|
|
|
|
use super::{Identifier, value::Value};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum Pattern {
|
|
Literal(Literal),
|
|
Binding(Identifier),
|
|
Variant(Identifier, Vec<Pattern>),
|
|
Universal,
|
|
}
|
|
|
|
impl Pattern {
|
|
pub fn matches<'a, 'b>(&'a self, value: &'b Value) -> Option<LinkedList<(&'a Identifier, &'b Value)>> {
|
|
match (value, self) {
|
|
(Value::Int(x1), Pattern::Literal(Literal::Int(x2))) =>
|
|
if *x1 as u64 == *x2 {
|
|
Some(LinkedList::new())
|
|
} else {
|
|
None
|
|
},
|
|
(Value::Structural(ident1, values1), Pattern::Variant(ident2, patterns2)) =>
|
|
if ident1 == ident2 && values1.len() == patterns2.len() {
|
|
values1.into_iter()
|
|
.zip(patterns2)
|
|
.fold(Some(LinkedList::new()), |bindings, (v1, p2)|
|
|
bindings.and_then(|bindings|
|
|
p2.matches(v1).map(|new_bindings|
|
|
join(
|
|
bindings,
|
|
new_bindings,
|
|
)
|
|
)
|
|
)
|
|
)
|
|
} else {
|
|
None
|
|
},
|
|
(_, Pattern::Universal) => Some(LinkedList::new()),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|