1use crate::{
2 cast::{Upcast, UpcastFrom},
3 collections::{Map, Set},
4 fold::CoreFold,
5 language::{CoreParameter, Language},
6 variable::CoreVariable,
7 visit::CoreVisit,
8};
9
10#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct CoreSubstitution<L: Language> {
12 map: Map<CoreVariable<L>, CoreParameter<L>>,
13}
14
15impl<L: Language> CoreSubstitution<L> {
16 pub fn domain(&self) -> Set<CoreVariable<L>> {
18 self.map.keys().cloned().collect()
19 }
20
21 pub fn range(&self) -> Set<CoreParameter<L>> {
23 self.map.values().cloned().collect()
24 }
25
26 pub fn maps(&self, v: CoreVariable<L>) -> bool {
28 self.map.contains_key(&v)
29 }
30
31 pub fn iter(&self) -> impl Iterator<Item = (CoreVariable<L>, CoreParameter<L>)> + '_ {
32 self.map.iter().map(|(v, p)| (*v, p.clone()))
33 }
34
35 pub fn is_empty(&self) -> bool {
37 self.map.is_empty()
38 }
39}
40
41impl<L: Language> std::fmt::Debug for CoreSubstitution<L> {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 let mut f = f.debug_set();
44 for (v, p) in self.iter() {
45 f.entry(&Entry { v, p });
46 struct Entry<L: Language> {
47 v: CoreVariable<L>,
48 p: CoreParameter<L>,
49 }
50 impl<L: Language> std::fmt::Debug for Entry<L> {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{:?} => {:?}", self.v, self.p)
53 }
54 }
55 }
56 f.finish()
57 }
58}
59
60impl<L: Language, Vs> std::ops::SubAssign<Vs> for CoreSubstitution<L>
61where
62 Vs: Upcast<Vec<CoreVariable<L>>>,
63{
64 fn sub_assign(&mut self, rhs: Vs) {
65 let rhs: Vec<CoreVariable<L>> = rhs.upcast();
66
67 for v in rhs {
68 self.map.remove(&v);
69 }
70 }
71}
72
73impl<L: Language> IntoIterator for CoreSubstitution<L> {
74 type Item = (CoreVariable<L>, CoreParameter<L>);
75
76 type IntoIter = std::collections::btree_map::IntoIter<CoreVariable<L>, CoreParameter<L>>;
77
78 fn into_iter(self) -> Self::IntoIter {
79 self.map.into_iter()
80 }
81}
82
83impl<L: Language, A, B> Extend<(A, B)> for CoreSubstitution<L>
84where
85 A: Upcast<CoreVariable<L>>,
86 B: Upcast<CoreParameter<L>>,
87{
88 fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, iter: T) {
89 self.map
90 .extend(iter.into_iter().map(|(v, p)| (v.upcast(), p.upcast())));
91 }
92}
93
94impl<L: Language, A, B> FromIterator<(A, B)> for CoreSubstitution<L>
95where
96 A: Upcast<CoreVariable<L>>,
97 B: Upcast<CoreParameter<L>>,
98{
99 fn from_iter<T: IntoIterator<Item = (A, B)>>(iter: T) -> Self {
100 let mut s = CoreSubstitution::default();
101 s.extend(iter);
102 s
103 }
104}
105
106impl<L: Language, A, B> UpcastFrom<(A, B)> for CoreSubstitution<L>
107where
108 A: Upcast<CoreVariable<L>>,
109 B: Upcast<CoreParameter<L>>,
110{
111 fn upcast_from(term: (A, B)) -> Self {
112 let term: (CoreVariable<L>, CoreParameter<L>) = term.upcast();
113 std::iter::once(term).collect()
114 }
115}
116
117impl<L: Language> CoreSubstitution<L> {
118 pub fn apply<T: CoreFold<L>>(&self, t: &T) -> T {
119 t.substitute(&mut |v| self.map.get(&v).cloned())
120 }
121
122 pub fn get(&self, v: CoreVariable<L>) -> Option<CoreParameter<L>> {
123 self.map.get(&v).cloned()
124 }
125}
126
127impl<L: Language> CoreFold<L> for CoreSubstitution<L> {
128 fn substitute(&self, substitution_fn: crate::fold::SubstitutionFn<'_, L>) -> Self {
129 self.iter()
130 .map(|(v, p)| (v, p.substitute(substitution_fn)))
131 .collect()
132 }
133}
134
135impl<L: Language> CoreVisit<L> for CoreSubstitution<L> {
136 fn free_variables(&self) -> Vec<CoreVariable<L>> {
137 let mut v = self.range().free_variables();
138 v.extend(self.domain());
139 v
140 }
141
142 fn size(&self) -> usize {
143 self.range().iter().map(|r| r.size()).sum()
144 }
145
146 fn assert_valid(&self) {
147 self.range().assert_valid()
148 }
149}
150
151impl<L: Language> std::ops::Index<CoreVariable<L>> for CoreSubstitution<L> {
152 type Output = CoreParameter<L>;
153
154 fn index(&self, index: CoreVariable<L>) -> &Self::Output {
155 &self.map[&index]
156 }
157}
158
159#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
162pub struct CoreVarSubstitution<L: Language> {
163 map: Map<CoreVariable<L>, CoreVariable<L>>,
164}
165
166impl<L, A, B> Extend<(A, B)> for CoreVarSubstitution<L>
167where
168 L: Language,
169 A: Upcast<CoreVariable<L>>,
170 B: Upcast<CoreVariable<L>>,
171{
172 fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, iter: T) {
173 self.map
174 .extend(iter.into_iter().map(|(v, p)| (v.upcast(), p.upcast())));
175 }
176}
177
178impl<L, A, B> FromIterator<(A, B)> for CoreVarSubstitution<L>
179where
180 L: Language,
181 A: Upcast<CoreVariable<L>>,
182 B: Upcast<CoreVariable<L>>,
183{
184 fn from_iter<T: IntoIterator<Item = (A, B)>>(iter: T) -> Self {
185 let mut s = CoreVarSubstitution::default();
186 s.extend(iter);
187 s
188 }
189}
190
191impl<L: Language> CoreVarSubstitution<L> {
192 pub fn reverse(&self) -> CoreVarSubstitution<L> {
193 self.map.iter().map(|(k, v)| (*v, *k)).collect()
194 }
195
196 pub fn apply<T: CoreFold<L>>(&self, t: &T) -> T {
197 t.substitute(&mut |v| Some(self.map.get(&v)?.upcast()))
198 }
199
200 pub fn map_var(&self, v: CoreVariable<L>) -> Option<CoreVariable<L>> {
201 self.map.get(&v).copied()
202 }
203
204 pub fn maps_var(&self, v: CoreVariable<L>) -> bool {
205 self.map.contains_key(&v)
206 }
207
208 pub fn insert_mapping(
209 &mut self,
210 from: impl Upcast<CoreVariable<L>>,
211 to: impl Upcast<CoreVariable<L>>,
212 ) {
213 let x = self.map.insert(from.upcast(), to.upcast());
214 assert!(x.is_none());
215 }
216}