Skip to content

Commit d853c53

Browse files
authored
Merge pull request #261 from ToposInstitute/model-diagram-wasm
Wasm bindings for diagrams for discrete theories, and frontend integration
2 parents 85b3f3d + 3206623 commit d853c53

34 files changed

+592
-365
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/catlog-wasm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ default = ["console_error_panic_hook"]
1414
all-the-same = "1.1.0"
1515
catlog = { path = "../catlog", features = ["ode", "serde-wasm"] }
1616
console_error_panic_hook = { version = "0.1.7", optional = true }
17+
derive_more = { version = "1", features = ["from", "try_into"] }
1718
getrandom = { version = "0.2", features = ["js"] }
1819
js-sys = "0.3.69"
1920
nonempty = { version = "0.10", features = ["serialize"] }

packages/catlog-wasm/src/diagram.rs

Lines changed: 0 additions & 68 deletions
This file was deleted.

packages/catlog-wasm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod result;
22

3-
pub mod diagram;
43
pub mod model;
4+
pub mod model_diagram;
55
pub mod model_morphism;
66
pub mod theory;
77

packages/catlog-wasm/src/model.rs

Lines changed: 57 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
//! Wasm bindings for models of double theories.
22
33
use all_the_same::all_the_same;
4+
use derive_more::{From, TryInto};
45
use uuid::Uuid;
56

67
use serde::{Deserialize, Serialize};
78
use tsify_next::Tsify;
89
use wasm_bindgen::prelude::*;
910

10-
use super::theory::*;
1111
use catlog::dbl::model::{self as dbl_model, FgDblModel, InvalidDiscreteDblModel};
1212
use catlog::one::fin_category::UstrFinCategory;
13-
use catlog::one::Path;
14-
use catlog::one::{Category as _, FgCategory};
15-
use catlog::validate::{self, Validate};
13+
use catlog::one::{Category as _, FgCategory, Path};
14+
use catlog::validate::Validate;
15+
16+
use super::result::JsResult;
17+
use super::theory::{DblTheory, DblTheoryBox, MorType, ObType};
1618

