@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.
Files changed (224) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/cctext/index.d.ts +1 -0
  4. package/dist/cctext/index.js +42 -0
  5. package/dist/cctext/index.js.map +1 -0
  6. package/dist/cctext/language-api.d.ts +43 -0
  7. package/dist/cctext/language-api.js +252 -0
  8. package/dist/cctext/language-api.js.map +1 -0
  9. package/dist/cctext/language.d.ts +58 -0
  10. package/dist/cctext/language.js +44 -0
  11. package/dist/cctext/language.js.map +1 -0
  12. package/dist/graph/graph.d.ts +62 -0
  13. package/dist/graph/graph.js +385 -0
  14. package/dist/graph/graph.js.map +1 -0
  15. package/dist/graph/index.d.ts +1 -0
  16. package/dist/graph/index.js +384 -0
  17. package/dist/graph/index.js.map +1 -0
  18. package/dist/index.d.ts +28 -0
  19. package/dist/index.js +5851 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/library/folder-tree.d.ts +32 -0
  22. package/dist/library/folder-tree.js +136 -0
  23. package/dist/library/folder-tree.js.map +1 -0
  24. package/dist/library/index.d.ts +17 -0
  25. package/dist/library/index.js +2800 -0
  26. package/dist/library/index.js.map +1 -0
  27. package/dist/library/library-api.d.ts +6 -0
  28. package/dist/library/library-api.js +13 -0
  29. package/dist/library/library-api.js.map +1 -0
  30. package/dist/library/library.d.ts +56 -0
  31. package/dist/library/library.js +23 -0
  32. package/dist/library/library.js.map +1 -0
  33. package/dist/library/oss-api.d.ts +47 -0
  34. package/dist/library/oss-api.js +1105 -0
  35. package/dist/library/oss-api.js.map +1 -0
  36. package/dist/library/oss-layout-api.d.ts +36 -0
  37. package/dist/library/oss-layout-api.js +330 -0
  38. package/dist/library/oss-layout-api.js.map +1 -0
  39. package/dist/library/oss-layout.d.ts +25 -0
  40. package/dist/library/oss-layout.js +1 -0
  41. package/dist/library/oss-layout.js.map +1 -0
  42. package/dist/library/oss.d.ts +136 -0
  43. package/dist/library/oss.js +30 -0
  44. package/dist/library/oss.js.map +1 -0
  45. package/dist/library/rsengine.d.ts +116 -0
  46. package/dist/library/rsengine.js +2604 -0
  47. package/dist/library/rsengine.js.map +1 -0
  48. package/dist/library/rsform-api.d.ts +74 -0
  49. package/dist/library/rsform-api.js +879 -0
  50. package/dist/library/rsform-api.js.map +1 -0
  51. package/dist/library/rsform.d.ts +206 -0
  52. package/dist/library/rsform.js +32 -0
  53. package/dist/library/rsform.js.map +1 -0
  54. package/dist/library/rsmodel-api.d.ts +43 -0
  55. package/dist/library/rsmodel-api.js +836 -0
  56. package/dist/library/rsmodel-api.js.map +1 -0
  57. package/dist/library/rsmodel.d.ts +52 -0
  58. package/dist/library/rsmodel.js +25 -0
  59. package/dist/library/rsmodel.js.map +1 -0
  60. package/dist/library/structure-planner.d.ts +33 -0
  61. package/dist/library/structure-planner.js +481 -0
  62. package/dist/library/structure-planner.js.map +1 -0
  63. package/dist/parsing/ast.d.ts +49 -0
  64. package/dist/parsing/ast.js +93 -0
  65. package/dist/parsing/ast.js.map +1 -0
  66. package/dist/parsing/index.d.ts +3 -0
  67. package/dist/parsing/index.js +141 -0
  68. package/dist/parsing/index.js.map +1 -0
  69. package/dist/parsing/lezer-tree.d.ts +13 -0
  70. package/dist/parsing/lezer-tree.js +50 -0
  71. package/dist/parsing/lezer-tree.js.map +1 -0
  72. package/dist/rslang/api.d.ts +53 -0
  73. package/dist/rslang/api.js +846 -0
  74. package/dist/rslang/api.js.map +1 -0
  75. package/dist/rslang/ast-annotations.d.ts +18 -0
  76. package/dist/rslang/ast-annotations.js +56 -0
  77. package/dist/rslang/ast-annotations.js.map +1 -0
  78. package/dist/rslang/error.d.ts +85 -0
  79. package/dist/rslang/error.js +159 -0
  80. package/dist/rslang/error.js.map +1 -0
  81. package/dist/rslang/eval/calculator.d.ts +43 -0
  82. package/dist/rslang/eval/calculator.js +1639 -0
  83. package/dist/rslang/eval/calculator.js.map +1 -0
  84. package/dist/rslang/eval/evaluation-cache.d.ts +36 -0
  85. package/dist/rslang/eval/evaluation-cache.js +310 -0
  86. package/dist/rslang/eval/evaluation-cache.js.map +1 -0
  87. package/dist/rslang/eval/evaluator.d.ts +70 -0
  88. package/dist/rslang/eval/evaluator.js +1514 -0
  89. package/dist/rslang/eval/evaluator.js.map +1 -0
  90. package/dist/rslang/eval/value-api.d.ts +48 -0
  91. package/dist/rslang/eval/value-api.js +490 -0
  92. package/dist/rslang/eval/value-api.js.map +1 -0
  93. package/dist/rslang/eval/value.d.ts +36 -0
  94. package/dist/rslang/eval/value.js +118 -0
  95. package/dist/rslang/eval/value.js.map +1 -0
  96. package/dist/rslang/index.d.ts +17 -0
  97. package/dist/rslang/index.js +4314 -0
  98. package/dist/rslang/index.js.map +1 -0
  99. package/dist/rslang/labels.d.ts +16 -0
  100. package/dist/rslang/labels.js +315 -0
  101. package/dist/rslang/labels.js.map +1 -0
  102. package/dist/rslang/parser/expression-generator.d.ts +10 -0
  103. package/dist/rslang/parser/expression-generator.js +451 -0
  104. package/dist/rslang/parser/expression-generator.js.map +1 -0
  105. package/dist/rslang/parser/normalize.d.ts +11 -0
  106. package/dist/rslang/parser/normalize.js +507 -0
  107. package/dist/rslang/parser/normalize.js.map +1 -0
  108. package/dist/rslang/parser/parser.d.ts +5 -0
  109. package/dist/rslang/parser/parser.js +24 -0
  110. package/dist/rslang/parser/parser.js.map +1 -0
  111. package/dist/rslang/parser/parser.terms.d.ts +42 -0
  112. package/dist/rslang/parser/parser.terms.js +84 -0
  113. package/dist/rslang/parser/parser.terms.js.map +1 -0
  114. package/dist/rslang/parser/syntax-errors.d.ts +11 -0
  115. package/dist/rslang/parser/syntax-errors.js +403 -0
  116. package/dist/rslang/parser/syntax-errors.js.map +1 -0
  117. package/dist/rslang/parser/token.d.ts +79 -0
  118. package/dist/rslang/parser/token.js +95 -0
  119. package/dist/rslang/parser/token.js.map +1 -0
  120. package/dist/rslang/semantic/analyzer.d.ts +39 -0
  121. package/dist/rslang/semantic/analyzer.js +2604 -0
  122. package/dist/rslang/semantic/analyzer.js.map +1 -0
  123. package/dist/rslang/semantic/arguments-extractor.d.ts +42 -0
  124. package/dist/rslang/semantic/arguments-extractor.js +366 -0
  125. package/dist/rslang/semantic/arguments-extractor.js.map +1 -0
  126. package/dist/rslang/semantic/type-auditor.d.ts +73 -0
  127. package/dist/rslang/semantic/type-auditor.js +1570 -0
  128. package/dist/rslang/semantic/type-auditor.js.map +1 -0
  129. package/dist/rslang/semantic/typification-api.d.ts +27 -0
  130. package/dist/rslang/semantic/typification-api.js +320 -0
  131. package/dist/rslang/semantic/typification-api.js.map +1 -0
  132. package/dist/rslang/semantic/typification-parser.d.ts +12 -0
  133. package/dist/rslang/semantic/typification-parser.js +226 -0
  134. package/dist/rslang/semantic/typification-parser.js.map +1 -0
  135. package/dist/rslang/semantic/typification.d.ts +119 -0
  136. package/dist/rslang/semantic/typification.js +74 -0
  137. package/dist/rslang/semantic/typification.js.map +1 -0
  138. package/dist/rslang/semantic/value-auditor.d.ts +43 -0
  139. package/dist/rslang/semantic/value-auditor.js +523 -0
  140. package/dist/rslang/semantic/value-auditor.js.map +1 -0
  141. package/dist/rslang/semantic/value-class.d.ts +10 -0
  142. package/dist/rslang/semantic/value-class.js +9 -0
  143. package/dist/rslang/semantic/value-class.js.map +1 -0
  144. package/dist/rslang/typification-graph.d.ts +33 -0
  145. package/dist/rslang/typification-graph.js +311 -0
  146. package/dist/rslang/typification-graph.js.map +1 -0
  147. package/dist/shared/branded.d.ts +7 -0
  148. package/dist/shared/branded.js +1 -0
  149. package/dist/shared/branded.js.map +1 -0
  150. package/dist/shared/hash.d.ts +6 -0
  151. package/dist/shared/hash.js +18 -0
  152. package/dist/shared/hash.js.map +1 -0
  153. package/dist/shared/index.d.ts +2 -0
  154. package/dist/shared/index.js +18 -0
  155. package/dist/shared/index.js.map +1 -0
  156. package/package.json +184 -0
  157. package/src/cctext/index.ts +9 -0
  158. package/src/cctext/language-api.test.ts +149 -0
  159. package/src/cctext/language-api.ts +285 -0
  160. package/src/cctext/language.ts +80 -0
  161. package/src/graph/graph.test.ts +392 -0
  162. package/src/graph/graph.ts +433 -0
  163. package/src/graph/index.ts +1 -0
  164. package/src/index.ts +96 -0
  165. package/src/library/folder-tree.test.ts +47 -0
  166. package/src/library/folder-tree.ts +156 -0
  167. package/src/library/index.ts +46 -0
  168. package/src/library/library-api.test.ts +32 -0
  169. package/src/library/library-api.ts +11 -0
  170. package/src/library/library.ts +61 -0
  171. package/src/library/oss-api.ts +449 -0
  172. package/src/library/oss-layout-api.ts +377 -0
  173. package/src/library/oss-layout.ts +27 -0
  174. package/src/library/oss.ts +150 -0
  175. package/src/library/rsengine.ts +593 -0
  176. package/src/library/rsform-api.ts +533 -0
  177. package/src/library/rsform.ts +228 -0
  178. package/src/library/rsmodel-api.ts +340 -0
  179. package/src/library/rsmodel.ts +50 -0
  180. package/src/library/structure-planner.ts +143 -0
  181. package/src/parsing/ast.ts +136 -0
  182. package/src/parsing/index.ts +15 -0
  183. package/src/parsing/lezer-tree.ts +69 -0
  184. package/src/rslang/api.test.ts +116 -0
  185. package/src/rslang/api.ts +183 -0
  186. package/src/rslang/ast-annotations.ts +70 -0
  187. package/src/rslang/error.ts +129 -0
  188. package/src/rslang/eval/calculator.test.ts +124 -0
  189. package/src/rslang/eval/calculator.ts +121 -0
  190. package/src/rslang/eval/evaluation-cache.ts +257 -0
  191. package/src/rslang/eval/evaluator.test.ts +352 -0
  192. package/src/rslang/eval/evaluator.ts +935 -0
  193. package/src/rslang/eval/value-api.test.ts +105 -0
  194. package/src/rslang/eval/value-api.ts +444 -0
  195. package/src/rslang/eval/value.ts +102 -0
  196. package/src/rslang/index.ts +23 -0
  197. package/src/rslang/labels.ts +191 -0
  198. package/src/rslang/parser/expression-generator.test.ts +100 -0
  199. package/src/rslang/parser/expression-generator.ts +466 -0
  200. package/src/rslang/parser/normalize.test.ts +99 -0
  201. package/src/rslang/parser/normalize.ts +462 -0
  202. package/src/rslang/parser/parser.terms.ts +42 -0
  203. package/src/rslang/parser/parser.test.ts +153 -0
  204. package/src/rslang/parser/parser.ts +20 -0
  205. package/src/rslang/parser/rslang.grammar +251 -0
  206. package/src/rslang/parser/syntax-errors.ts +209 -0
  207. package/src/rslang/parser/token.ts +106 -0
  208. package/src/rslang/semantic/analyzer.test.ts +59 -0
  209. package/src/rslang/semantic/analyzer.ts +179 -0
  210. package/src/rslang/semantic/arguments-extractor.ts +327 -0
  211. package/src/rslang/semantic/type-auditor.test.ts +326 -0
  212. package/src/rslang/semantic/type-auditor.ts +1049 -0
  213. package/src/rslang/semantic/typification-api.test.ts +46 -0
  214. package/src/rslang/semantic/typification-api.ts +321 -0
  215. package/src/rslang/semantic/typification-parser.test.ts +50 -0
  216. package/src/rslang/semantic/typification-parser.ts +220 -0
  217. package/src/rslang/semantic/typification.ts +180 -0
  218. package/src/rslang/semantic/value-auditor.test.ts +206 -0
  219. package/src/rslang/semantic/value-auditor.ts +332 -0
  220. package/src/rslang/semantic/value-class.ts +11 -0
  221. package/src/rslang/typification-graph.ts +155 -0
  222. package/src/shared/branded.ts +6 -0
  223. package/src/shared/hash.ts +17 -0
  224. package/src/shared/index.ts +2 -0
