1use std::collections::HashMap;
4use std::rc::Rc;
5
6use all_the_same::all_the_same;
7use derive_more::{From, TryInto};
8use ustr::Ustr;
9
10use wasm_bindgen::prelude::*;
11
12use catlog::dbl::theory::{
13 self, DblTheory as _, ModalMorType, ModalObOp, ModalObType, ModeApp, TabMorType, TabObOp,
14 TabObType,
15};
16use catlog::one::{Path, QualifiedPath, ShortPath};
17use catlog::tt::{
18 self,
19 notebook_elab::{demote_modality, promote_modality},
20};
21use catlog::zero::{NameSegment, QualifiedName};
22use notebook_types::current::theory::*;
23
24use super::notation::*;
25
26impl CanElaborate<ObType, QualifiedName> for Elaborator {
28 fn elab(&self, ob_type: &ObType) -> Result<QualifiedName, String> {
29 match ob_type {
30 ObType::Basic(id) => Ok((*id).into()),
31 _ => Err(format!("Cannot use object type in discrete double theory: {ob_type:#?}")),
32 }
33 }
34}
35
36impl CanElaborate<MorType, QualifiedPath> for Elaborator {
38 fn elab(&self, mor_type: &MorType) -> Result<QualifiedPath, String> {
39 match mor_type {
40 MorType::Basic(id) => Ok(Path::single((*id).into())),
41 MorType::Composite(fs) => {
42 let fs: Result<Vec<_>, _> = fs.iter().map(|f| self.elab(f)).collect();
43 let path = Path::from_vec(fs?).ok_or("Composite should not be empty")?;
44 Ok(path.flatten())
45 }
46 MorType::Hom(ob_type) => Ok(Path::Id(self.elab(ob_type.as_ref())?)),
47 _ => Err(format!("Cannot use morphsim type in discrete double theory: {mor_type:#?}")),
48 }
49 }
50}
51
52impl CanElaborate<ObOp, QualifiedName> for Elaborator {
54 fn elab(&self, op: &ObOp) -> Result<QualifiedName, String> {
55 Err(format!("Cannot use operation in discrete double theory: {op:#?}"))
56 }
57}
58
59impl CanElaborate<ObType, TabObType> for Elaborator {
61 fn elab(&self, ob_type: &ObType) -> Result<TabObType, String> {
62 match ob_type {
63 ObType::Basic(id) => Ok(TabObType::Basic((*id).into())),
64 ObType::Tabulator(mor_type) => {
65 Ok(TabObType::Tabulator(Box::new(self.elab(mor_type.as_ref())?)))
66 }
67 _ => Err(format!("Cannot use object type in discrete tabulator theory: {ob_type:#?}")),
68 }
69 }
70}
71
72impl CanElaborate<MorType, TabMorType> for Elaborator {
74 fn elab(&self, mor_type: &MorType) -> Result<TabMorType, String> {
75 match mor_type {
76 MorType::Basic(id) => Ok(TabMorType::Basic((*id).into())),
77 MorType::Composite(_) => {
78 Err("Composites not yet implemented for tabulator theories".into())
79 }
80 MorType::Hom(ob_type) => Ok(TabMorType::Hom(Box::new(self.elab(ob_type.as_ref())?))),
81 _ => {
82 Err(format!("Cannot use morphism type in discrete tabulator theory: {mor_type:#?}"))
83 }
84 }
85 }
86}
87
88impl CanElaborate<ObOp, TabObOp> for Elaborator {
90 fn elab(&self, op: &ObOp) -> Result<TabObOp, String> {
91 Err(format!("Cannot use operation in discrete tabulator theory: {op:#?}"))
92 }
93}
94
95impl CanElaborate<ObType, ModalObType> for Elaborator {
97 fn elab(&self, ob_type: &ObType) -> Result<ModalObType, String> {
98 match ob_type {
99 ObType::Basic(id) => Ok(ModeApp::new((*id).into())),
100 ObType::ModeApp { modality, ob_type } => Ok({
101 let ob_type: ModalObType = self.elab(ob_type.as_ref())?;
102 ob_type.apply(promote_modality(*modality))
103 }),
104 _ => Err(format!("Cannot use object type in modal theory: {ob_type:#?}")),
105 }
106 }
107}
108
109impl CanElaborate<MorType, ModalMorType> for Elaborator {
111 fn elab(&self, mor_type: &MorType) -> Result<ModalMorType, String> {
112 match mor_type {
113 MorType::Basic(id) => Ok(ModeApp::new((*id).into()).into()),
114 MorType::Hom(ob_type) => Ok(ShortPath::Zero(self.elab(ob_type.as_ref())?)),
115 MorType::ModeApp { modality, mor_type } => Ok({
116 let mor_type: ModalMorType = self.elab(mor_type.as_ref())?;
117 mor_type.apply(promote_modality(*modality))
118 }),
119 _ => Err(format!("Cannot use morphism type in modal theory: {mor_type:#?}")),
120 }
121 }
122}
123
124impl CanElaborate<ObOp, ModalObOp> for Elaborator {
126 fn elab(&self, op: &ObOp) -> Result<ModalObOp, String> {
127 match op {
128 ObOp::Basic(id) => Ok(ModalObOp::generator((*id).into())),
129 }
130 }
131}
132
133pub(crate) fn expect_single_name(name: &QualifiedName) -> Ustr {
134 match name.only() {
135 Some(NameSegment::Text(text)) => text,
136 _ => panic!("Only singleton names are currently supported in notebook types"),
137 }
138}
139
140impl CanQuote<QualifiedName, ObType> for Quoter {
142 fn quote(&self, name: &QualifiedName) -> ObType {
143 ObType::Basic(expect_single_name(name))
144 }
145}
146
147impl CanQuote<QualifiedPath, MorType> for Quoter {
149 fn quote(&self, path: &QualifiedPath) -> MorType {
150 match path {
151 Path::Id(v) => MorType::Hom(Box::new(ObType::Basic(expect_single_name(v)))),
152 Path::Seq(edges) => {
153 if edges.len() == 1 {
154 MorType::Basic(expect_single_name(&edges.head))
155 } else {
156 MorType::Composite(
157 edges.iter().map(|e| MorType::Basic(expect_single_name(e))).collect(),
158 )
159 }
160 }
161 }
162 }
163}
164
165impl CanQuote<TabObType, ObType> for Quoter {
167 fn quote(&self, ob_type: &TabObType) -> ObType {
168 match ob_type {
169 TabObType::Basic(name) => ObType::Basic(expect_single_name(name)),
170 TabObType::Tabulator(mor_type) => {
171 ObType::Tabulator(Box::new(self.quote(mor_type.as_ref())))
172 }
173 }
174 }
175}
176
177impl CanQuote<TabMorType, MorType> for Quoter {
179 fn quote(&self, mor_type: &TabMorType) -> MorType {
180 match mor_type {
181 TabMorType::Basic(name) => MorType::Basic(expect_single_name(name)),
182 TabMorType::Hom(ob_type) => MorType::Hom(Box::new(self.quote(ob_type.as_ref()))),
183 }
184 }
185}
186
187impl CanQuote<ModalObType, ObType> for Quoter {
189 fn quote(&self, app: &ModalObType) -> ObType {
190 let mut quoted = ObType::Basic(expect_single_name(&app.arg));
191 for modality in &app.modalities {
192 quoted = ObType::ModeApp {
193 modality: demote_modality(*modality),
194 ob_type: quoted.into(),
195 }
196 }
197 quoted
198 }
199}
200
201impl CanQuote<ModalMorType, MorType> for Quoter {
203 fn quote(&self, mor_type: &ModalMorType) -> MorType {
204 match mor_type {
205 ShortPath::Zero(ob_type) => MorType::Hom(Box::new(self.quote(ob_type))),
206 ShortPath::One(app) => {
207 let mut quoted = MorType::Basic(expect_single_name(&app.arg));
208 for modality in &app.modalities {
209 quoted = MorType::ModeApp {
210 modality: demote_modality(*modality),
211 mor_type: quoted.into(),
212 }
213 }
214 quoted
215 }
216 }
217 }
218}
219
220#[derive(From, TryInto)]
227#[try_into(ref)]
228pub enum DblTheoryBox {
229 Discrete(Rc<theory::DiscreteDblTheory>),
231 DiscreteTab(Rc<theory::DiscreteTabTheory>),
233 Modal(Rc<theory::ModalDblTheory>),
235}
236
237#[wasm_bindgen]
239pub struct DblTheory(#[wasm_bindgen(skip)] pub DblTheoryBox);
240
241impl DblTheory {
242 pub fn discrete(&self) -> Result<&Rc<theory::DiscreteDblTheory>, String> {
244 (&self.0).try_into().map_err(|_| "Theory should be discrete".into())
245 }
246
247 pub fn try_into_tt(&self) -> Option<tt::theory::TheoryDef> {
249 match &self.0 {
250 DblTheoryBox::Discrete(th) => Some(tt::theory::TheoryDef::Discrete(th.clone())),
251 DblTheoryBox::Modal(th) => Some(tt::theory::TheoryDef::Modal(th.clone())),
252 _ => None,
253 }
254 }
255}
256
257#[wasm_bindgen]
258impl DblTheory {
259 #[wasm_bindgen(js_name = "hasObType")]
261 pub fn has_ob_type(&self, ob_type: ObType) -> Result<bool, String> {
262 all_the_same!(match &self.0 {
263 DblTheoryBox::[Discrete, DiscreteTab, Modal](th) => {
264 Ok(th.has_ob_type(&Elaborator.elab(&ob_type)?))
265 }
266 })
267 }
268
269 #[wasm_bindgen(js_name = "hasMorType")]
271 pub fn has_mor_type(&self, mor_type: MorType) -> Result<bool, String> {
272 all_the_same!(match &self.0 {
273 DblTheoryBox::[Discrete, DiscreteTab, Modal](th) => {
274 Ok(th.has_mor_type(&Elaborator.elab(&mor_type)?))
275 }
276 })
277 }
278
279 #[wasm_bindgen]
281 pub fn src(&self, mor_type: MorType) -> Result<ObType, String> {
282 all_the_same!(match &self.0 {
283 DblTheoryBox::[Discrete, DiscreteTab, Modal](th) => {
284 let mor_type = Elaborator.elab(&mor_type)?;
285 Ok(Quoter.quote(&th.src_type(&mor_type)))
286 }
287 })
288 }
289
290 #[wasm_bindgen]
292 pub fn tgt(&self, mor_type: MorType) -> Result<ObType, String> {
293 all_the_same!(match &self.0 {
294 DblTheoryBox::[Discrete, DiscreteTab, Modal](th) => {
295 let mor_type = Elaborator.elab(&mor_type)?;
296 Ok(Quoter.quote(&th.tgt_type(&mor_type)))
297 }
298 })
299 }
300
301 #[wasm_bindgen]
303 pub fn dom(&self, op: ObOp) -> Result<ObType, String> {
304 all_the_same!(match &self.0 {
305 DblTheoryBox::[Discrete, DiscreteTab, Modal](th) => {
306 let op = Elaborator.elab(&op)?;
307 Ok(Quoter.quote(&th.ob_op_dom(&op)))
308 }
309 })
310 }
311
312 #[wasm_bindgen]
314 pub fn cod(&self, op: ObOp) -> Result<ObType, String> {
315 all_the_same!(match &self.0 {
316 DblTheoryBox::[Discrete, DiscreteTab, Modal](th) => {
317 let op = Elaborator.elab(&op)?;
318 Ok(Quoter.quote(&th.ob_op_cod(&op)))
319 }
320 })
321 }
322
323 #[wasm_bindgen(js_name = "canInstantiateModels")]
328 pub fn can_instantiate_models(&self) -> bool {
329 !matches!(&self.0, DblTheoryBox::DiscreteTab(_))
330 }
331}
332
333#[wasm_bindgen]
338#[derive(Clone, Default)]
339pub struct ObTypeIndex(HashMap<ObType, usize>);
340
341#[wasm_bindgen]
342impl ObTypeIndex {
343 #[wasm_bindgen(constructor)]
345 pub fn new() -> Self {
346 Default::default()
347 }
348
349 #[wasm_bindgen(js_name = "has")]
351 pub fn contains_key(&self, x: &ObType) -> bool {
352 self.0.contains_key(x)
353 }
354
355 #[wasm_bindgen]
357 pub fn get(&self, x: &ObType) -> Option<usize> {
358 self.0.get(x).copied()
359 }
360
361 #[wasm_bindgen(js_name = "set")]
363 pub fn insert(&mut self, x: ObType, i: usize) {
364 self.0.insert(x, i);
365 }
366}
367
368#[wasm_bindgen]
373#[derive(Clone, Default)]
374pub struct MorTypeIndex(HashMap<MorType, usize>);
375
376#[wasm_bindgen]
377impl MorTypeIndex {
378 #[wasm_bindgen(constructor)]
380 pub fn new() -> Self {
381 Default::default()
382 }
383
384 #[wasm_bindgen(js_name = "has")]
386 pub fn contains_key(&self, m: &MorType) -> bool {
387 self.0.contains_key(m)
388 }
389
390 #[wasm_bindgen]
392 pub fn get(&self, m: &MorType) -> Option<usize> {
393 self.0.get(m).copied()
394 }
395
396 #[wasm_bindgen(js_name = "set")]
398 pub fn insert(&mut self, m: MorType, i: usize) {
399 self.0.insert(m, i);
400 }
401}