Skip to main content

formality_core/
substitution.rs

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    /// Returns the variables that will be substituted for a new value.
17    pub fn domain(&self) -> Set<CoreVariable<L>> {
18        self.map.keys().cloned().collect()
19    }
20
21    /// Returns the parameters that that will be substituted for a new value.
22    pub fn range(&self) -> Set<CoreParameter<L>> {
23        self.map.values().cloned().collect()
24    }
25
26    /// True if `v` is in this substitution's domain
27    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    /// An empty substitution is just the identity function.
36    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/// A substitution that is only between variables.
160/// These are reversible.
161#[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}