catlog/tt/stx.rs
1//! Syntax for types and terms.
2//!
3//! See [crate::tt] for what this means.
4
5use ::pretty::RcDoc;
6use derive_more::Constructor;
7
8#[cfg(doc)]
9use crate::dbl::discrete::theory::DiscreteDblTheory;
10use crate::zero::LabelSegment;
11use crate::{tt::prelude::*, zero::QualifiedName};
12use std::fmt;
13use std::fmt::Write as _;
14use std::ops::Deref;
15
16/// Object types are just qualified names, see [DiscreteDblTheory].
17pub type ObjectType = QualifiedName;
18/// Morphism types are paths of qualified names, see [DiscreteDblTheory].
19#[derive(Clone, PartialEq, Eq)]
20pub struct MorphismType(pub Path<QualifiedName, QualifiedName>);
21
22impl fmt::Display for MorphismType {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match &self.0 {
25 Path::Id(ot) => write!(f, "Id {ot}"),
26 Path::Seq(non_empty) => {
27 for (i, segment) in non_empty.iter().enumerate() {
28 if i > 0 {
29 write!(f, " · ")?;
30 }
31 write!(f, "{segment}")?;
32 }
33 Ok(())
34 }
35 }
36 }
37}
38
39impl MorphismType {
40 fn to_doc<'a>(&self) -> D<'a> {
41 match &self.0 {
42 Path::Id(ot) => (t("Id") + s() + t(format!("{ot}"))).parens(),
43 Path::Seq(non_empty) => {
44 if non_empty.len() == 1 {
45 t(format!("{}", non_empty[0]))
46 } else {
47 D(RcDoc::intersperse(non_empty.iter().map(|x| t(format!("{x}")).0), t(" · ").0))
48 .parens()
49 }
50 }
51 }
52 }
53}
54
55/// Type in the base type theory.
56///
57/// See [crate::tt] for more information about what this means. Note that this
58/// is a simple type, so we don't need syntax and value variants.
59#[derive(Clone, PartialEq, Eq)]
60pub enum Ty0 {
61 /// The type of (objects of a given object type).
62 Object(ObjectType),
63 /// Non-dependent record type.
64 Record(Row<Ty0>),
65 /// Unit type.
66 Unit,
67}
68
69/// Content of record type syntax.
70#[derive(Clone, Constructor)]
71pub struct RecordS {
72 /// The base types of the fields.
73 pub fields0: Row<Ty0>,
74 /// The total types of the fields.
75 ///
76 /// Each of these types is meant to be evaluated in an environment
77 /// where the last element is a value of type `fields0`.
78 pub fields1: Row<TyS>,
79}
80
81/// Inner enum for [TyS].
82pub enum TyS_ {
83 /// A reference to a top-level declaration
84 TopVar(TopVarName),
85 /// Type constructor for object types.
86 ///
87 /// Example syntax: `Entity` (top-level constants are bound by the elaborator to
88 /// various object types).
89 ///
90 /// A term of type `Object(ot)` represents an object of object type `ot`.
91 ///
92 /// The base type for `Object(ot)` is `Ty0::Object(ot)`.
93 Object(ObjectType),
94
95 /// Type constructor for morphism types.
96 ///
97 /// Example syntax: `Attr x a` (top-level constants are bound by the elaborator
98 /// to constructors for morphism types).
99 ///
100 /// A term of type `Morphism(mt, dom, cod)` represents an morphism of morphism
101 /// type `mt` from `dom` to `cod`.
102 ///
103 /// The base type for `Morphism(mt, dom, cod)` is Ty0::Unit.
104 Morphism(MorphismType, TmS, TmS),
105
106 /// Type constructor for record types.
107 ///
108 /// Example syntax: `[x : A, y : B]`.
109 ///
110 /// A term `x` of type `Record(r)` represents a record where field `f` has type
111 /// `eval(env.snoc(eval(env, x)), r.fields1[f])`.
112 ///
113 /// The base type for `Record(r)` is `Ty0::Record(r.fields0)`.
114 Record(RecordS),
115
116 /// Type constructor for singleton types.
117 ///
118 /// Example syntax: `@sing a` (assuming `a` is a term that synthesizes a type).
119 ///
120 /// A term `x` of type `Sing(ty, tm)` is a term of `ty` that is convertable with
121 /// `tm`.
122 Sing(TyS, TmS),
123
124 /// Type constructor for specialized types.
125 ///
126 /// Example syntax: `A & [ .x : @sing a ]`.
127 ///
128 /// A term `x` of type `Specialize(ty, d)` is a term of `ty` where additionally
129 /// for each path `p` (e.g. `.x`, `.a.b`, etc.) in `d`, `x.p` is of type `d[p]`.
130 ///
131 /// In order to form this type, it must be the case that `d[p]` is a subtype of
132 /// the type of the field at path `p`.
133 Specialize(TyS, Vec<(Vec<(FieldName, LabelSegment)>, TyS)>),
134
135 /// Type constructor for the unit type.
136 ///
137 /// Example syntax: `Unit`.
138 ///
139 /// All terms of this type are convertable with `tt : Unit`.
140 Unit,
141}
142
143/// Syntax for total types, dereferences to [TyS_].
144///
145/// See [crate::tt] for an explanation of what total types are, and for an
146/// explanation of our approach to Rc pointers in abstract syntax trees.
147#[derive(Clone)]
148pub struct TyS(Rc<TyS_>);
149
150impl Deref for TyS {
151 type Target = TyS_;
152
153 fn deref(&self) -> &Self::Target {
154 &self.0
155 }
156}
157
158impl TyS {
159 /// Smart constructor for [TyS], [TyS_::TopVar] case.
160 pub fn topvar(name: TopVarName) -> Self {
161 Self(Rc::new(TyS_::TopVar(name)))
162 }
163
164 /// Smart constructor for [TyS], [TyS_::Object] case.
165 pub fn object(object_type: ObjectType) -> Self {
166 Self(Rc::new(TyS_::Object(object_type)))
167 }
168
169 /// Smart constructor for [TyS], [TyS_::Morphism] case.
170 pub fn morphism(morphism_type: MorphismType, dom: TmS, cod: TmS) -> Self {
171 Self(Rc::new(TyS_::Morphism(morphism_type, dom, cod)))
172 }
173
174 /// Smart constructor for [TyS], [TyS_::Record] case.
175 pub fn record(record_s: RecordS) -> Self {
176 Self(Rc::new(TyS_::Record(record_s)))
177 }
178
179 /// Smart constructor for [TyS], [TyS_::Sing] case.
180 pub fn sing(ty: TyS, tm: TmS) -> Self {
181 Self(Rc::new(TyS_::Sing(ty, tm)))
182 }
183
184 /// Smart constructor for [TyS], [TyS_::Specialize] case.
185 pub fn specialize(
186 ty: TyS,
187 specializations: Vec<(Vec<(FieldName, LabelSegment)>, TyS)>,
188 ) -> Self {
189 Self(Rc::new(TyS_::Specialize(ty, specializations)))
190 }
191
192 /// Smart constructor for [TyS], [TyS_::Unit] case.
193 pub fn unit() -> Self {
194 Self(Rc::new(TyS_::Unit))
195 }
196
197 fn to_doc<'a>(&self) -> D<'a> {
198 match &**self {
199 TyS_::TopVar(name) => t(format!("{}", name)),
200 TyS_::Object(object_type) => t(format!("{}", object_type)),
201 TyS_::Morphism(morphism_type, dom, cod) => {
202 morphism_type.to_doc() + tuple([dom.to_doc(), cod.to_doc()])
203 }
204 TyS_::Record(r) => {
205 tuple(r.fields1.iter().map(|(_, (label, ty))| {
206 binop(":", t(format!("{}", label)).group(), ty.to_doc())
207 }))
208 }
209 TyS_::Sing(_, tm) => t("@sing") + s() + tm.to_doc(),
210 TyS_::Specialize(ty, d) => binop(
211 "&",
212 ty.to_doc(),
213 tuple(d.iter().map(|(name, ty)| binop(":", t(path_to_string(name)), ty.to_doc()))),
214 ),
215 TyS_::Unit => t("Unit"),
216 }
217 }
218}
219
220fn path_to_string(path: &[(FieldName, LabelSegment)]) -> String {
221 let mut out = String::new();
222 for (_, seg) in path {
223 write!(&mut out, ".{}", seg).unwrap();
224 }
225 out
226}
227
228impl fmt::Display for TyS {
229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230 write!(f, "{}", self.to_doc().group().pretty())
231 }
232}
233
234/// Inner enum for [TmS].
235pub enum TmS_ {
236 /// A reference to a top-level constant def
237 TopVar(TopVarName),
238 /// An application of a top-level term judgment to arguments
239 TopApp(TopVarName, Vec<TmS>),
240 /// Variable syntax.
241 ///
242 /// We use a backward index, as when we evaluate we store the
243 /// environment in a [bwd::Bwd], and this indexes into that.
244 Var(BwdIdx, VarName, LabelSegment),
245 /// Record introduction.
246 Cons(Row<TmS>),
247 /// Record elimination.
248 Proj(TmS, FieldName, LabelSegment),
249 /// Unit introduction.
250 ///
251 /// Note that eta-expansion takes care of elimination for units
252 Tt,
253 /// Identity morphism at an object
254 Id(TmS),
255 /// Composition of two morphisms
256 Compose(TmS, TmS),
257 /// An opaque term.
258 ///
259 /// This only appears when we quote a value
260 Opaque,
261}
262
263/// Syntax for total terms, dereferences to [TmS_].
264///
265/// See [crate::tt] for an explanation of what total types are, and for an
266/// explanation of our approach to Rc pointers in abstract syntax trees.
267#[derive(Clone)]
268pub struct TmS(Rc<TmS_>);
269
270impl Deref for TmS {
271 type Target = TmS_;
272
273 fn deref(&self) -> &Self::Target {
274 &self.0
275 }
276}
277
278impl TmS {
279 /// Smart constructor for [TmS], [TmS_::TopVar] case.
280 pub fn topvar(var_name: VarName) -> Self {
281 Self(Rc::new(TmS_::TopVar(var_name)))
282 }
283
284 /// Smart constructor for [TmS], [TmS_::TopApp] case.
285 pub fn topapp(var_name: VarName, args: Vec<TmS>) -> Self {
286 Self(Rc::new(TmS_::TopApp(var_name, args)))
287 }
288
289 /// Smart constructor for [TmS], [TmS_::Var] case.
290 pub fn var(bwd_idx: BwdIdx, var_name: VarName, label: LabelSegment) -> Self {
291 Self(Rc::new(TmS_::Var(bwd_idx, var_name, label)))
292 }
293
294 /// Smart constructor for [TmS], [TmS_::Cons] case.
295 pub fn cons(row: Row<TmS>) -> Self {
296 Self(Rc::new(TmS_::Cons(row)))
297 }
298
299 /// Smart constructor for [TmS], [TmS_::Proj] case.
300 pub fn proj(tm_s: TmS, field_name: FieldName, label: LabelSegment) -> Self {
301 Self(Rc::new(TmS_::Proj(tm_s, field_name, label)))
302 }
303
304 /// Smart constructor for [TmS], [TmS_::Tt] case.
305 pub fn tt() -> Self {
306 Self(Rc::new(TmS_::Tt))
307 }
308
309 /// Smart constructor for [TmS], [TmS_::Id] case.
310 pub fn id(ob: TmS) -> Self {
311 Self(Rc::new(TmS_::Id(ob)))
312 }
313
314 /// Smart constructor for [TmS], [TmS_::Compose] case.
315 pub fn compose(f: TmS, g: TmS) -> Self {
316 Self(Rc::new(TmS_::Compose(f, g)))
317 }
318
319 /// An opaque term
320 pub fn opaque() -> Self {
321 Self(Rc::new(TmS_::Opaque))
322 }
323
324 fn to_doc<'a>(&self) -> D<'a> {
325 match &**self {
326 TmS_::TopVar(name) => t(format!("{}", name)),
327 TmS_::TopApp(name, args) => {
328 t(format!("{}", name)) + tuple(args.iter().map(|arg| arg.to_doc()))
329 }
330 TmS_::Var(_, _, label) => t(format!("{}", label)),
331 TmS_::Proj(tm, _, label) => tm.to_doc() + t(format!(".{}", label)),
332 TmS_::Cons(fields) => {
333 tuple(fields.iter().map(|(_, (label, field))| {
334 binop(":=", t(format!("{}", label)), field.to_doc())
335 }))
336 }
337 TmS_::Id(ob) => (t("@id") + s() + ob.to_doc()).parens(),
338 TmS_::Compose(f, g) => binop("·", f.to_doc(), g.to_doc()),
339 TmS_::Tt => t("tt"),
340 TmS_::Opaque => t("<opaque>"),
341 }
342 }
343}
344
345impl fmt::Display for TmS {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 write!(f, "{}", self.to_doc().group().pretty())
348 }
349}