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 } } }