From c4ee47647a5bf1a06ae88ebb9410117c927868ee Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Mon, 12 Oct 2026 01:31:00 -0400 Subject: Major refactor, generate relation traits with macros --- crates/elfmind/src/knowledge/traits.rs | 273 +++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 crates/elfmind/src/knowledge/traits.rs (limited to 'crates/elfmind/src/knowledge/traits.rs') diff --git a/crates/elfmind/src/knowledge/traits.rs b/crates/elfmind/src/knowledge/traits.rs new file mode 100644 index 0000000..6db9250 --- /dev/null +++ b/crates/elfmind/src/knowledge/traits.rs @@ -0,0 +1,273 @@ +use crate::knowledge::*; + +pub trait DisplayNoun { + fn display_noun(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result; +} + +pub trait DisplayTuple { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result; +} +impl DisplayTuple for A { + // display any single noun as a 1-tuple + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.display_noun(f)?; + write!(f, ")") + } +} +impl DisplayTuple for (A, B) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; + write!(f, ")") + } +} +impl DisplayTuple for (A, B, C) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; write!(f, ", ")?; + self.2.display_noun(f)?; + write!(f, ")") + } +} +impl DisplayTuple for (A, B, C, D) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; write!(f, ", ")?; + self.2.display_noun(f)?; write!(f, ", ")?; + self.3.display_noun(f)?; + write!(f, ")") + } +} +impl DisplayTuple for (A, B, C, D, E) { + fn display_tuple(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + self.0.display_noun(f)?; write!(f, ", ")?; + self.1.display_noun(f)?; write!(f, ", ")?; + self.2.display_noun(f)?; write!(f, ", ")?; + self.3.display_noun(f)?; write!(f, ", ")?; + self.4.display_noun(f)?; + write!(f, ")") + } +} + +pub trait Concretizable { + type Concrete; + fn concretize(&self) -> Option; +} +impl Concretizable for Hole { + type Concrete = A; + fn concretize(&self) -> Option { + match self { + Self::Val(x) => Some(x.clone()), + _ => None, + } + } +} +impl< + A: Clone, + B: Clone, + > Concretizable for (Hole, Hole) { + type Concrete = (A, B); + fn concretize(&self) -> Option { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + Some((a, b)) + } +} +impl< + A: Clone, + B: Clone, + C: Clone, + > Concretizable for (Hole, Hole, Hole) { + type Concrete = (A, B, C); + fn concretize(&self) -> Option { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + let c = self.2.concretize()?; + Some((a, b, c)) + } +} +impl< + A: Clone, + B: Clone, + C: Clone, + D: Clone, + > Concretizable for (Hole, Hole, Hole, Hole) { + type Concrete = (A, B, C, D); + fn concretize(&self) -> Option { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + let c = self.2.concretize()?; + let d = self.3.concretize()?; + Some((a, b, c, d)) + } +} +impl< + A: Clone, + B: Clone, + C: Clone, + D: Clone, + E: Clone, + > Concretizable for (Hole, Hole, Hole, Hole, Hole) { + type Concrete = (A, B, C, D, E); + fn concretize(&self) -> Option { + let a = self.0.concretize()?; + let b = self.1.concretize()?; + let c = self.2.concretize()?; + let d = self.3.concretize()?; + let e = self.4.concretize()?; + Some((a, b, c, d, e)) + } +} + +pub trait Substitutable { + fn substitute(&self, u: &Unification) -> Self; + fn map_variables(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var; +} +impl> Substitutable for Hole { + 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(), + } + } + fn map_variables(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + match self { + Self::Var(v) => Self::Var(f(*v)), + x => x.clone(), + } + } +} +impl< + A: Clone + TryFrom, + B: Clone + TryFrom + > Substitutable for (Hole, Hole) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b) = self; + (a.substitute(u), b.substitute(u)) + } + fn map_variables(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b) = self; + (a.map_variables(f), b.map_variables(f)) + } +} +impl< + A: Clone + TryFrom, + B: Clone + TryFrom, + C: Clone + TryFrom, + > Substitutable for (Hole, Hole, Hole) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c) = self; + (a.substitute(u), b.substitute(u), c.substitute(u)) + } + fn map_variables(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b, c) = self; + (a.map_variables(f), b.map_variables(f), c.map_variables(f)) + } +} +impl< + A: Clone + TryFrom, + B: Clone + TryFrom, + C: Clone + TryFrom, + D: Clone + TryFrom, + > Substitutable for (Hole, Hole, Hole, Hole) { + fn substitute(&self, u: &Unification) -> Self { + let (a, b, c, d) = self; + (a.substitute(u), b.substitute(u), c.substitute(u), d.substitute(u)) + } + fn map_variables(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b, c, d) = self; + (a.map_variables(f), b.map_variables(f), c.map_variables(f), d.map_variables(f)) + } +} +impl< + A: Clone + TryFrom, + B: Clone + TryFrom, + C: Clone + TryFrom, + D: Clone + TryFrom, + E: Clone + TryFrom, + > Substitutable for (Hole, Hole, Hole, Hole, Hole) { + 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)) + } + fn map_variables(&self, f: &mut F) -> Self where F: FnMut(Var) -> Var { + let (a, b, c, d, e) = self; + (a.map_variables(f), b.map_variables(f), c.map_variables(f), d.map_variables(f), e.map_variables(f)) + } +} + +pub trait Unifiable: Concretizable { + fn unify(&self, other: &Self::Concrete, u: Unification) -> Option; +} +impl Unifiable for Hole where + Noun: From, A: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option { + if u.unify_hole(self, other) { + Some(u) + } else { None } + } +} +impl Unifiable for (Hole, Hole) where + Noun: From, A: Copy, + Noun: From, B: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option { + let (a1, b1) = self; + let (a2, b2) = other; + if u.unify_hole(a1, a2) && u.unify_hole(b1, b2) { + Some(u) + } else { None } + } +} +impl Unifiable for (Hole, Hole, Hole) where + Noun: From, A: Copy, + Noun: From, B: Copy, + Noun: From, C: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option { + 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 Unifiable for (Hole, Hole, Hole, Hole) where + Noun: From, A: Copy, + Noun: From, B: Copy, + Noun: From, C: Copy, + Noun: From, D: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option { + 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 Unifiable for (Hole, Hole, Hole, Hole, Hole) where + Noun: From, A: Copy, + Noun: From, B: Copy, + Noun: From, C: Copy, + Noun: From, D: Copy, + Noun: From, E: Copy, +{ + fn unify(&self, other: &Self::Concrete, mut u: Unification) -> Option { + 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 } + } +} -- cgit v1.3.1