@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,191 @@
1
+ import { type AstNodeBase } from '../parsing';
2
+
3
+ import { TokenID } from './parser/token';
4
+ import { type ExpressionType, TypeID } from './semantic/typification';
5
+
6
+ const INTEGER_TYPE_NAME = 'Z';
7
+ const ANY_TYPE_NAME = 'R0';
8
+ const LOGIC_TYPE_NAME = 'Logic';
9
+
10
+ const labelTokenRecord: Partial<Record<TokenID, string>> = {
11
+ [TokenID.DECART]: '×',
12
+ [TokenID.PUNCTUATION_PL]: '( )',
13
+ [TokenID.PUNCTUATION_SL]: '[ ]',
14
+ [TokenID.QUANTOR_UNIVERSAL]: '∀',
15
+ [TokenID.QUANTOR_EXISTS]: '∃',
16
+ [TokenID.LOGIC_NOT]: '¬',
17
+ [TokenID.LOGIC_AND]: '&',
18
+ [TokenID.LOGIC_OR]: '∨',
19
+ [TokenID.LOGIC_IMPLICATION]: '⇒',
20
+ [TokenID.LOGIC_EQUIVALENT]: '⇔',
21
+ [TokenID.LIT_EMPTYSET]: '∅',
22
+ [TokenID.LIT_WHOLE_NUMBERS]: 'Z',
23
+ [TokenID.MULTIPLY]: '*',
24
+ [TokenID.EQUAL]: '=',
25
+ [TokenID.NOTEQUAL]: '≠',
26
+ [TokenID.GREATER_OR_EQ]: '≥',
27
+ [TokenID.LESSER_OR_EQ]: '≤',
28
+ [TokenID.SET_IN]: '∈',
29
+ [TokenID.SET_NOT_IN]: '∉',
30
+ [TokenID.SUBSET_OR_EQ]: '⊆',
31
+ [TokenID.SUBSET]: '⊂',
32
+ [TokenID.NOT_SUBSET]: '⊄',
33
+ [TokenID.SET_INTERSECTION]: '∩',
34
+ [TokenID.SET_UNION]: '∪',
35
+ [TokenID.SET_MINUS]: '\\',
36
+ [TokenID.SET_SYMMETRIC_MINUS]: '∆',
37
+ [TokenID.BOOLEAN]: 'ℬ()',
38
+ [TokenID.NT_DECLARATIVE_EXPR]: 'D{}',
39
+ [TokenID.NT_IMPERATIVE_EXPR]: 'I{}',
40
+ [TokenID.NT_RECURSIVE_FULL]: 'R{}',
41
+ [TokenID.BIGPR]: 'Pr1()',
42
+ [TokenID.SMALLPR]: 'pr1()',
43
+ [TokenID.FILTER]: 'Fi1[]()',
44
+ [TokenID.REDUCE]: 'red()',
45
+ [TokenID.CARD]: 'card()',
46
+ [TokenID.BOOL]: 'bool()',
47
+ [TokenID.DEBOOL]: 'debool()',
48
+ [TokenID.ASSIGN]: ':=',
49
+ [TokenID.ITERATE]: ':∈'
50
+ };
51
+
52
+ /** Retrieves label for {@link TokenID}. */
53
+ export function labelToken(id: TokenID): string {
54
+ const text = labelTokenRecord[id];
55
+ return text ?? 'UNKNOWN TOKEN: ' + String(id);
56
+ }
57
+
58
+ /** Generates label for {@link AstNodeBase}. */
59
+ export function labelRSLangNode(node: AstNodeBase): string {
60
+ // prettier-ignore
61
+ switch (node.typeID) {
62
+ case TokenID.ERROR: return '[ERROR]';
63
+ case TokenID.ID_LOCAL:
64
+ case TokenID.ID_GLOBAL:
65
+ case TokenID.ID_FUNCTION:
66
+ case TokenID.ID_PREDICATE:
67
+ case TokenID.ID_RADICAL:
68
+ return node.data.value as string;
69
+
70
+ case TokenID.LIT_INTEGER: return String(node.data.value);
71
+
72
+ case TokenID.BIGPR: return 'Pr' + (node.data.value as string[]).toString();
73
+ case TokenID.SMALLPR: return 'pr' + (node.data.value as string[]).toString();
74
+ case TokenID.FILTER: return 'Fi' + (node.data.value as string[]).toString();
75
+
76
+ case TokenID.NT_DECLARATIVE_EXPR: return 'DECLARATIVE';
77
+ case TokenID.NT_IMPERATIVE_EXPR: return 'IMPERATIVE';
78
+ case TokenID.NT_RECURSIVE_FULL: return 'RECURSIVE';
79
+ case TokenID.NT_RECURSIVE_SHORT: return 'RECURSIVE';
80
+
81
+ case TokenID.BOOLEAN: return 'ℬ';
82
+ case TokenID.REDUCE: return 'red';
83
+ case TokenID.CARD: return 'card';
84
+ case TokenID.BOOL: return 'bool';
85
+ case TokenID.DEBOOL: return 'debool';
86
+
87
+ case TokenID.PLUS: return '+';
88
+ case TokenID.MINUS: return '-';
89
+ case TokenID.MULTIPLY: return '*';
90
+ case TokenID.GREATER: return '>';
91
+ case TokenID.LESSER: return '<';
92
+
93
+ case TokenID.NT_TUPLE: return 'TUPLE';
94
+ case TokenID.NT_ENUMERATION: return 'ENUM';
95
+
96
+ case TokenID.NT_ENUM_DECL: return 'ENUM_DECLARE';
97
+ case TokenID.NT_TUPLE_DECL: return 'TUPLE_DECLARE';
98
+ case TokenID.PUNCTUATION_DEFINE: return 'DEFINITION';
99
+ case TokenID.PUNCTUATION_STRUCT: return 'STRUCTURE_DEFINE';
100
+
101
+ case TokenID.NT_ARG_DECL: return 'ARG';
102
+ case TokenID.NT_FUNC_CALL: return 'CALL';
103
+ case TokenID.NT_ARGUMENTS: return 'ARGS';
104
+
105
+ case TokenID.NT_FUNC_DEFINITION: return 'FUNCTION_DEFINE';
106
+
107
+ case TokenID.DECART:
108
+ case TokenID.QUANTOR_UNIVERSAL:
109
+ case TokenID.QUANTOR_EXISTS:
110
+ case TokenID.LOGIC_NOT:
111
+ case TokenID.LOGIC_AND:
112
+ case TokenID.LOGIC_OR:
113
+ case TokenID.LOGIC_IMPLICATION:
114
+ case TokenID.LOGIC_EQUIVALENT:
115
+ case TokenID.LIT_EMPTYSET:
116
+ case TokenID.LIT_WHOLE_NUMBERS:
117
+ case TokenID.EQUAL:
118
+ case TokenID.NOTEQUAL:
119
+ case TokenID.GREATER_OR_EQ:
120
+ case TokenID.LESSER_OR_EQ:
121
+ case TokenID.SET_IN:
122
+ case TokenID.SET_NOT_IN:
123
+ case TokenID.SUBSET_OR_EQ:
124
+ case TokenID.SUBSET:
125
+ case TokenID.NOT_SUBSET:
126
+ case TokenID.SET_INTERSECTION:
127
+ case TokenID.SET_UNION:
128
+ case TokenID.SET_MINUS:
129
+ case TokenID.SET_SYMMETRIC_MINUS:
130
+ case TokenID.ASSIGN:
131
+ case TokenID.ITERATE:
132
+ return labelToken(node.typeID);
133
+ }
134
+ if (node.data.value) {
135
+ return node.data.value as string;
136
+ }
137
+ return 'UNKNOWN NODE: ' + String(node.typeID);
138
+ }
139
+
140
+ /** Converts expression type to string. */
141
+ export function labelType(type: ExpressionType | null): string {
142
+ if (!type) {
143
+ return 'N/A';
144
+ }
145
+ switch (type.typeID) {
146
+ case TypeID.anyTypification:
147
+ return ANY_TYPE_NAME;
148
+ case TypeID.integer:
149
+ return INTEGER_TYPE_NAME;
150
+ case TypeID.basic:
151
+ return type.baseID;
152
+ case TypeID.tuple:
153
+ return type.factors
154
+ .map(factor => (factor.typeID === TypeID.tuple ? `(${labelType(factor)})` : labelType(factor)))
155
+ .join('×');
156
+ case TypeID.collection:
157
+ return type.base.typeID === TypeID.collection ? `ℬ${labelType(type.base)}` : `ℬ(${labelType(type.base)})`;
158
+ case TypeID.logic:
159
+ return LOGIC_TYPE_NAME;
160
+ case TypeID.predicate:
161
+ case TypeID.function:
162
+ const argsText = type.args.map(arg => labelType(arg.type)).join(', ');
163
+ return `[${argsText}] → ${labelType(type.result)}`;
164
+ }
165
+ }
166
+
167
+ /** Converts expression type to normalized string. */
168
+ export function normalizeType(type: ExpressionType | null): string {
169
+ if (!type) {
170
+ return 'N/A';
171
+ }
172
+ switch (type.typeID) {
173
+ case TypeID.anyTypification:
174
+ return ANY_TYPE_NAME;
175
+ case TypeID.integer:
176
+ case TypeID.basic:
177
+ return 'X1';
178
+ case TypeID.tuple:
179
+ return type.factors
180
+ .map(factor => (factor.typeID === TypeID.tuple ? `(${normalizeType(factor)})` : normalizeType(factor)))
181
+ .join('×');
182
+ case TypeID.collection:
183
+ return type.base.typeID === TypeID.collection ? `ℬ${normalizeType(type.base)}` : `ℬ(${normalizeType(type.base)})`;
184
+ case TypeID.logic:
185
+ return LOGIC_TYPE_NAME;
186
+ case TypeID.predicate:
187
+ case TypeID.function:
188
+ const argsText = type.args.map(arg => normalizeType(arg.type)).join(', ');
189
+ return `[${argsText}] → ${normalizeType(type.result)}`;
190
+ }
191
+ }
@@ -0,0 +1,100 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { RSLangAnalyzer } from '../index';
4
+
5
+ import { generateExpressionFromAst } from './expression-generator';
6
+
7
+ const analyzer = new RSLangAnalyzer();
8
+
9
+ function parseAst(expression: string) {
10
+ const ast = analyzer.checkFast(expression).ast;
11
+ if (!ast) {
12
+ throw new Error(`Failed to parse expression: ${expression}`);
13
+ }
14
+ return ast;
15
+ }
16
+
17
+ const testNormalized = [
18
+ // Predicates
19
+ ['1 = 2', '1=2'],
20
+ ['1 < X1', '1<X1'],
21
+ ['1 > 2', '1>2'],
22
+ ['1 < 2', '1<2'],
23
+ ['X1 ≠ a', 'X1≠a1'],
24
+ ['P1[a,b]', 'P1[a1, a2]'],
25
+ // Logic operators
26
+ ['¬1=2', '¬(1=2)'],
27
+ ['1=1 & 2=2 & 3=3', '1=1 & 2=2 & 3=3'],
28
+ ['1=1 & (2=2 & 3=3)', '1=1 & 2=2 & 3=3'],
29
+ ['(1=1 & 2=2) & 3=3', '1=1 & 2=2 & 3=3'],
30
+ ['1=1 ∨ 2=2 ∨ 3=3', '1=1 ∨ 2=2 ∨ 3=3'],
31
+ ['1=1 ⇒ 2=2 ⇒ 3=3', '1=1 ⇒ 2=2 ⇒ 3=3'],
32
+ ['(1=1 ⇒ 2=2) ⇒ 3=3', '1=1 ⇒ 2=2 ⇒ 3=3'],
33
+ ['1=1 ⇒ (2=2 ⇒ 3=3)', '1=1 ⇒ (2=2 ⇒ 3=3)'],
34
+ ['1=1 ⇔ 2=2 ⇔ 3=3', '1=1 ⇔ 2=2 ⇔ 3=3'],
35
+ ['(1=1 ∨ 2=2) & 3=3', '(1=1 ∨ 2=2) & 3=3'],
36
+ // Quantifiers
37
+ ['∀a∈X1 1=1', '∀a1∈X1 1=1'],
38
+ ['∃a∈X1 1=1', '∃a1∈X1 1=1'],
39
+ ['∀a∈X1 ∃b∈X1 1=1 & 2=2', '∀a1∈X1 ∃a2∈X1 1=1 & 2=2'],
40
+ ['∀a∈X1 1=1 & 2=2', '∀a1∈X1 1=1 & 2=2'],
41
+ ['∀a∈X1 (1=1 & 2=2)', '∀a1∈X1 (1=1 & 2=2)'],
42
+ ['∀a∈X1 (a=a & a=a)', '∀a1∈X1 (a1=a1 & a1=a1)'],
43
+ ['∀a,b∈X1 1=2', '∀a1, a2∈X1 1=2'],
44
+ ['∀(a,b),(c,d)∈S1 1=2', '∀(a1, a2), (a3, a4)∈S1 1=2'],
45
+ // Setexpr operators
46
+ ['1+2+3', '(1+2)+3'],
47
+ ['((a ∪ b) ∩ (c \\ d)) ∆ (e × f)', '((a1∪a2)∩(a3\\a4))∆(a5×a6)'],
48
+ // Function calls / text functions
49
+ ['card(X1)', 'card(X1)'],
50
+ ['card(1)', 'card(1)'],
51
+ ['card(a)', 'card(a1)'],
52
+ ['Pr2(a)', 'Pr2(a1)'],
53
+ ['bool(a)', 'bool(a1)'],
54
+ ['debool(a)', 'debool(a1)'],
55
+ ['red(a)', 'red(a1)'],
56
+ ['Fi1,2[b](a)', 'Fi1,2[a1](a2)'],
57
+ ['F1[a]', 'F1[a1]'],
58
+ ['F1[a,b]', 'F1[a1, a2]'],
59
+ ['F1[{(a,b)}]', 'F1[{(a1, a2)}]'],
60
+ // Tuple & Set constructors
61
+ ['(a,b,c)', '(a1, a2, a3)'],
62
+ ['{a,b,c}', '{a1, a2, a3}'],
63
+ ['{a}', '{a1}'],
64
+ ['{(a,b)}', '{(a1, a2)}'],
65
+ ['{(a,b),(b,c)}', '{(a1, a2), (a2, a3)}'],
66
+ ['{{a, b}, {c, d}}', '{{a1, a2}, {a3, a4}}'],
67
+ ['ℬ(a)', 'ℬ(a1)'],
68
+ ['ℬℬ(a)', 'ℬℬ(a1)'],
69
+ ['a×b×c', 'a1×a2×a3'],
70
+ ['a×(b×c)', 'a1×(a2×a3)'],
71
+ // Term constructors
72
+ ['D{a∈X1 | 1=2}', 'D{a1∈X1 | 1=2}'],
73
+ ['{a∈X1 | 1=2}', 'D{a1∈X1 | 1=2}'],
74
+ ['D{(a,b)∈X1 | 1=2}', 'D{(a1, a2)∈X1 | 1=2}'],
75
+ ['R{a:=S1 | card(a)<10 | a \\ a}', 'R{a1:=S1 | card(a1)<10 | a1\\a1}'],
76
+ ['R{a:=S1 | a \\ a}', 'R{a1:=S1 | a1\\a1}'],
77
+ ['R{(a,b):=S1 | (a \\ a, b)}', 'R{(a1, a2):=S1 | (a1\\a1, a2)}'],
78
+ ['I{(a, b) | a:∈X1; b:=a}', 'I{(a1, a2) | a1:∈X1; a2:=a1}'],
79
+ ['I{(a, b) | (a,b):∈Z×Z}', 'I{(a1, a2) | (a1, a2):∈Z×Z}'],
80
+ ['I{(a, b) | a:∈X1; b:=a; (a,b) ∈ S1}', 'I{(a1, a2) | a1:∈X1; a2:=a1; (a1, a2)∈S1}'],
81
+ // Functions
82
+ ['[σ∈ℬ((R1×R1)×R1)] ∀((α1,α2),γ)∈σ ((α2,α1),γ)∈σ', '[a1∈ℬ((R1×R1)×R1)] ∀((a2, a3), a4)∈a1 ((a3, a2), a4)∈a1']
83
+ ];
84
+
85
+ describe('Testing AST expression generator', () => {
86
+ testNormalized.forEach(([input, normalized]) => {
87
+ it(`Normalize "${input}"`, () => {
88
+ expect(generateExpressionFromAst(parseAst(input), { normalize: true })).toBe(normalized);
89
+ });
90
+ });
91
+
92
+ it('normalizes local names consistently across declarations and usage', () => {
93
+ const expression = '[a∈X1, b∈X1] a=b';
94
+ expect(generateExpressionFromAst(parseAst(expression), { normalize: true })).toBe('[a1∈X1, a2∈X1] a1=a2');
95
+ });
96
+
97
+ it('normalizes radical names when requested', () => {
98
+ expect(generateExpressionFromAst(parseAst('R7=R3'), { normalize: true })).toBe('R1=R2');
99
+ });
100
+ });