@@ -0,0 +1,105 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { TypeID } from '../index';
4
+ import { basic, IntegerT, LogicT, tuple as makeTuple } from '../semantic/typification';
5
+
6
+ import { TUPLE_ID, type Value, VALUE_FALSE, VALUE_TRUE } from './value';
7
+ import { normalizeValue, validateValue } from './value-api';
8
+
9
+ describe('validateValue', () => {
10
+ const basics = new Map([
11
+ ['X1', [1, 2, 3]],
12
+ ['X2', [7, 8, 42]]
13
+ ]);
14
+
15
+ it('validates integers', () => {
16
+ expect(validateValue(42, IntegerT, basics)).toBe(true);
17
+ expect(validateValue([], IntegerT, basics)).toBe(false);
18
+ expect(validateValue([1, 2, 3], IntegerT, basics)).toBe(false);
19
+ expect(validateValue([1, [], 3], IntegerT, basics)).toBe(false);
20
+ });
21
+
22
+ it('validates logic values', () => {
23
+ expect(validateValue(VALUE_TRUE, LogicT, basics)).toBe(true);
24
+ expect(validateValue(VALUE_FALSE, LogicT, basics)).toBe(true);
25
+ expect(validateValue(2, LogicT, basics)).toBe(false);
26
+ expect(validateValue([], LogicT, basics)).toBe(false);
27
+ expect(validateValue([1, [], 3], LogicT, basics)).toBe(false);
28
+ });
29
+
30
+ it('validates basic types', () => {
31
+ const basicType = basic('X1');
32
+ expect(validateValue(1, basicType, basics)).toBe(true);
33
+ expect(validateValue(2, basicType, basics)).toBe(true);
34
+ expect(validateValue(42, basicType, basics)).toBe(false);
35
+ expect(validateValue(7, basicType, basics)).toBe(false);
36
+ expect(validateValue([1], basicType, basics)).toBe(false);
37
+ const missingType = { typeID: TypeID.basic, baseID: 'NOT_PRESENT' };
38
+ expect(validateValue(1, missingType, basics)).toBe(false);
39
+ });
40
+
41
+ it('validates tuple values', () => {
42
+ const tupleType = makeTuple([IntegerT, basic('X1')]);
43
+ // valid tuple
44
+ expect(validateValue([TUPLE_ID, 7, 1], tupleType, basics)).toBe(true);
45
+ // Wrong length
46
+ expect(validateValue([TUPLE_ID, 11], tupleType, basics)).toBe(false);
47
+ // Wrong ID in first element
48
+ expect(validateValue([0, 11, 1], tupleType, basics)).toBe(false);
49
+ // First component invalid
50
+ expect(validateValue([TUPLE_ID, [], 1], tupleType, basics)).toBe(false);
51
+ // Second component invalid
52
+ expect(validateValue([TUPLE_ID, 11, 999], tupleType, basics)).toBe(false);
53
+ });
54
+
55
+ it('validates collections', () => {
56
+ const collectionType = {
57
+ typeID: TypeID.collection,
58
+ base: basic('X1')
59
+ };
60
+ // All valid elements
61
+ expect(validateValue([1, 2, 3], collectionType, basics)).toBe(true);
62
+ // Some invalid
63
+ expect(validateValue([1, 99], collectionType, basics)).toBe(false);
64
+ // Not an array
65
+ expect(validateValue(1, collectionType, basics)).toBe(false);
66
+ // Array of tuples (should not have TUPLE_ID at first position)
67
+ expect(validateValue([TUPLE_ID, 1, 2], collectionType, basics)).toBe(false);
68
+ });
69
+
70
+ it('returns false for unsupported types', () => {
71
+ expect(validateValue(1, { typeID: TypeID.anyTypification }, basics)).toBe(false);
72
+ expect(validateValue(1, { typeID: TypeID.predicate, result: LogicT, args: [] }, basics)).toBe(false);
73
+ expect(validateValue(1, { typeID: TypeID.function, result: basic('X1'), args: [] }, basics)).toBe(false);
74
+ });
75
+
76
+ it('normalizes data values correctly', () => {
77
+ const arr = [3, 1, 2, 2, 3, 4];
78
+ normalizeValue(arr);
79
+ expect(arr).toEqual([1, 2, 3, 4]);
80
+
81
+ const arr2: Value = [
82
+ [TUPLE_ID, 3, 1],
83
+ [TUPLE_ID, 1, 2],
84
+ [TUPLE_ID, 1, 2], // duplicate tuple
85
+ [TUPLE_ID, 2, 3]
86
+ ];
87
+ normalizeValue(arr2);
88
+ expect(arr2.length).toBe(3);
89
+ expect(arr2[0]).toEqual([TUPLE_ID, 1, 2]);
90
+ expect(arr2[1]).toEqual([TUPLE_ID, 2, 3]);
91
+ expect(arr2[2]).toEqual([TUPLE_ID, 3, 1]);
92
+
93
+ const num = 42;
94
+ normalizeValue(num);
95
+ expect(num).toBe(42);
96
+
97
+ const empty: Value[] = [];
98
+ normalizeValue(empty);
99
+ expect(empty).toEqual([]);
100
+
101
+ const val: Value = [TUPLE_ID, [3, 2, 1, 1], 1];
102
+ normalizeValue(val);
103
+ expect(val[1]).toEqual([1, 2, 3]);
104
+ });
105
+ });
@@ -0,0 +1,444 @@
1
+ import { generateStub } from '../../shared';
2
+ import { type ExpressionType, TypeID, type TypePath, type Typification } from '../semantic/typification';
3
+
4
+ import {
5
+ BOOL_INFINITY,
6
+ compare,
7
+ EmptySetV,
8
+ INVALID_ELEMENT,
9
+ makeValuePath,
10
+ set,
11
+ SET_INFINITY,
12
+ tuple,
13
+ TUPLE_ID,
14
+ type Value,
15
+ VALUE_FALSE,
16
+ VALUE_TRUE,
17
+ type ValueContext,
18
+ type ValuePath
19
+ } from './value';
20
+
21
+ /** Cartesian product of factor sets. */
22
+ export function cartesianProduct(factors: Value[][]): Value[] | null {
23
+ const cardinality = factors.reduce((acc, f) => acc * f.length, 1);
24
+ if (cardinality > SET_INFINITY) {
25
+ return null;
26
+ }
27
+ if (cardinality === 0 || factors.length === 0) {
28
+ return EmptySetV;
29
+ }
30
+
31
+ let accumulator: Value[][] = [[]];
32
+ for (const factor of factors) {
33
+ const next: Value[][] = [];
34
+ for (const prefix of accumulator) {
35
+ for (const value of factor) {
36
+ next.push([...prefix, value]);
37
+ }
38
+ }
39
+ accumulator = next;
40
+ }
41
+ return accumulator.map(tuple);
42
+ }
43
+
44
+ /** Boolean power set ℬ(X). No cache - materialized. */
45
+ export function boolean(base: Value[]): Value[] | null {
46
+ if (base.length > BOOL_INFINITY) {
47
+ return null;
48
+ }
49
+ return powerset(base);
50
+ }
51
+
52
+ /** Powerset of array. */
53
+ function powerset(arr: readonly Value[]): Value[][] {
54
+ const result: Value[][] = [[]];
55
+ if (arr.length === 0) {
56
+ return result;
57
+ }
58
+
59
+ let current: Value[][] = [[]];
60
+ let maxIndex: number[] = [-1];
61
+ while (current.length > 0) {
62
+ const next: Value[][] = [];
63
+ const nextMaxIndex: number[] = [];
64
+ for (let i = 0; i < current.length; i++) {
65
+ for (let j = maxIndex[i] + 1; j < arr.length; j++) {
66
+ const subset = [...current[i], arr[j]];
67
+ result.push(subset);
68
+ if (j < arr.length - 1) {
69
+ next.push(subset);
70
+ nextMaxIndex.push(j);
71
+ }
72
+ }
73
+ }
74
+ current = next;
75
+ maxIndex = nextMaxIndex;
76
+ }
77
+ return result;
78
+ }
79
+
80
+ /** Check if set contains element. */
81
+ export function contains(setData: Value[], element: Value): boolean {
82
+ let left = 0;
83
+ let right = setData.length - 1;
84
+ while (left <= right) {
85
+ const mid = Math.floor((left + right) / 2);
86
+ const cmp = compare(setData[mid], element);
87
+ if (cmp === 0) {
88
+ return true;
89
+ } else if (cmp < 0) {
90
+ left = mid + 1;
91
+ } else {
92
+ right = mid - 1;
93
+ }
94
+ }
95
+ return false;
96
+ }
97
+
98
+ /** Is A ⊆ B. */
99
+ export function isSubsetOrEq(a: Value[], b: Value[]): boolean {
100
+ let i = 0,
101
+ j = 0;
102
+ while (i < a.length && j < b.length) {
103
+ const cmp = compare(a[i], b[j]);
104
+ if (cmp === 0) {
105
+ i++;
106
+ j++;
107
+ } else if (cmp > 0) {
108
+ j++;
109
+ } else {
110
+ return false;
111
+ }
112
+ }
113
+ return i === a.length;
114
+ }
115
+
116
+ /** Reduce: flatten double boolean to single boolean. */
117
+ export function reduce(target: Value[][]): Value[] {
118
+ const result: Value[] = [];
119
+ for (const element of target) {
120
+ result.push(...element);
121
+ }
122
+ return set(result);
123
+ }
124
+
125
+ /** Union A ∪ B. */
126
+ export function setUnion(set1: Value[], set2: Value[]): Value[] {
127
+ const result: Value[] = [];
128
+ let i = 0,
129
+ j = 0;
130
+ while (i < set1.length && j < set2.length) {
131
+ const cmp = compare(set1[i], set2[j]);
132
+ if (cmp < 0) {
133
+ result.push(set1[i]);
134
+ i++;
135
+ } else if (cmp > 0) {
136
+ result.push(set2[j]);
137
+ j++;
138
+ } else {
139
+ result.push(set1[i]);
140
+ i++;
141
+ j++;
142
+ }
143
+ }
144
+ while (i < set1.length) {
145
+ result.push(set1[i]);
146
+ i++;
147
+ }
148
+ while (j < set2.length) {
149
+ result.push(set2[j]);
150
+ j++;
151
+ }
152
+ return result;
153
+ }
154
+
155
+ /** Intersection A ∩ B. */
156
+ export function setIntersection(set1: Value[], set2: Value[]): Value[] {
157
+ const result: Value[] = [];
158
+ for (let i = 0, j = 0; i < set1.length && j < set2.length; ) {
159
+ const cmp = compare(set1[i], set2[j]);
160
+ if (cmp < 0) {
161
+ i++;
162
+ } else if (cmp > 0) {
163
+ j++;
164
+ } else {
165
+ result.push(set1[i]);
166
+ i++;
167
+ j++;
168
+ }
169
+ }
170
+ return result;
171
+ }
172
+
173
+ /** Difference A \ B. */
174
+ export function setDiff(set1: Value[], set2: Value[]): Value[] {
175
+ const result: Value[] = [];
176
+ let i = 0,
177
+ j = 0;
178
+ while (i < set1.length && j < set2.length) {
179
+ const cmp = compare(set1[i], set2[j]);
180
+ if (cmp < 0) {
181
+ result.push(set1[i]);
182
+ i++;
183
+ } else if (cmp > 0) {
184
+ j++;
185
+ } else {
186
+ i++;
187
+ j++;
188
+ }
189
+ }
190
+ while (i < set1.length) {
191
+ result.push(set1[i]);
192
+ i++;
193
+ }
194
+ return result;
195
+ }
196
+
197
+ /** Symmetric difference A ∆ B. */
198
+ export function setSymDiff(set1: Value[], set2: Value[]): Value[] {
199
+ const result: Value[] = [];
200
+ let i = 0,
201
+ j = 0;
202
+ while (i < set1.length && j < set2.length) {
203
+ const cmp = compare(set1[i], set2[j]);
204
+ if (cmp < 0) {
205
+ result.push(set1[i]);
206
+ i++;
207
+ } else if (cmp > 0) {
208
+ result.push(set2[j]);
209
+ j++;
210
+ } else {
211
+ i++;
212
+ j++;
213
+ }
214
+ }
215
+ while (i < set1.length) {
216
+ result.push(set1[i]);
217
+ i++;
218
+ }
219
+ while (j < set2.length) {
220
+ result.push(set2[j]);
221
+ j++;
222
+ }
223
+ return result;
224
+ }
225
+
226
+ /** Projection of set by indices (BigPr). */
227
+ export function projection(target: Value[][], indices: number[]): Value[] {
228
+ const projectedElements: Value[] = target.map(element => {
229
+ const newComponents = indices.map(idx => element[idx]);
230
+ return indices.length === 1 ? newComponents[0] : tuple(newComponents);
231
+ });
232
+ return set(projectedElements);
233
+ }
234
+
235
+ /** Condensed string representation. */
236
+ export function printValue(data: Value | null): string {
237
+ if (!Array.isArray(data)) {
238
+ return String(data);
239
+ }
240
+ const len = data.length;
241
+ if (data.length === 0) {
242
+ return '{}';
243
+ }
244
+
245
+ const isTuple = data[0] === TUPLE_ID;
246
+ const start = isTuple ? 1 : 0;
247
+
248
+ let result = isTuple ? '(' : '{';
249
+ for (let i = start; i < len; i++) {
250
+ if (i > start) result += ', ';
251
+ result += printValue(data[i]);
252
+ }
253
+ result += isTuple ? ')' : '}';
254
+ return result;
255
+ }
256
+
257
+ /** Generates stub ID for value. */
258
+ export function valueStub(value: Value | null): string {
259
+ if (value == null) {
260
+ return '';
261
+ }
262
+ const str = printValue(value);
263
+ return generateStub(str);
264
+ }
265
+
266
+ /** Checks if value is a set representation, not a tuple representation. */
267
+ export function isSetValue(data: Value | null): data is Value[] {
268
+ return Array.isArray(data) && (data.length === 0 || data[0] !== TUPLE_ID);
269
+ }
270
+
271
+ /** Checks if value is a tuple representation. */
272
+ export function isTupleValue(data: Value | null): data is Value[] {
273
+ return Array.isArray(data) && data.length > 1 && data[0] === TUPLE_ID;
274
+ }
275
+
276
+ /** Normalize unsorted array of values. */
277
+ export function normalizeValue(data: Value): void {
278
+ if (!Array.isArray(data) || data.length === 0) {
279
+ return;
280
+ }
281
+
282
+ if (data[0] === TUPLE_ID) {
283
+ for (let i = 1; i < data.length; i++) {
284
+ normalizeValue(data[i]);
285
+ }
286
+ return;
287
+ }
288
+
289
+ for (const item of data) {
290
+ normalizeValue(item);
291
+ }
292
+
293
+ data.sort((a, b) => compare(a, b));
294
+ let i = 1;
295
+ while (i < data.length) {
296
+ if (compare(data[i - 1], data[i]) === 0) {
297
+ data.splice(i, 1);
298
+ } else {
299
+ i++;
300
+ }
301
+ }
302
+ }
303
+
304
+ /** Validates value for {@link ExpressionType} and value of basic sets. */
305
+ export function validateValue(value: Value, type: ExpressionType, basics: ValueContext): boolean {
306
+ switch (type.typeID) {
307
+ case TypeID.integer:
308
+ return typeof value === 'number';
309
+ case TypeID.logic: {
310
+ if (typeof value !== 'number') {
311
+ return false;
312
+ }
313
+ return value === VALUE_TRUE || value === VALUE_FALSE;
314
+ }
315
+ case TypeID.basic: {
316
+ if (typeof value !== 'number') {
317
+ return false;
318
+ }
319
+ const domain = basics.get(type.baseID);
320
+ return !!domain && Array.isArray(domain) && domain.includes(value);
321
+ }
322
+
323
+ case TypeID.tuple: {
324
+ if (!Array.isArray(value) || value.length !== type.factors.length + 1 || value[0] !== TUPLE_ID) {
325
+ return false;
326
+ }
327
+ for (let i = 0; i < type.factors.length; i++) {
328
+ if (!validateValue(value[i + 1], type.factors[i], basics)) {
329
+ return false;
330
+ }
331
+ }
332
+ return true;
333
+ }
334
+
335
+ case TypeID.collection: {
336
+ if (!isSetValue(value)) {
337
+ return false;
338
+ }
339
+ for (const item of value) {
340
+ if (!validateValue(item, type.base, basics)) {
341
+ return false;
342
+ }
343
+ }
344
+ return true;
345
+ }
346
+
347
+ case TypeID.anyTypification:
348
+ case TypeID.predicate:
349
+ case TypeID.function:
350
+ return false;
351
+ }
352
+ }
353
+
354
+ /** Converts value path to type path. */
355
+ export function convertPathToType(path: ValuePath, type: Typification): TypePath | null {
356
+ const result: number[] = [];
357
+ if (path.length === 0) {
358
+ return result as TypePath;
359
+ }
360
+
361
+ let curType = type;
362
+ let index = 0;
363
+ while (index < path.length) {
364
+ switch (curType.typeID) {
365
+ case TypeID.collection: {
366
+ result.push(0);
367
+ curType = curType.base;
368
+ index++;
369
+ break;
370
+ }
371
+ case TypeID.tuple: {
372
+ const tupleIdx = path[index];
373
+ if (typeof tupleIdx !== 'number' || tupleIdx < 1 || tupleIdx > curType.factors.length) {
374
+ return null;
375
+ }
376
+ result.push(tupleIdx);
377
+ curType = curType.factors[tupleIdx - 1];
378
+ index++;
379
+ break;
380
+ }
381
+ case TypeID.basic:
382
+ case TypeID.integer:
383
+ case TypeID.anyTypification:
384
+ return null;
385
+ }
386
+ }
387
+ return result as TypePath;
388
+ }
389
+
390
+ /** Extracts value from a target by path. */
391
+ export function extractValue(target: Value, path: ValuePath): Value | null {
392
+ let current: Value = target;
393
+ let i = 0;
394
+ while (i < path.length) {
395
+ if (!Array.isArray(current) || current.length <= path[i]) {
396
+ return null;
397
+ }
398
+ current = current[path[i]];
399
+ i++;
400
+ }
401
+ return current;
402
+ }
403
+
404
+ /** Makes default value for a type. */
405
+ export function makeDefaultValue(type: Typification): Value {
406
+ switch (type.typeID) {
407
+ case TypeID.anyTypification:
408
+ case TypeID.integer:
409
+ case TypeID.basic:
410
+ return INVALID_ELEMENT;
411
+ case TypeID.collection:
412
+ return [];
413
+ case TypeID.tuple:
414
+ return tuple(type.factors.map(item => makeDefaultValue(item)));
415
+ }
416
+ }
417
+
418
+ /** Perform immutable deep copy update. */
419
+ export function setNestedValue(target: Value | null, path: ValuePath, newVal: Value): Value {
420
+ if (path.length === 0) {
421
+ return newVal;
422
+ }
423
+ const [head, ...rest] = path;
424
+ const arr = Array.isArray(target) ? [...target] : [];
425
+ arr[head] = setNestedValue(arr[head], makeValuePath(rest), newVal);
426
+ return arr;
427
+ }
428
+
429
+ /** Test if value contains invalid elements. */
430
+ export function testInvalid(value: Value): boolean {
431
+ const stack = [value];
432
+ while (stack.length > 0) {
433
+ const current = stack.pop();
434
+ if (current === INVALID_ELEMENT) {
435
+ return true;
436
+ }
437
+ if (Array.isArray(current)) {
438
+ for (const element of current) {
439
+ stack.push(element);
440
+ }
441
+ }
442
+ }
443
+ return false;
444
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Module: Structured data for RSLang expression evaluation.
3
+ */
4
+
5
+ import { type Branded } from '../../shared';
6
+
7
+ import { printValue } from './value-api';
8
+
9
+ /** Tuple ID for array distinction. */
10
+ export const TUPLE_ID = -111;
11
+
12
+ /** Invalid value for structured data. */
13
+ export const INVALID_ELEMENT = -1;
14
+
15
+ /** Boolean values: true. */
16
+ export const VALUE_TRUE = 1;
17
+
18
+ /** Boolean values: false. */
19
+ export const VALUE_FALSE = 0;
20
+
21
+ /** Cardinality threshold for "infinite" sets (e.g. Z). */
22
+ export const SET_INFINITY = 10_000_000;
23
+
24
+ /** Cardinality threshold for Boolean power set. */
25
+ export const BOOL_INFINITY = 18;
26
+
27
+ /** Expression evaluation result: structured data. */
28
+ export type Value = number | Value[];
29
+
30
+ /** Values context. */
31
+ export type ValueContext = Map<string, Value>;
32
+
33
+ /** Value extraction path. */
34
+ export type ValuePath = Branded<number[], 'ValuePath'>;
35
+
36
+ /** Creates value path. */
37
+ export function makeValuePath(path: number[]): ValuePath {
38
+ return path as ValuePath;
39
+ }
40
+
41
+ /** Empty set ∅. */
42
+ export const EmptySetV = [];
43
+
44
+ /** Compare two structured data without recursive calls. */
45
+ export function compare(v1: Value, v2: Value): number {
46
+ const stack1: Value[] = [v1];
47
+ const stack2: Value[] = [v2];
48
+
49
+ while (stack1.length > 0 && stack2.length > 0) {
50
+ const el1 = stack1.pop();
51
+ const el2 = stack2.pop();
52
+ if (el1 === el2) {
53
+ continue;
54
+ }
55
+
56
+ const type1 = typeof el1;
57
+ const type2 = typeof el2;
58
+ if (type1 === 'number' && type2 === 'number') {
59
+ const numDiff = (el1 as number) - (el2 as number);
60
+ if (numDiff !== 0) return numDiff;
61
+ continue;
62
+ }
63
+
64
+ const isArray1 = Array.isArray(el1);
65
+ const isArray2 = Array.isArray(el2);
66
+ if (!isArray1 || !isArray2) {
67
+ throw new Error(`Cannot compare different types ${printValue(el1!)} and ${printValue(el2!)}`);
68
+ }
69
+
70
+ const arr1 = el1;
71
+ const arr2 = el2;
72
+ const len1 = arr1.length;
73
+ const len2 = arr2.length;
74
+ if (len1 !== len2) {
75
+ return len1 - len2;
76
+ }
77
+
78
+ for (let i = len1 - 1; i >= 0; i--) {
79
+ stack1.push(arr1[i]);
80
+ stack2.push(arr2[i]);
81
+ }
82
+ }
83
+ return 0;
84
+ }
85
+
86
+ /** Tuple from components. */
87
+ export function tuple(components: Value[]): Value {
88
+ return [TUPLE_ID, ...components];
89
+ }
90
+
91
+ /** Set from elements (unique). Value[] - materialized. */
92
+ export function set(elements: Value[]): Value[] {
93
+ const sorted = [...elements].sort(compare);
94
+ for (let i = 1; i < sorted.length; ) {
95
+ if (compare(sorted[i - 1], sorted[i]) === 0) {
96
+ sorted.splice(i, 1);
97
+ } else {
98
+ i++;
99
+ }
100
+ }
101
+ return sorted;
102
+ }
@@ -0,0 +1,23 @@
1
+ export { readErrorAnnotation, readTypeAnnotation } from './ast-annotations';
2
+ export { RSErrorCode, type RSErrorDescription } from './error';
3
+ export { type CalculatorEvaluateOptions, type CalculatorResult, RSCalculator } from './eval/calculator';
4
+ export { makeValuePath, type Value, type ValuePath } from './eval/value';
5
+ export { printValue } from './eval/value-api';
6
+ export { parser as rslangParser } from './parser/parser';
7
+ export { TokenID } from './parser/token';
8
+ export { type AnalysisBase, type AnalysisFast, type AnalysisFull, RSLangAnalyzer } from './semantic/analyzer';
9
+ export { type ArgumentsType } from './semantic/arguments-extractor';
10
+ export {
11
+ AnyTypificationT,
12
+ EmptySetT,
13
+ type ExpressionType,
14
+ LogicT,
15
+ makeTypePath,
16
+ TypeClass,
17
+ TypeID,
18
+ type TypePath,
19
+ type Typification
20
+ } from './semantic/typification';
21
+ export { applyAsciiTypeSubstitutions, parseTypeText } from './semantic/typification-parser';
22
+ export { ValueClass } from './semantic/value-class';
23
+ export { TypificationGraph, type TypificationNodeData } from './typification-graph';