1use all_the_same::all_the_same;
11use derivative::Derivative;
12use derive_more::{Constructor, From, TryInto};
13use std::{fmt, rc::Rc};
14
15use super::prelude::*;
16use crate::dbl::{
17 discrete, discrete_tabulator, modal,
18 model::PrintableDblModel,
19 theory::{DblTheory, DblTheoryKind, NonUnital, Unital},
20};
21use crate::one::QualifiedPath;
22use crate::stdlib::theories;
23use crate::zero::{QualifiedName, name};
24
25#[derive(Constructor, Clone, Derivative)]
30#[derivative(PartialEq, Eq)]
31pub struct Theory {
32 pub name: QualifiedName,
34 #[derivative(PartialEq = "ignore")]
36 pub definition: TheoryDef,
37}
38
39impl fmt::Display for Theory {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "{}", self.name)
42 }
43}
44
45#[derive(Clone, From)]
47pub enum TheoryDef {
48 Discrete(Rc<discrete::DiscreteDblTheory>),
50 DiscreteTab(Rc<discrete_tabulator::DiscreteTabTheory>),
52 ModalUnital(Rc<modal::ModalDblTheory<Unital>>),
54 ModalNonUnital(Rc<modal::ModalDblTheory<NonUnital>>),
56}
57
58impl TheoryDef {
59 pub fn discrete(theory: discrete::DiscreteDblTheory) -> Self {
61 TheoryDef::Discrete(Rc::new(theory))
62 }
63
64 pub fn discrete_tab(theory: discrete_tabulator::DiscreteTabTheory) -> Self {
66 TheoryDef::DiscreteTab(Rc::new(theory))
67 }
68
69 pub fn modal_unital(theory: modal::ModalDblTheory<Unital>) -> Self {
71 TheoryDef::ModalUnital(Rc::new(theory))
72 }
73
74 pub fn modal_non_unital(theory: modal::ModalDblTheory<NonUnital>) -> Self {
76 TheoryDef::ModalNonUnital(Rc::new(theory))
77 }
78
79 pub fn basic_ob_type(&self, name: QualifiedName) -> Option<ObType> {
81 let ob_type = match self {
82 TheoryDef::Discrete(_) => ObType::Discrete(name),
83 TheoryDef::DiscreteTab(_) => ObType::DiscreteTab(name.into()),
84 TheoryDef::ModalUnital(_) | TheoryDef::ModalNonUnital(_) => {
85 ObType::Modal(modal::ModeApp::new(name))
86 }
87 };
88 all_the_same!(match self {
89 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
90 if th.has_ob_type((&ob_type).try_into().unwrap()) {
91 Some(ob_type)
92 } else {
93 None
94 }
95 }
96 })
97 }
98
99 pub fn basic_mor_type(&self, name: QualifiedName) -> Option<MorType> {
101 let mor_type = match self {
102 TheoryDef::Discrete(_) => MorType::Discrete(name.into()),
103 TheoryDef::DiscreteTab(_) => {
104 MorType::DiscreteTab(discrete_tabulator::TabMorType::Basic(name))
105 }
106 TheoryDef::ModalUnital(_) | TheoryDef::ModalNonUnital(_) => {
107 MorType::Modal(modal::ModeApp::new(name).into())
108 }
109 };
110 all_the_same!(match self {
111 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
112 if th.has_mor_type((&mor_type).try_into().unwrap()) {
113 Some(mor_type)
114 } else {
115 None
116 }
117 }
118 })
119 }
120
121 pub fn basic_ob_op(&self, name: QualifiedName) -> Option<ObOp> {
123 match self {
124 TheoryDef::Discrete(_) | TheoryDef::DiscreteTab(_) => None,
125 TheoryDef::ModalUnital(th) => Self::basic_ob_op_modal(th, name),
126 TheoryDef::ModalNonUnital(th) => Self::basic_ob_op_modal(th, name),
127 }
128 }
129
130 fn basic_ob_op_modal<Kind: DblTheoryKind>(
131 th: &modal::ModalDblTheory<Kind>,
132 name: QualifiedName,
133 ) -> Option<ObOp> {
134 let op = modal::ModalObOp::generator(name);
135 if th.has_ob_op(&op) {
136 Some(ObOp::Modal(op))
137 } else {
138 None
139 }
140 }
141
142 pub fn src_type(&self, mor_type: &MorType) -> ObType {
144 all_the_same!(match self {
145 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
146 th.src_type(mor_type.try_into().unwrap()).into()
147 }
148 })
149 }
150
151 pub fn tgt_type(&self, mor_type: &MorType) -> ObType {
153 all_the_same!(match self {
154 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
155 th.tgt_type(mor_type.try_into().unwrap()).into()
156 }
157 })
158 }
159
160 pub fn hom_type(&self, ob_type: ObType) -> Option<MorType> {
162 match self {
163 TheoryDef::Discrete(th) => Some(th.hom_type(ob_type.try_into().unwrap()).into()),
164 TheoryDef::DiscreteTab(th) => Some(th.hom_type(ob_type.try_into().unwrap()).into()),
165 TheoryDef::ModalUnital(th) => Some(th.hom_type(ob_type.try_into().unwrap()).into()),
166 TheoryDef::ModalNonUnital(th) => {
167 th.hom_type(ob_type.try_into().unwrap()).map(|mt| mt.into())
168 }
169 }
170 }
171
172 pub fn compose_types2(&self, mt1: MorType, mt2: MorType) -> Option<MorType> {
174 all_the_same!(match self {
175 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
176 let path = Path::pair(mt1.try_into().unwrap(), mt2.try_into().unwrap());
177 th.compose_types(path).map(|mt| mt.into())
178 }
179 })
180 }
181
182 pub fn tabulator(&self, mor_type: MorType) -> Option<ObType> {
184 match self {
185 TheoryDef::Discrete(_) => None,
186 TheoryDef::DiscreteTab(th) => Some(th.tabulator(mor_type.try_into().unwrap()).into()),
187 TheoryDef::ModalUnital(_) | TheoryDef::ModalNonUnital(_) => None,
188 }
189 }
190
191 pub fn ob_op_dom(&self, ob_op: &ObOp) -> ObType {
193 all_the_same!(match self {
194 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
195 th.ob_op_dom(ob_op.try_into().unwrap()).into()
196 }
197 })
198 }
199
200 pub fn ob_op_cod(&self, ob_op: &ObOp) -> ObType {
202 all_the_same!(match self {
203 TheoryDef::[Discrete, DiscreteTab, ModalUnital, ModalNonUnital](th) => {
204 th.ob_op_cod(ob_op.try_into().unwrap()).into()
205 }
206 })
207 }
208}
209
210#[derive(Clone, Debug, From, TryInto, PartialEq, Eq)]
212#[try_into(owned, ref)]
213pub enum ObType {
214 Discrete(QualifiedName),
216 DiscreteTab(discrete_tabulator::TabObType),
218 Modal(modal::ModalObType),
220}
221
222impl ObType {
223 pub fn mode_app(self) -> Option<(modal::Modality, ObType)> {
225 match self {
226 ObType::Discrete(_) | ObType::DiscreteTab(_) => None,
227 ObType::Modal(ob_type) => {
228 let (maybe_modality, ob_type) = ob_type.pop_app();
229 maybe_modality.map(|modality| (modality, ob_type.into()))
230 }
231 }
232 }
233
234 pub fn list_arg(self) -> Option<ObType> {
236 self.mode_app().and_then(|(modality, ob_type)| match modality {
237 modal::Modality::List(_) => Some(ob_type),
238 _ => None,
239 })
240 }
241}
242
243impl ToDoc for ObType {
244 fn to_doc<'a>(&self) -> D<'a> {
245 match self {
246 ObType::Discrete(name) => discrete::DiscreteDblModel::ob_type_to_doc(name),
247 ObType::DiscreteTab(name) => discrete_tabulator::DiscreteTabModel::ob_type_to_doc(name),
248 ObType::Modal(ob_type) => modal::ModalDblModel::<Unital>::ob_type_to_doc(ob_type),
249 }
250 }
251}
252
253impl fmt::Display for ObType {
254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255 write!(f, "{}", self.to_doc().group().pretty())
256 }
257}
258
259#[derive(Clone, Debug, From, TryInto, PartialEq, Eq)]
261#[try_into(owned, ref)]
262pub enum MorType {
263 Discrete(QualifiedPath),
265 DiscreteTab(discrete_tabulator::TabMorType),
267 Modal(modal::ModalMorType),
269}
270
271impl ToDoc for MorType {
272 fn to_doc<'a>(&self) -> D<'a> {
273 match self {
274 MorType::Discrete(path) => discrete::DiscreteDblModel::mor_type_to_doc(path),
275 MorType::DiscreteTab(mor_type) => {
276 discrete_tabulator::DiscreteTabModel::mor_type_to_doc(mor_type)
277 }
278 MorType::Modal(mor_type) => modal::ModalDblModel::<Unital>::mor_type_to_doc(mor_type),
279 }
280 }
281}
282
283impl fmt::Display for MorType {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 write!(f, "{}", self.to_doc().group().pretty())
286 }
287}
288
289#[derive(Clone, Debug, TryInto)]
291#[try_into(owned, ref)]
292pub enum ObOp {
293 Discrete(QualifiedName),
295 DiscreteTab(discrete_tabulator::TabObOp),
297 Modal(modal::ModalObOp),
299}
300
301pub fn std_theories() -> HashMap<QualifiedName, Theory> {
303 [
304 (name("ThSchema"), TheoryDef::discrete(theories::th_schema())),
305 (name("ThCategory"), TheoryDef::discrete(theories::th_category())),
306 (name("ThSignedCategory"), TheoryDef::discrete(theories::th_signed_category())),
307 (name("ThCategoryLinks"), TheoryDef::discrete_tab(theories::th_category_links())),
308 (name("ThMulticategory"), TheoryDef::modal_unital(theories::th_multicategory())),
309 (
310 name("ThSymMonoidalCategory"),
311 TheoryDef::modal_unital(theories::th_sym_monoidal_category()),
312 ),
313 ]
314 .into_iter()
315 .map(|(name, def)| (name.clone(), Theory::new(name, def)))
316 .collect()
317}