-
Notifications
You must be signed in to change notification settings - Fork 48
Auto-detect and import Petrinaut JSON #1187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| import { v7 } from "uuid"; | ||
|
|
||
| import { | ||
| currentVersion, | ||
| type Document, | ||
| type ModelJudgment, | ||
| type NotebookCell, | ||
| type Ob, | ||
| } from "catlog-wasm"; | ||
|
|
||
| /** Detects a Petrinaut-exported JSON file. */ | ||
| export function isFromPetrinaut(data: unknown): boolean { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a typical use case for type predicates: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates So the signature of this function would become: export function isFromPetrinaut(data: unknown): data is PetrinautFile { |
||
| if (typeof data !== "object" || data === null) { | ||
| return false; | ||
| } | ||
| const { meta } = data as Record<string, unknown>; | ||
| if (typeof meta !== "object" || meta === null) { | ||
| return false; | ||
| } | ||
| const { generator } = meta as Record<string, unknown>; | ||
| return generator === "Petrinaut"; | ||
| } | ||
|
|
||
| // Petrinaut schema fragment that we're interested in | ||
|
|
||
| type PetrinautArc = { placeId: string }; | ||
|
|
||
| type PetrinautPlace = { id: string; name: string }; | ||
|
|
||
| type PetrinautTransition = { | ||
| id: string; | ||
| name: string; | ||
| inputArcs: PetrinautArc[]; | ||
| outputArcs: PetrinautArc[]; | ||
| }; | ||
|
|
||
| type PetrinautFile = { | ||
| title: string; | ||
| places: PetrinautPlace[]; | ||
| transitions: PetrinautTransition[]; | ||
| }; | ||
|
|
||
| function tensorOb(contentIds: string[]): Ob { | ||
| return { | ||
| tag: "App", | ||
| content: { | ||
| op: { tag: "Basic", content: "tensor" }, | ||
| ob: { | ||
| tag: "List", | ||
| content: { | ||
| modality: "SymmetricList", | ||
| objects: contentIds.map((id) => ({ tag: "Basic", content: id })), | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| /** Converts a Petrinaut-exported JSON file to a CatCoLab petri-net model document. */ | ||
| export function convertFromPetrinaut(data: unknown): Document { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the above change, you can give this function the desired signature and avoid an explicit type in the function body: export function convertFromPetrinaut(data: PetrinautFile): Document { |
||
| const { title, places, transitions } = data as PetrinautFile; | ||
|
|
||
| const placeIds = new Map<string, { cellId: string; contentId: string }>(); | ||
| for (const place of places) { | ||
| placeIds.set(place.id, { cellId: v7(), contentId: v7() }); | ||
| } | ||
|
|
||
| const cellOrder: string[] = []; | ||
| const cellContents: Record<string, NotebookCell<ModelJudgment>> = {}; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not too important, but I'd suggest using the helpers in |
||
|
|
||
| for (const place of places) { | ||
| const { cellId, contentId } = placeIds.get(place.id)!; | ||
| cellOrder.push(cellId); | ||
| cellContents[cellId] = { | ||
| id: cellId, | ||
| tag: "formal", | ||
| content: { | ||
| tag: "object", | ||
| id: contentId, | ||
| name: place.name, | ||
| obType: { tag: "Basic" as const, content: "Object" }, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| for (const transition of transitions) { | ||
| const cellId = v7(); | ||
| const contentId = v7(); | ||
| const domContentIds = transition.inputArcs.map( | ||
| (arc) => placeIds.get(arc.placeId)!.contentId, | ||
| ); | ||
| const codContentIds = transition.outputArcs.map( | ||
| (arc) => placeIds.get(arc.placeId)!.contentId, | ||
| ); | ||
| cellOrder.push(cellId); | ||
| cellContents[cellId] = { | ||
| id: cellId, | ||
| tag: "formal", | ||
| content: { | ||
| tag: "morphism", | ||
| id: contentId, | ||
| name: transition.name, | ||
| morType: { | ||
| tag: "Hom" as const, | ||
| content: { tag: "Basic" as const, content: "Object" }, | ||
| }, | ||
| dom: tensorOb(domContentIds), | ||
| cod: tensorOb(codContentIds), | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| return { | ||
| type: "model", | ||
| theory: "petri-net", | ||
| name: title, | ||
| version: currentVersion(), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A more future proof way would be to set this to "1" explicitly and call
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't have strong feelings about this, only to say that i hope that by the time the schema changes the way that we interop with petrinaut is not via parsing some fraction of their json schema and converting it to our notebook schema :) |
||
| notebook: { cellOrder, cellContents }, | ||
| }; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this code isn't intended to stick around for a long time (famous last words), but this folder still feels like the wrong place for it. Perhaps
src/model/orsrc/stdlib/instead?