mini_kanren/core/
structure.rs1use crate::core::logic_variable::{ReifiedVar, Var};
4use crate::core::substitution::Substitution;
5use crate::core::value::Value;
6use std::any::Any;
7use std::rc::Rc;
8use std::sync::Arc;
9
10pub trait Structure: std::any::Any + std::fmt::Debug {
12 fn occurs<'s>(&self, x: &Var, s: &Substitution<'s>) -> bool;
15
16 fn unify<'s>(&self, v: &Value, s: Substitution<'s>) -> Option<Substitution<'s>>;
18
19 fn walk_star(self: Arc<Self>, s: &Substitution<'_>) -> Value;
22
23 fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s>;
25
26 fn as_any(&self) -> &dyn Any;
28
29 fn eqv(&self, other: &Value) -> bool;
31}
32
33impl Structure for Var {
34 fn occurs<'s>(&self, x: &Var, _s: &Substitution<'s>) -> bool {
35 self == x
36 }
37
38 fn unify<'s>(&self, v: &Value, s: Substitution<'s>) -> Option<Substitution<'s>> {
39 if let Some(var) = v.try_as_var() {
40 if self == &var {
41 return Some(s);
42 }
43 }
44
45 let v = v.clone();
46 s.extend(*self, v)
47 }
48
49 fn walk_star(self: Arc<Self>, _: &Substitution<'_>) -> Value {
50 Value::var(*self)
51 }
52
53 fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s> {
54 let reified = Value::new(ReifiedVar(s.n_subs()));
55 s.extend(*self, reified).unwrap()
56 }
57
58 fn as_any(&self) -> &dyn Any {
59 self
60 }
61
62 fn eqv(&self, other: &Value) -> bool {
63 other
64 .downcast_ref::<Self>()
65 .map(|v| v == self)
66 .unwrap_or(false)
67 }
68}
69
70impl Structure for ReifiedVar {
71 fn occurs<'s>(&self, _x: &Var, _s: &Substitution<'s>) -> bool {
72 false
73 }
74
75 fn unify<'s>(&self, _v: &Value, _s: Substitution<'s>) -> Option<Substitution<'s>> {
76 unimplemented!()
77 }
78
79 fn walk_star(self: Arc<Self>, _: &Substitution<'_>) -> Value {
80 Value::from_arc(self)
81 }
82
83 fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s> {
84 s
85 }
86
87 fn as_any(&self) -> &dyn Any {
88 self
89 }
90
91 fn eqv(&self, other: &Value) -> bool {
92 other
93 .downcast_ref::<Self>()
94 .map(|v| v == self)
95 .unwrap_or(false)
96 }
97}
98
99impl Structure for Option<Value> {
100 fn occurs<'s>(&self, x: &Var, s: &Substitution<'s>) -> bool {
101 match self {
102 Some(v) => s.occurs(x, v),
103 None => false,
104 }
105 }
106
107 fn unify<'s>(&self, v: &Value, s: Substitution<'s>) -> Option<Substitution<'s>> {
108 let other = v.downcast_ref::<Self>()?;
109 match (self, other) {
110 (Some(su), Some(sv)) => s.unify(su, sv),
111 (None, None) => Some(s),
112 _ => None,
113 }
114 }
115
116 fn walk_star(self: Arc<Self>, s: &Substitution<'_>) -> Value {
117 match &*self {
118 None => Value::from_arc(self),
119 Some(v) => s.walk_star(v),
120 }
121 }
122
123 fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s> {
124 match &*self {
125 None => s,
126 Some(v) => s.reify_s(v),
127 }
128 }
129
130 fn as_any(&self) -> &dyn Any {
131 self
132 }
133
134 fn eqv(&self, other: &Value) -> bool {
135 other
136 .downcast_ref::<Self>()
137 .map(|v| v == self)
138 .unwrap_or(false)
139 }
140}
141
142impl<T: 'static + Atomic + PartialEq> Structure for T {
143 fn occurs<'s>(&self, _x: &Var, _s: &Substitution<'s>) -> bool {
144 false
145 }
146
147 fn unify<'s>(&self, v: &Value, s: Substitution<'s>) -> Option<Substitution<'s>> {
148 if self.eqv(v) {
149 Some(s)
150 } else {
151 None
152 }
153 }
154
155 fn walk_star(self: Arc<Self>, _: &Substitution<'_>) -> Value {
156 Value::from_arc(self)
157 }
158
159 fn reify_s<'s>(&self, s: Substitution<'s>) -> Substitution<'s> {
160 s
161 }
162
163 fn as_any(&self) -> &dyn Any {
164 self
165 }
166
167 fn eqv(&self, other: &Value) -> bool {
168 other
169 .downcast_ref::<Self>()
170 .map(|o| o == self)
171 .unwrap_or(false)
172 }
173}
174
175pub trait Atomic: std::fmt::Debug {}
177
178impl Atomic for () {}
179
180impl Atomic for bool {}
181
182impl Atomic for u8 {}
183
184impl Atomic for u16 {}
185
186impl Atomic for u32 {}
187
188impl Atomic for u64 {}
189
190impl Atomic for u128 {}
191
192impl Atomic for i8 {}
193
194impl Atomic for i16 {}
195
196impl Atomic for i32 {}
197
198impl Atomic for i64 {}
199
200impl Atomic for i128 {}
201
202impl Atomic for char {}
203
204impl Atomic for f64 {}
205
206impl Atomic for f32 {}
207
208impl Atomic for String {}
209
210impl Atomic for &str {}
211
212impl<T: Atomic> Atomic for Option<T> {}
213impl<T: Atomic> Atomic for Box<T> {}
214impl<T: Atomic> Atomic for Arc<T> {}
215impl<T: Atomic> Atomic for Rc<T> {}