1use crate::level::LevelId;
7use crate::symbol::SymbolId;
8use std::fmt;
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
12pub struct TermId(u32);
13
14impl TermId {
15 pub(crate) fn new(id: u32) -> Self {
17 Self(id)
18 }
19
20 pub fn raw(self) -> u32 {
22 self.0
23 }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct Binder {
29 pub name: SymbolId,
31
32 pub ty: TermId,
34
35 pub implicit: bool,
37
38 pub info: BinderInfo,
40}
41
42#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
44pub enum BinderInfo {
45 Default,
47
48 Implicit,
50
51 StrictImplicit,
53
54 InstImplicit,
56}
57
58impl Binder {
59 pub fn new(name: SymbolId, ty: TermId) -> Self {
61 Self {
62 name,
63 ty,
64 implicit: false,
65 info: BinderInfo::Default,
66 }
67 }
68
69 pub fn implicit(name: SymbolId, ty: TermId) -> Self {
71 Self {
72 name,
73 ty,
74 implicit: true,
75 info: BinderInfo::Implicit,
76 }
77 }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq, Hash)]
82pub enum TermKind {
83 Sort(LevelId),
85
86 Const(SymbolId, Vec<LevelId>),
88
89 Var(u32),
91
92 App(TermId, TermId),
94
95 Lam(Binder, TermId),
97
98 Pi(Binder, TermId),
100
101 Let(Binder, TermId, TermId),
103
104 MVar(MetaVarId),
106
107 Lit(Literal),
109}
110
111#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
113pub struct MetaVarId(u32);
114
115impl MetaVarId {
116 pub fn new(id: u32) -> Self {
118 Self(id)
119 }
120
121 pub fn raw(self) -> u32 {
123 self.0
124 }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
129pub enum Literal {
130 Nat(u64),
132
133 String(String),
135}
136
137#[derive(Debug, Clone)]
139pub struct Term {
140 pub kind: TermKind,
142
143 hash: u64,
145}
146
147impl Term {
148 pub fn new(kind: TermKind) -> Self {
150 use std::collections::hash_map::DefaultHasher;
151 use std::hash::{Hash, Hasher};
152
153 let mut hasher = DefaultHasher::new();
154 kind.hash(&mut hasher);
155 let hash = hasher.finish();
156
157 Self { kind, hash }
158 }
159
160 pub fn hash(&self) -> u64 {
162 self.hash
163 }
164
165 pub fn is_sort(&self) -> bool {
167 matches!(self.kind, TermKind::Sort(_))
168 }
169
170 pub fn is_var(&self) -> bool {
172 matches!(self.kind, TermKind::Var(_))
173 }
174
175 pub fn is_lam(&self) -> bool {
177 matches!(self.kind, TermKind::Lam(_, _))
178 }
179
180 pub fn is_pi(&self) -> bool {
182 matches!(self.kind, TermKind::Pi(_, _))
183 }
184
185 pub fn is_app(&self) -> bool {
187 matches!(self.kind, TermKind::App(_, _))
188 }
189}
190
191impl PartialEq for Term {
192 fn eq(&self, other: &Self) -> bool {
193 self.hash == other.hash && self.kind == other.kind
194 }
195}
196
197impl Eq for Term {}
198
199impl std::hash::Hash for Term {
200 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
201 self.hash.hash(state);
202 }
203}
204
205impl fmt::Display for TermKind {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 match self {
208 TermKind::Sort(l) => write!(f, "Sort({})", l.raw()),
209 TermKind::Const(name, levels) => {
210 write!(f, "Const({}, [", name.raw())?;
211 for (i, l) in levels.iter().enumerate() {
212 if i > 0 {
213 write!(f, ", ")?;
214 }
215 write!(f, "{}", l.raw())?;
216 }
217 write!(f, "])")
218 }
219 TermKind::Var(idx) => write!(f, "#{}", idx),
220 TermKind::App(func, arg) => write!(f, "({} {})", func.raw(), arg.raw()),
221 TermKind::Lam(binder, body) => {
222 write!(f, "(λ {} : {} . {})", binder.name.raw(), binder.ty.raw(), body.raw())
223 }
224 TermKind::Pi(binder, body) => {
225 write!(f, "(Π {} : {} . {})", binder.name.raw(), binder.ty.raw(), body.raw())
226 }
227 TermKind::Let(binder, val, body) => write!(
228 f,
229 "(let {} : {} := {} in {})",
230 binder.name.raw(),
231 binder.ty.raw(),
232 val.raw(),
233 body.raw()
234 ),
235 TermKind::MVar(id) => write!(f, "?{}", id.raw()),
236 TermKind::Lit(lit) => match lit {
237 Literal::Nat(n) => write!(f, "{}", n),
238 Literal::String(s) => write!(f, "\"{}\"", s),
239 },
240 }
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn test_term_creation() {
250 let term1 = Term::new(TermKind::Var(0));
251 let term2 = Term::new(TermKind::Var(0));
252
253 assert_eq!(term1.hash(), term2.hash());
254 }
255
256 #[test]
257 fn test_binder_info() {
258 let binder = Binder::new(SymbolId::new(0), TermId::new(0));
259 assert!(!binder.implicit);
260
261 let implicit = Binder::implicit(SymbolId::new(0), TermId::new(0));
262 assert!(implicit.implicit);
263 }
264}