formality_core/
variable.rs1use crate::cast::Upcast;
2use crate::language::CoreKind;
3use crate::language::Language;
4use crate::visit::CoreVisit;
5
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub enum CoreVariable<L: Language> {
9 UniversalVar(CoreUniversalVar<L>),
16
17 ExistentialVar(CoreExistentialVar<L>),
24
25 BoundVar(CoreBoundVar<L>),
28}
29
30impl<L: Language> CoreVariable<L> {
31 pub fn kind(&self) -> CoreKind<L> {
32 match self {
33 CoreVariable::UniversalVar(v) => v.kind,
34 CoreVariable::ExistentialVar(v) => v.kind,
35 CoreVariable::BoundVar(v) => v.kind,
36 }
37 }
38
39 pub fn shift_in(&self) -> Self {
42 if let CoreVariable::BoundVar(CoreBoundVar {
43 debruijn: Some(db),
44 var_index,
45 kind,
46 }) = self
47 {
48 CoreBoundVar {
49 debruijn: Some(db.shift_in()),
50 var_index: *var_index,
51 kind: *kind,
52 }
53 .upcast()
54 } else {
55 *self
56 }
57 }
58
59 pub fn shift_out(&self) -> Option<Self> {
63 if let CoreVariable::BoundVar(CoreBoundVar {
64 debruijn: Some(db),
65 var_index,
66 kind,
67 }) = self
68 {
69 db.shift_out().map(|db1| {
70 CoreBoundVar {
71 debruijn: Some(db1),
72 var_index: *var_index,
73 kind: *kind,
74 }
75 .upcast()
76 })
77 } else {
78 Some(*self)
79 }
80 }
81
82 pub fn is_free(&self) -> bool {
87 match self {
88 CoreVariable::UniversalVar(_)
89 | CoreVariable::ExistentialVar(_)
90 | CoreVariable::BoundVar(CoreBoundVar {
91 debruijn: None,
92 var_index: _,
93 kind: _,
94 }) => true,
95
96 CoreVariable::BoundVar(CoreBoundVar {
97 debruijn: Some(_),
98 var_index: _,
99 kind: _,
100 }) => false,
101 }
102 }
103
104 pub fn is_universal(&self) -> bool {
105 match self {
106 CoreVariable::UniversalVar(_) => true,
107 CoreVariable::ExistentialVar(_) => false,
108 CoreVariable::BoundVar(_) => false,
109 }
110 }
111}
112
113impl<L: Language> CoreVisit<L> for CoreVariable<L> {
114 fn free_variables(&self) -> Vec<CoreVariable<L>> {
115 if self.is_free() {
116 vec![*self]
117 } else {
118 vec![]
119 }
120 }
121
122 fn size(&self) -> usize {
123 1
124 }
125
126 fn assert_valid(&self) {}
127}
128
129#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
130pub struct CoreExistentialVar<L: Language> {
131 pub kind: CoreKind<L>,
132 pub var_index: VarIndex,
133}
134
135impl<L: Language> CoreVisit<L> for CoreExistentialVar<L> {
136 fn free_variables(&self) -> Vec<CoreVariable<L>> {
137 vec![self.upcast()]
138 }
139
140 fn size(&self) -> usize {
141 1
142 }
143
144 fn assert_valid(&self) {}
145}
146
147#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
151pub struct CoreUniversalVar<L: Language> {
152 pub kind: CoreKind<L>,
153 pub var_index: VarIndex,
154}
155
156#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
158pub struct CoreBoundVar<L: Language> {
159 pub debruijn: Option<DebruijnIndex>,
163 pub var_index: VarIndex,
164 pub kind: CoreKind<L>,
165}
166
167#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
168pub struct DebruijnIndex {
169 pub index: usize,
170}
171
172impl DebruijnIndex {
173 pub const INNERMOST: DebruijnIndex = DebruijnIndex { index: 0 };
174
175 pub fn shift_in(&self) -> Self {
177 DebruijnIndex {
178 index: self.index + 1,
179 }
180 }
181
182 pub fn shift_out(&self) -> Option<Self> {
184 if self.index > 0 {
185 Some(DebruijnIndex {
186 index: self.index - 1,
187 })
188 } else {
189 None
190 }
191 }
192}
193
194#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
195pub struct VarIndex {
196 pub index: usize,
197}
198
199impl VarIndex {
200 pub const ZERO: VarIndex = VarIndex { index: 0 };
201}
202
203impl std::ops::Add<usize> for VarIndex {
204 type Output = VarIndex;
205
206 fn add(self, rhs: usize) -> Self::Output {
207 VarIndex {
208 index: self.index + rhs,
209 }
210 }
211}
212
213mod cast_impls;
214mod debug_impls;