@rsconcept/domain 1.7.4 → 1.7.6

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 (48) hide show
  1. package/dist/{analyzer-QxWs73gP.d.ts → analyzer-DqjdciC5.d.ts} +3 -3
  2. package/dist/{arguments-extractor-1acwjQNc.d.ts → arguments-extractor-Dd1lFom9.d.ts} +2 -2
  3. package/dist/{ast-annotations-CtF7C9uK.d.ts → ast-annotations-CZCzs9Uk.d.ts} +3 -3
  4. package/dist/{calculator-REeX2ZS1.d.ts → calculator-Dt03dsnd.d.ts} +3 -3
  5. package/dist/{error-toW0TUHF.d.ts → error-CzIbnP-N.d.ts} +3 -3
  6. package/dist/index.d.ts +9 -9
  7. package/dist/library/rsengine.d.ts +1 -1
  8. package/dist/library/rsform-api.d.ts +2 -2
  9. package/dist/library/rsform.d.ts +2 -2
  10. package/dist/library/rsmodel-api.d.ts +1 -1
  11. package/dist/library/structure-planner.d.ts +1 -1
  12. package/dist/rslang/api.d.ts +1 -1
  13. package/dist/rslang/ast-annotations.d.ts +1 -1
  14. package/dist/rslang/error.d.ts +1 -1
  15. package/dist/rslang/error.js +4 -3
  16. package/dist/rslang/error.js.map +1 -1
  17. package/dist/rslang/eval/calculator.d.ts +1 -1
  18. package/dist/rslang/eval/evaluator.d.ts +1 -1
  19. package/dist/rslang/eval/value-api.d.ts +1 -1
  20. package/dist/rslang/index.d.ts +9 -9
  21. package/dist/rslang/labels.d.ts +1 -1
  22. package/dist/rslang/parser/syntax-errors/index.d.ts +2 -2
  23. package/dist/rslang/semantic/analyzer.d.ts +1 -1
  24. package/dist/rslang/semantic/arguments-extractor.d.ts +1 -1
  25. package/dist/rslang/semantic/type-auditor.d.ts +2 -2
  26. package/dist/rslang/semantic/type-auditor.js +11 -13
  27. package/dist/rslang/semantic/type-auditor.js.map +1 -1
  28. package/dist/rslang/semantic/typification-api.d.ts +4 -2
  29. package/dist/rslang/semantic/typification-api.js +17 -1
  30. package/dist/rslang/semantic/typification-api.js.map +1 -1
  31. package/dist/rslang/semantic/typification-parser.d.ts +1 -1
  32. package/dist/rslang/semantic/typification.d.ts +2 -2
  33. package/dist/rslang/semantic/typification.js +11 -3
  34. package/dist/rslang/semantic/typification.js.map +1 -1
  35. package/dist/rslang/semantic/value-auditor.d.ts +1 -1
  36. package/dist/rslang/typification-graph.d.ts +1 -1
  37. package/dist/{typification-Dk-fisgO.d.ts → typification-DDuv88ir.d.ts} +7 -3
  38. package/dist/{typification-graph-6HcZ-rKH.d.ts → typification-graph-8VdK6_Fh.d.ts} +2 -2
  39. package/dist/{typification-parser-BBVx1RxP.d.ts → typification-parser-DHO42ZRc.d.ts} +2 -2
  40. package/dist/{value-api-B6T6f4Ia.d.ts → value-api-C2X4Pom5.d.ts} +2 -2
  41. package/package.json +4 -4
  42. package/src/rslang/error.ts +6 -3
  43. package/src/rslang/semantic/analyzer.test.ts +8 -0
  44. package/src/rslang/semantic/type-auditor.test.ts +19 -1
  45. package/src/rslang/semantic/type-auditor.ts +13 -12
  46. package/src/rslang/semantic/typification-api.test.ts +19 -2
  47. package/src/rslang/semantic/typification-api.ts +15 -0
  48. package/src/rslang/semantic/typification.ts +12 -2
