use serde::{Deserialize, Serialize};
use crate::model::names::RecordName;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ArgShape {
Variable,
Atom { name: String },
Integer,
Float,
Binary,
List,
Tuple { size: usize },
Record { name: RecordName },
String,
Fun,
Unknown,
}
impl ArgShape {
pub fn satisfies(&self, pattern: &ArgShape) -> bool {
if matches!(self, ArgShape::Unknown) || matches!(pattern, ArgShape::Unknown) {
return true;
}
if matches!(self, ArgShape::Variable) || matches!(pattern, ArgShape::Variable) {
return true;
}
match (self, pattern) {
(ArgShape::Atom { name: a }, ArgShape::Atom { name: b }) => a == b,
(ArgShape::Tuple { size: a }, ArgShape::Tuple { size: b }) => a == b,
(ArgShape::Record { name: a }, ArgShape::Record { name: b }) => a == b,
(ArgShape::Integer, ArgShape::Integer)
| (ArgShape::Float, ArgShape::Float)
| (ArgShape::Binary, ArgShape::Binary)
| (ArgShape::List, ArgShape::List)
| (ArgShape::String, ArgShape::String)
| (ArgShape::Fun, ArgShape::Fun) => true,
_ => false,
}
}
}
pub fn satisfies_any(args: &[ArgShape], clauses: &[Vec<ArgShape>]) -> bool {
if clauses.is_empty() {
return true;
}
clauses.iter().any(|clause| {
clause.len() == args.len()
&& args
.iter()
.zip(clause.iter())
.all(|(actual, pattern)| actual.satisfies(pattern))
})
}