@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,433 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module: Custom graph data structure.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Represents single node of a {@link Graph}, as implemented by storing outgoing and incoming connections. */
|
|
6
|
+
export class GraphNode<NodeID> {
|
|
7
|
+
/** Unique identifier of the node. */
|
|
8
|
+
id: NodeID;
|
|
9
|
+
/** List of outgoing nodes. */
|
|
10
|
+
outputs: NodeID[];
|
|
11
|
+
/** List of incoming nodes. */
|
|
12
|
+
inputs: NodeID[];
|
|
13
|
+
|
|
14
|
+
constructor(id: NodeID) {
|
|
15
|
+
this.id = id;
|
|
16
|
+
this.outputs = [];
|
|
17
|
+
this.inputs = [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
clone(): GraphNode<NodeID> {
|
|
21
|
+
const result = new GraphNode(this.id);
|
|
22
|
+
result.outputs = [...this.outputs];
|
|
23
|
+
result.inputs = [...this.inputs];
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
addOutput(node: NodeID): void {
|
|
28
|
+
this.outputs.push(node);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
addInput(node: NodeID): void {
|
|
32
|
+
this.inputs.push(node);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
removeInput(target: NodeID): NodeID | null {
|
|
36
|
+
const index = this.inputs.findIndex(node => node === target);
|
|
37
|
+
return index > -1 ? this.inputs.splice(index, 1)[0] : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
removeOutput(target: NodeID): NodeID | null {
|
|
41
|
+
const index = this.outputs.findIndex(node => node === target);
|
|
42
|
+
return index > -1 ? this.outputs.splice(index, 1)[0] : null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Represents a Graph.
|
|
48
|
+
*
|
|
49
|
+
* This class is optimized for TermGraph use case and not supposed to be used as generic graph implementation.
|
|
50
|
+
*/
|
|
51
|
+
export class Graph<NodeID = number> {
|
|
52
|
+
/** Map of nodes. */
|
|
53
|
+
nodes = new Map<NodeID, GraphNode<NodeID>>();
|
|
54
|
+
|
|
55
|
+
constructor(arr?: NodeID[][]) {
|
|
56
|
+
if (!arr) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
arr.forEach(edge => {
|
|
60
|
+
if (edge.length === 1) {
|
|
61
|
+
this.addNode(edge[0]);
|
|
62
|
+
} else {
|
|
63
|
+
this.addEdge(edge[0], edge[1]);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
clone(): Graph<NodeID> {
|
|
69
|
+
const result = new Graph<NodeID>();
|
|
70
|
+
this.nodes.forEach(node => result.nodes.set(node.id, node.clone()));
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
at(target: NodeID): GraphNode<NodeID> | undefined {
|
|
75
|
+
return this.nodes.get(target);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
addNode(target: NodeID): GraphNode<NodeID> {
|
|
79
|
+
let node = this.nodes.get(target);
|
|
80
|
+
if (!node) {
|
|
81
|
+
node = new GraphNode(target);
|
|
82
|
+
this.nodes.set(target, node);
|
|
83
|
+
}
|
|
84
|
+
return node;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
hasNode(target: NodeID): boolean {
|
|
88
|
+
return !!this.nodes.get(target);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
removeNode(target: NodeID): void {
|
|
92
|
+
this.nodes.forEach(node => {
|
|
93
|
+
node.removeInput(target);
|
|
94
|
+
node.removeOutput(target);
|
|
95
|
+
});
|
|
96
|
+
this.nodes.delete(target);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
foldNode(target: NodeID): void {
|
|
100
|
+
const nodeToRemove = this.nodes.get(target);
|
|
101
|
+
if (!nodeToRemove) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
nodeToRemove.inputs.forEach(input => {
|
|
105
|
+
nodeToRemove.outputs.forEach(output => {
|
|
106
|
+
this.addEdge(input, output);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
this.removeNode(target);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
removeIsolated(): GraphNode<NodeID>[] {
|
|
113
|
+
const result: GraphNode<NodeID>[] = [];
|
|
114
|
+
this.nodes.forEach(node => {
|
|
115
|
+
if (node.outputs.length === 0 && node.inputs.length === 0) {
|
|
116
|
+
result.push(node);
|
|
117
|
+
this.nodes.delete(node.id);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
addEdge(source: NodeID, destination: NodeID): void {
|
|
124
|
+
if (this.hasEdge(source, destination)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const sourceNode = this.addNode(source);
|
|
128
|
+
const destinationNode = this.addNode(destination);
|
|
129
|
+
sourceNode.addOutput(destinationNode.id);
|
|
130
|
+
destinationNode.addInput(sourceNode.id);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
removeEdge(source: NodeID, destination: NodeID): void {
|
|
134
|
+
const sourceNode = this.nodes.get(source);
|
|
135
|
+
const destinationNode = this.nodes.get(destination);
|
|
136
|
+
if (sourceNode && destinationNode) {
|
|
137
|
+
sourceNode.removeOutput(destination);
|
|
138
|
+
destinationNode.removeInput(source);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
hasEdge(source: NodeID, destination: NodeID): boolean {
|
|
143
|
+
const sourceNode = this.nodes.get(source);
|
|
144
|
+
if (!sourceNode) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
return !!sourceNode.outputs.find(id => id === destination);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
isReachable(source: NodeID, destination: NodeID): boolean {
|
|
151
|
+
return this.expandAllOutputs([source]).includes(destination);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
rootNodes(): NodeID[] {
|
|
155
|
+
return [...this.nodes.keys()].filter(id => !this.nodes.get(id)?.inputs.length);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
expandOutputs(origin: NodeID[]): NodeID[] {
|
|
159
|
+
const result: NodeID[] = [];
|
|
160
|
+
origin.forEach(id => {
|
|
161
|
+
const node = this.nodes.get(id);
|
|
162
|
+
if (node) {
|
|
163
|
+
node.outputs.forEach(child => {
|
|
164
|
+
if (!origin.includes(child) && !result.includes(child)) {
|
|
165
|
+
result.push(child);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
expandInputs(origin: NodeID[]): NodeID[] {
|
|
174
|
+
const result: NodeID[] = [];
|
|
175
|
+
origin.forEach(id => {
|
|
176
|
+
const node = this.nodes.get(id);
|
|
177
|
+
if (node) {
|
|
178
|
+
node.inputs.forEach(child => {
|
|
179
|
+
if (!origin.includes(child) && !result.includes(child)) {
|
|
180
|
+
result.push(child);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
expandAllOutputs(origin: NodeID[]): NodeID[] {
|
|
189
|
+
const result: NodeID[] = this.expandOutputs(origin);
|
|
190
|
+
if (result.length === 0) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const marked = new Map<NodeID, boolean>();
|
|
195
|
+
origin.forEach(id => marked.set(id, true));
|
|
196
|
+
let position = 0;
|
|
197
|
+
while (position < result.length) {
|
|
198
|
+
const node = this.nodes.get(result[position]);
|
|
199
|
+
if (node && !marked.get(node.id)) {
|
|
200
|
+
marked.set(node.id, true);
|
|
201
|
+
node.outputs.forEach(child => {
|
|
202
|
+
if (!marked.get(child) && !result.find(id => id === child)) {
|
|
203
|
+
result.push(child);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
position += 1;
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
expandAllInputs(origin: NodeID[]): NodeID[] {
|
|
213
|
+
const result: NodeID[] = this.expandInputs(origin);
|
|
214
|
+
if (result.length === 0) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const marked = new Map<NodeID, boolean>();
|
|
219
|
+
origin.forEach(id => marked.set(id, true));
|
|
220
|
+
let position = 0;
|
|
221
|
+
while (position < result.length) {
|
|
222
|
+
const node = this.nodes.get(result[position]);
|
|
223
|
+
if (node && !marked.get(node.id)) {
|
|
224
|
+
marked.set(node.id, true);
|
|
225
|
+
node.inputs.forEach(child => {
|
|
226
|
+
if (!marked.get(child) && !result.find(id => id === child)) {
|
|
227
|
+
result.push(child);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
position += 1;
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
maximizePart(origin: NodeID[]): NodeID[] {
|
|
237
|
+
const outputs: NodeID[] = this.expandAllOutputs(origin);
|
|
238
|
+
const result = [...origin];
|
|
239
|
+
this.topologicalOrder()
|
|
240
|
+
.filter(id => outputs.includes(id))
|
|
241
|
+
.forEach(id => {
|
|
242
|
+
const node = this.nodes.get(id);
|
|
243
|
+
if (node?.inputs.every(parent => result.includes(parent))) {
|
|
244
|
+
result.push(id);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
topologicalOrder(): NodeID[] {
|
|
251
|
+
const result: NodeID[] = [];
|
|
252
|
+
const marked = new Set<NodeID>();
|
|
253
|
+
const nodeStack: NodeID[] = [];
|
|
254
|
+
this.nodes.forEach(node => {
|
|
255
|
+
if (marked.has(node.id)) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
nodeStack.push(node.id);
|
|
259
|
+
while (nodeStack.length > 0) {
|
|
260
|
+
const item = nodeStack[nodeStack.length - 1];
|
|
261
|
+
if (marked.has(item)) {
|
|
262
|
+
if (!result.find(id => id === item)) {
|
|
263
|
+
result.push(item);
|
|
264
|
+
}
|
|
265
|
+
nodeStack.pop();
|
|
266
|
+
} else {
|
|
267
|
+
marked.add(item);
|
|
268
|
+
const itemNode = this.nodes.get(item);
|
|
269
|
+
if (itemNode && itemNode.outputs.length > 0) {
|
|
270
|
+
itemNode.outputs.forEach(child => {
|
|
271
|
+
if (!marked.has(child)) {
|
|
272
|
+
nodeStack.push(child);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return result.reverse();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Stably reorders the given node ids so that, for this DAG, no node appears before a transitive
|
|
284
|
+
* successor (edges: source → dependent; {@link GraphNode.outputs} lists dependents).
|
|
285
|
+
*/
|
|
286
|
+
sortStable(target: NodeID[]): NodeID[] {
|
|
287
|
+
if (target.length <= 1) {
|
|
288
|
+
return [...target];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const reachable = this.buildTransitiveClosureForSort();
|
|
292
|
+
const testSet = new Set<NodeID>();
|
|
293
|
+
const result: NodeID[] = [];
|
|
294
|
+
|
|
295
|
+
for (const nodeId of [...target].reverse()) {
|
|
296
|
+
const nodeReachable = reachable.get(nodeId) ?? new Set<NodeID>();
|
|
297
|
+
const needMove = testSet.has(nodeId);
|
|
298
|
+
for (const childId of nodeReachable) {
|
|
299
|
+
testSet.add(childId);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (!needMove) {
|
|
303
|
+
result.push(nodeId);
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
let inserted = false;
|
|
308
|
+
for (let index = 0; index < result.length; index++) {
|
|
309
|
+
const parent = result[index];
|
|
310
|
+
const parentReachable = reachable.get(parent) ?? new Set<NodeID>();
|
|
311
|
+
if (nodeReachable.has(parent)) {
|
|
312
|
+
if (parentReachable.has(nodeId)) {
|
|
313
|
+
result.push(nodeId);
|
|
314
|
+
} else {
|
|
315
|
+
result.splice(index, 0, nodeId);
|
|
316
|
+
}
|
|
317
|
+
inserted = true;
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (!inserted) {
|
|
322
|
+
result.push(nodeId);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
result.reverse();
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private buildTransitiveClosureForSort(): Map<NodeID, Set<NodeID>> {
|
|
331
|
+
const closure = new Map<NodeID, Set<NodeID>>();
|
|
332
|
+
for (const node of this.nodes.values()) {
|
|
333
|
+
closure.set(node.id, new Set(node.outputs));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const order = this.topologicalOrder();
|
|
337
|
+
for (const nodeId of [...order].reverse()) {
|
|
338
|
+
const node = this.at(nodeId);
|
|
339
|
+
if (!node) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const nodeClosure = closure.get(nodeId) ?? new Set<NodeID>();
|
|
343
|
+
for (const parentId of node.inputs) {
|
|
344
|
+
const parentClosure = closure.get(parentId) ?? new Set<NodeID>();
|
|
345
|
+
for (const childId of nodeClosure) {
|
|
346
|
+
parentClosure.add(childId);
|
|
347
|
+
}
|
|
348
|
+
closure.set(parentId, parentClosure);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return closure;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
transitiveReduction() {
|
|
356
|
+
const order = this.topologicalOrder();
|
|
357
|
+
const marked = new Map<NodeID, boolean>();
|
|
358
|
+
order.forEach(nodeID => {
|
|
359
|
+
if (marked.get(nodeID)) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const stack: { id: NodeID; parents: NodeID[] }[] = [];
|
|
363
|
+
stack.push({ id: nodeID, parents: [] });
|
|
364
|
+
while (stack.length > 0) {
|
|
365
|
+
const item = stack.splice(0, 1)[0];
|
|
366
|
+
const node = this.nodes.get(item.id);
|
|
367
|
+
if (node) {
|
|
368
|
+
node.outputs.forEach(child => {
|
|
369
|
+
item.parents.forEach(parent => this.removeEdge(parent, child));
|
|
370
|
+
stack.push({ id: child, parents: [item.id, ...item.parents] });
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
marked.set(item.id, true);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Finds a cycle in the graph.
|
|
380
|
+
*
|
|
381
|
+
* @returns {NodeID[] | null} The cycle if found, otherwise `null`.
|
|
382
|
+
* Uses non-recursive DFS.
|
|
383
|
+
*/
|
|
384
|
+
findCycle(): NodeID[] | null {
|
|
385
|
+
const visited = new Set<NodeID>();
|
|
386
|
+
const nodeStack = new Set<NodeID>();
|
|
387
|
+
const parents = new Map<NodeID, NodeID>();
|
|
388
|
+
|
|
389
|
+
for (const nodeId of this.nodes.keys()) {
|
|
390
|
+
if (visited.has(nodeId)) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const callStack: { nodeId: NodeID; parentId: NodeID | null }[] = [];
|
|
395
|
+
callStack.push({ nodeId: nodeId, parentId: null });
|
|
396
|
+
while (callStack.length > 0) {
|
|
397
|
+
const { nodeId, parentId } = callStack[callStack.length - 1];
|
|
398
|
+
if (visited.has(nodeId)) {
|
|
399
|
+
nodeStack.delete(nodeId);
|
|
400
|
+
callStack.pop();
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
visited.add(nodeId);
|
|
404
|
+
nodeStack.add(nodeId);
|
|
405
|
+
if (parentId !== null) {
|
|
406
|
+
parents.set(nodeId, parentId);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const currentNode = this.nodes.get(nodeId)!;
|
|
410
|
+
for (const child of currentNode.outputs) {
|
|
411
|
+
if (!visited.has(child)) {
|
|
412
|
+
callStack.push({ nodeId: child, parentId: nodeId });
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (!nodeStack.has(child)) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
const cycle: NodeID[] = [];
|
|
419
|
+
let current = nodeId;
|
|
420
|
+
cycle.push(child);
|
|
421
|
+
while (current !== child) {
|
|
422
|
+
cycle.push(current);
|
|
423
|
+
current = parents.get(current)!;
|
|
424
|
+
}
|
|
425
|
+
cycle.push(child);
|
|
426
|
+
cycle.reverse();
|
|
427
|
+
return cycle;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Graph } from './graph';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type EntityReference,
|
|
3
|
+
Grammeme,
|
|
4
|
+
ReferenceType,
|
|
5
|
+
supportedGrammemes,
|
|
6
|
+
type SyntacticReference,
|
|
7
|
+
type TermContext,
|
|
8
|
+
type WordForm
|
|
9
|
+
} from './cctext/language';
|
|
10
|
+
export { Graph } from './graph/graph';
|
|
11
|
+
export { FolderNode, FolderTree } from './library/folder-tree';
|
|
12
|
+
export {
|
|
13
|
+
AccessPolicy,
|
|
14
|
+
type CurrentVersion,
|
|
15
|
+
type LibraryItem,
|
|
16
|
+
type LibraryItemReference,
|
|
17
|
+
LibraryItemType,
|
|
18
|
+
LocationHead,
|
|
19
|
+
type VersionInfo
|
|
20
|
+
} from './library/library';
|
|
21
|
+
export type { Block } from './library/oss';
|
|
22
|
+
export {
|
|
23
|
+
type CstSubstituteInfo,
|
|
24
|
+
NodeType,
|
|
25
|
+
type Operation,
|
|
26
|
+
type OperationInput,
|
|
27
|
+
type OperationSchema,
|
|
28
|
+
type OperationSchemaStats,
|
|
29
|
+
type OperationSynthesis,
|
|
30
|
+
OperationType,
|
|
31
|
+
type OssItem,
|
|
32
|
+
type SubstitutionErrorDescription,
|
|
33
|
+
SubstitutionErrorType
|
|
34
|
+
} from './library/oss';
|
|
35
|
+
export { type OssLayout, type Position2D } from './library/oss-layout';
|
|
36
|
+
export { RSEngine } from './library/rsengine';
|
|
37
|
+
export {
|
|
38
|
+
type ArgumentValue,
|
|
39
|
+
type Attribution,
|
|
40
|
+
type Constituenta,
|
|
41
|
+
CstClass,
|
|
42
|
+
CstStatus,
|
|
43
|
+
CstType,
|
|
44
|
+
type RSForm,
|
|
45
|
+
type RSFormStats,
|
|
46
|
+
type Substitution,
|
|
47
|
+
type TypeInfo
|
|
48
|
+
} from './library/rsform';
|
|
49
|
+
export {
|
|
50
|
+
type BasicBinding,
|
|
51
|
+
type BasicsContext,
|
|
52
|
+
DEFAULT_VALUE_TEXT,
|
|
53
|
+
EvalStatus,
|
|
54
|
+
type RSModel,
|
|
55
|
+
type RSModelStats
|
|
56
|
+
} from './library/rsmodel';
|
|
57
|
+
export {
|
|
58
|
+
type AstNode,
|
|
59
|
+
type AstNodeBase,
|
|
60
|
+
buildTree,
|
|
61
|
+
findByUid,
|
|
62
|
+
type FlatAST,
|
|
63
|
+
type FlatAstNode,
|
|
64
|
+
flattenAst,
|
|
65
|
+
getNodeIndices,
|
|
66
|
+
getNodeText,
|
|
67
|
+
printAst,
|
|
68
|
+
TOKEN_ERROR,
|
|
69
|
+
visitAstDFS
|
|
70
|
+
} from './parsing/ast';
|
|
71
|
+
export { type CMSyntaxNode, printTree } from './parsing/lezer-tree';
|
|
72
|
+
export { readErrorAnnotation, readTypeAnnotation } from './rslang/ast-annotations';
|
|
73
|
+
export { RSErrorCode, type RSErrorDescription } from './rslang/error';
|
|
74
|
+
export { type CalculatorEvaluateOptions, type CalculatorResult, RSCalculator } from './rslang/eval/calculator';
|
|
75
|
+
export { makeValuePath, type Value, type ValuePath } from './rslang/eval/value';
|
|
76
|
+
export { printValue } from './rslang/eval/value-api';
|
|
77
|
+
export { parser as rslangParser } from './rslang/parser/parser';
|
|
78
|
+
export { TokenID } from './rslang/parser/token';
|
|
79
|
+
export { type AnalysisBase, type AnalysisFast, type AnalysisFull, RSLangAnalyzer } from './rslang/semantic/analyzer';
|
|
80
|
+
export { type ArgumentsType } from './rslang/semantic/arguments-extractor';
|
|
81
|
+
export {
|
|
82
|
+
AnyTypificationT,
|
|
83
|
+
EmptySetT,
|
|
84
|
+
type ExpressionType,
|
|
85
|
+
LogicT,
|
|
86
|
+
makeTypePath,
|
|
87
|
+
TypeClass,
|
|
88
|
+
TypeID,
|
|
89
|
+
type TypePath,
|
|
90
|
+
type Typification
|
|
91
|
+
} from './rslang/semantic/typification';
|
|
92
|
+
export { applyAsciiTypeSubstitutions, parseTypeText } from './rslang/semantic/typification-parser';
|
|
93
|
+
export { ValueClass } from './rslang/semantic/value-class';
|
|
94
|
+
export { TypificationGraph, type TypificationNodeData } from './rslang/typification-graph';
|
|
95
|
+
export { type Branded } from './shared/branded';
|
|
96
|
+
export { applyHash_fnv1a, generateStub } from './shared/hash';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { FolderTree } from './folder-tree';
|
|
4
|
+
|
|
5
|
+
describe('Testing Tree construction', () => {
|
|
6
|
+
it('empty Tree should be empty', () => {
|
|
7
|
+
const tree = new FolderTree();
|
|
8
|
+
expect(tree.roots.size).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('constructing from paths', () => {
|
|
12
|
+
const tree = new FolderTree(['/S', '/S/project1/123', '/U']);
|
|
13
|
+
expect(tree.roots.size).toBe(2);
|
|
14
|
+
expect(tree.roots.get('S')?.children.size).toBe(1);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('Testing Tree editing', () => {
|
|
19
|
+
it('add invalid path', () => {
|
|
20
|
+
const tree = new FolderTree();
|
|
21
|
+
expect(() => tree.addPath('invalid')).toThrow(Error);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('add valid path', () => {
|
|
25
|
+
const tree = new FolderTree();
|
|
26
|
+
const node = tree.addPath('/S/test');
|
|
27
|
+
expect(node.getPath()).toBe('/S/test');
|
|
28
|
+
expect(node.filesInside).toBe(1);
|
|
29
|
+
expect(node.filesTotal).toBe(1);
|
|
30
|
+
|
|
31
|
+
expect(node.parent?.getPath()).toBe('/S');
|
|
32
|
+
expect(node.parent?.filesInside).toBe(0);
|
|
33
|
+
expect(node.parent?.filesTotal).toBe(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('incrementing counter', () => {
|
|
37
|
+
const tree = new FolderTree();
|
|
38
|
+
const node1 = tree.addPath('/S/test', 0);
|
|
39
|
+
expect(node1.filesInside).toBe(0);
|
|
40
|
+
expect(node1.filesTotal).toBe(0);
|
|
41
|
+
|
|
42
|
+
const node2 = tree.addPath('/S/test', 2);
|
|
43
|
+
expect(node1).toBe(node2);
|
|
44
|
+
expect(node2.filesInside).toBe(2);
|
|
45
|
+
expect(node2.filesTotal).toBe(2);
|
|
46
|
+
});
|
|
47
|
+
});
|