diff options
| author | LLLL Colonq <llll@colonq> | 2026-09-11 15:47:34 -0400 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2026-09-11 15:47:34 -0400 |
| commit | 09ff5f929853cc2ba1a1ed7ddb20566cd8fe021d (patch) | |
| tree | 19738908beef19315def760c9e85e42536cbda7a /crates/elfmind/src/knowledge/relation.rs | |
| parent | ed7819a3c3139a2caaf4e9bcdf0a968b8d3b0069 (diff) | |
More Datalog
Diffstat (limited to 'crates/elfmind/src/knowledge/relation.rs')
| -rw-r--r-- | crates/elfmind/src/knowledge/relation.rs | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/crates/elfmind/src/knowledge/relation.rs b/crates/elfmind/src/knowledge/relation.rs new file mode 100644 index 0000000..754bf0f --- /dev/null +++ b/crates/elfmind/src/knowledge/relation.rs @@ -0,0 +1,163 @@ +use super::{Value, Hole, Unification}; + +use crate::time::*; +use crate::item::*; +use crate::character::*; + +use enum_map::Enum; +use strum::EnumDiscriminants; + +pub trait Substitutable { + fn substitute(&self, u: &Unification) -> Self; +} +impl<A: Clone + TryFrom<Value>> Substitutable for Hole<A> { + fn substitute(&self, u: &Unification) -> Self { + match self { + x@Self::Var(v) => if let Some(y) = u.lookup(v) && let Ok(z) = A::try_from(y) { + Hole::Val(z) + } else { + x.clone() + } + x => x.clone(), + } + } +} +impl< + A: Clone + TryFrom<Value>, + B: Clone + TryFrom<Value> + > Substitutable for (Hole<A>, Hole<B>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b) = self; + (a.substitute(u), b.substitute(u)) + } +} +impl< + A: Clone + TryFrom<Value>, + B: Clone + TryFrom<Value>, + C: Clone + TryFrom<Value>, + > Substitutable for (Hole<A>, Hole<B>, Hole<C>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c) = self; + (a.substitute(u), b.substitute(u), c.substitute(u)) + } +} +impl< + A: Clone + TryFrom<Value>, + B: Clone + TryFrom<Value>, + C: Clone + TryFrom<Value>, + D: Clone + TryFrom<Value>, + > Substitutable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c, d) = self; + (a.substitute(u), b.substitute(u), c.substitute(u), d.substitute(u)) + } +} +impl< + A: Clone + TryFrom<Value>, + B: Clone + TryFrom<Value>, + C: Clone + TryFrom<Value>, + D: Clone + TryFrom<Value>, + E: Clone + TryFrom<Value>, + > Substitutable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>, Hole<E>) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c, d, e) = self; + (a.substitute(u), b.substitute(u), c.substitute(u), d.substitute(u), e.substitute(u)) + } +} + +pub trait Unifiable { + fn unify(&self, other: &Self, u: Unification) -> Option<Unification>; +} +impl<A> Unifiable for Hole<A> where + Value: From<A>, A: Copy, +{ + fn unify(&self, other: &Self, mut u: Unification) -> Option<Unification> { + if u.unify_hole(self, other) { + Some(u) + } else { None } + } +} +impl<A, B> Unifiable for (Hole<A>, Hole<B>) where + Value: From<A>, A: Copy, + Value: From<B>, B: Copy, +{ + fn unify(&self, other: &Self, mut u: Unification) -> Option<Unification> { + let (a1, b1) = self; + let (a2, b2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) { + Some(u) + } else { None } + } +} +impl<A, B, C> Unifiable for (Hole<A>, Hole<B>, Hole<C>) where + Value: From<A>, A: Copy, + Value: From<B>, B: Copy, + Value: From<C>, C: Copy, +{ + fn unify(&self, other: &Self, mut u: Unification) -> Option<Unification> { + let (a1, b1, c1) = self; + let (a2, b2, c2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) && u.unify_hole(c1, c2) { + Some(u) + } else { None } + } +} +impl<A, B, C, D> Unifiable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>) where + Value: From<A>, A: Copy, + Value: From<B>, B: Copy, + Value: From<C>, C: Copy, + Value: From<D>, D: Copy, +{ + fn unify(&self, other: &Self, mut u: Unification) -> Option<Unification> { + let (a1, b1, c1, d1) = self; + let (a2, b2, c2, d2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) && u.unify_hole(c1, c2) && u.unify_hole(d1, d2) { + Some(u) + } else { None } + } +} +impl<A, B, C, D, E> Unifiable for (Hole<A>, Hole<B>, Hole<C>, Hole<D>, Hole<E>) where + Value: From<A>, A: Copy, + Value: From<B>, B: Copy, + Value: From<C>, C: Copy, + Value: From<D>, D: Copy, + Value: From<E>, E: Copy, +{ + fn unify(&self, other: &Self, mut u: Unification) -> Option<Unification> { + let (a1, b1, c1, d1, e1) = self; + let (a2, b2, c2, d2, e2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) && u.unify_hole(c1, c2) && u.unify_hole(d1, d2) && u.unify_hole(e1, e2) { + Some(u) + } else { None } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, EnumDiscriminants)] +#[strum_discriminants(derive(Enum))] +pub enum Relation { + HasItem((Hole<Character>, Hole<Item>)), + UsedItemAt((Hole<Character>, Hole<Item>, Hole<Time>)), + TimeIs(Hole<Time>), + FriendOf((Hole<Character>, Hole<Character>)), +} +impl Substitutable for Relation { + fn substitute(&self, u: &Unification) -> Self { + match self { + Self::HasItem(x) => Self::HasItem(x.substitute(u)), + Self::UsedItemAt(x) => Self::UsedItemAt(x.substitute(u)), + Self::TimeIs(x) => Self::TimeIs(x.substitute(u)), + Self::FriendOf(x) => Self::FriendOf(x.substitute(u)), + } + } +} +impl Unifiable for Relation { + fn unify(&self, other: &Self, u: Unification) -> Option<Unification> { + match (self, other) { + (Self::HasItem(a), Self::HasItem(b)) => a.unify(b, u), + (Self::UsedItemAt(a), Self::UsedItemAt(b)) => a.unify(b, u), + (Self::TimeIs(a), Self::TimeIs(b)) => a.unify(b, u), + (Self::FriendOf(a), Self::FriendOf(b)) => a.unify(b, u), + _ => None, + } + } +} |