@@ -313,7 +313,25 @@ describe('TypeAuditor', () => {
313
313
  code: RSErrorCode.invalidArgumentType,
314
314
  from: 7,
315
315
  to: 12,
316
- params: ['b∈R1F2', 'ℬℬ(X1)']
316
+ params: ['b∈X1', 'ℬℬ(X1)']
317
+ });
318
+ });
319
+
320
+ it('Resolves templated radicals in invalidArgumentType message', () => {
321
+ typeContext.set('S5', bool(bool(basic('X1'))));
322
+ typeContext.set('P2', {
323
+ typeID: TypeID.predicate,
324
+ result: LogicT,
325
+ args: [
326
+ { alias: 'σ', type: bool(bool(basic('R1'))) },
327
+ { alias: 'ζ', type: bool(bool(basic('R1'))) }
328
+ ]
329
+ });
330
+ expectError('P2[S5, 12]', {
331
+ code: RSErrorCode.invalidArgumentType,
332
+ from: 7,
333
+ to: 9,
334
+ params: ['ζ∈ℬℬ(X1)', 'Z']
317
335
  });
318
336
  });
319
337
 
@@ -17,9 +17,10 @@ import {
17
17
  EmptySetT,
18
18
  type ExpressionType,
19
19
  IntegerT,
20
- isRadical,
20
+ isTemplateRadical,
21
21
  isTypification,
22
22
  LogicT,
23
+ mangleRadicalId,
23
24
  type Parametrized,
24
25
  tuple,
25
26
  type TypeContext,
@@ -29,6 +30,7 @@ import {
29
30
  import {
30
31
  checkCompatibility,
31
32
  checkEquality,
33
+ cloneTypification,
32
34
  compareTemplated,
33
35
  hasGenerics,
34
36
  mergeTypifications,
@@ -1018,8 +1020,12 @@ export class TypeAuditor {
1018
1020
  }
1019
1021
  const argType = mangleRadicals(alias, type.args[child - 1].type);
1020
1022
  if (!compareTemplated(substitutes, argType, childType)) {
1023
+ const expectedType = cloneTypification(argType);
1024
+ if (substitutes.size > 0) {
1025
+ substituteBase(expectedType, substitutes);
1026
+ }
1021
1027
  this.onError(RSErrorCode.invalidArgumentType, node.children[child], [
1022
- `${type.args[child - 1].alias}∈${labelType(argType)}`,
1028
+ `${type.args[child - 1].alias}∈${labelType(expectedType)}`,
1023
1029
  labelType(childType)
1024
1030
  ]);
1025
1031
  return null;
@@ -1038,10 +1044,10 @@ function mangleRadicals(funcName: string, type: Typification): Typification {
1038
1044
  case TypeID.integer:
1039
1045
  return type;
1040
1046
  case TypeID.basic: {
1041
- if (isRadical(type.baseID)) {
1047
+ if (isTemplateRadical(type.baseID)) {
1042
1048
  return {
1043
1049
  typeID: type.typeID,
1044
- baseID: type.baseID + funcName
1050
+ baseID: mangleRadicalId(type.baseID, funcName)
1045
1051
  };
1046
1052
  }
1047
1053
  return type;
@@ -1157,10 +1163,7 @@ class LocalContext {
1157
1163
  return false;
1158
1164
  } else {
1159
1165
  this.onError(RSErrorCode.localDoubleDeclare, node, [alias]);
1160
- const index = this.data.indexOf(existing);
1161
- if (index !== -1) {
1162
- this.data.splice(index, 1);
1163
- }
1166
+ return false;
1164
1167
  }
1165
1168
  }
1166
1169
  this.data.push({ alias, type, level: 1, useCount: 0 });
@@ -1171,8 +1174,7 @@ class LocalContext {
1171
1174
  const alias = getNodeText(node);
1172
1175
  const local = this.data.find(data => data.alias === alias);
1173
1176
  if (local === undefined) {
1174
- this.onError(RSErrorCode.localUndeclared, node, [alias]);
1175
- return null;
1177
+ return this.onError(RSErrorCode.localUndeclared, node, [alias]);
1176
1178
  } else if (local.level < 1) {
1177
1179
  const subexprRoot = findRightLogicOperandRoot(node);
1178
1180
  if (subexprRoot !== null) {
@@ -1181,8 +1183,7 @@ class LocalContext {
1181
1183
  }
1182
1184
  return this.onError(RSErrorCode.localOutOfScopeParentheses, node, [alias]);
1183
1185
  }
1184
- this.onError(RSErrorCode.localOutOfScope, node, [alias]);
1185
- return null;
1186
+ return this.onError(RSErrorCode.localOutOfScope, node, [alias]);
1186
1187
  } else {
1187
1188
  local.useCount++;
1188
1189
  return local.type;
@@ -1,8 +1,8 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
3
  import type { TypePath } from './typification';
4
- import { AnyTypificationT, basic, bool, IntegerT, tuple, type Typification } from './typification';
5
- import { applyPath, compareTemplated } from './typification-api';
4
+ import { AnyTypificationT, basic, bool, IntegerT, mangleRadicalId, tuple, type Typification } from './typification';
5
+ import { applyPath, cloneTypification, compareTemplated, substituteBase } from './typification-api';
6
6
 
7
7
  describe('applyPath', () => {
8
8
  function typePath(path: number[]): TypePath {
@@ -53,3 +53,20 @@ describe('compareTemplated', () => {
53
53
  expect(compareTemplated(substitutes, AnyTypificationT, AnyTypificationT)).toBe(true);
54
54
  });
55
55
  });
56
+
57
+ describe('mangleRadicalId', () => {
58
+ it('qualifies template radical with function name', () => {
59
+ expect(mangleRadicalId('R1', 'P2')).toBe('R1<P2>');
60
+ expect(mangleRadicalId('R2', 'F10')).toBe('R2<F10>');
61
+ });
62
+ });
63
+
64
+ describe('cloneTypification + substituteBase', () => {
65
+ it('resolves mangled radicals for error messages', () => {
66
+ const argType = bool(basic('R1<F2>'));
67
+ const substitutes = new Map<string, Typification>([['R1<F2>', basic('X1')]]);
68
+ const expectedType = cloneTypification(argType);
69
+ substituteBase(expectedType, substitutes);
70
+ expect(expectedType).toEqual(bool(basic('X1')));
71
+ });
72
+ });
@@ -227,6 +227,21 @@ export function compareTemplated(
227
227
  }
228
228
  }
229
229
 
230
+ /** Clone typification tree. */
231
+ export function cloneTypification(type: Typification): Typification {
232
+ switch (type.typeID) {
233
+ case TypeID.anyTypification:
234
+ case TypeID.integer:
235
+ return type;
236
+ case TypeID.basic:
237
+ return { ...type };
238
+ case TypeID.collection:
239
+ return { typeID: type.typeID, base: cloneTypification(type.base) };
240
+ case TypeID.tuple:
241
+ return { typeID: type.typeID, factors: type.factors.map(cloneTypification) };
242
+ }
243
+ }
244
+
230
245
  /** Apply substitutions to typification. */
231
246
  export function substituteBase(target: Typification, substitutes: Map<string, Typification>): void {
232
247
  switch (target.typeID) {
@@ -174,7 +174,17 @@ export function isTypification(type: ExpressionType | null): boolean {
174
174
  );
175
175
  }
176
176
 
177
- /** Checks if given type is radical. */
177
+ /** Checks if given alias is a template or mangled radical. */
178
178
  export function isRadical(alias: string): boolean {
179
- return alias.length > 0 && alias.startsWith('R') && alias[1] !== '0';
179
+ return /^R[1-9]\d*(?:<[^>]+>)?$/.test(alias);
180
+ }
181
+
182
+ /** Checks if given alias is an unmangled template radical. */
183
+ export function isTemplateRadical(alias: string): boolean {
184
+ return /^R[1-9]\d*$/.test(alias);
185
+ }
186
+
187
+ /** Mangle template radical with calling function name. */
188
+ export function mangleRadicalId(radical: string, funcName: string): string {
189
+ return `${radical}<${funcName}>`;
180
190
  }