@rsconcept/domain 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/dist/cctext/index.d.ts +1 -0
- package/dist/cctext/index.js +42 -0
- package/dist/cctext/index.js.map +1 -0
- package/dist/cctext/language-api.d.ts +43 -0
- package/dist/cctext/language-api.js +252 -0
- package/dist/cctext/language-api.js.map +1 -0
- package/dist/cctext/language.d.ts +58 -0
- package/dist/cctext/language.js +44 -0
- package/dist/cctext/language.js.map +1 -0
- package/dist/graph/graph.d.ts +62 -0
- package/dist/graph/graph.js +385 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/index.d.ts +1 -0
- package/dist/graph/index.js +384 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +5851 -0
- package/dist/index.js.map +1 -0
- package/dist/library/folder-tree.d.ts +32 -0
- package/dist/library/folder-tree.js +136 -0
- package/dist/library/folder-tree.js.map +1 -0
- package/dist/library/index.d.ts +17 -0
- package/dist/library/index.js +2800 -0
- package/dist/library/index.js.map +1 -0
- package/dist/library/library-api.d.ts +6 -0
- package/dist/library/library-api.js +13 -0
- package/dist/library/library-api.js.map +1 -0
- package/dist/library/library.d.ts +56 -0
- package/dist/library/library.js +23 -0
- package/dist/library/library.js.map +1 -0
- package/dist/library/oss-api.d.ts +47 -0
- package/dist/library/oss-api.js +1105 -0
- package/dist/library/oss-api.js.map +1 -0
- package/dist/library/oss-layout-api.d.ts +36 -0
- package/dist/library/oss-layout-api.js +330 -0
- package/dist/library/oss-layout-api.js.map +1 -0
- package/dist/library/oss-layout.d.ts +25 -0
- package/dist/library/oss-layout.js +1 -0
- package/dist/library/oss-layout.js.map +1 -0
- package/dist/library/oss.d.ts +136 -0
- package/dist/library/oss.js +30 -0
- package/dist/library/oss.js.map +1 -0
- package/dist/library/rsengine.d.ts +116 -0
- package/dist/library/rsengine.js +2604 -0
- package/dist/library/rsengine.js.map +1 -0
- package/dist/library/rsform-api.d.ts +74 -0
- package/dist/library/rsform-api.js +879 -0
- package/dist/library/rsform-api.js.map +1 -0
- package/dist/library/rsform.d.ts +206 -0
- package/dist/library/rsform.js +32 -0
- package/dist/library/rsform.js.map +1 -0
- package/dist/library/rsmodel-api.d.ts +43 -0
- package/dist/library/rsmodel-api.js +836 -0
- package/dist/library/rsmodel-api.js.map +1 -0
- package/dist/library/rsmodel.d.ts +52 -0
- package/dist/library/rsmodel.js +25 -0
- package/dist/library/rsmodel.js.map +1 -0
- package/dist/library/structure-planner.d.ts +33 -0
- package/dist/library/structure-planner.js +481 -0
- package/dist/library/structure-planner.js.map +1 -0
- package/dist/parsing/ast.d.ts +49 -0
- package/dist/parsing/ast.js +93 -0
- package/dist/parsing/ast.js.map +1 -0
- package/dist/parsing/index.d.ts +3 -0
- package/dist/parsing/index.js +141 -0
- package/dist/parsing/index.js.map +1 -0
- package/dist/parsing/lezer-tree.d.ts +13 -0
- package/dist/parsing/lezer-tree.js +50 -0
- package/dist/parsing/lezer-tree.js.map +1 -0
- package/dist/rslang/api.d.ts +53 -0
- package/dist/rslang/api.js +846 -0
- package/dist/rslang/api.js.map +1 -0
- package/dist/rslang/ast-annotations.d.ts +18 -0
- package/dist/rslang/ast-annotations.js +56 -0
- package/dist/rslang/ast-annotations.js.map +1 -0
- package/dist/rslang/error.d.ts +85 -0
- package/dist/rslang/error.js +159 -0
- package/dist/rslang/error.js.map +1 -0
- package/dist/rslang/eval/calculator.d.ts +43 -0
- package/dist/rslang/eval/calculator.js +1639 -0
- package/dist/rslang/eval/calculator.js.map +1 -0
- package/dist/rslang/eval/evaluation-cache.d.ts +36 -0
- package/dist/rslang/eval/evaluation-cache.js +310 -0
- package/dist/rslang/eval/evaluation-cache.js.map +1 -0
- package/dist/rslang/eval/evaluator.d.ts +70 -0
- package/dist/rslang/eval/evaluator.js +1514 -0
- package/dist/rslang/eval/evaluator.js.map +1 -0
- package/dist/rslang/eval/value-api.d.ts +48 -0
- package/dist/rslang/eval/value-api.js +490 -0
- package/dist/rslang/eval/value-api.js.map +1 -0
- package/dist/rslang/eval/value.d.ts +36 -0
- package/dist/rslang/eval/value.js +118 -0
- package/dist/rslang/eval/value.js.map +1 -0
- package/dist/rslang/index.d.ts +17 -0
- package/dist/rslang/index.js +4314 -0
- package/dist/rslang/index.js.map +1 -0
- package/dist/rslang/labels.d.ts +16 -0
- package/dist/rslang/labels.js +315 -0
- package/dist/rslang/labels.js.map +1 -0
- package/dist/rslang/parser/expression-generator.d.ts +10 -0
- package/dist/rslang/parser/expression-generator.js +451 -0
- package/dist/rslang/parser/expression-generator.js.map +1 -0
- package/dist/rslang/parser/normalize.d.ts +11 -0
- package/dist/rslang/parser/normalize.js +507 -0
- package/dist/rslang/parser/normalize.js.map +1 -0
- package/dist/rslang/parser/parser.d.ts +5 -0
- package/dist/rslang/parser/parser.js +24 -0
- package/dist/rslang/parser/parser.js.map +1 -0
- package/dist/rslang/parser/parser.terms.d.ts +42 -0
- package/dist/rslang/parser/parser.terms.js +84 -0
- package/dist/rslang/parser/parser.terms.js.map +1 -0
- package/dist/rslang/parser/syntax-errors.d.ts +11 -0
- package/dist/rslang/parser/syntax-errors.js +403 -0
- package/dist/rslang/parser/syntax-errors.js.map +1 -0
- package/dist/rslang/parser/token.d.ts +79 -0
- package/dist/rslang/parser/token.js +95 -0
- package/dist/rslang/parser/token.js.map +1 -0
- package/dist/rslang/semantic/analyzer.d.ts +39 -0
- package/dist/rslang/semantic/analyzer.js +2604 -0
- package/dist/rslang/semantic/analyzer.js.map +1 -0
- package/dist/rslang/semantic/arguments-extractor.d.ts +42 -0
- package/dist/rslang/semantic/arguments-extractor.js +366 -0
- package/dist/rslang/semantic/arguments-extractor.js.map +1 -0
- package/dist/rslang/semantic/type-auditor.d.ts +73 -0
- package/dist/rslang/semantic/type-auditor.js +1570 -0
- package/dist/rslang/semantic/type-auditor.js.map +1 -0
- package/dist/rslang/semantic/typification-api.d.ts +27 -0
- package/dist/rslang/semantic/typification-api.js +320 -0
- package/dist/rslang/semantic/typification-api.js.map +1 -0
- package/dist/rslang/semantic/typification-parser.d.ts +12 -0
- package/dist/rslang/semantic/typification-parser.js +226 -0
- package/dist/rslang/semantic/typification-parser.js.map +1 -0
- package/dist/rslang/semantic/typification.d.ts +119 -0
- package/dist/rslang/semantic/typification.js +74 -0
- package/dist/rslang/semantic/typification.js.map +1 -0
- package/dist/rslang/semantic/value-auditor.d.ts +43 -0
- package/dist/rslang/semantic/value-auditor.js +523 -0
- package/dist/rslang/semantic/value-auditor.js.map +1 -0
- package/dist/rslang/semantic/value-class.d.ts +10 -0
- package/dist/rslang/semantic/value-class.js +9 -0
- package/dist/rslang/semantic/value-class.js.map +1 -0
- package/dist/rslang/typification-graph.d.ts +33 -0
- package/dist/rslang/typification-graph.js +311 -0
- package/dist/rslang/typification-graph.js.map +1 -0
- package/dist/shared/branded.d.ts +7 -0
- package/dist/shared/branded.js +1 -0
- package/dist/shared/branded.js.map +1 -0
- package/dist/shared/hash.d.ts +6 -0
- package/dist/shared/hash.js +18 -0
- package/dist/shared/hash.js.map +1 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +18 -0
- package/dist/shared/index.js.map +1 -0
- package/package.json +184 -0
- package/src/cctext/index.ts +9 -0
- package/src/cctext/language-api.test.ts +149 -0
- package/src/cctext/language-api.ts +285 -0
- package/src/cctext/language.ts +80 -0
- package/src/graph/graph.test.ts +392 -0
- package/src/graph/graph.ts +433 -0
- package/src/graph/index.ts +1 -0
- package/src/index.ts +96 -0
- package/src/library/folder-tree.test.ts +47 -0
- package/src/library/folder-tree.ts +156 -0
- package/src/library/index.ts +46 -0
- package/src/library/library-api.test.ts +32 -0
- package/src/library/library-api.ts +11 -0
- package/src/library/library.ts +61 -0
- package/src/library/oss-api.ts +449 -0
- package/src/library/oss-layout-api.ts +377 -0
- package/src/library/oss-layout.ts +27 -0
- package/src/library/oss.ts +150 -0
- package/src/library/rsengine.ts +593 -0
- package/src/library/rsform-api.ts +533 -0
- package/src/library/rsform.ts +228 -0
- package/src/library/rsmodel-api.ts +340 -0
- package/src/library/rsmodel.ts +50 -0
- package/src/library/structure-planner.ts +143 -0
- package/src/parsing/ast.ts +136 -0
- package/src/parsing/index.ts +15 -0
- package/src/parsing/lezer-tree.ts +69 -0
- package/src/rslang/api.test.ts +116 -0
- package/src/rslang/api.ts +183 -0
- package/src/rslang/ast-annotations.ts +70 -0
- package/src/rslang/error.ts +129 -0
- package/src/rslang/eval/calculator.test.ts +124 -0
- package/src/rslang/eval/calculator.ts +121 -0
- package/src/rslang/eval/evaluation-cache.ts +257 -0
- package/src/rslang/eval/evaluator.test.ts +352 -0
- package/src/rslang/eval/evaluator.ts +935 -0
- package/src/rslang/eval/value-api.test.ts +105 -0
- package/src/rslang/eval/value-api.ts +444 -0
- package/src/rslang/eval/value.ts +102 -0
- package/src/rslang/index.ts +23 -0
- package/src/rslang/labels.ts +191 -0
- package/src/rslang/parser/expression-generator.test.ts +100 -0
- package/src/rslang/parser/expression-generator.ts +466 -0
- package/src/rslang/parser/normalize.test.ts +99 -0
- package/src/rslang/parser/normalize.ts +462 -0
- package/src/rslang/parser/parser.terms.ts +42 -0
- package/src/rslang/parser/parser.test.ts +153 -0
- package/src/rslang/parser/parser.ts +20 -0
- package/src/rslang/parser/rslang.grammar +251 -0
- package/src/rslang/parser/syntax-errors.ts +209 -0
- package/src/rslang/parser/token.ts +106 -0
- package/src/rslang/semantic/analyzer.test.ts +59 -0
- package/src/rslang/semantic/analyzer.ts +179 -0
- package/src/rslang/semantic/arguments-extractor.ts +327 -0
- package/src/rslang/semantic/type-auditor.test.ts +326 -0
- package/src/rslang/semantic/type-auditor.ts +1049 -0
- package/src/rslang/semantic/typification-api.test.ts +46 -0
- package/src/rslang/semantic/typification-api.ts +321 -0
- package/src/rslang/semantic/typification-parser.test.ts +50 -0
- package/src/rslang/semantic/typification-parser.ts +220 -0
- package/src/rslang/semantic/typification.ts +180 -0
- package/src/rslang/semantic/value-auditor.test.ts +206 -0
- package/src/rslang/semantic/value-auditor.ts +332 -0
- package/src/rslang/semantic/value-class.ts +11 -0
- package/src/rslang/typification-graph.ts +155 -0
- package/src/shared/branded.ts +6 -0
- package/src/shared/hash.ts +17 -0
- package/src/shared/index.ts +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/graph/graph.ts","../../src/parsing/ast.ts","../../src/rslang/parser/token.ts","../../src/rslang/api.ts","../../src/rslang/semantic/typification.ts","../../src/rslang/labels.ts","../../src/rslang/semantic/typification-api.ts","../../src/library/oss.ts","../../src/library/rsform.ts","../../src/library/oss-api.ts"],"sourcesContent":["/**\n * Module: Custom graph data structure.\n */\n\n/** Represents single node of a {@link Graph}, as implemented by storing outgoing and incoming connections. */\nexport class GraphNode<NodeID> {\n /** Unique identifier of the node. */\n id: NodeID;\n /** List of outgoing nodes. */\n outputs: NodeID[];\n /** List of incoming nodes. */\n inputs: NodeID[];\n\n constructor(id: NodeID) {\n this.id = id;\n this.outputs = [];\n this.inputs = [];\n }\n\n clone(): GraphNode<NodeID> {\n const result = new GraphNode(this.id);\n result.outputs = [...this.outputs];\n result.inputs = [...this.inputs];\n return result;\n }\n\n addOutput(node: NodeID): void {\n this.outputs.push(node);\n }\n\n addInput(node: NodeID): void {\n this.inputs.push(node);\n }\n\n removeInput(target: NodeID): NodeID | null {\n const index = this.inputs.findIndex(node => node === target);\n return index > -1 ? this.inputs.splice(index, 1)[0] : null;\n }\n\n removeOutput(target: NodeID): NodeID | null {\n const index = this.outputs.findIndex(node => node === target);\n return index > -1 ? this.outputs.splice(index, 1)[0] : null;\n }\n}\n\n/**\n * Represents a Graph.\n *\n * This class is optimized for TermGraph use case and not supposed to be used as generic graph implementation.\n */\nexport class Graph<NodeID = number> {\n /** Map of nodes. */\n nodes = new Map<NodeID, GraphNode<NodeID>>();\n\n constructor(arr?: NodeID[][]) {\n if (!arr) {\n return;\n }\n arr.forEach(edge => {\n if (edge.length === 1) {\n this.addNode(edge[0]);\n } else {\n this.addEdge(edge[0], edge[1]);\n }\n });\n }\n\n clone(): Graph<NodeID> {\n const result = new Graph<NodeID>();\n this.nodes.forEach(node => result.nodes.set(node.id, node.clone()));\n return result;\n }\n\n at(target: NodeID): GraphNode<NodeID> | undefined {\n return this.nodes.get(target);\n }\n\n addNode(target: NodeID): GraphNode<NodeID> {\n let node = this.nodes.get(target);\n if (!node) {\n node = new GraphNode(target);\n this.nodes.set(target, node);\n }\n return node;\n }\n\n hasNode(target: NodeID): boolean {\n return !!this.nodes.get(target);\n }\n\n removeNode(target: NodeID): void {\n this.nodes.forEach(node => {\n node.removeInput(target);\n node.removeOutput(target);\n });\n this.nodes.delete(target);\n }\n\n foldNode(target: NodeID): void {\n const nodeToRemove = this.nodes.get(target);\n if (!nodeToRemove) {\n return;\n }\n nodeToRemove.inputs.forEach(input => {\n nodeToRemove.outputs.forEach(output => {\n this.addEdge(input, output);\n });\n });\n this.removeNode(target);\n }\n\n removeIsolated(): GraphNode<NodeID>[] {\n const result: GraphNode<NodeID>[] = [];\n this.nodes.forEach(node => {\n if (node.outputs.length === 0 && node.inputs.length === 0) {\n result.push(node);\n this.nodes.delete(node.id);\n }\n });\n return result;\n }\n\n addEdge(source: NodeID, destination: NodeID): void {\n if (this.hasEdge(source, destination)) {\n return;\n }\n const sourceNode = this.addNode(source);\n const destinationNode = this.addNode(destination);\n sourceNode.addOutput(destinationNode.id);\n destinationNode.addInput(sourceNode.id);\n }\n\n removeEdge(source: NodeID, destination: NodeID): void {\n const sourceNode = this.nodes.get(source);\n const destinationNode = this.nodes.get(destination);\n if (sourceNode && destinationNode) {\n sourceNode.removeOutput(destination);\n destinationNode.removeInput(source);\n }\n }\n\n hasEdge(source: NodeID, destination: NodeID): boolean {\n const sourceNode = this.nodes.get(source);\n if (!sourceNode) {\n return false;\n }\n return !!sourceNode.outputs.find(id => id === destination);\n }\n\n isReachable(source: NodeID, destination: NodeID): boolean {\n return this.expandAllOutputs([source]).includes(destination);\n }\n\n rootNodes(): NodeID[] {\n return [...this.nodes.keys()].filter(id => !this.nodes.get(id)?.inputs.length);\n }\n\n expandOutputs(origin: NodeID[]): NodeID[] {\n const result: NodeID[] = [];\n origin.forEach(id => {\n const node = this.nodes.get(id);\n if (node) {\n node.outputs.forEach(child => {\n if (!origin.includes(child) && !result.includes(child)) {\n result.push(child);\n }\n });\n }\n });\n return result;\n }\n\n expandInputs(origin: NodeID[]): NodeID[] {\n const result: NodeID[] = [];\n origin.forEach(id => {\n const node = this.nodes.get(id);\n if (node) {\n node.inputs.forEach(child => {\n if (!origin.includes(child) && !result.includes(child)) {\n result.push(child);\n }\n });\n }\n });\n return result;\n }\n\n expandAllOutputs(origin: NodeID[]): NodeID[] {\n const result: NodeID[] = this.expandOutputs(origin);\n if (result.length === 0) {\n return [];\n }\n\n const marked = new Map<NodeID, boolean>();\n origin.forEach(id => marked.set(id, true));\n let position = 0;\n while (position < result.length) {\n const node = this.nodes.get(result[position]);\n if (node && !marked.get(node.id)) {\n marked.set(node.id, true);\n node.outputs.forEach(child => {\n if (!marked.get(child) && !result.find(id => id === child)) {\n result.push(child);\n }\n });\n }\n position += 1;\n }\n return result;\n }\n\n expandAllInputs(origin: NodeID[]): NodeID[] {\n const result: NodeID[] = this.expandInputs(origin);\n if (result.length === 0) {\n return [];\n }\n\n const marked = new Map<NodeID, boolean>();\n origin.forEach(id => marked.set(id, true));\n let position = 0;\n while (position < result.length) {\n const node = this.nodes.get(result[position]);\n if (node && !marked.get(node.id)) {\n marked.set(node.id, true);\n node.inputs.forEach(child => {\n if (!marked.get(child) && !result.find(id => id === child)) {\n result.push(child);\n }\n });\n }\n position += 1;\n }\n return result;\n }\n\n maximizePart(origin: NodeID[]): NodeID[] {\n const outputs: NodeID[] = this.expandAllOutputs(origin);\n const result = [...origin];\n this.topologicalOrder()\n .filter(id => outputs.includes(id))\n .forEach(id => {\n const node = this.nodes.get(id);\n if (node?.inputs.every(parent => result.includes(parent))) {\n result.push(id);\n }\n });\n return result;\n }\n\n topologicalOrder(): NodeID[] {\n const result: NodeID[] = [];\n const marked = new Set<NodeID>();\n const nodeStack: NodeID[] = [];\n this.nodes.forEach(node => {\n if (marked.has(node.id)) {\n return;\n }\n nodeStack.push(node.id);\n while (nodeStack.length > 0) {\n const item = nodeStack[nodeStack.length - 1];\n if (marked.has(item)) {\n if (!result.find(id => id === item)) {\n result.push(item);\n }\n nodeStack.pop();\n } else {\n marked.add(item);\n const itemNode = this.nodes.get(item);\n if (itemNode && itemNode.outputs.length > 0) {\n itemNode.outputs.forEach(child => {\n if (!marked.has(child)) {\n nodeStack.push(child);\n }\n });\n }\n }\n }\n });\n return result.reverse();\n }\n\n /**\n * Stably reorders the given node ids so that, for this DAG, no node appears before a transitive\n * successor (edges: source → dependent; {@link GraphNode.outputs} lists dependents).\n */\n sortStable(target: NodeID[]): NodeID[] {\n if (target.length <= 1) {\n return [...target];\n }\n\n const reachable = this.buildTransitiveClosureForSort();\n const testSet = new Set<NodeID>();\n const result: NodeID[] = [];\n\n for (const nodeId of [...target].reverse()) {\n const nodeReachable = reachable.get(nodeId) ?? new Set<NodeID>();\n const needMove = testSet.has(nodeId);\n for (const childId of nodeReachable) {\n testSet.add(childId);\n }\n\n if (!needMove) {\n result.push(nodeId);\n continue;\n }\n\n let inserted = false;\n for (let index = 0; index < result.length; index++) {\n const parent = result[index];\n const parentReachable = reachable.get(parent) ?? new Set<NodeID>();\n if (nodeReachable.has(parent)) {\n if (parentReachable.has(nodeId)) {\n result.push(nodeId);\n } else {\n result.splice(index, 0, nodeId);\n }\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n result.push(nodeId);\n }\n }\n\n result.reverse();\n return result;\n }\n\n private buildTransitiveClosureForSort(): Map<NodeID, Set<NodeID>> {\n const closure = new Map<NodeID, Set<NodeID>>();\n for (const node of this.nodes.values()) {\n closure.set(node.id, new Set(node.outputs));\n }\n\n const order = this.topologicalOrder();\n for (const nodeId of [...order].reverse()) {\n const node = this.at(nodeId);\n if (!node) {\n continue;\n }\n const nodeClosure = closure.get(nodeId) ?? new Set<NodeID>();\n for (const parentId of node.inputs) {\n const parentClosure = closure.get(parentId) ?? new Set<NodeID>();\n for (const childId of nodeClosure) {\n parentClosure.add(childId);\n }\n closure.set(parentId, parentClosure);\n }\n }\n\n return closure;\n }\n\n transitiveReduction() {\n const order = this.topologicalOrder();\n const marked = new Map<NodeID, boolean>();\n order.forEach(nodeID => {\n if (marked.get(nodeID)) {\n return;\n }\n const stack: { id: NodeID; parents: NodeID[] }[] = [];\n stack.push({ id: nodeID, parents: [] });\n while (stack.length > 0) {\n const item = stack.splice(0, 1)[0];\n const node = this.nodes.get(item.id);\n if (node) {\n node.outputs.forEach(child => {\n item.parents.forEach(parent => this.removeEdge(parent, child));\n stack.push({ id: child, parents: [item.id, ...item.parents] });\n });\n }\n marked.set(item.id, true);\n }\n });\n }\n\n /**\n * Finds a cycle in the graph.\n *\n * @returns {NodeID[] | null} The cycle if found, otherwise `null`.\n * Uses non-recursive DFS.\n */\n findCycle(): NodeID[] | null {\n const visited = new Set<NodeID>();\n const nodeStack = new Set<NodeID>();\n const parents = new Map<NodeID, NodeID>();\n\n for (const nodeId of this.nodes.keys()) {\n if (visited.has(nodeId)) {\n continue;\n }\n\n const callStack: { nodeId: NodeID; parentId: NodeID | null }[] = [];\n callStack.push({ nodeId: nodeId, parentId: null });\n while (callStack.length > 0) {\n const { nodeId, parentId } = callStack[callStack.length - 1];\n if (visited.has(nodeId)) {\n nodeStack.delete(nodeId);\n callStack.pop();\n continue;\n }\n visited.add(nodeId);\n nodeStack.add(nodeId);\n if (parentId !== null) {\n parents.set(nodeId, parentId);\n }\n\n const currentNode = this.nodes.get(nodeId)!;\n for (const child of currentNode.outputs) {\n if (!visited.has(child)) {\n callStack.push({ nodeId: child, parentId: nodeId });\n continue;\n }\n if (!nodeStack.has(child)) {\n continue;\n }\n const cycle: NodeID[] = [];\n let current = nodeId;\n cycle.push(child);\n while (current !== child) {\n cycle.push(current);\n current = parents.get(current)!;\n }\n cycle.push(child);\n cycle.reverse();\n return cycle;\n }\n }\n }\n return null;\n }\n}\n","import { type TreeCursor } from './lezer-tree';\n\nexport const TOKEN_ERROR = 0;\n\n/** Represents AST node data. */\ninterface AstNodeData extends Record<string, unknown> {\n dataType: string;\n value: unknown;\n}\n\n/** Represents AST structured node base. */\nexport interface AstNodeBase {\n typeID: number;\n data: AstNodeData;\n annotation?: Record<string, unknown>;\n}\n\n/** Represents AST structured node. */\nexport interface AstNode extends Record<string, unknown>, AstNodeBase {\n uid: number;\n from: number;\n to: number;\n hasError: boolean;\n parenthesis?: boolean;\n parent: AstNode | null;\n children: AstNode[];\n}\n\n/** Represents AST node. */\nexport interface FlatAstNode extends Record<string, unknown>, AstNodeBase {\n uid: number;\n parent: number | null;\n from: number;\n to: number;\n}\n\n/** Represents Syntax tree flat representation. */\nexport type FlatAST = FlatAstNode[];\n\n/** Builds AST tree from a given tree cursor, generating unique uids for each node. */\nexport function buildTree(cursor: TreeCursor): AstNode {\n let nextUid = 1;\n function genUid() {\n return nextUid++;\n }\n return buildTreeInternal(cursor, null, genUid);\n}\n\n/** Flattens AST tree to a array form. */\nexport function flattenAst(node: AstNode, parent: number | null = null, out: FlatAST = []): FlatAST {\n out.push({\n uid: node.uid,\n parent: parent,\n typeID: node.typeID,\n from: node.from,\n to: node.to,\n data: node.data,\n annotation: node.annotation\n });\n for (const child of node.children) {\n flattenAst(child, node.uid, out);\n }\n return out;\n}\n\n/** Visits AST tree in depth-first order. */\nexport function visitAstDFS(node: AstNode, callback: (node: AstNode) => void) {\n for (const child of node.children) {\n visitAstDFS(child, callback);\n }\n callback(node);\n}\n\n/** Finds and returns the AstNode with the given ui. */\nexport function findByUid(root: AstNode, uid: number): AstNode | null {\n let found: AstNode | null = null;\n visitAstDFS(root, node => {\n if (node.uid === uid && !found) {\n found = node;\n }\n });\n return found;\n}\n\n/** Prints AST tree. */\nexport function printAst(node: AstNode, printNode: (node: AstNode) => string): string {\n let children: string = '';\n for (const child of node.children) {\n children += `${printAst(child, printNode)}`;\n }\n return `[${printNode(node)}${children}]`;\n}\n\n/** Extracts node text. */\nexport function getNodeText(node: AstNode): string {\n if (node.data.dataType === 'string' && typeof node.data.value === 'string') {\n return node.data.value;\n }\n return `NO DATA NODE: ${node.typeID}`;\n}\n\n/** Extracts node indices. */\nexport function getNodeIndices(node: AstNode): number[] {\n if (node.data.dataType === 'string[]' && Array.isArray(node.data.value)) {\n return (node.data.value as string[]).map(s => parseInt(s, 10)).filter(n => !isNaN(n));\n }\n return [];\n}\n\n// ======== Internals ========\nfunction buildTreeInternal(cursor: TreeCursor, parent: AstNode | null = null, genUid: () => number): AstNode {\n const node = cursor.node;\n\n const result: AstNode = {\n uid: genUid(),\n typeID: node.type.isError ? 0 : node.type.id,\n from: node.from,\n to: node.to,\n hasError: node.type.isError,\n data: node.type.isError ? { dataType: 'null', value: null } : { dataType: 'string', value: node.type.name },\n parent,\n children: []\n };\n\n if (cursor.firstChild()) {\n do {\n const child = buildTreeInternal(cursor, result, genUid);\n if (child.hasError) {\n result.hasError = true;\n }\n result.children.push(child);\n } while (cursor.nextSibling());\n cursor.parent();\n }\n return result;\n}\n","import { TOKEN_ERROR } from '../../parsing';\n\n/** Represents RSLang token types. */\nexport const TokenID = {\n // Global, local IDs and literals\n ERROR: TOKEN_ERROR,\n\n ID_LOCAL: 258,\n ID_GLOBAL: 259,\n ID_FUNCTION: 260,\n ID_PREDICATE: 261,\n ID_RADICAL: 262,\n LIT_INTEGER: 263,\n LIT_WHOLE_NUMBERS: 264,\n LIT_EMPTYSET: 265,\n\n // Arithmetic\n PLUS: 266,\n MINUS: 267,\n MULTIPLY: 268,\n\n // Integer predicate symbols\n GREATER: 269,\n LESSER: 270,\n GREATER_OR_EQ: 271,\n LESSER_OR_EQ: 272,\n\n // Equality comparison\n EQUAL: 273,\n NOTEQUAL: 274,\n\n // Logic predicate symbols\n QUANTOR_UNIVERSAL: 275,\n QUANTOR_EXISTS: 276,\n LOGIC_NOT: 277,\n LOGIC_EQUIVALENT: 278,\n LOGIC_IMPLICATION: 279,\n LOGIC_OR: 280,\n LOGIC_AND: 281,\n\n // Set theory predicate symbols\n SET_IN: 282,\n SET_NOT_IN: 283,\n SUBSET: 284,\n SUBSET_OR_EQ: 285,\n NOT_SUBSET: 286,\n\n // Set theory operators\n DECART: 287,\n SET_UNION: 288,\n SET_INTERSECTION: 289,\n SET_MINUS: 290,\n SET_SYMMETRIC_MINUS: 291,\n BOOLEAN: 292,\n\n // Structure operations\n BIGPR: 293,\n SMALLPR: 294,\n FILTER: 295,\n CARD: 296,\n BOOL: 297,\n DEBOOL: 298,\n REDUCE: 299,\n\n // Term constructions prefixes\n DECLARATIVE: 300,\n RECURSIVE: 301,\n IMPERATIVE: 302,\n\n ITERATE: 303,\n ASSIGN: 304,\n\n // Punctuation\n PUNCTUATION_DEFINE: 305,\n PUNCTUATION_STRUCT: 306,\n PUNCTUATION_PL: 307,\n PUNCTUATION_PR: 308,\n PUNCTUATION_CL: 309,\n PUNCTUATION_CR: 310,\n PUNCTUATION_SL: 311,\n PUNCTUATION_SR: 312,\n PUNCTUATION_BAR: 313,\n PUNCTUATION_COMMA: 314,\n PUNCTUATION_SEMICOLON: 315,\n\n // ======= Non-terminal tokens =========\n NT_ENUM_DECL: 316,\n NT_TUPLE: 317,\n NT_ENUMERATION: 318,\n NT_TUPLE_DECL: 319,\n NT_ARG_DECL: 320,\n\n NT_FUNC_DEFINITION: 321,\n NT_ARGUMENTS: 322,\n NT_FUNC_CALL: 323,\n\n NT_DECLARATIVE_EXPR: 324,\n NT_IMPERATIVE_EXPR: 325,\n NT_RECURSIVE_FULL: 326,\n NT_RECURSIVE_SHORT: 327,\n\n // ======= Helper tokens ========\n INTERRUPT: 328,\n END: 329\n} as const;\nexport type TokenID = (typeof TokenID)[keyof typeof TokenID];\n","/**\n * Module: API for RSLanguage.\n */\nimport { type AstNode } from '../parsing';\n\nimport { ArgumentsExtractor, type ArgumentsType } from './semantic/arguments-extractor';\nexport { generateExpressionFromAst } from './parser/expression-generator';\n\n/** Represents alias mapping. */\nexport type AliasMapping = Record<string, string>;\n\n// cspell:disable\nconst LOCALS_REGEXP = /[_a-zα-ω][a-zα-ω]*\\d*/g;\nconst GLOBALS_REGEXP = /[XCSADFPTN]\\d+/g;\nconst COMPLEX_SYMBOLS_REGEXP = /[∀∃×ℬ;|:]/g;\nconst TYPIFICATION_SET = /^ℬ+\\([ℬ\\(((X|C)\\d+|Z)\\)×]*\\)$/g;\n// cspell:enable\n\n/** Extract arguments from AST. */\nexport function extractArguments(ast: AstNode): ArgumentsType[] {\n return new ArgumentsExtractor().run(ast);\n}\n\n/** Extracts global variable names from a given expression. */\nexport function extractGlobals(expression: string): Set<string> {\n return new Set(expression.match(GLOBALS_REGEXP) ?? []);\n}\n\n/** Check if expression is simple derivation. */\nexport function isSimpleExpression(text: string): boolean {\n return !text.match(COMPLEX_SYMBOLS_REGEXP);\n}\n\n/** Check if expression is set typification. */\nexport function isSetTypification(text: string): boolean {\n return !!text.match(TYPIFICATION_SET);\n}\n\n/**\n * Splits a string containing a template definition into its head and body parts.\n *\n * A template definition is expected to have the following format: `[head] body`.\n * If the input string does not contain the opening square bracket '[', the entire\n * string is treated as the body, and an empty string is assigned to the head.\n * If the opening bracket is present, the function attempts to find the matching\n * closing bracket ']' to determine the head and body parts.\n *\n * @example\n * const template = '[header] body content';\n * const result = splitTemplateDefinition(template);\n * // result: `{ head: 'header', body: 'body content' }`\n */\nexport function splitTemplateDefinition(target: string) {\n let start = 0;\n for (; start < target.length && target[start] !== '['; ++start);\n if (start < target.length) {\n for (let counter = 0, end = start + 1; end < target.length; ++end) {\n if (target[end] === '[') {\n ++counter;\n } else if (target[end] === ']') {\n if (counter !== 0) {\n --counter;\n } else {\n return {\n head: target.substring(start + 1, end).trim(),\n body: target.substring(end + 1).trim()\n };\n }\n }\n }\n }\n return {\n head: '',\n body: target\n };\n}\n\n/**\n * Substitutes values for template arguments in a given expression.\n *\n * This function takes an input mathematical expression and a list of argument values.\n * It replaces template argument placeholders in the expression with their corresponding values\n * from the provided arguments.\n */\nexport function substituteTemplateArgs(expression: string, mapping: AliasMapping): string {\n if (Object.keys(mapping).length === 0) {\n return expression;\n }\n let { head, body } = splitTemplateDefinition(expression);\n body = applyPattern(body, mapping, LOCALS_REGEXP);\n const argTexts = head.split(',').map(text => text.trim());\n head = argTexts\n .filter(arg => [...arg.matchAll(LOCALS_REGEXP)].every(local => local.every(match => !(match in mapping))))\n .join(', ');\n\n if (!head) {\n return body;\n } else {\n return `[${head}] ${body}`;\n }\n}\n\n/** Apply alias mapping. */\nexport function applyAliasMapping(target: string, mapping: AliasMapping): string {\n return applyPattern(target, mapping, GLOBALS_REGEXP);\n}\n\n/** Apply alias typification mapping. */\nexport function applyTypificationMapping(target: string, mapping: AliasMapping): string {\n const modified = applyAliasMapping(target, mapping);\n if (modified === target) {\n return target;\n }\n\n const deleteBrackets: number[] = [];\n const positions: number[] = [];\n const booleans: number[] = [];\n let boolCount: number = 0;\n let stackSize: number = 0;\n\n for (let i = 0; i < modified.length; i++) {\n const char = modified[i];\n if (char === 'ℬ') {\n boolCount++;\n continue;\n }\n if (char === '(') {\n stackSize++;\n positions.push(i);\n booleans.push(boolCount);\n }\n boolCount = 0;\n if (char === ')') {\n if (\n i < modified.length - 1 &&\n modified[i + 1] === ')' &&\n stackSize > 1 &&\n positions[stackSize - 2] + booleans[stackSize - 1] + 1 === positions[stackSize - 1]\n ) {\n deleteBrackets.push(i);\n deleteBrackets.push(positions[stackSize - 2]);\n }\n if (i === modified.length - 1 && stackSize === 1 && positions[0] === 0) {\n deleteBrackets.push(i);\n deleteBrackets.push(positions[0]);\n }\n stackSize--;\n positions.pop();\n booleans.pop();\n }\n }\n\n let result = '';\n for (let i = 0; i < modified.length; i++) {\n if (!deleteBrackets.includes(i)) {\n result += modified[i];\n }\n }\n\n return result;\n}\n\n// ====== Internals =========\n/** Text substitution guided by mapping and regular expression. */\nfunction applyPattern(text: string, mapping: AliasMapping, pattern: RegExp): string {\n if (text === '' || pattern === null) {\n return text;\n }\n let posInput = 0;\n let output = '';\n const patternMatches = text.matchAll(pattern);\n for (const segment of patternMatches) {\n const entity = segment[0];\n const start = segment.index ?? 0;\n if (entity in mapping) {\n output += text.substring(posInput, start);\n output += mapping[entity];\n posInput = start + segment[0].length;\n }\n }\n output += text.substring(posInput);\n return output;\n}\n","/*\n * Module: Typification for RSLang.\n */\n\nimport { type Branded } from '../../shared';\n\n/** Typification structure enumeration. */\nexport const TypeID = {\n anyTypification: 1,\n integer: 2,\n basic: 3,\n tuple: 4,\n collection: 5,\n logic: 6,\n function: 7,\n predicate: 8\n} as const;\nexport type TypeID = (typeof TypeID)[keyof typeof TypeID];\n\n/** Represents type class. */\nexport const TypeClass = {\n logic: 1,\n typification: 2,\n function: 3,\n predicate: 4\n} as const;\nexport type TypeClass = (typeof TypeClass)[keyof typeof TypeClass];\n\n/** Logic type object. */\nexport const LogicT = { typeID: TypeID.logic } as const;\n\n/** Integer type object. */\nexport const IntegerT = {\n typeID: TypeID.integer,\n isOrdered: true,\n isArithmetic: true,\n isIntegerCompatible: true\n} as const;\n\n/** Type transformation path. */\nexport type TypePath = Branded<number[], 'TypePath'>;\n\n/** Creates type path. */\nexport function makeTypePath(path: number[]): TypePath {\n return path as TypePath;\n}\n\n/** AnyTyped type object. */\nexport const AnyTypificationT = { typeID: TypeID.anyTypification } as const;\n\n/** Empty set typification. */\nexport const EmptySetT = bool(AnyTypificationT);\n\n/** Parametrized typification. */\nexport type Parametrized = EchelonFunctional | EchelonPredicate;\n\n/** General expression types. */\nexport type ExpressionType =\n | EchelonLogic\n | EchelonBase\n | EchelonTuple\n | EchelonCollection\n | EchelonFunctional\n | EchelonPredicate\n | EchelonAnyTyped\n | EchelonInteger;\n\n/** Setexpr type. */\nexport type Typification = EchelonBase | EchelonAnyTyped | EchelonInteger | EchelonCollection | EchelonTuple;\n\n/** Typification context. */\nexport type TypeContext = Map<string, ExpressionType>;\n\n/** Functional argument. */\nexport interface Argument {\n readonly alias: string;\n readonly type: Typification;\n}\n\n/** Type: Logic. */\nexport interface EchelonLogic {\n readonly typeID: typeof TypeID.logic;\n}\n\n/** Type: AnyTyped. */\nexport interface EchelonAnyTyped {\n readonly typeID: typeof TypeID.anyTypification;\n}\n\n/** Type: Integer. */\nexport interface EchelonInteger {\n readonly typeID: typeof TypeID.integer;\n readonly isOrdered: true;\n readonly isArithmetic: true;\n readonly isIntegerCompatible: true;\n}\n\n/** Type: Element of basic set. */\nexport interface EchelonBase {\n readonly typeID: typeof TypeID.basic;\n readonly baseID: string;\n readonly isOrdered?: boolean;\n readonly isArithmetic?: boolean;\n readonly isIntegerCompatible?: boolean;\n}\n\n/** Type: Tuple. */\nexport interface EchelonTuple {\n readonly typeID: typeof TypeID.tuple;\n readonly factors: readonly Typification[];\n}\n\n/** Type: Collection. */\nexport interface EchelonCollection {\n readonly typeID: typeof TypeID.collection;\n readonly base: Typification;\n}\n\n/** Type: Functional. */\nexport interface EchelonFunctional {\n readonly typeID: typeof TypeID.function;\n readonly result: Typification;\n readonly args: readonly Argument[];\n}\n\n/** Type: Predicate. */\nexport interface EchelonPredicate {\n readonly typeID: typeof TypeID.predicate;\n readonly result: EchelonLogic;\n readonly args: readonly Argument[];\n}\n\n/** Create basic element typification. */\nexport function basic(alias: string): EchelonBase {\n return { typeID: TypeID.basic, baseID: alias };\n}\n\n/** Create constant element typification. */\nexport function constant(alias: string): EchelonBase {\n return { typeID: TypeID.basic, baseID: alias, isOrdered: true, isArithmetic: true, isIntegerCompatible: true };\n}\n\n/** Create boolean typification. */\nexport function bool(base: Typification): EchelonCollection {\n return { typeID: TypeID.collection, base };\n}\n\n/** Create tuple typification. */\nexport function tuple(factors: Typification[]): EchelonTuple {\n if (factors.length < 2) {\n throw new Error('Tuple with less than two factors is not allowed');\n }\n return { typeID: TypeID.tuple, factors };\n}\n\n/** Remove boolean from typification. */\nexport function debool(target: EchelonCollection): Typification {\n return target.base;\n}\n\n/** Extract component from tuple. */\nexport function component(target: EchelonTuple, index: number): Typification | null {\n return target.factors[index - 1] ?? null;\n}\n\n/** Checks if given type is typification. */\nexport function isTypification(type: ExpressionType | null): boolean {\n return (\n type?.typeID === TypeID.basic ||\n type?.typeID === TypeID.anyTypification ||\n type?.typeID === TypeID.integer ||\n type?.typeID === TypeID.collection ||\n type?.typeID === TypeID.tuple\n );\n}\n\n/** Checks if given type is radical. */\nexport function isRadical(alias: string): boolean {\n return alias.length > 0 && alias.startsWith('R') && alias[1] !== '0';\n}\n","import { type AstNodeBase } from '../parsing';\n\nimport { TokenID } from './parser/token';\nimport { type ExpressionType, TypeID } from './semantic/typification';\n\nconst INTEGER_TYPE_NAME = 'Z';\nconst ANY_TYPE_NAME = 'R0';\nconst LOGIC_TYPE_NAME = 'Logic';\n\nconst labelTokenRecord: Partial<Record<TokenID, string>> = {\n [TokenID.DECART]: '×',\n [TokenID.PUNCTUATION_PL]: '( )',\n [TokenID.PUNCTUATION_SL]: '[ ]',\n [TokenID.QUANTOR_UNIVERSAL]: '∀',\n [TokenID.QUANTOR_EXISTS]: '∃',\n [TokenID.LOGIC_NOT]: '¬',\n [TokenID.LOGIC_AND]: '&',\n [TokenID.LOGIC_OR]: '∨',\n [TokenID.LOGIC_IMPLICATION]: '⇒',\n [TokenID.LOGIC_EQUIVALENT]: '⇔',\n [TokenID.LIT_EMPTYSET]: '∅',\n [TokenID.LIT_WHOLE_NUMBERS]: 'Z',\n [TokenID.MULTIPLY]: '*',\n [TokenID.EQUAL]: '=',\n [TokenID.NOTEQUAL]: '≠',\n [TokenID.GREATER_OR_EQ]: '≥',\n [TokenID.LESSER_OR_EQ]: '≤',\n [TokenID.SET_IN]: '∈',\n [TokenID.SET_NOT_IN]: '∉',\n [TokenID.SUBSET_OR_EQ]: '⊆',\n [TokenID.SUBSET]: '⊂',\n [TokenID.NOT_SUBSET]: '⊄',\n [TokenID.SET_INTERSECTION]: '∩',\n [TokenID.SET_UNION]: '∪',\n [TokenID.SET_MINUS]: '\\\\',\n [TokenID.SET_SYMMETRIC_MINUS]: '∆',\n [TokenID.BOOLEAN]: 'ℬ()',\n [TokenID.NT_DECLARATIVE_EXPR]: 'D{}',\n [TokenID.NT_IMPERATIVE_EXPR]: 'I{}',\n [TokenID.NT_RECURSIVE_FULL]: 'R{}',\n [TokenID.BIGPR]: 'Pr1()',\n [TokenID.SMALLPR]: 'pr1()',\n [TokenID.FILTER]: 'Fi1[]()',\n [TokenID.REDUCE]: 'red()',\n [TokenID.CARD]: 'card()',\n [TokenID.BOOL]: 'bool()',\n [TokenID.DEBOOL]: 'debool()',\n [TokenID.ASSIGN]: ':=',\n [TokenID.ITERATE]: ':∈'\n};\n\n/** Retrieves label for {@link TokenID}. */\nexport function labelToken(id: TokenID): string {\n const text = labelTokenRecord[id];\n return text ?? 'UNKNOWN TOKEN: ' + String(id);\n}\n\n/** Generates label for {@link AstNodeBase}. */\nexport function labelRSLangNode(node: AstNodeBase): string {\n // prettier-ignore\n switch (node.typeID) {\n case TokenID.ERROR: return '[ERROR]';\n case TokenID.ID_LOCAL:\n case TokenID.ID_GLOBAL:\n case TokenID.ID_FUNCTION:\n case TokenID.ID_PREDICATE:\n case TokenID.ID_RADICAL:\n return node.data.value as string;\n\n case TokenID.LIT_INTEGER: return String(node.data.value);\n\n case TokenID.BIGPR: return 'Pr' + (node.data.value as string[]).toString();\n case TokenID.SMALLPR: return 'pr' + (node.data.value as string[]).toString();\n case TokenID.FILTER: return 'Fi' + (node.data.value as string[]).toString();\n\n case TokenID.NT_DECLARATIVE_EXPR: return 'DECLARATIVE';\n case TokenID.NT_IMPERATIVE_EXPR: return 'IMPERATIVE';\n case TokenID.NT_RECURSIVE_FULL: return 'RECURSIVE';\n case TokenID.NT_RECURSIVE_SHORT: return 'RECURSIVE';\n\n case TokenID.BOOLEAN: return 'ℬ';\n case TokenID.REDUCE: return 'red';\n case TokenID.CARD: return 'card';\n case TokenID.BOOL: return 'bool';\n case TokenID.DEBOOL: return 'debool';\n\n case TokenID.PLUS: return '+';\n case TokenID.MINUS: return '-';\n case TokenID.MULTIPLY: return '*';\n case TokenID.GREATER: return '>';\n case TokenID.LESSER: return '<';\n\n case TokenID.NT_TUPLE: return 'TUPLE';\n case TokenID.NT_ENUMERATION: return 'ENUM';\n\n case TokenID.NT_ENUM_DECL: return 'ENUM_DECLARE';\n case TokenID.NT_TUPLE_DECL: return 'TUPLE_DECLARE';\n case TokenID.PUNCTUATION_DEFINE: return 'DEFINITION';\n case TokenID.PUNCTUATION_STRUCT: return 'STRUCTURE_DEFINE';\n\n case TokenID.NT_ARG_DECL: return 'ARG';\n case TokenID.NT_FUNC_CALL: return 'CALL';\n case TokenID.NT_ARGUMENTS: return 'ARGS';\n\n case TokenID.NT_FUNC_DEFINITION: return 'FUNCTION_DEFINE';\n\n case TokenID.DECART:\n case TokenID.QUANTOR_UNIVERSAL:\n case TokenID.QUANTOR_EXISTS:\n case TokenID.LOGIC_NOT:\n case TokenID.LOGIC_AND:\n case TokenID.LOGIC_OR:\n case TokenID.LOGIC_IMPLICATION:\n case TokenID.LOGIC_EQUIVALENT:\n case TokenID.LIT_EMPTYSET:\n case TokenID.LIT_WHOLE_NUMBERS:\n case TokenID.EQUAL:\n case TokenID.NOTEQUAL:\n case TokenID.GREATER_OR_EQ:\n case TokenID.LESSER_OR_EQ:\n case TokenID.SET_IN:\n case TokenID.SET_NOT_IN:\n case TokenID.SUBSET_OR_EQ:\n case TokenID.SUBSET:\n case TokenID.NOT_SUBSET:\n case TokenID.SET_INTERSECTION:\n case TokenID.SET_UNION:\n case TokenID.SET_MINUS:\n case TokenID.SET_SYMMETRIC_MINUS:\n case TokenID.ASSIGN:\n case TokenID.ITERATE:\n return labelToken(node.typeID);\n }\n if (node.data.value) {\n return node.data.value as string;\n }\n return 'UNKNOWN NODE: ' + String(node.typeID);\n}\n\n/** Converts expression type to string. */\nexport function labelType(type: ExpressionType | null): string {\n if (!type) {\n return 'N/A';\n }\n switch (type.typeID) {\n case TypeID.anyTypification:\n return ANY_TYPE_NAME;\n case TypeID.integer:\n return INTEGER_TYPE_NAME;\n case TypeID.basic:\n return type.baseID;\n case TypeID.tuple:\n return type.factors\n .map(factor => (factor.typeID === TypeID.tuple ? `(${labelType(factor)})` : labelType(factor)))\n .join('×');\n case TypeID.collection:\n return type.base.typeID === TypeID.collection ? `ℬ${labelType(type.base)}` : `ℬ(${labelType(type.base)})`;\n case TypeID.logic:\n return LOGIC_TYPE_NAME;\n case TypeID.predicate:\n case TypeID.function:\n const argsText = type.args.map(arg => labelType(arg.type)).join(', ');\n return `[${argsText}] → ${labelType(type.result)}`;\n }\n}\n\n/** Converts expression type to normalized string. */\nexport function normalizeType(type: ExpressionType | null): string {\n if (!type) {\n return 'N/A';\n }\n switch (type.typeID) {\n case TypeID.anyTypification:\n return ANY_TYPE_NAME;\n case TypeID.integer:\n case TypeID.basic:\n return 'X1';\n case TypeID.tuple:\n return type.factors\n .map(factor => (factor.typeID === TypeID.tuple ? `(${normalizeType(factor)})` : normalizeType(factor)))\n .join('×');\n case TypeID.collection:\n return type.base.typeID === TypeID.collection ? `ℬ${normalizeType(type.base)}` : `ℬ(${normalizeType(type.base)})`;\n case TypeID.logic:\n return LOGIC_TYPE_NAME;\n case TypeID.predicate:\n case TypeID.function:\n const argsText = type.args.map(arg => normalizeType(arg.type)).join(', ');\n return `[${argsText}] → ${normalizeType(type.result)}`;\n }\n}\n","/**\n * Module: Typification API for RSLang.\n */\n\nimport {\n bool,\n component,\n type EchelonBase,\n type EchelonCollection,\n type EchelonTuple,\n type ExpressionType,\n IntegerT,\n isRadical,\n isTypification,\n tuple,\n TypeClass,\n TypeID,\n type TypePath,\n type Typification\n} from './typification';\n\n/** Record map from typeID to typeClass. */\nconst TypeIDToClass: Record<TypeID, TypeClass> = {\n [TypeID.anyTypification]: TypeClass.typification,\n [TypeID.integer]: TypeClass.typification,\n [TypeID.basic]: TypeClass.typification,\n [TypeID.tuple]: TypeClass.typification,\n [TypeID.collection]: TypeClass.typification,\n [TypeID.logic]: TypeClass.logic,\n [TypeID.function]: TypeClass.function,\n [TypeID.predicate]: TypeClass.predicate\n};\n\n/** Returns the TypeClass associated with the given TypeID. */\nexport function getTypeClass(typeID: TypeID): TypeClass {\n return TypeIDToClass[typeID];\n}\n\n/** Returns true if the given typification is generic. */\nexport function hasGenerics(type: Typification): boolean {\n switch (type.typeID) {\n case TypeID.anyTypification:\n return true;\n case TypeID.integer:\n return false;\n case TypeID.basic:\n return isRadical(type.baseID);\n case TypeID.collection:\n return hasGenerics(type.base);\n case TypeID.tuple:\n for (const factor of type.factors) {\n if (hasGenerics(factor)) {\n return true;\n }\n }\n return false;\n }\n}\n\n/** Checks if two typifications are equal. */\nexport function checkEquality(type1: Typification, type2: Typification): boolean {\n if (type1 === type2) {\n return true;\n }\n if (type1.typeID !== type2.typeID) {\n return false;\n }\n switch (type1.typeID) {\n case TypeID.integer:\n case TypeID.anyTypification:\n return true;\n case TypeID.basic:\n return type1.baseID === (type2 as EchelonBase).baseID;\n case TypeID.collection:\n return checkEquality(type1.base, (type2 as EchelonCollection).base);\n case TypeID.tuple: {\n if (type1.factors.length !== (type2 as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < type1.factors.length; ++index) {\n if (!checkEquality(type1.factors[index], (type2 as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n }\n }\n}\n\n/** Merge two types to get result of binary operation. */\nexport function mergeTypifications(type1: Typification, type2: Typification): Typification | null {\n if (type1 === type2) {\n return type1;\n }\n if (type1.typeID === TypeID.anyTypification) {\n return isTypification(type2) ? type2 : null;\n }\n if (type2.typeID === TypeID.anyTypification) {\n return isTypification(type1) ? type1 : null;\n }\n\n switch (type1.typeID) {\n case TypeID.integer:\n case TypeID.basic:\n return commonType(type1, type2);\n case TypeID.collection:\n if (type2.typeID !== TypeID.collection) {\n return null;\n }\n const base = mergeTypifications(type1.base, type2.base);\n return base ? bool(base) : null;\n case TypeID.tuple:\n if (type2.typeID !== TypeID.tuple) {\n return null;\n }\n if (type1.factors.length !== type2.factors.length) {\n return null;\n }\n const components: Typification[] = [];\n for (let index = 0; index < type1.factors.length; ++index) {\n const component = mergeTypifications(type1.factors[index], type2.factors[index]);\n if (component === null) {\n return null;\n }\n components.push(component);\n }\n return tuple(components);\n }\n}\n\n/** Check compatibility of typifications. */\nexport function checkCompatibility(type1: ExpressionType, type2: ExpressionType): boolean {\n if (type1 === type2) {\n return true;\n }\n if (type1.typeID === TypeID.anyTypification) {\n return isTypification(type2);\n }\n if (type2.typeID === TypeID.anyTypification) {\n return isTypification(type1);\n }\n if (isTypification(type1) !== isTypification(type2)) {\n return false;\n }\n if (\n type1.typeID === TypeID.integer ||\n type1.typeID === TypeID.basic ||\n type2.typeID === TypeID.integer ||\n type2.typeID === TypeID.basic\n ) {\n return commonType(type1 as Typification, type2 as Typification) !== null;\n }\n\n if (type1.typeID !== type2.typeID) {\n return false;\n }\n switch (type1.typeID) {\n case TypeID.collection:\n return checkCompatibility(type1.base, (type2 as EchelonCollection).base);\n case TypeID.tuple:\n if (type1.factors.length !== (type2 as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < type1.factors.length; ++index) {\n if (!checkCompatibility(type1.factors[index], (type2 as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n case TypeID.logic:\n case TypeID.predicate:\n case TypeID.function:\n return false;\n }\n}\n\n/** Compare typification with substitutions. */\nexport function compareTemplated(\n substitutes: Map<string, Typification>,\n arg: Typification,\n value: Typification\n): boolean {\n if (arg === value) {\n return true;\n }\n if (arg.typeID === TypeID.basic && isRadical(arg.baseID)) {\n if (!substitutes.has(arg.baseID)) {\n substitutes.set(arg.baseID, value);\n return true;\n } else {\n const mergeType = mergeTypifications(substitutes.get(arg.baseID)!, value);\n if (mergeType === null) {\n return false;\n }\n substitutes.set(arg.baseID, mergeType);\n return true;\n }\n }\n if (value.typeID === TypeID.anyTypification) {\n return true;\n }\n if (\n arg.typeID === TypeID.integer ||\n arg.typeID === TypeID.basic ||\n value.typeID === TypeID.integer ||\n value.typeID === TypeID.basic\n ) {\n return commonType(arg, value) !== null;\n }\n if (arg.typeID !== value.typeID) {\n return false;\n }\n switch (arg.typeID) {\n case TypeID.collection:\n return compareTemplated(substitutes, arg.base, (value as EchelonCollection).base);\n case TypeID.tuple: {\n if (arg.factors.length !== (value as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < arg.factors.length; ++index) {\n if (!compareTemplated(substitutes, arg.factors[index], (value as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n }\n }\n}\n\n/** Apply substitutions to typification. */\nexport function substituteBase(target: Typification, substitutes: Map<string, Typification>): void {\n switch (target.typeID) {\n case TypeID.basic: {\n if (substitutes.has(target.baseID)) {\n Object.assign(target, substitutes.get(target.baseID)!);\n }\n return;\n }\n case TypeID.collection: {\n substituteBase(target.base, substitutes);\n return;\n }\n case TypeID.tuple: {\n for (const factor of target.factors) {\n substituteBase(factor, substitutes);\n }\n return;\n }\n }\n}\n\n/** Extract bases from typification. */\nexport function extractBases(target: ExpressionType): Set<string> {\n return new Set(extractBasesImpl(target));\n}\n\n/** Apply type path to typification. */\nexport function applyPath(target: Typification, path: TypePath, index = 0): Typification | null {\n let current: Typification | null = target;\n let i = index;\n while (i < path.length && current) {\n switch (current.typeID) {\n case TypeID.anyTypification:\n case TypeID.integer:\n case TypeID.basic:\n return null;\n case TypeID.collection:\n current = current.base;\n i++;\n break;\n case TypeID.tuple:\n current = component(current, path[i]);\n if (current === null) {\n return null;\n }\n i++;\n break;\n }\n }\n return current;\n}\n\n// ===== Internals =====\nfunction commonType(type1: Typification, type2: Typification): Typification | null {\n if (type1 === type2) {\n return type1;\n }\n const int1 = 'isIntegerCompatible' in type1 && type1.isIntegerCompatible;\n const int2 = 'isIntegerCompatible' in type2 && type2.isIntegerCompatible;\n if (!int1 || !int2) {\n if (type1.typeID === TypeID.basic && type2.typeID === TypeID.basic) {\n return type1.baseID === type2.baseID ? type1 : null;\n }\n return null;\n }\n if (type1.typeID === TypeID.integer) {\n return type2;\n } else if (type2.typeID === TypeID.integer) {\n return type1;\n } else {\n return IntegerT;\n }\n}\n\nfunction extractBasesImpl(target: ExpressionType): string[] {\n switch (target.typeID) {\n case TypeID.basic:\n return [target.baseID];\n case TypeID.collection:\n return extractBasesImpl(target.base);\n case TypeID.tuple:\n return target.factors.reduce((result, factor) => result.concat(extractBasesImpl(factor)), [] as string[]);\n case TypeID.function:\n const result = extractBasesImpl(target.result);\n return target.args.reduce((result, arg) => result.concat(extractBasesImpl(arg.type)), result);\n case TypeID.predicate:\n return target.args.reduce((result, arg) => result.concat(extractBasesImpl(arg.type)), [] as string[]);\n default:\n return [];\n }\n}\n","/**\n * Module: Schema of Synthesis Operations.\n */\n\nimport { type Graph } from '../graph';\n\nimport { type LibraryItem } from './library';\nimport { type NodePosition, type OssLayout } from './oss-layout';\n\n/** Represents OSS node type. */\nexport const NodeType = {\n OPERATION: 1,\n BLOCK: 2\n} as const;\nexport type NodeType = (typeof NodeType)[keyof typeof NodeType];\n\n/** Represents OSS graph node. */\ninterface OssNode extends NodePosition {\n nodeType: NodeType;\n parent: number | null;\n}\n\n/** Represents {@link Operation} type. */\nexport const OperationType = {\n INPUT: 'input',\n SYNTHESIS: 'synthesis',\n REPLICA: 'replica'\n} as const;\nexport type OperationType = (typeof OperationType)[keyof typeof OperationType];\n\n/** Represents {@link Substitution} extended data. */\nexport interface CstSubstituteInfo {\n original: number;\n substitution: number;\n operation: number;\n original_schema: number;\n original_alias: string;\n original_term: string;\n substitution_schema: number;\n substitution_alias: string;\n substitution_term: string;\n}\n\n/** Represents Operation common attributes. */\ninterface OperationBase extends OssNode {\n id: number;\n alias: string;\n title: string;\n description: string;\n operation_type: OperationType;\n result: number | null;\n nodeType: typeof NodeType.OPERATION;\n has_additions: boolean;\n}\n\n/** Represents Input Operation. */\nexport interface OperationInput extends OperationBase {\n operation_type: typeof OperationType.INPUT;\n is_import: boolean;\n}\n\n/** Represents Replica Operation. */\ninterface OperationReplica extends OperationBase {\n operation_type: typeof OperationType.REPLICA;\n target: number;\n}\n\n/** Represents Synthesis Operation. */\nexport interface OperationSynthesis extends OperationBase {\n operation_type: typeof OperationType.SYNTHESIS;\n is_consolidation: boolean; // aka 'diamond synthesis'\n substitutions: CstSubstituteInfo[];\n arguments: number[];\n}\n\n/** Represents Operation. */\nexport type Operation = OperationInput | OperationReplica | OperationSynthesis;\n\n/** Represents Block. */\nexport interface Block extends OssNode {\n id: number;\n oss: number;\n title: string;\n description: string;\n parent: number | null;\n nodeType: typeof NodeType.BLOCK;\n}\n\n/** Represents item of OperationSchema. */\nexport type OssItem = Operation | Block;\n\n/** Represents {@link OperationSchema} statistics. */\nexport interface OperationSchemaStats {\n count_all: number;\n count_inputs: number;\n count_synthesis: number;\n count_schemas: number;\n count_owned: number;\n count_block: number;\n count_references: number;\n}\n\n/** Represents OperationSchema. */\nexport interface OperationSchema extends LibraryItem {\n editors: number[];\n operations: Operation[];\n blocks: Block[];\n replicas: {\n original: number;\n replica: number;\n }[];\n layout: OssLayout;\n arguments: {\n operation: number;\n argument: number;\n }[];\n substitutions: CstSubstituteInfo[];\n\n graph: Graph;\n extendedGraph: Graph;\n hierarchy: Graph<string>;\n schemas: number[];\n stats: OperationSchemaStats;\n operationByID: Map<number, Operation>;\n blockByID: Map<number, Block>;\n itemByNodeID: Map<string, OssItem>;\n}\n\n/** Represents substitution error description. */\nexport interface SubstitutionErrorDescription {\n errorType: SubstitutionErrorType;\n params: string[];\n}\n\n/** Represents Substitution table error types. */\nexport const SubstitutionErrorType = {\n invalidIDs: 0,\n incorrectCst: 1,\n invalidClasses: 2,\n invalidBasic: 3,\n invalidConstant: 4,\n typificationCycle: 5,\n baseSubstitutionNotSet: 6,\n unequalTypification: 7,\n unequalExpressions: 8,\n unequalArgsCount: 9,\n unequalArgs: 10,\n invalidNominal: 11\n} as const;\nexport type SubstitutionErrorType = (typeof SubstitutionErrorType)[keyof typeof SubstitutionErrorType];\n","/**\n * Module: Models for formal representation for systems of concepts.\n */\n\nimport { type Graph } from '../graph';\nimport { type AnalysisBase, type ExpressionType, type RSLangAnalyzer, type TypePath } from '../rslang';\n\nimport { type CurrentVersion, type LibraryItem, type LibraryItemReference, type VersionInfo } from './library';\n\n/** Represents {@link Constituenta} type. */\nexport const CstType = {\n NOMINAL: 'nominal',\n BASE: 'basic',\n STRUCTURED: 'structure',\n TERM: 'term',\n AXIOM: 'axiom',\n FUNCTION: 'function',\n PREDICATE: 'predicate',\n CONSTANT: 'constant',\n STATEMENT: 'statement'\n} as const;\nexport type CstType = (typeof CstType)[keyof typeof CstType];\n\n/** Represents attribution of a {@link Constituenta} to another {@link Constituenta}. */\nexport interface Attribution {\n container: number;\n attribute: number;\n}\n\n/** Represents global identifier type info. */\nexport interface TypeInfo {\n alias: string;\n type: ExpressionType;\n}\n\n/** Represents function argument value. */\nexport interface ArgumentValue {\n alias: string;\n typification: string;\n value?: string;\n}\n\n/** Represents Constituenta classification in terms of system of concepts. */\nexport const CstClass = {\n NOMINAL: 'nominal',\n BASIC: 'basic',\n DERIVED: 'derived',\n STATEMENT: 'statement',\n TEMPLATE: 'template'\n} as const;\nexport type CstClass = (typeof CstClass)[keyof typeof CstClass];\n\n/** Represents formal expression Status. */\nexport const CstStatus = {\n VERIFIED: 'verified',\n INCORRECT: 'incorrect',\n INCALCULABLE: 'incalculable',\n PROPERTY: 'property',\n UNKNOWN: 'unknown'\n} as const;\nexport type CstStatus = (typeof CstStatus)[keyof typeof CstStatus];\n\n/** Represents substitution of {@link Constituenta}. */\nexport interface Substitution {\n original: number;\n substitution: number;\n}\n\n/** Represents word form for natural language. */\ninterface TermForm {\n text: string;\n tags: string;\n}\n\n/** Represents Constituenta. */\nexport interface Constituenta {\n id: number;\n crucial: boolean;\n alias: string;\n convention: string;\n cst_type: CstType;\n definition_formal: string;\n definition_raw: string;\n definition_resolved: string;\n term_raw: string;\n term_resolved: string;\n term_forms: TermForm[];\n attributes: number[];\n\n /** Manual typification of the constituent */\n typification_manual: string;\n\n /** Controls whether base concepts expose property values or full values */\n value_is_property: boolean;\n\n homonyms: number[];\n formalDuplicates: number[];\n analysis: AnalysisBase;\n\n /** Typification used for dependents, model values, and display (manual when it overrides computed). */\n effectiveType: ExpressionType | null;\n\n /**\n * True when manual typification is non-empty, parses to a type, and its label differs from the\n * typification inferred from the formal definition ({@link Constituenta.analysis}.type).\n */\n is_type_mismatch: boolean;\n\n /** Identifier of {@link LibraryItem} containing this {@link Constituenta}. */\n schema: number;\n\n /** {@link CstClass} of this {@link Constituenta}. */\n cst_class: CstClass;\n /** {@link CstStatus} of this {@link Constituenta}. */\n status: CstStatus;\n\n /** Indicates if this {@link Constituenta} is a template. */\n is_template: boolean;\n /** Indicates if this {@link Constituenta} has a simple expression. */\n is_simple_expression: boolean;\n\n /** Index of {@link LibraryItem} that contains this cst (or inheritance parent).\n * 0 - not inherited, 1 - inherited by 1st schema, 2 - inherited by 2nd schema, etc.\n */\n parent_schema_index: number;\n /** {@link LibraryItem} that contains parent of this inherited {@link Constituenta}. */\n parent_schema: number | null;\n /** Indicates if this {@link Constituenta} is inherited. */\n is_inherited: boolean;\n /** Indicates if this {@link Constituenta} has children that are inherited. */\n has_inherited_children: boolean;\n\n /** {@link Constituenta} that spawned this one. */\n spawner?: number;\n /** Alias of {@link Constituenta} that spawned this one. */\n spawner_alias?: string;\n /** Structure path that spawned this one. */\n spawner_path?: TypePath;\n\n /** List of {@link Constituenta} that are spawned by this one. */\n spawn: number[];\n /** List of aliases of {@link Constituenta} that are spawned by this one. */\n spawn_alias: string[];\n}\n\n/** Represents {@link RSForm} statistics. */\nexport interface RSFormStats {\n step_complexity: number;\n\n /** Total number of constituents in the RSForm. */\n count_all: number;\n /** Number of crucial constituents in the RSForm. */\n count_crucial: number;\n\n count_problematic: number;\n /** Constituents that have same term. */\n count_homonyms: number;\n /** Constituents that have same formal definition and term. */\n count_formal_duplicates: number;\n /** Base constituents with no convention and alias. */\n count_missing_convention: number;\n /** Constituents with non-empty manual typification that disagrees with inferred typification. */\n count_type_mismatch: number;\n\n count_incorrect: number;\n count_property: number;\n count_incalculable: number;\n count_inherited: number;\n\n count_text_term: number;\n count_definition: number;\n count_convention: number;\n count_comment: number;\n\n count_base: number;\n count_constant: number;\n count_structured: number;\n count_axiom: number;\n count_term: number;\n count_function: number;\n count_predicate: number;\n count_statement: number;\n count_nominal: number;\n}\n\n/** Represents inheritance data for {@link RSForm}. */\ninterface InheritanceInfo {\n child: number;\n child_source: number;\n parent: number;\n parent_source: number;\n}\n\n/** Represents formal explication for set of concepts. */\nexport interface RSForm extends LibraryItem {\n /** Whether this RSForm was produced (vs imported or inherited) */\n is_produced: boolean;\n /** Whether this RSForm has attribution feature */\n is_attributive: boolean;\n /** List of user IDs who can edit this RSForm */\n editors: number[];\n /** Information about the current version of this RSForm */\n version: CurrentVersion;\n /** Full version history of this RSForm */\n versions: VersionInfo[];\n\n /** Full list of constituents in the RSForm */\n items: Constituenta[];\n /** List of inheritance relationships between constituents */\n inheritance: InheritanceInfo[];\n /** List of constituent attribution relationships */\n attribution: Attribution[];\n /** References to Operational Schemes/Systems associated with the RSForm */\n oss: LibraryItemReference[];\n /** References to conceptual models associated with the RSForm */\n models: LibraryItemReference[];\n\n /** Analyzer instance for RS language features and validation */\n analyzer: RSLangAnalyzer;\n /** Graph structure representing formal dependencies between constituents */\n graph: Graph;\n /** Graph structure representing attribution relationships */\n attribution_graph: Graph;\n /** Map for quick lookup of constituents by alias */\n cstByAlias: Map<string, Constituenta>;\n /** Map for quick lookup of constituents by ID */\n cstByID: Map<number, Constituenta>;\n}\n","/**\n * Module: API for OperationSystem.\n */\n\nimport { Graph } from '../graph';\nimport { type AliasMapping, applyAliasMapping, applyTypificationMapping, isSetTypification } from '../rslang/api';\nimport { labelType } from '../rslang/labels';\nimport { extractBases } from '../rslang/semantic/typification-api';\n\nimport { type LibraryItem } from './library';\nimport { NodeType, type OperationSchema, type SubstitutionErrorDescription, SubstitutionErrorType } from './oss';\nimport { type Constituenta, CstClass, CstType, type RSForm, type Substitution } from './rsform';\n\nconst STARTING_SUB_INDEX = 900; // max semantic index for starting substitution\n\nexport function constructNodeID(type: NodeType, itemID: number): string {\n return type === NodeType.OPERATION ? 'o' + String(itemID) : 'b' + String(itemID);\n}\n\n/** Sorts library items relevant for the specified {@link OperationSchema}. */\nexport function sortItemsForOSS(oss: OperationSchema, items: readonly LibraryItem[]): LibraryItem[] {\n const result = items.filter(item => item.location === oss.location);\n for (const item of items) {\n if (item.visible && item.owner === oss.owner && !result.includes(item)) {\n result.push(item);\n }\n }\n for (const item of items) {\n if (item.visible && !result.includes(item)) {\n result.push(item);\n }\n }\n for (const item of items) {\n if (!result.includes(item)) {\n result.push(item);\n }\n }\n return result;\n}\n\ntype CrossMapping = Map<number, AliasMapping>;\n\n/** Validator for Substitution table. */\nexport class SubstitutionValidator {\n public errors: SubstitutionErrorDescription[] = [];\n public suggestions: Substitution[] = [];\n\n private schemas: RSForm[];\n private substitutions: Substitution[];\n private constituents = new Set<number>();\n private originals = new Set<number>();\n private mapping: CrossMapping = new Map();\n\n private cstByID = new Map<number, Constituenta>();\n private schemaByID = new Map<number, RSForm>();\n private schemaByCst = new Map<number, RSForm>();\n\n constructor(schemas: RSForm[], substitutions: Substitution[]) {\n this.schemas = schemas;\n this.substitutions = substitutions;\n if (schemas.length === 0 || substitutions.length === 0) {\n return;\n }\n\n for (const schema of schemas) {\n this.schemaByID.set(schema.id, schema);\n this.mapping.set(schema.id, {});\n for (const item of schema.items) {\n this.cstByID.set(item.id, item);\n this.schemaByCst.set(item.id, schema);\n }\n }\n let index = STARTING_SUB_INDEX;\n for (const item of substitutions) {\n this.constituents.add(item.original);\n this.constituents.add(item.substitution);\n this.originals.add(item.original);\n const original = this.cstByID.get(item.original);\n const substitution = this.cstByID.get(item.substitution);\n if (!original || !substitution) {\n return;\n }\n index++;\n const newAlias = `${substitution.alias[0]}${index}`;\n this.mapping.get(original.schema)![original.alias] = newAlias;\n this.mapping.get(substitution.schema)![substitution.alias] = newAlias;\n }\n }\n\n public validate(): boolean {\n this.errors = [];\n this.suggestions = [];\n this.calculateSuggestions();\n if (this.substitutions.length === 0) {\n return true;\n }\n if (!this.checkTypes()) {\n return false;\n }\n if (!this.checkCycles()) {\n return false;\n }\n if (!this.checkSubstitutions()) {\n return false;\n }\n return true;\n }\n\n private calculateSuggestions(): void {\n const candidates = new Map<number, string>();\n const minors = new Set<number>();\n const schemaByCst = new Map<number, RSForm>();\n for (const schema of this.schemas) {\n for (const cst of schema.items) {\n if (this.originals.has(cst.id)) {\n continue;\n }\n if (cst.cst_class === CstClass.BASIC || cst.definition_formal.length === 0) {\n continue;\n }\n const inputs = schema.graph.at(cst.id)!.inputs;\n if (inputs.some(id => !this.constituents.has(id))) {\n continue;\n }\n if (inputs.some(id => this.originals.has(id))) {\n minors.add(cst.id);\n }\n candidates.set(cst.id, applyAliasMapping(cst.definition_formal, this.mapping.get(schema.id)!).replace(' ', ''));\n schemaByCst.set(cst.id, schema);\n }\n }\n for (const [key1, value1] of candidates) {\n for (const [key2, value2] of candidates) {\n if (key1 >= key2) {\n continue;\n }\n if (schemaByCst.get(key1) === schemaByCst.get(key2)) {\n continue;\n }\n if (value1 != value2) {\n continue;\n }\n if (minors.has(key2)) {\n this.suggestions.push({\n original: key2,\n substitution: key1\n });\n } else {\n this.suggestions.push({\n original: key1,\n substitution: key2\n });\n }\n }\n }\n }\n\n private checkTypes(): boolean {\n for (const item of this.substitutions) {\n const original = this.cstByID.get(item.original);\n const substitution = this.cstByID.get(item.substitution);\n if (!original || !substitution) {\n return this.reportError(SubstitutionErrorType.invalidIDs, []);\n }\n if (\n substitution.analysis &&\n original.analysis &&\n (!original.analysis.success || !substitution.analysis.success)\n ) {\n return this.reportError(SubstitutionErrorType.incorrectCst, [substitution.alias, original.alias]);\n }\n switch (substitution.cst_type) {\n case CstType.NOMINAL: {\n if (original.cst_type !== CstType.NOMINAL) {\n return this.reportError(SubstitutionErrorType.invalidNominal, [substitution.alias, original.alias]);\n }\n break;\n }\n case CstType.BASE: {\n if (\n original.cst_type !== CstType.BASE &&\n original.cst_type !== CstType.CONSTANT &&\n original.cst_type !== CstType.NOMINAL\n ) {\n return this.reportError(SubstitutionErrorType.invalidBasic, [substitution.alias, original.alias]);\n }\n break;\n }\n\n case CstType.CONSTANT: {\n if (original.cst_type !== CstType.CONSTANT) {\n return this.reportError(SubstitutionErrorType.invalidConstant, [substitution.alias, original.alias]);\n }\n break;\n }\n\n case CstType.AXIOM:\n case CstType.STATEMENT: {\n if (original.cst_type !== CstType.AXIOM && original.cst_type !== CstType.STATEMENT) {\n return this.reportError(SubstitutionErrorType.invalidClasses, [substitution.alias, original.alias]);\n }\n break;\n }\n\n case CstType.FUNCTION: {\n if (original.cst_type !== CstType.FUNCTION) {\n return this.reportError(SubstitutionErrorType.invalidClasses, [substitution.alias, original.alias]);\n }\n break;\n }\n case CstType.PREDICATE: {\n if (original.cst_type !== CstType.PREDICATE) {\n return this.reportError(SubstitutionErrorType.invalidClasses, [substitution.alias, original.alias]);\n }\n break;\n }\n\n case CstType.TERM:\n case CstType.STRUCTURED: {\n if (\n original.cst_type !== CstType.TERM &&\n original.cst_type !== CstType.STRUCTURED &&\n original.cst_type !== CstType.BASE\n ) {\n return this.reportError(SubstitutionErrorType.invalidClasses, [substitution.alias, original.alias]);\n }\n break;\n }\n }\n }\n return true;\n }\n\n private checkCycles(): boolean {\n const graph = new Graph();\n for (const schema of this.schemas) {\n for (const cst of schema.items) {\n if (cst.cst_type === CstType.BASE || cst.cst_type === CstType.CONSTANT) {\n graph.addNode(cst.id);\n }\n }\n }\n for (const item of this.substitutions) {\n const original = this.cstByID.get(item.original)!;\n const substitution = this.cstByID.get(item.substitution)!;\n for (const cst of [original, substitution]) {\n if (cst.cst_type === CstType.BASE || cst.cst_type === CstType.CONSTANT) {\n continue;\n }\n graph.addNode(cst.id);\n if (cst.effectiveType === null) {\n continue;\n }\n const parents = extractBases(cst.effectiveType);\n if (parents.size === 0) {\n continue;\n }\n const schema = this.schemaByID.get(cst.schema)!;\n for (const alias of parents) {\n const parent = schema.cstByAlias.get(alias);\n if (parent) {\n graph.addEdge(parent.id, cst.id);\n }\n }\n }\n graph.addEdge(substitution.id, original.id);\n }\n const cycle = graph.findCycle();\n if (cycle !== null) {\n const cycleMsg = cycle\n .map(id => {\n const cst = this.cstByID.get(id)!;\n const schema = this.schemaByID.get(cst.schema)!;\n return `[${schema.alias}]-${cst.alias}`;\n })\n .join(', ');\n return this.reportError(SubstitutionErrorType.typificationCycle, [cycleMsg]);\n }\n return true;\n }\n\n private checkSubstitutions(): boolean {\n const baseMappings = this.prepareBaseMappings();\n const typeMappings = this.calculateSubstituteMappings(baseMappings);\n if (typeMappings === null) {\n return false;\n }\n for (const item of this.substitutions) {\n const original = this.cstByID.get(item.original)!;\n if (\n original.cst_type === CstType.BASE ||\n original.cst_type === CstType.CONSTANT ||\n original.cst_type === CstType.NOMINAL\n ) {\n continue;\n }\n const substitution = this.cstByID.get(item.substitution)!;\n if (original.cst_type === substitution.cst_type && original.cst_class !== CstClass.BASIC) {\n if (!this.checkEqual(original, substitution)) {\n this.reportError(SubstitutionErrorType.unequalExpressions, [substitution.alias, original.alias]);\n // Note: do not interrupt the validation process. Only warn about the problem.\n }\n }\n\n if (original.analysis.success !== substitution.analysis.success) {\n return this.reportError(SubstitutionErrorType.unequalTypification, [substitution.alias, original.alias]);\n }\n if (!original.analysis.success || !substitution.analysis.success) {\n continue;\n }\n\n const originalType = applyTypificationMapping(\n applyAliasMapping(labelType(original.effectiveType), baseMappings.get(original.schema)!),\n typeMappings\n );\n const substitutionType = applyTypificationMapping(\n applyAliasMapping(labelType(substitution.effectiveType), baseMappings.get(substitution.schema)!),\n typeMappings\n );\n if (originalType !== substitutionType) {\n return this.reportError(SubstitutionErrorType.unequalTypification, [substitution.alias, original.alias]);\n }\n }\n return true;\n }\n\n private prepareBaseMappings(): CrossMapping {\n const result: CrossMapping = new Map();\n let baseCount = 0;\n let constCount = 0;\n for (const schema of this.schemas) {\n const mapping: AliasMapping = {};\n for (const cst of schema.items) {\n if (cst.cst_type === CstType.BASE) {\n baseCount++;\n mapping[cst.alias] = `X${baseCount}`;\n } else if (cst.cst_type === CstType.CONSTANT) {\n constCount++;\n mapping[cst.alias] = `C${constCount}`;\n }\n result.set(schema.id, mapping);\n }\n }\n return result;\n }\n\n private calculateSubstituteMappings(baseMappings: CrossMapping): AliasMapping | null {\n const result: AliasMapping = {};\n const processed = new Set<string>();\n for (const item of this.substitutions) {\n const original = this.cstByID.get(item.original)!;\n if (original.cst_type !== CstType.BASE && original.cst_type !== CstType.CONSTANT) {\n continue;\n }\n const originalAlias = baseMappings.get(original.schema)![original.alias];\n\n const substitution = this.cstByID.get(item.substitution)!;\n let substitutionText = '';\n if (substitution.cst_type === original.cst_type || !substitution.effectiveType) {\n substitutionText = baseMappings.get(substitution.schema)![substitution.alias];\n } else {\n const typeText = labelType(substitution.effectiveType);\n substitutionText = applyAliasMapping(typeText, baseMappings.get(substitution.schema)!);\n substitutionText = applyTypificationMapping(substitutionText, result);\n if (!isSetTypification(substitutionText)) {\n this.reportError(SubstitutionErrorType.baseSubstitutionNotSet, [substitution.alias, typeText]);\n return null;\n }\n if (substitutionText.includes('×') || substitutionText.startsWith('ℬℬ')) {\n substitutionText = substitutionText.slice(1);\n } else {\n substitutionText = substitutionText.slice(2, -1);\n }\n }\n for (const prevAlias of processed) {\n result[prevAlias] = applyTypificationMapping(result[prevAlias], { [originalAlias]: substitutionText });\n }\n result[originalAlias] = substitutionText;\n processed.add(originalAlias);\n }\n return result;\n }\n\n private checkEqual(left: Constituenta, right: Constituenta): boolean {\n const schema1 = this.schemaByID.get(left.schema)!;\n const inputs1 = schema1.graph.at(left.id)!.inputs;\n if (inputs1.some(id => !this.constituents.has(id))) {\n return false;\n }\n const schema2 = this.schemaByID.get(right.schema)!;\n const inputs2 = schema2.graph.at(right.id)!.inputs;\n if (inputs2.some(id => !this.constituents.has(id))) {\n return false;\n }\n const expression1 = applyAliasMapping(left.definition_formal, this.mapping.get(schema1.id)!);\n const expression2 = applyAliasMapping(right.definition_formal, this.mapping.get(schema2.id)!);\n return expression1.replace(' ', '') === expression2.replace(' ', '');\n }\n\n private reportError(errorType: SubstitutionErrorType, params: string[]): boolean {\n this.errors.push({\n errorType: errorType,\n params: params\n });\n return false;\n }\n}\n\n/** Filter relocate candidates from gives schema. */\nexport function getRelocateCandidates(\n source: number,\n destination: number,\n schema: RSForm,\n oss: OperationSchema\n): Constituenta[] {\n const destinationSchema = oss.operationByID.get(destination)?.result;\n if (!destinationSchema) {\n return [];\n }\n const node = oss.graph.at(source);\n if (!node) {\n return [];\n }\n\n if (node.outputs.includes(destination)) {\n return schema.items;\n }\n\n const addedCst = schema.items.filter(item => !item.is_inherited).map(cst => cst.id);\n\n const unreachableBases: number[] = [];\n for (const cst of schema.items.filter(item => item.is_inherited)) {\n if (cst.parent_schema == destinationSchema) {\n continue;\n }\n const parent = schema.inheritance.find(item => item.child === cst.id && item.child_source === cst.schema)?.parent;\n if (parent) {\n const original = oss.substitutions.find(sub => sub.substitution === parent)?.original;\n if (original) {\n continue;\n }\n }\n unreachableBases.push(cst.id);\n }\n const unreachable = schema.graph.expandAllOutputs(unreachableBases);\n return schema.items.filter(\n cst => cst.parent_schema === destinationSchema || (addedCst.includes(cst.id) && !unreachable.includes(cst.id))\n );\n}\n"],"mappings":"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","names":["nodeId","result"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { OperationSchema } from './oss.js';
|
|
2
|
+
import { OssLayout, Rectangle2D } from './oss-layout.js';
|
|
3
|
+
import '../graph/graph.js';
|
|
4
|
+
import './library.js';
|
|
5
|
+
|
|
6
|
+
declare const GRID_SIZE = 10;
|
|
7
|
+
declare const OPERATION_NODE_WIDTH = 150;
|
|
8
|
+
declare const OPERATION_NODE_HEIGHT = 40;
|
|
9
|
+
/** Layout manipulations for {@link OperationSchema}. */
|
|
10
|
+
declare class LayoutManager {
|
|
11
|
+
oss: OperationSchema;
|
|
12
|
+
layout: OssLayout;
|
|
13
|
+
constructor(oss: OperationSchema, layout?: OssLayout);
|
|
14
|
+
/** Calculate insert position for a new {@link Operation} */
|
|
15
|
+
newOperationPosition(position: Rectangle2D, parent: number | null, args?: number[]): Rectangle2D;
|
|
16
|
+
/** Calculate insert position for a new {@link Block} */
|
|
17
|
+
newBlockPosition(position: Rectangle2D, parent: number | null, blocks: number[], operations: number[]): Rectangle2D;
|
|
18
|
+
/** Calculate insert position for a new clone of {@link Operation} */
|
|
19
|
+
newClonePosition(targetID: string): Rectangle2D | null;
|
|
20
|
+
/** Update layout when parent changes */
|
|
21
|
+
onChangeParent(targetID: string, newParent: string | null): void;
|
|
22
|
+
/** Calculate closest node to the left */
|
|
23
|
+
selectLeft(targetID: string): string | null;
|
|
24
|
+
/** Calculate closest node to the right */
|
|
25
|
+
selectRight(targetID: string): string | null;
|
|
26
|
+
/** Calculate closest node upwards */
|
|
27
|
+
selectUp(targetID: string): string | null;
|
|
28
|
+
/** Calculate closest node downwards */
|
|
29
|
+
selectDown(targetID: string): string | null;
|
|
30
|
+
private extendParentBounds;
|
|
31
|
+
private calculatePositionForFreeOperation;
|
|
32
|
+
private calculatePositionForFreeBlock;
|
|
33
|
+
private calculateOffsetForParentChange;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { GRID_SIZE, LayoutManager, OPERATION_NODE_HEIGHT, OPERATION_NODE_WIDTH };
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// src/library/oss.ts
|
|
2
|
+
var NodeType = {
|
|
3
|
+
OPERATION: 1,
|
|
4
|
+
BLOCK: 2
|
|
5
|
+
};
|
|
6
|
+
var OperationType = {
|
|
7
|
+
INPUT: "input",
|
|
8
|
+
SYNTHESIS: "synthesis",
|
|
9
|
+
REPLICA: "replica"
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/library/oss-layout-api.ts
|
|
13
|
+
var GRID_SIZE = 10;
|
|
14
|
+
var MIN_DISTANCE = 2 * GRID_SIZE;
|
|
15
|
+
var OPERATION_NODE_WIDTH = 150;
|
|
16
|
+
var OPERATION_NODE_HEIGHT = 40;
|
|
17
|
+
var LayoutManager = class {
|
|
18
|
+
oss;
|
|
19
|
+
layout;
|
|
20
|
+
constructor(oss, layout) {
|
|
21
|
+
this.oss = oss;
|
|
22
|
+
if (layout) {
|
|
23
|
+
this.layout = layout;
|
|
24
|
+
} else {
|
|
25
|
+
this.layout = this.oss.layout;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Calculate insert position for a new {@link Operation} */
|
|
29
|
+
newOperationPosition(position, parent, args = []) {
|
|
30
|
+
const result = { ...position };
|
|
31
|
+
const parentNode = this.layout.find((pos) => pos.nodeID === `b${parent}`) ?? null;
|
|
32
|
+
const operations = this.layout.filter((pos) => pos.nodeID.startsWith("o"));
|
|
33
|
+
const hasArguments = args.length !== 0;
|
|
34
|
+
if (hasArguments) {
|
|
35
|
+
const pos = calculatePositionFromArgs(operations.filter((node) => args.includes(Number(node.nodeID.slice(1)))));
|
|
36
|
+
result.x = pos.x;
|
|
37
|
+
result.y = pos.y;
|
|
38
|
+
} else if (parentNode) {
|
|
39
|
+
result.x = parentNode.x + MIN_DISTANCE;
|
|
40
|
+
result.y = parentNode.y + MIN_DISTANCE;
|
|
41
|
+
} else {
|
|
42
|
+
const pos = this.calculatePositionForFreeOperation(result);
|
|
43
|
+
result.x = pos.x;
|
|
44
|
+
result.y = pos.y;
|
|
45
|
+
}
|
|
46
|
+
const siblingBlocks = this.oss.blocks.filter((block) => block.parent === parent).map((block) => block.nodeID);
|
|
47
|
+
preventOverlap(
|
|
48
|
+
result,
|
|
49
|
+
this.layout.filter((node) => siblingBlocks.includes(node.nodeID)),
|
|
50
|
+
{
|
|
51
|
+
moveX: !hasArguments,
|
|
52
|
+
moveY: hasArguments
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
preventOverlap(result, operations);
|
|
56
|
+
this.extendParentBounds(parentNode, result);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
/** Calculate insert position for a new {@link Block} */
|
|
60
|
+
newBlockPosition(position, parent, blocks, operations) {
|
|
61
|
+
const blockNodes = blocks.map((id) => this.layout.find((block) => block.nodeID === `b${id}`)).filter((node) => !!node);
|
|
62
|
+
const operationNodes = operations.map((id) => this.layout.find((operation) => operation.nodeID === `o${id}`)).filter((node) => !!node);
|
|
63
|
+
const parentNode = this.layout.find((pos) => pos.nodeID === `b${parent}`) ?? null;
|
|
64
|
+
const parentID = parentNode ? parent : null;
|
|
65
|
+
let result = { ...position };
|
|
66
|
+
if (blockNodes.length !== 0 || operationNodes.length !== 0) {
|
|
67
|
+
result = calculatePositionFromChildren(position, operationNodes, blockNodes);
|
|
68
|
+
} else if (parentNode) {
|
|
69
|
+
result = {
|
|
70
|
+
x: parentNode.x + MIN_DISTANCE,
|
|
71
|
+
y: parentNode.y + MIN_DISTANCE,
|
|
72
|
+
width: position.width,
|
|
73
|
+
height: position.height
|
|
74
|
+
};
|
|
75
|
+
} else {
|
|
76
|
+
result = this.calculatePositionForFreeBlock(result);
|
|
77
|
+
}
|
|
78
|
+
if (blockNodes.length === 0 && operationNodes.length === 0) {
|
|
79
|
+
const siblings = this.oss.blocks.filter((block) => block.parent === parentID).map((block) => block.nodeID);
|
|
80
|
+
preventOverlap(
|
|
81
|
+
result,
|
|
82
|
+
this.layout.filter((node) => siblings.includes(node.nodeID))
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
this.extendParentBounds(parentNode, result);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/** Calculate insert position for a new clone of {@link Operation} */
|
|
89
|
+
newClonePosition(targetID) {
|
|
90
|
+
const targetNode = this.layout.find((pos) => pos.nodeID === targetID);
|
|
91
|
+
if (!targetNode) {
|
|
92
|
+
return null;
|
|
93
|
+
} else {
|
|
94
|
+
return {
|
|
95
|
+
x: targetNode.x + targetNode.width / 2 + GRID_SIZE,
|
|
96
|
+
y: targetNode.y + targetNode.height / 2 + GRID_SIZE,
|
|
97
|
+
width: OPERATION_NODE_WIDTH,
|
|
98
|
+
height: OPERATION_NODE_HEIGHT
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Update layout when parent changes */
|
|
103
|
+
onChangeParent(targetID, newParent) {
|
|
104
|
+
const targetNode = this.layout.find((pos) => pos.nodeID === targetID);
|
|
105
|
+
if (!targetNode) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const parentNode = this.layout.find((pos) => pos.nodeID === newParent) ?? null;
|
|
109
|
+
const offset = this.calculateOffsetForParentChange(targetNode, parentNode);
|
|
110
|
+
if (offset.x === 0 && offset.y === 0) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
targetNode.x += offset.x;
|
|
114
|
+
targetNode.y += offset.y;
|
|
115
|
+
const children = this.oss.hierarchy.expandAllOutputs([targetID]);
|
|
116
|
+
const childrenPositions = this.layout.filter((pos) => children.includes(pos.nodeID));
|
|
117
|
+
for (const child of childrenPositions) {
|
|
118
|
+
child.x += offset.x;
|
|
119
|
+
child.y += offset.y;
|
|
120
|
+
}
|
|
121
|
+
this.extendParentBounds(parentNode, targetNode);
|
|
122
|
+
}
|
|
123
|
+
/** Calculate closest node to the left */
|
|
124
|
+
selectLeft(targetID) {
|
|
125
|
+
const targetNode = this.layout.find((pos) => pos.nodeID === targetID);
|
|
126
|
+
if (!targetNode) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const operationNodes = this.layout.filter((pos) => pos.nodeID !== targetID && pos.nodeID.startsWith("o"));
|
|
130
|
+
const leftNodes = operationNodes.filter((pos) => pos.x <= targetNode.x);
|
|
131
|
+
if (leftNodes.length === 0) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const similarYNodes = leftNodes.filter((pos) => Math.abs(pos.y - targetNode.y) <= MIN_DISTANCE);
|
|
135
|
+
let closestNode = null;
|
|
136
|
+
if (similarYNodes.length > 0) {
|
|
137
|
+
closestNode = similarYNodes.reduce((prev, curr) => curr.x > prev.x ? curr : prev);
|
|
138
|
+
} else {
|
|
139
|
+
closestNode = findClosestNodeByDistance(leftNodes, targetNode);
|
|
140
|
+
}
|
|
141
|
+
return closestNode?.nodeID ?? null;
|
|
142
|
+
}
|
|
143
|
+
/** Calculate closest node to the right */
|
|
144
|
+
selectRight(targetID) {
|
|
145
|
+
const targetNode = this.layout.find((pos) => pos.nodeID === targetID);
|
|
146
|
+
if (!targetNode) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const operationNodes = this.layout.filter((pos) => pos.nodeID !== targetID && pos.nodeID.startsWith("o"));
|
|
150
|
+
const rightNodes = operationNodes.filter((pos) => pos.x >= targetNode.x);
|
|
151
|
+
if (rightNodes.length === 0) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const similarYNodes = rightNodes.filter((pos) => Math.abs(pos.y - targetNode.y) <= MIN_DISTANCE);
|
|
155
|
+
let closestNode = null;
|
|
156
|
+
if (similarYNodes.length > 0) {
|
|
157
|
+
closestNode = similarYNodes.reduce((prev, curr) => curr.x < prev.x ? curr : prev);
|
|
158
|
+
} else {
|
|
159
|
+
closestNode = findClosestNodeByDistance(rightNodes, targetNode);
|
|
160
|
+
}
|
|
161
|
+
return closestNode?.nodeID ?? null;
|
|
162
|
+
}
|
|
163
|
+
/** Calculate closest node upwards */
|
|
164
|
+
selectUp(targetID) {
|
|
165
|
+
const targetNode = this.layout.find((pos) => pos.nodeID === targetID);
|
|
166
|
+
if (!targetNode) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const operationNodes = this.layout.filter((pos) => pos.nodeID !== targetID && pos.nodeID.startsWith("o"));
|
|
170
|
+
const upperNodes = operationNodes.filter((pos) => pos.y <= targetNode.y - MIN_DISTANCE);
|
|
171
|
+
const targetOperation = this.oss.itemByNodeID.get(targetID);
|
|
172
|
+
if (upperNodes.length === 0 || !targetOperation || targetOperation.nodeType === NodeType.BLOCK) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const predecessors = this.oss.graph.expandAllInputs([targetOperation.id]);
|
|
176
|
+
const predecessorNodes = upperNodes.filter((pos) => predecessors.includes(Number(pos.nodeID.slice(1))));
|
|
177
|
+
let closestNode = null;
|
|
178
|
+
if (predecessorNodes.length > 0) {
|
|
179
|
+
closestNode = findClosestNodeByDistance(predecessorNodes, targetNode);
|
|
180
|
+
} else {
|
|
181
|
+
closestNode = findClosestNodeByDistance(upperNodes, targetNode);
|
|
182
|
+
}
|
|
183
|
+
return closestNode?.nodeID ?? null;
|
|
184
|
+
}
|
|
185
|
+
/** Calculate closest node downwards */
|
|
186
|
+
selectDown(targetID) {
|
|
187
|
+
const targetNode = this.layout.find((pos) => pos.nodeID === targetID);
|
|
188
|
+
if (!targetNode) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const operationNodes = this.layout.filter((pos) => pos.nodeID !== targetID && pos.nodeID.startsWith("o"));
|
|
192
|
+
const lowerNodes = operationNodes.filter((pos) => pos.y >= targetNode.y - MIN_DISTANCE);
|
|
193
|
+
const targetOperation = this.oss.itemByNodeID.get(targetID);
|
|
194
|
+
if (lowerNodes.length === 0 || !targetOperation || targetOperation.nodeType === NodeType.BLOCK) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const descendants = this.oss.graph.expandAllOutputs([targetOperation.id]);
|
|
198
|
+
const descendantsNodes = lowerNodes.filter((pos) => descendants.includes(Number(pos.nodeID.slice(1))));
|
|
199
|
+
let closestNode = null;
|
|
200
|
+
if (descendantsNodes.length > 0) {
|
|
201
|
+
closestNode = findClosestNodeByDistance(descendantsNodes, targetNode);
|
|
202
|
+
} else {
|
|
203
|
+
closestNode = findClosestNodeByDistance(lowerNodes, targetNode);
|
|
204
|
+
}
|
|
205
|
+
return closestNode?.nodeID ?? null;
|
|
206
|
+
}
|
|
207
|
+
extendParentBounds(parent, child) {
|
|
208
|
+
if (!parent) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const borderX = child.x + child.width + MIN_DISTANCE;
|
|
212
|
+
const borderY = child.y + child.height + MIN_DISTANCE;
|
|
213
|
+
parent.width = Math.max(parent.width, borderX - parent.x);
|
|
214
|
+
parent.height = Math.max(parent.height, borderY - parent.y);
|
|
215
|
+
}
|
|
216
|
+
calculatePositionForFreeOperation(initial) {
|
|
217
|
+
if (this.oss.operations.length === 0) {
|
|
218
|
+
return initial;
|
|
219
|
+
}
|
|
220
|
+
const freeInputs = this.oss.operations.filter(
|
|
221
|
+
(operation) => operation.parent === null && (operation.operation_type !== OperationType.SYNTHESIS || operation.arguments.length === 0)
|
|
222
|
+
).map((operation) => operation.nodeID);
|
|
223
|
+
let inputsPositions = this.layout.filter((pos) => freeInputs.includes(pos.nodeID));
|
|
224
|
+
if (inputsPositions.length === 0) {
|
|
225
|
+
inputsPositions = this.layout.filter((pos) => pos.nodeID.startsWith("o"));
|
|
226
|
+
}
|
|
227
|
+
const maxX = Math.max(...inputsPositions.map((node) => node.x));
|
|
228
|
+
const minY = Math.min(...inputsPositions.map((node) => node.y));
|
|
229
|
+
return {
|
|
230
|
+
x: maxX + OPERATION_NODE_WIDTH + MIN_DISTANCE + GRID_SIZE,
|
|
231
|
+
y: minY
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
calculatePositionForFreeBlock(initial) {
|
|
235
|
+
const rootBlocks = this.oss.blocks.filter((block) => block.parent === null).map((block) => block.nodeID);
|
|
236
|
+
const blocksPositions = this.layout.filter((pos) => rootBlocks.includes(pos.nodeID));
|
|
237
|
+
if (blocksPositions.length === 0) {
|
|
238
|
+
return initial;
|
|
239
|
+
}
|
|
240
|
+
const maxX = Math.max(...blocksPositions.map((node) => node.x + node.width));
|
|
241
|
+
const minY = Math.min(...blocksPositions.map((node) => node.y));
|
|
242
|
+
return { ...initial, x: maxX + MIN_DISTANCE, y: minY };
|
|
243
|
+
}
|
|
244
|
+
calculateOffsetForParentChange(target, parent) {
|
|
245
|
+
const newPosition = { ...target };
|
|
246
|
+
if (parent === null) {
|
|
247
|
+
const rootElements = this.oss.hierarchy.rootNodes();
|
|
248
|
+
const positions = this.layout.filter((pos) => rootElements.includes(pos.nodeID));
|
|
249
|
+
preventOverlap(newPosition, positions);
|
|
250
|
+
} else if (!rectanglesStrictOverlap(target, parent)) {
|
|
251
|
+
newPosition.x = parent.x + MIN_DISTANCE;
|
|
252
|
+
newPosition.y = parent.y + MIN_DISTANCE;
|
|
253
|
+
const siblings = this.oss.hierarchy.at(parent.nodeID)?.outputs ?? [];
|
|
254
|
+
const siblingsPositions = this.layout.filter((pos) => siblings.includes(pos.nodeID));
|
|
255
|
+
preventOverlap(newPosition, siblingsPositions);
|
|
256
|
+
}
|
|
257
|
+
return { x: newPosition.x - target.x, y: newPosition.y - target.y };
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
function rectanglesOverlap(a, b) {
|
|
261
|
+
return !(a.x + a.width + MIN_DISTANCE <= b.x || b.x + b.width + MIN_DISTANCE <= a.x || a.y + a.height + MIN_DISTANCE <= b.y || b.y + b.height + MIN_DISTANCE <= a.y);
|
|
262
|
+
}
|
|
263
|
+
function rectanglesStrictOverlap(a, b) {
|
|
264
|
+
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
|
|
265
|
+
}
|
|
266
|
+
function preventOverlap(target, fixedRectangles, options = { moveX: true, moveY: true }) {
|
|
267
|
+
if (!options.moveX && !options.moveY || fixedRectangles.length === 0) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
let hasOverlap;
|
|
271
|
+
do {
|
|
272
|
+
hasOverlap = false;
|
|
273
|
+
for (const fixed of fixedRectangles) {
|
|
274
|
+
if (rectanglesOverlap(target, fixed)) {
|
|
275
|
+
hasOverlap = true;
|
|
276
|
+
if (options.moveX) {
|
|
277
|
+
target.x += MIN_DISTANCE;
|
|
278
|
+
}
|
|
279
|
+
if (options.moveY) {
|
|
280
|
+
target.y += MIN_DISTANCE;
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
} while (hasOverlap);
|
|
286
|
+
}
|
|
287
|
+
function calculatePositionFromArgs(args) {
|
|
288
|
+
const maxY = Math.max(...args.map((node) => node.y));
|
|
289
|
+
const minX = Math.min(...args.map((node) => node.x));
|
|
290
|
+
const maxX = Math.max(...args.map((node) => node.x));
|
|
291
|
+
return {
|
|
292
|
+
x: Math.ceil((maxX + minX) / 2 / GRID_SIZE) * GRID_SIZE,
|
|
293
|
+
y: maxY + 2 * OPERATION_NODE_HEIGHT + MIN_DISTANCE
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function calculatePositionFromChildren(initial, operations, blocks) {
|
|
297
|
+
const allNodes = [...blocks, ...operations];
|
|
298
|
+
if (allNodes.length === 0) {
|
|
299
|
+
return initial;
|
|
300
|
+
}
|
|
301
|
+
const left = Math.min(...allNodes.map((n) => n.x)) - MIN_DISTANCE;
|
|
302
|
+
const top = Math.min(...allNodes.map((n) => n.y)) - MIN_DISTANCE;
|
|
303
|
+
const right = Math.max(...allNodes.map((n) => n.x + n.width)) + MIN_DISTANCE;
|
|
304
|
+
const bottom = Math.max(...allNodes.map((n) => n.y + n.height)) + MIN_DISTANCE;
|
|
305
|
+
return {
|
|
306
|
+
x: left,
|
|
307
|
+
y: top,
|
|
308
|
+
width: right - left,
|
|
309
|
+
height: bottom - top
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function findClosestNodeByDistance(nodes, target) {
|
|
313
|
+
let minDist = Infinity;
|
|
314
|
+
let minNode = null;
|
|
315
|
+
for (const curr of nodes) {
|
|
316
|
+
const currDist = Math.hypot(curr.x - target.x, curr.y - target.y);
|
|
317
|
+
if (currDist < minDist) {
|
|
318
|
+
minDist = currDist;
|
|
319
|
+
minNode = curr;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return minNode;
|
|
323
|
+
}
|
|
324
|
+
export {
|
|
325
|
+
GRID_SIZE,
|
|
326
|
+
LayoutManager,
|
|
327
|
+
OPERATION_NODE_HEIGHT,
|
|
328
|
+
OPERATION_NODE_WIDTH
|
|
329
|
+
};
|
|
330
|
+
//# sourceMappingURL=oss-layout-api.js.map
|