1719
/// An object in a model of a double theory.
18-
#[derive(Debug, Serialize, Deserialize, Tsify)]
20+
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Tsify)]
1921
#[serde(tag = "tag", content = "content")]
2022
#[tsify(into_wasm_abi, from_wasm_abi)]
2123
pub enum Ob {
@@ -27,7 +29,7 @@ pub enum Ob {
2729
}
2830

2931
/// A morphism in a model of a double theory.
30-
#[derive(Debug, Serialize, Deserialize, Tsify)]
32+
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Tsify)]
3133
#[serde(tag = "tag", content = "content")]
3234
#[tsify(into_wasm_abi, from_wasm_abi)]
3335
pub enum Mor {
@@ -113,36 +115,19 @@ pub struct MorDecl {
113115
pub cod: Option<Ob>,
114116
}
115117

116-
type UuidDiscreteDblModel = dbl_model::DiscreteDblModel<Uuid, UstrFinCategory>;
118+
pub(crate) type DiscreteDblModel = dbl_model::DiscreteDblModel<Uuid, UstrFinCategory>;
117119

118120
/** A box containing a model of a double theory of any kind.
119121
120122
See [`DblTheoryBox`] for motivation.
121123
*/
124+
#[derive(From, TryInto)]
125+
#[try_into(ref)]
122126
pub enum DblModelBox {
123-
Discrete(UuidDiscreteDblModel),
127+
Discrete(DiscreteDblModel),
124128
// DiscreteTab(()), // TODO: Not yet implemented.
125129
}
126130

127-
/// Converts from a model of a discrete double theory.
128-
impl From<UuidDiscreteDblModel> for DblModel {
129-
fn from(model: UuidDiscreteDblModel) -> Self {
130-
DblModel(DblModelBox::Discrete(model))
131-
}
132-
}
133-
134-
/// Converts into a model of a dicrete double theory.
135-
impl<'a> TryFrom<&'a DblModel> for &'a UuidDiscreteDblModel {
136-
type Error = String;
137-
138-
fn try_from(model: &'a DblModel) -> Result<Self, Self::Error> {
139-
match &model.0 {
140-
DblModelBox::Discrete(model) => Ok(model),
141-
//_ => Err("Cannot cast into a model of a discrete double theory".into()),
142-
}
143-
}
144-
}
145-
146131
/// Wasm bindings for a model of a double theory.
147132
#[wasm_bindgen]
148133
pub struct DblModel(#[wasm_bindgen(skip)] pub DblModelBox);
@@ -153,9 +138,7 @@ impl DblModel {
153138
#[wasm_bindgen(constructor)]
154139
pub fn new(theory: &DblTheory) -> Self {
155140
Self(match &theory.0 {
156-
DblTheoryBox::Discrete(th) => {
157-
DblModelBox::Discrete(UuidDiscreteDblModel::new(th.clone()))
158-
}
141+
DblTheoryBox::Discrete(th) => DiscreteDblModel::new(th.clone()).into(),
159142
DblTheoryBox::DiscreteTab(_) => panic!("Not implemented"),
160143
})
161144
}
@@ -178,10 +161,12 @@ impl DblModel {
178161
DblModelBox::[Discrete](model) => {
179162
let mor_type = decl.mor_type.try_into()?;
180163
let res = model.make_mor(decl.id, mor_type);
181-
let dom = decl.dom.map(|ob| ob.try_into()).transpose()?;
182-
let cod = decl.cod.map(|ob| ob.try_into()).transpose()?;
183-
model.update_dom(decl.id, dom);
184-
model.update_cod(decl.id, cod);
164+
if let Some(dom) = decl.dom.map(|ob| ob.try_into()).transpose()? {
165+
model.set_dom(decl.id, dom);
166+
}
167+
if let Some(cod) = decl.cod.map(|ob| ob.try_into()).transpose()? {
168+
model.set_cod(decl.id, cod);
169+
}
185170
Ok(res)
186171
}
187172
})
@@ -249,48 +234,68 @@ impl DblModel {
249234

250235
/// Validates that the model is well defined.
251236
#[wasm_bindgen]
252-
pub fn validate(&self) -> Vec<InvalidDiscreteDblModel<Uuid>> {
237+
pub fn validate(&self) -> ModelValidationResult {
253238
all_the_same!(match &self.0 {
254-
DblModelBox::[Discrete](model) => validate::unwrap_errors(model.validate())
239+
DblModelBox::[Discrete](model) => {
240+
let res = model.validate();
241+
ModelValidationResult(res.map_err(|errs| errs.into()).into())
242+
}
255243
})
256244
}
257245
}
258246

247+
/// Result of validating a model of a double theory.
248+
#[derive(Serialize, Deserialize, Tsify)]
249+
#[tsify(into_wasm_abi, from_wasm_abi)]
250+
pub struct ModelValidationResult(pub JsResult<(), Vec<InvalidDiscreteDblModel<Uuid>>>);
251+
259252
#[cfg(test)]
260-
mod tests {
253+
pub(crate) mod tests {
261254
use super::*;
262255
use crate::theories::*;
263256

264-
#[test]
265-
fn model_schema() {
266-
let th = ThSchema::new().theory();
267-
let mut model = DblModel::new(&th);
268-
let (x, y, a) = (Uuid::now_v7(), Uuid::now_v7(), Uuid::now_v7());
257+
pub(crate) fn sch_walking_attr(th: &DblTheory, ids: [Uuid; 3]) -> DblModel {
258+
let mut model = DblModel::new(th);
259+
let [attr, entity, attr_type] = ids;
269260
assert!(model
270261
.add_ob(ObDecl {
271-
id: x,
262+
id: entity,
272263
ob_type: ObType::Basic("Entity".into()),
273264
})
274265
.is_ok());
275266
assert!(model
276267
.add_ob(ObDecl {
277-
id: y,
268+
id: attr_type,
278269
ob_type: ObType::Basic("AttrType".into()),
279270
})
280271
.is_ok());
281272
assert!(model
282273
.add_mor(MorDecl {
283-
id: a,
274+
id: attr,
284275
mor_type: MorType::Basic("Attr".into()),
285-
dom: Some(Ob::Basic(x)),
286-
cod: Some(Ob::Basic(y)),
276+
dom: Some(Ob::Basic(entity)),
277+
cod: Some(Ob::Basic(attr_type)),
287278
})
288279
.is_ok());
280+
model
281+
}
282+
283+
#[test]
284+
fn model_schema() {
285+
let th = ThSchema::new().theory();
286+
let [a, x, y] = [Uuid::now_v7(), Uuid::now_v7(), Uuid::now_v7()];
287+
let model = sch_walking_attr(&th, [a, x, y]);
288+
289289
assert_eq!(model.has_ob(Ob::Basic(x)), Ok(true));
290290
assert_eq!(model.has_mor(Mor::Basic(a)), Ok(true));
291291
assert_eq!(model.objects().len(), 2);
292292
assert_eq!(model.morphisms().len(), 1);
293-
assert!(model.validate().is_empty());
293+
assert_eq!(model.objects_with_type(ObType::Basic("Entity".into())), Ok(vec![Ob::Basic(x)]));
294+
assert_eq!(
295+
model.morphisms_with_type(MorType::Basic("Attr".into())),
296+
Ok(vec![Mor::Basic(a)])
297+
);
298+
assert_eq!(model.validate().0, JsResult::Ok(()));
294299

295300
let mut model = DblModel::new(&th);
296301
assert!(model
@@ -301,6 +306,9 @@ mod tests {
301306
cod: Some(Ob::Basic(y)),
302307
})
303308
.is_ok());
304-
assert_eq!(model.validate().len(), 2);
309+
let JsResult::Err(errs) = model.validate().0 else {
310+
panic!("Model should not validate")
311+
};
312+
assert_eq!(errs.len(), 2);
305313
}
306314
}

0 commit comments

Comments
 (0)