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}