catlog/tt/
toplevel.rs

1//! Data structures for managing toplevel declarations in the type theory.
2//!
3//! Specifically, notebooks will produce [TopDecl::Type] declarations.
4
5use std::fmt;
6
7use crate::{
8    dbl::theory::DiscreteDblTheory,
9    stdlib::{th_category, th_schema, th_signed_category},
10    tt::{prelude::*, stx::*, val::*},
11    zero::{QualifiedName, name},
12};
13
14/// A theory supported by doublett.
15///
16/// Equality of these theories is nominal; two theories are the same if and only
17/// if they have the same name.
18///
19/// When we add features to doublett, this will become an enum; doublett will
20/// never be parametric (e.g., we will not thread a "theory" type through a bunch
21/// of structs in doublett).
22#[derive(Clone)]
23pub struct Theory {
24    /// The name of the theory.
25    pub name: QualifiedName,
26    /// The definition of the theory.
27    pub definition: Rc<DiscreteDblTheory>,
28}
29
30impl Theory {
31    /// Default constructor for [Theory].
32    pub fn new(name: QualifiedName, definition: Rc<DiscreteDblTheory>) -> Self {
33        Self { name, definition }
34    }
35}
36
37impl PartialEq for Theory {
38    fn eq(&self, other: &Self) -> bool {
39        self.name == other.name
40    }
41}
42
43impl Eq for Theory {}
44
45impl fmt::Display for Theory {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        write!(f, "{}", self.name)
48    }
49}
50
51/// A toplevel declaration.
52#[derive(Clone)]
53pub enum TopDecl {
54    /// See [Type]
55    Type(Type),
56    /// See [DefConst]
57    DefConst(DefConst),
58    /// See [Def]
59    Def(Def),
60}
61
62/// A toplevel declaration of a type.
63///
64/// Also stores the evaluation of that type. Because this is an evaluation in
65/// the empty context, this is OK to use in any other context as well.
66#[derive(Clone)]
67pub struct Type {
68    /// The theory for the type
69    pub theory: Theory,
70    /// The syntax of the type (unnormalized)
71    pub stx: TyS,
72    /// The value of the type (normalized)
73    pub val: TyV,
74}
75
76impl Type {
77    /// Default constructor for [Type]
78    pub fn new(theory: Theory, stx: TyS, val: TyV) -> Self {
79        Self { theory, stx, val }
80    }
81}
82
83/// A toplevel declaration of a term in the empty context.
84///
85/// Also stores the evaluation of that term, and the evaluation of the corresponding type of that term. Because this is an evaluation in the
86/// empty context, this is OK to use in any other context as well.
87#[derive(Clone)]
88pub struct DefConst {
89    /// The theory that the constant is defined in
90    pub theory: Theory,
91    /// The syntax of the constant (unnormalized)
92    pub stx: TmS,
93    /// The value of the constant (normalized)
94    pub val: TmV,
95    /// The type of the constant
96    pub ty: TyV,
97}
98
99impl DefConst {
100    /// Default constructor for [DefConst]
101    pub fn new(theory: Theory, stx: TmS, val: TmV, ty: TyV) -> Self {
102        Self {
103            theory,
104            stx,
105            val,
106            ty,
107        }
108    }
109}
110
111/// A toplevel declaration of a term judgment
112#[derive(Clone)]
113pub struct Def {
114    /// The theory that the definition is defined in
115    pub theory: Theory,
116    /// The arguments for the definition
117    pub args: Row<TyS>,
118    /// The return type of the definition (to be evaluated in an environment
119    /// with values for the arguments)
120    pub ret_ty: TyS,
121    /// The body of the definition (to be evaluated in an environment with
122    /// values for the arguments)
123    pub body: TmS,
124}
125
126impl Def {
127    /// Default constructor for [Def]
128    pub fn new(theory: Theory, args: Row<TyS>, ret_ty: TyS, body: TmS) -> Self {
129        Self {
130            theory,
131            args,
132            ret_ty,
133            body,
134        }
135    }
136}
137
138impl TopDecl {
139    /// Extract the type for a toplevel-declaration of a type.
140    ///
141    /// This should only be used after type checking, when we know that a toplevel
142    /// variable name does in fact point to a toplevel declaration for a type.
143    pub fn as_ty(&self) -> Type {
144        match self {
145            TopDecl::Type(ty) => ty.clone(),
146            _ => panic!("expected type"),
147        }
148    }
149
150    /// Extract the term for a toplevel declaration of a term.
151    ///
152    /// This should only be used after type checking, when we know that a toplevel
153    /// variable name does in fact point to a toplevel declaration for a term.
154    pub fn as_const(&self) -> DefConst {
155        match self {
156            TopDecl::DefConst(d) => d.clone(),
157            _ => panic!("expected const"),
158        }
159    }
160
161    /// Extract the definition for a toplevel term judgment
162    pub fn as_def(&self) -> Def {
163        match self {
164            TopDecl::Def(d) => d.clone(),
165            _ => panic!("expected def"),
166        }
167    }
168}
169
170/// Construct a library of standard theories
171pub fn std_theories() -> HashMap<QualifiedName, Theory> {
172    [
173        (name("ThSchema"), th_schema()),
174        (name("ThCategory"), th_category()),
175        (name("ThSignedCategory"), th_signed_category()),
176    ]
177    .into_iter()
178    .map(|(name, def)| (name.clone(), Theory::new(name.clone(), Rc::new(def))))
179    .collect()
180}
181
182/// Storage for toplevel declarations.
183pub struct Toplevel {
184    /// Library of theories, indexed by name
185    pub theory_library: HashMap<QualifiedName, Theory>,
186    /// The toplevel declarations, indexed by their name.
187    pub declarations: HashMap<TopVarName, TopDecl>,
188}
189
190impl Toplevel {
191    /// Constructor for an empty [Toplevel].
192    pub fn new(theory_library: HashMap<QualifiedName, Theory>) -> Self {
193        Toplevel {
194            theory_library,
195            declarations: HashMap::new(),
196        }
197    }
198
199    /// Lookup a toplevel declaration by name.
200    pub fn lookup(&self, name: TopVarName) -> Option<&TopDecl> {
201        self.declarations.get(&name)
202    }
203}