@rsconcept/domain 1.2.0 → 1.4.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 (53) hide show
  1. package/dist/{analyzer-DlSq3Y3r.d.ts → analyzer-BliNe3pV.d.ts} +2 -2
  2. package/dist/{ast-annotations-BiMjkKvz.d.ts → ast-annotations-GOkbNN8F.d.ts} +2 -2
  3. package/dist/{calculator-C9W2jkSx.d.ts → calculator-DFevxZyV.d.ts} +3 -3
  4. package/dist/{error-E1LVq_3w.d.ts → error-deey7EiC.d.ts} +2 -1
  5. package/dist/index.d.ts +6 -6
  6. package/dist/index.js +1 -1
  7. package/dist/library/rsengine.d.ts +2 -3
  8. package/dist/library/rsengine.js +15 -43
  9. package/dist/library/rsengine.js.map +1 -1
  10. package/dist/library/rsform-api.d.ts +1 -1
  11. package/dist/library/rsform.d.ts +1 -1
  12. package/dist/library/rsmodel-api.d.ts +1 -1
  13. package/dist/library/rsmodel-api.js +1 -1
  14. package/dist/library/rsmodel.d.ts +1 -1
  15. package/dist/rslang/ast-annotations.d.ts +1 -1
  16. package/dist/rslang/error.d.ts +1 -1
  17. package/dist/rslang/error.js +1 -0
  18. package/dist/rslang/error.js.map +1 -1
  19. package/dist/rslang/eval/calculator.d.ts +1 -1
  20. package/dist/rslang/eval/calculator.js +1 -1
  21. package/dist/rslang/eval/evaluation-cache.d.ts +1 -1
  22. package/dist/rslang/eval/evaluator.d.ts +2 -2
  23. package/dist/rslang/eval/evaluator.js +17 -11
  24. package/dist/rslang/eval/evaluator.js.map +1 -1
  25. package/dist/rslang/eval/value-api.d.ts +1 -1
  26. package/dist/rslang/eval/value-api.js +1 -1
  27. package/dist/rslang/eval/value.d.ts +2 -2
  28. package/dist/rslang/eval/value.js +2 -2
  29. package/dist/rslang/index.d.ts +6 -6
  30. package/dist/rslang/index.js +1 -1
  31. package/dist/rslang/parser/syntax-errors.d.ts +1 -1
  32. package/dist/rslang/semantic/analyzer.d.ts +1 -1
  33. package/dist/rslang/semantic/type-auditor.d.ts +1 -1
  34. package/dist/rslang/semantic/type-auditor.js +2 -1
  35. package/dist/rslang/semantic/type-auditor.js.map +1 -1
  36. package/dist/rslang/semantic/typification-api.js +1 -1
  37. package/dist/rslang/semantic/typification-api.js.map +1 -1
  38. package/dist/rslang/semantic/value-auditor.d.ts +1 -1
  39. package/dist/{value-CTjX6825.d.ts → value-BduA_ZGp.d.ts} +8 -2
  40. package/dist/{value-api-Bw-SgaYY.d.ts → value-api-B6T6f4Ia.d.ts} +2 -2
  41. package/dist/{value-B8UtCqaK.js → value-ybFBRuz6.js} +14 -3
  42. package/dist/{value-B8UtCqaK.js.map → value-ybFBRuz6.js.map} +1 -1
  43. package/package.json +2 -2
  44. package/src/library/rsengine.ts +14 -59
  45. package/src/rslang/error.ts +1 -0
  46. package/src/rslang/eval/calculator.test.ts +8 -0
  47. package/src/rslang/eval/evaluator.test.ts +5 -1
  48. package/src/rslang/eval/evaluator.ts +22 -13
  49. package/src/rslang/eval/value.ts +14 -1
  50. package/src/rslang/semantic/type-auditor.test.ts +21 -1
  51. package/src/rslang/semantic/type-auditor.ts +2 -1
  52. package/src/rslang/semantic/typification-api.test.ts +11 -2
  53. package/src/rslang/semantic/typification-api.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"typification-api.js","names":[],"sources":["../../../src/rslang/semantic/typification-api.ts"],"sourcesContent":["/**\n * Module: Typification API for RSLang.\n */\n\nimport {\n bool,\n component,\n type EchelonBase,\n type EchelonCollection,\n type EchelonTuple,\n type ExpressionType,\n IntegerT,\n isRadical,\n isTypification,\n tuple,\n TypeClass,\n TypeID,\n type TypePath,\n type Typification\n} from './typification';\n\n/** Record map from typeID to typeClass. */\nconst TypeIDToClass: Record<TypeID, TypeClass> = {\n [TypeID.anyTypification]: TypeClass.typification,\n [TypeID.integer]: TypeClass.typification,\n [TypeID.basic]: TypeClass.typification,\n [TypeID.tuple]: TypeClass.typification,\n [TypeID.collection]: TypeClass.typification,\n [TypeID.logic]: TypeClass.logic,\n [TypeID.function]: TypeClass.function,\n [TypeID.predicate]: TypeClass.predicate\n};\n\n/** Returns the TypeClass associated with the given TypeID. */\nexport function getTypeClass(typeID: TypeID): TypeClass {\n return TypeIDToClass[typeID];\n}\n\n/** Returns true if the given typification is generic. */\nexport function hasGenerics(type: Typification): boolean {\n switch (type.typeID) {\n case TypeID.anyTypification:\n return true;\n case TypeID.integer:\n return false;\n case TypeID.basic:\n return isRadical(type.baseID);\n case TypeID.collection:\n return hasGenerics(type.base);\n case TypeID.tuple:\n for (const factor of type.factors) {\n if (hasGenerics(factor)) {\n return true;\n }\n }\n return false;\n }\n}\n\n/** Checks if two typifications are equal. */\nexport function checkEquality(type1: Typification, type2: Typification): boolean {\n if (type1 === type2) {\n return true;\n }\n if (type1.typeID !== type2.typeID) {\n return false;\n }\n switch (type1.typeID) {\n case TypeID.integer:\n case TypeID.anyTypification:\n return true;\n case TypeID.basic:\n return type1.baseID === (type2 as EchelonBase).baseID;\n case TypeID.collection:\n return checkEquality(type1.base, (type2 as EchelonCollection).base);\n case TypeID.tuple: {\n if (type1.factors.length !== (type2 as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < type1.factors.length; ++index) {\n if (!checkEquality(type1.factors[index], (type2 as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n }\n }\n}\n\n/** Merge two types to get result of binary operation. */\nexport function mergeTypifications(type1: Typification, type2: Typification): Typification | null {\n if (type1 === type2) {\n return type1;\n }\n if (type1.typeID === TypeID.anyTypification) {\n return isTypification(type2) ? type2 : null;\n }\n if (type2.typeID === TypeID.anyTypification) {\n return isTypification(type1) ? type1 : null;\n }\n\n switch (type1.typeID) {\n case TypeID.integer:\n case TypeID.basic:\n return commonType(type1, type2);\n case TypeID.collection:\n if (type2.typeID !== TypeID.collection) {\n return null;\n }\n const base = mergeTypifications(type1.base, type2.base);\n return base ? bool(base) : null;\n case TypeID.tuple:\n if (type2.typeID !== TypeID.tuple) {\n return null;\n }\n if (type1.factors.length !== type2.factors.length) {\n return null;\n }\n const components: Typification[] = [];\n for (let index = 0; index < type1.factors.length; ++index) {\n const component = mergeTypifications(type1.factors[index], type2.factors[index]);\n if (component === null) {\n return null;\n }\n components.push(component);\n }\n return tuple(components);\n }\n}\n\n/** Check compatibility of typifications. */\nexport function checkCompatibility(type1: ExpressionType, type2: ExpressionType): boolean {\n if (type1 === type2) {\n return true;\n }\n if (type1.typeID === TypeID.anyTypification) {\n return isTypification(type2);\n }\n if (type2.typeID === TypeID.anyTypification) {\n return isTypification(type1);\n }\n if (isTypification(type1) !== isTypification(type2)) {\n return false;\n }\n if (\n type1.typeID === TypeID.integer ||\n type1.typeID === TypeID.basic ||\n type2.typeID === TypeID.integer ||\n type2.typeID === TypeID.basic\n ) {\n return commonType(type1 as Typification, type2 as Typification) !== null;\n }\n\n if (type1.typeID !== type2.typeID) {\n return false;\n }\n switch (type1.typeID) {\n case TypeID.collection:\n return checkCompatibility(type1.base, (type2 as EchelonCollection).base);\n case TypeID.tuple:\n if (type1.factors.length !== (type2 as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < type1.factors.length; ++index) {\n if (!checkCompatibility(type1.factors[index], (type2 as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n case TypeID.logic:\n case TypeID.predicate:\n case TypeID.function:\n return false;\n }\n}\n\n/** Compare typification with substitutions. */\nexport function compareTemplated(\n substitutes: Map<string, Typification>,\n arg: Typification,\n value: Typification\n): boolean {\n if (arg === value) {\n return true;\n }\n if (arg.typeID === TypeID.basic && isRadical(arg.baseID)) {\n if (!substitutes.has(arg.baseID)) {\n substitutes.set(arg.baseID, value);\n return true;\n } else {\n const mergeType = mergeTypifications(substitutes.get(arg.baseID)!, value);\n if (mergeType === null) {\n return false;\n }\n substitutes.set(arg.baseID, mergeType);\n return true;\n }\n }\n if (value.typeID === TypeID.anyTypification) {\n return true;\n }\n if (\n arg.typeID === TypeID.integer ||\n arg.typeID === TypeID.basic ||\n value.typeID === TypeID.integer ||\n value.typeID === TypeID.basic\n ) {\n return commonType(arg, value) !== null;\n }\n if (arg.typeID !== value.typeID) {\n return false;\n }\n switch (arg.typeID) {\n case TypeID.collection:\n return compareTemplated(substitutes, arg.base, (value as EchelonCollection).base);\n case TypeID.tuple: {\n if (arg.factors.length !== (value as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < arg.factors.length; ++index) {\n if (!compareTemplated(substitutes, arg.factors[index], (value as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n }\n }\n}\n\n/** Apply substitutions to typification. */\nexport function substituteBase(target: Typification, substitutes: Map<string, Typification>): void {\n switch (target.typeID) {\n case TypeID.basic: {\n if (substitutes.has(target.baseID)) {\n Object.assign(target, substitutes.get(target.baseID)!);\n }\n return;\n }\n case TypeID.collection: {\n substituteBase(target.base, substitutes);\n return;\n }\n case TypeID.tuple: {\n for (const factor of target.factors) {\n substituteBase(factor, substitutes);\n }\n return;\n }\n }\n}\n\n/** Extract bases from typification. */\nexport function extractBases(target: ExpressionType): Set<string> {\n return new Set(extractBasesImpl(target));\n}\n\n/** Apply type path to typification. */\nexport function applyPath(target: Typification, path: TypePath, index = 0): Typification | null {\n let current: Typification | null = target;\n let i = index;\n while (i < path.length && current) {\n switch (current.typeID) {\n case TypeID.anyTypification:\n case TypeID.integer:\n case TypeID.basic:\n return null;\n case TypeID.collection:\n current = current.base;\n i++;\n break;\n case TypeID.tuple:\n current = component(current, path[i]);\n if (current === null) {\n return null;\n }\n i++;\n break;\n }\n }\n return current;\n}\n\n// ===== Internals =====\nfunction commonType(type1: Typification, type2: Typification): Typification | null {\n if (type1 === type2) {\n return type1;\n }\n const int1 = 'isIntegerCompatible' in type1 && type1.isIntegerCompatible;\n const int2 = 'isIntegerCompatible' in type2 && type2.isIntegerCompatible;\n if (!int1 || !int2) {\n if (type1.typeID === TypeID.basic && type2.typeID === TypeID.basic) {\n return type1.baseID === type2.baseID ? type1 : null;\n }\n return null;\n }\n if (type1.typeID === TypeID.integer) {\n return type2;\n } else if (type2.typeID === TypeID.integer) {\n return type1;\n } else {\n return IntegerT;\n }\n}\n\nfunction extractBasesImpl(target: ExpressionType): string[] {\n switch (target.typeID) {\n case TypeID.basic:\n return [target.baseID];\n case TypeID.collection:\n return extractBasesImpl(target.base);\n case TypeID.tuple:\n return target.factors.reduce((result, factor) => result.concat(extractBasesImpl(factor)), [] as string[]);\n case TypeID.function:\n const result = extractBasesImpl(target.result);\n return target.args.reduce((result, arg) => result.concat(extractBasesImpl(arg.type)), result);\n case TypeID.predicate:\n return target.args.reduce((result, arg) => result.concat(extractBasesImpl(arg.type)), [] as string[]);\n default:\n return [];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"typification-api.js","names":[],"sources":["../../../src/rslang/semantic/typification-api.ts"],"sourcesContent":["/**\n * Module: Typification API for RSLang.\n */\n\nimport {\n bool,\n component,\n type EchelonBase,\n type EchelonCollection,\n type EchelonTuple,\n type ExpressionType,\n IntegerT,\n isRadical,\n isTypification,\n tuple,\n TypeClass,\n TypeID,\n type TypePath,\n type Typification\n} from './typification';\n\n/** Record map from typeID to typeClass. */\nconst TypeIDToClass: Record<TypeID, TypeClass> = {\n [TypeID.anyTypification]: TypeClass.typification,\n [TypeID.integer]: TypeClass.typification,\n [TypeID.basic]: TypeClass.typification,\n [TypeID.tuple]: TypeClass.typification,\n [TypeID.collection]: TypeClass.typification,\n [TypeID.logic]: TypeClass.logic,\n [TypeID.function]: TypeClass.function,\n [TypeID.predicate]: TypeClass.predicate\n};\n\n/** Returns the TypeClass associated with the given TypeID. */\nexport function getTypeClass(typeID: TypeID): TypeClass {\n return TypeIDToClass[typeID];\n}\n\n/** Returns true if the given typification is generic. */\nexport function hasGenerics(type: Typification): boolean {\n switch (type.typeID) {\n case TypeID.anyTypification:\n return true;\n case TypeID.integer:\n return false;\n case TypeID.basic:\n return isRadical(type.baseID);\n case TypeID.collection:\n return hasGenerics(type.base);\n case TypeID.tuple:\n for (const factor of type.factors) {\n if (hasGenerics(factor)) {\n return true;\n }\n }\n return false;\n }\n}\n\n/** Checks if two typifications are equal. */\nexport function checkEquality(type1: Typification, type2: Typification): boolean {\n if (type1 === type2) {\n return true;\n }\n if (type1.typeID !== type2.typeID) {\n return false;\n }\n switch (type1.typeID) {\n case TypeID.integer:\n case TypeID.anyTypification:\n return true;\n case TypeID.basic:\n return type1.baseID === (type2 as EchelonBase).baseID;\n case TypeID.collection:\n return checkEquality(type1.base, (type2 as EchelonCollection).base);\n case TypeID.tuple: {\n if (type1.factors.length !== (type2 as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < type1.factors.length; ++index) {\n if (!checkEquality(type1.factors[index], (type2 as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n }\n }\n}\n\n/** Merge two types to get result of binary operation. */\nexport function mergeTypifications(type1: Typification, type2: Typification): Typification | null {\n if (type1 === type2) {\n return type1;\n }\n if (type1.typeID === TypeID.anyTypification) {\n return isTypification(type2) ? type2 : null;\n }\n if (type2.typeID === TypeID.anyTypification) {\n return isTypification(type1) ? type1 : null;\n }\n\n switch (type1.typeID) {\n case TypeID.integer:\n case TypeID.basic:\n return commonType(type1, type2);\n case TypeID.collection:\n if (type2.typeID !== TypeID.collection) {\n return null;\n }\n const base = mergeTypifications(type1.base, type2.base);\n return base ? bool(base) : null;\n case TypeID.tuple:\n if (type2.typeID !== TypeID.tuple) {\n return null;\n }\n if (type1.factors.length !== type2.factors.length) {\n return null;\n }\n const components: Typification[] = [];\n for (let index = 0; index < type1.factors.length; ++index) {\n const component = mergeTypifications(type1.factors[index], type2.factors[index]);\n if (component === null) {\n return null;\n }\n components.push(component);\n }\n return tuple(components);\n }\n}\n\n/** Check compatibility of typifications. */\nexport function checkCompatibility(type1: ExpressionType, type2: ExpressionType): boolean {\n if (type1 === type2) {\n return true;\n }\n if (type1.typeID === TypeID.anyTypification) {\n return isTypification(type2);\n }\n if (type2.typeID === TypeID.anyTypification) {\n return isTypification(type1);\n }\n if (isTypification(type1) !== isTypification(type2)) {\n return false;\n }\n if (\n type1.typeID === TypeID.integer ||\n type1.typeID === TypeID.basic ||\n type2.typeID === TypeID.integer ||\n type2.typeID === TypeID.basic\n ) {\n return commonType(type1 as Typification, type2 as Typification) !== null;\n }\n\n if (type1.typeID !== type2.typeID) {\n return false;\n }\n switch (type1.typeID) {\n case TypeID.collection:\n return checkCompatibility(type1.base, (type2 as EchelonCollection).base);\n case TypeID.tuple:\n if (type1.factors.length !== (type2 as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < type1.factors.length; ++index) {\n if (!checkCompatibility(type1.factors[index], (type2 as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n case TypeID.logic:\n case TypeID.predicate:\n case TypeID.function:\n return false;\n }\n}\n\n/** Compare typification with substitutions. */\nexport function compareTemplated(\n substitutes: Map<string, Typification>,\n arg: Typification,\n value: Typification\n): boolean {\n if (arg === value) {\n return true;\n }\n if (arg.typeID === TypeID.basic && isRadical(arg.baseID)) {\n if (!substitutes.has(arg.baseID)) {\n substitutes.set(arg.baseID, value);\n return true;\n } else {\n const mergeType = mergeTypifications(substitutes.get(arg.baseID)!, value);\n if (mergeType === null) {\n return false;\n }\n substitutes.set(arg.baseID, mergeType);\n return true;\n }\n }\n if (arg.typeID === TypeID.anyTypification || value.typeID === TypeID.anyTypification) {\n return true;\n }\n if (\n arg.typeID === TypeID.integer ||\n arg.typeID === TypeID.basic ||\n value.typeID === TypeID.integer ||\n value.typeID === TypeID.basic\n ) {\n return commonType(arg, value) !== null;\n }\n if (arg.typeID !== value.typeID) {\n return false;\n }\n switch (arg.typeID) {\n case TypeID.collection:\n return compareTemplated(substitutes, arg.base, (value as EchelonCollection).base);\n case TypeID.tuple: {\n if (arg.factors.length !== (value as EchelonTuple).factors.length) {\n return false;\n }\n for (let index = 0; index < arg.factors.length; ++index) {\n if (!compareTemplated(substitutes, arg.factors[index], (value as EchelonTuple).factors[index])) {\n return false;\n }\n }\n return true;\n }\n }\n}\n\n/** Apply substitutions to typification. */\nexport function substituteBase(target: Typification, substitutes: Map<string, Typification>): void {\n switch (target.typeID) {\n case TypeID.basic: {\n if (substitutes.has(target.baseID)) {\n Object.assign(target, substitutes.get(target.baseID)!);\n }\n return;\n }\n case TypeID.collection: {\n substituteBase(target.base, substitutes);\n return;\n }\n case TypeID.tuple: {\n for (const factor of target.factors) {\n substituteBase(factor, substitutes);\n }\n return;\n }\n }\n}\n\n/** Extract bases from typification. */\nexport function extractBases(target: ExpressionType): Set<string> {\n return new Set(extractBasesImpl(target));\n}\n\n/** Apply type path to typification. */\nexport function applyPath(target: Typification, path: TypePath, index = 0): Typification | null {\n let current: Typification | null = target;\n let i = index;\n while (i < path.length && current) {\n switch (current.typeID) {\n case TypeID.anyTypification:\n case TypeID.integer:\n case TypeID.basic:\n return null;\n case TypeID.collection:\n current = current.base;\n i++;\n break;\n case TypeID.tuple:\n current = component(current, path[i]);\n if (current === null) {\n return null;\n }\n i++;\n break;\n }\n }\n return current;\n}\n\n// ===== Internals =====\nfunction commonType(type1: Typification, type2: Typification): Typification | null {\n if (type1 === type2) {\n return type1;\n }\n const int1 = 'isIntegerCompatible' in type1 && type1.isIntegerCompatible;\n const int2 = 'isIntegerCompatible' in type2 && type2.isIntegerCompatible;\n if (!int1 || !int2) {\n if (type1.typeID === TypeID.basic && type2.typeID === TypeID.basic) {\n return type1.baseID === type2.baseID ? type1 : null;\n }\n return null;\n }\n if (type1.typeID === TypeID.integer) {\n return type2;\n } else if (type2.typeID === TypeID.integer) {\n return type1;\n } else {\n return IntegerT;\n }\n}\n\nfunction extractBasesImpl(target: ExpressionType): string[] {\n switch (target.typeID) {\n case TypeID.basic:\n return [target.baseID];\n case TypeID.collection:\n return extractBasesImpl(target.base);\n case TypeID.tuple:\n return target.factors.reduce((result, factor) => result.concat(extractBasesImpl(factor)), [] as string[]);\n case TypeID.function:\n const result = extractBasesImpl(target.result);\n return target.args.reduce((result, arg) => result.concat(extractBasesImpl(arg.type)), result);\n case TypeID.predicate:\n return target.args.reduce((result, arg) => result.concat(extractBasesImpl(arg.type)), [] as string[]);\n default:\n return [];\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { t as AstNode } from "../../ast-C8sIpKdL.js";
2
- import { t as ErrorReporter } from "../../error-E1LVq_3w.js";
2
+ import { t as ErrorReporter } from "../../error-deey7EiC.js";
3
3
  import { n as ValueClassContext, t as ValueClass } from "../../value-class-CNI-lqXJ.js";
4
4
 
5
5
  //#region src/rslang/semantic/value-auditor.d.ts
@@ -22,6 +22,12 @@ type ValuePath = Branded<number[], 'ValuePath'>;
22
22
  declare function makeValuePath(path: number[]): ValuePath;
23
23
  /** Empty set ∅. */
24
24
  declare const EmptySetV: never[];
25
+ /** Thrown when a runtime value operation cannot be applied to the given operands. */
26
+ declare class CalcInvalidDataError extends Error {
27
+ readonly left: string;
28
+ readonly right: string;
29
+ constructor(left: string, right: string);
30
+ }
25
31
  /** Compare two structured data without recursive calls. */
26
32
  declare function compare(v1: Value, v2: Value): number;
27
33
  /** Tuple from components. */
@@ -29,5 +35,5 @@ declare function tuple(components: Value[]): Value;
29
35
  /** Set from elements (unique). Value[] - materialized. */
30
36
  declare function set(elements: Value[]): Value[];
31
37
  //#endregion
32
- export { TUPLE_ID as a, Value as c, compare as d, makeValuePath as f, SET_INFINITY as i, ValueContext as l, tuple as m, EmptySetV as n, VALUE_FALSE as o, set as p, INVALID_ELEMENT as r, VALUE_TRUE as s, BOOL_INFINITY as t, ValuePath as u };
33
- //# sourceMappingURL=value-CTjX6825.d.ts.map
38
+ export { SET_INFINITY as a, VALUE_TRUE as c, ValuePath as d, compare as f, tuple as h, INVALID_ELEMENT as i, Value as l, set as m, CalcInvalidDataError as n, TUPLE_ID as o, makeValuePath as p, EmptySetV as r, VALUE_FALSE as s, BOOL_INFINITY as t, ValueContext as u };
39
+ //# sourceMappingURL=value-BduA_ZGp.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { b as Typification, f as ExpressionType, y as TypePath } from "./typification-Dk-fisgO.js";
2
- import { c as Value, l as ValueContext, u as ValuePath } from "./value-CTjX6825.js";
2
+ import { d as ValuePath, l as Value, u as ValueContext } from "./value-BduA_ZGp.js";
3
3
 
4
4
  //#region src/rslang/eval/value-api.d.ts
5
5
  /** Cartesian product of factor sets. */
@@ -46,4 +46,4 @@ declare function setNestedValue(target: Value | null, path: ValuePath, newVal: V
46
46
  declare function testInvalid(value: Value): boolean;
47
47
  //#endregion
48
48
  export { setSymDiff as _, extractValue as a, validateValue as b, isTupleValue as c, printValue as d, projection as f, setNestedValue as g, setIntersection as h, convertPathToType as i, makeDefaultValue as l, setDiff as m, cartesianProduct as n, isSetValue as o, reduce as p, contains as r, isSubsetOrEq as s, boolean as t, normalizeValue as u, setUnion as v, valueStub as x, testInvalid as y };
49
- //# sourceMappingURL=value-api-Bw-SgaYY.d.ts.map
49
+ //# sourceMappingURL=value-api-B6T6f4Ia.d.ts.map
@@ -323,6 +323,17 @@ function makeValuePath(path) {
323
323
  }
324
324
  /** Empty set ∅. */
325
325
  const EmptySetV = [];
326
+ /** Thrown when a runtime value operation cannot be applied to the given operands. */
327
+ var CalcInvalidDataError = class extends Error {
328
+ left;
329
+ right;
330
+ constructor(left, right) {
331
+ super(`Cannot compare different types ${left} and ${right}`);
332
+ this.name = "CalcInvalidDataError";
333
+ this.left = left;
334
+ this.right = right;
335
+ }
336
+ };
326
337
  /** Compare two structured data without recursive calls. */
327
338
  function compare(v1, v2) {
328
339
  const stack1 = [v1];
@@ -336,7 +347,7 @@ function compare(v1, v2) {
336
347
  if (numDiff !== 0) return numDiff;
337
348
  continue;
338
349
  }
339
- if (!Array.isArray(el1) || !Array.isArray(el2)) throw new Error(`Cannot compare different types ${printValue(el1)} and ${printValue(el2)}`);
350
+ if (!Array.isArray(el1) || !Array.isArray(el2)) throw new CalcInvalidDataError(printValue(el1), printValue(el2));
340
351
  const arr1 = el1;
341
352
  const arr2 = el2;
342
353
  const len1 = arr1.length;
@@ -361,6 +372,6 @@ function set(elements) {
361
372
  return sorted;
362
373
  }
363
374
  //#endregion
364
- export { testInvalid as A, projection as C, setNestedValue as D, setIntersection as E, valueStub as M, setSymDiff as O, printValue as S, setDiff as T, isSetValue as _, TUPLE_ID as a, makeDefaultValue as b, compare as c, tuple as d, boolean as f, extractValue as g, convertPathToType as h, SET_INFINITY as i, validateValue as j, setUnion as k, makeValuePath as l, contains as m, EmptySetV as n, VALUE_FALSE as o, cartesianProduct as p, INVALID_ELEMENT as r, VALUE_TRUE as s, BOOL_INFINITY as t, set as u, isSubsetOrEq as v, reduce as w, normalizeValue as x, isTupleValue as y };
375
+ export { setUnion as A, printValue as C, setIntersection as D, setDiff as E, validateValue as M, valueStub as N, setNestedValue as O, normalizeValue as S, reduce as T, extractValue as _, SET_INFINITY as a, isTupleValue as b, VALUE_TRUE as c, set as d, tuple as f, convertPathToType as g, contains as h, INVALID_ELEMENT as i, testInvalid as j, setSymDiff as k, compare as l, cartesianProduct as m, CalcInvalidDataError as n, TUPLE_ID as o, boolean as p, EmptySetV as r, VALUE_FALSE as s, BOOL_INFINITY as t, makeValuePath as u, isSetValue as v, projection as w, makeDefaultValue as x, isSubsetOrEq as y };
365
376
 
366
- //# sourceMappingURL=value-B8UtCqaK.js.map
377
+ //# sourceMappingURL=value-ybFBRuz6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"value-B8UtCqaK.js","names":[],"sources":["../src/rslang/eval/value-api.ts","../src/rslang/eval/value.ts"],"sourcesContent":["import { generateStub } from '../../shared';\nimport { type ExpressionType, TypeID, type TypePath, type Typification } from '../semantic/typification';\n\nimport {\n BOOL_INFINITY,\n compare,\n EmptySetV,\n INVALID_ELEMENT,\n makeValuePath,\n set,\n SET_INFINITY,\n tuple,\n TUPLE_ID,\n type Value,\n VALUE_FALSE,\n VALUE_TRUE,\n type ValueContext,\n type ValuePath\n} from './value';\n\n/** Cartesian product of factor sets. */\nexport function cartesianProduct(factors: Value[][]): Value[] | null {\n const cardinality = factors.reduce((acc, f) => acc * f.length, 1);\n if (cardinality > SET_INFINITY) {\n return null;\n }\n if (cardinality === 0 || factors.length === 0) {\n return EmptySetV;\n }\n\n let accumulator: Value[][] = [[]];\n for (const factor of factors) {\n const next: Value[][] = [];\n for (const prefix of accumulator) {\n for (const value of factor) {\n next.push([...prefix, value]);\n }\n }\n accumulator = next;\n }\n return accumulator.map(tuple);\n}\n\n/** Boolean power set ℬ(X). No cache - materialized. */\nexport function boolean(base: Value[]): Value[] | null {\n if (base.length > BOOL_INFINITY) {\n return null;\n }\n return powerset(base);\n}\n\n/** Powerset of array. */\nfunction powerset(arr: readonly Value[]): Value[][] {\n const result: Value[][] = [[]];\n if (arr.length === 0) {\n return result;\n }\n\n let current: Value[][] = [[]];\n let maxIndex: number[] = [-1];\n while (current.length > 0) {\n const next: Value[][] = [];\n const nextMaxIndex: number[] = [];\n for (let i = 0; i < current.length; i++) {\n for (let j = maxIndex[i] + 1; j < arr.length; j++) {\n const subset = [...current[i], arr[j]];\n result.push(subset);\n if (j < arr.length - 1) {\n next.push(subset);\n nextMaxIndex.push(j);\n }\n }\n }\n current = next;\n maxIndex = nextMaxIndex;\n }\n return result;\n}\n\n/** Check if set contains element. */\nexport function contains(setData: Value[], element: Value): boolean {\n let left = 0;\n let right = setData.length - 1;\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n const cmp = compare(setData[mid], element);\n if (cmp === 0) {\n return true;\n } else if (cmp < 0) {\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n return false;\n}\n\n/** Is A ⊆ B. */\nexport function isSubsetOrEq(a: Value[], b: Value[]): boolean {\n let i = 0,\n j = 0;\n while (i < a.length && j < b.length) {\n const cmp = compare(a[i], b[j]);\n if (cmp === 0) {\n i++;\n j++;\n } else if (cmp > 0) {\n j++;\n } else {\n return false;\n }\n }\n return i === a.length;\n}\n\n/** Reduce: flatten double boolean to single boolean. */\nexport function reduce(target: Value[][]): Value[] {\n const result: Value[] = [];\n for (const element of target) {\n result.push(...element);\n }\n return set(result);\n}\n\n/** Union A ∪ B. */\nexport function setUnion(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n let i = 0,\n j = 0;\n while (i < set1.length && j < set2.length) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n result.push(set1[i]);\n i++;\n } else if (cmp > 0) {\n result.push(set2[j]);\n j++;\n } else {\n result.push(set1[i]);\n i++;\n j++;\n }\n }\n while (i < set1.length) {\n result.push(set1[i]);\n i++;\n }\n while (j < set2.length) {\n result.push(set2[j]);\n j++;\n }\n return result;\n}\n\n/** Intersection A ∩ B. */\nexport function setIntersection(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n for (let i = 0, j = 0; i < set1.length && j < set2.length; ) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n i++;\n } else if (cmp > 0) {\n j++;\n } else {\n result.push(set1[i]);\n i++;\n j++;\n }\n }\n return result;\n}\n\n/** Difference A \\ B. */\nexport function setDiff(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n let i = 0,\n j = 0;\n while (i < set1.length && j < set2.length) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n result.push(set1[i]);\n i++;\n } else if (cmp > 0) {\n j++;\n } else {\n i++;\n j++;\n }\n }\n while (i < set1.length) {\n result.push(set1[i]);\n i++;\n }\n return result;\n}\n\n/** Symmetric difference A ∆ B. */\nexport function setSymDiff(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n let i = 0,\n j = 0;\n while (i < set1.length && j < set2.length) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n result.push(set1[i]);\n i++;\n } else if (cmp > 0) {\n result.push(set2[j]);\n j++;\n } else {\n i++;\n j++;\n }\n }\n while (i < set1.length) {\n result.push(set1[i]);\n i++;\n }\n while (j < set2.length) {\n result.push(set2[j]);\n j++;\n }\n return result;\n}\n\n/** Projection of set by indices (BigPr). */\nexport function projection(target: Value[][], indices: number[]): Value[] {\n const projectedElements: Value[] = target.map(element => {\n const newComponents = indices.map(idx => element[idx]);\n return indices.length === 1 ? newComponents[0] : tuple(newComponents);\n });\n return set(projectedElements);\n}\n\n/** Condensed string representation. */\nexport function printValue(data: Value | null): string {\n if (!Array.isArray(data)) {\n return String(data);\n }\n const len = data.length;\n if (data.length === 0) {\n return '{}';\n }\n\n const isTuple = data[0] === TUPLE_ID;\n const start = isTuple ? 1 : 0;\n\n let result = isTuple ? '(' : '{';\n for (let i = start; i < len; i++) {\n if (i > start) result += ', ';\n result += printValue(data[i]);\n }\n result += isTuple ? ')' : '}';\n return result;\n}\n\n/** Generates stub ID for value. */\nexport function valueStub(value: Value | null): string {\n if (value == null) {\n return '';\n }\n const str = printValue(value);\n return generateStub(str);\n}\n\n/** Checks if value is a set representation, not a tuple representation. */\nexport function isSetValue(data: Value | null): data is Value[] {\n return Array.isArray(data) && (data.length === 0 || data[0] !== TUPLE_ID);\n}\n\n/** Checks if value is a tuple representation. */\nexport function isTupleValue(data: Value | null): data is Value[] {\n return Array.isArray(data) && data.length > 1 && data[0] === TUPLE_ID;\n}\n\n/** Normalize unsorted array of values. */\nexport function normalizeValue(data: Value): void {\n if (!Array.isArray(data) || data.length === 0) {\n return;\n }\n\n if (data[0] === TUPLE_ID) {\n for (let i = 1; i < data.length; i++) {\n normalizeValue(data[i]);\n }\n return;\n }\n\n for (const item of data) {\n normalizeValue(item);\n }\n\n data.sort((a, b) => compare(a, b));\n let i = 1;\n while (i < data.length) {\n if (compare(data[i - 1], data[i]) === 0) {\n data.splice(i, 1);\n } else {\n i++;\n }\n }\n}\n\n/** Validates value for {@link ExpressionType} and value of basic sets. */\nexport function validateValue(value: Value, type: ExpressionType, basics: ValueContext): boolean {\n switch (type.typeID) {\n case TypeID.integer:\n return typeof value === 'number';\n case TypeID.logic: {\n if (typeof value !== 'number') {\n return false;\n }\n return value === VALUE_TRUE || value === VALUE_FALSE;\n }\n case TypeID.basic: {\n if (typeof value !== 'number') {\n return false;\n }\n const domain = basics.get(type.baseID);\n return !!domain && Array.isArray(domain) && domain.includes(value);\n }\n\n case TypeID.tuple: {\n if (!Array.isArray(value) || value.length !== type.factors.length + 1 || value[0] !== TUPLE_ID) {\n return false;\n }\n for (let i = 0; i < type.factors.length; i++) {\n if (!validateValue(value[i + 1], type.factors[i], basics)) {\n return false;\n }\n }\n return true;\n }\n\n case TypeID.collection: {\n if (!isSetValue(value)) {\n return false;\n }\n for (const item of value) {\n if (!validateValue(item, type.base, basics)) {\n return false;\n }\n }\n return true;\n }\n\n case TypeID.anyTypification:\n case TypeID.predicate:\n case TypeID.function:\n return false;\n }\n}\n\n/** Converts value path to type path. */\nexport function convertPathToType(path: ValuePath, type: Typification): TypePath | null {\n const result: number[] = [];\n if (path.length === 0) {\n return result as TypePath;\n }\n\n let curType = type;\n let index = 0;\n while (index < path.length) {\n switch (curType.typeID) {\n case TypeID.collection: {\n result.push(0);\n curType = curType.base;\n index++;\n break;\n }\n case TypeID.tuple: {\n const tupleIdx = path[index];\n if (typeof tupleIdx !== 'number' || tupleIdx < 1 || tupleIdx > curType.factors.length) {\n return null;\n }\n result.push(tupleIdx);\n curType = curType.factors[tupleIdx - 1];\n index++;\n break;\n }\n case TypeID.basic:\n case TypeID.integer:\n case TypeID.anyTypification:\n return null;\n }\n }\n return result as TypePath;\n}\n\n/** Extracts value from a target by path. */\nexport function extractValue(target: Value, path: ValuePath): Value | null {\n let current: Value = target;\n let i = 0;\n while (i < path.length) {\n if (!Array.isArray(current) || current.length <= path[i]) {\n return null;\n }\n current = current[path[i]];\n i++;\n }\n return current;\n}\n\n/** Makes default value for a type. */\nexport function makeDefaultValue(type: Typification): Value {\n switch (type.typeID) {\n case TypeID.anyTypification:\n case TypeID.integer:\n case TypeID.basic:\n return INVALID_ELEMENT;\n case TypeID.collection:\n return [];\n case TypeID.tuple:\n return tuple(type.factors.map(item => makeDefaultValue(item)));\n }\n}\n\n/** Perform immutable deep copy update. */\nexport function setNestedValue(target: Value | null, path: ValuePath, newVal: Value): Value {\n if (path.length === 0) {\n return newVal;\n }\n const [head, ...rest] = path;\n const arr = Array.isArray(target) ? [...target] : [];\n arr[head] = setNestedValue(arr[head], makeValuePath(rest), newVal);\n return arr;\n}\n\n/** Test if value contains invalid elements. */\nexport function testInvalid(value: Value): boolean {\n const stack = [value];\n while (stack.length > 0) {\n const current = stack.pop();\n if (current === INVALID_ELEMENT) {\n return true;\n }\n if (Array.isArray(current)) {\n for (const element of current) {\n stack.push(element);\n }\n }\n }\n return false;\n}\n","/**\n * Module: Structured data for RSLang expression evaluation.\n */\n\nimport { type Branded } from '../../shared';\n\nimport { printValue } from './value-api';\n\n/** Tuple ID for array distinction. */\nexport const TUPLE_ID = -111;\n\n/** Invalid value for structured data. */\nexport const INVALID_ELEMENT = -1;\n\n/** Boolean values: true. */\nexport const VALUE_TRUE = 1;\n\n/** Boolean values: false. */\nexport const VALUE_FALSE = 0;\n\n/** Cardinality threshold for \"infinite\" sets (e.g. Z). */\nexport const SET_INFINITY = 10_000_000;\n\n/** Cardinality threshold for Boolean power set. */\nexport const BOOL_INFINITY = 18;\n\n/** Expression evaluation result: structured data. */\nexport type Value = number | Value[];\n\n/** Values context. */\nexport type ValueContext = Map<string, Value>;\n\n/** Value extraction path. */\nexport type ValuePath = Branded<number[], 'ValuePath'>;\n\n/** Creates value path. */\nexport function makeValuePath(path: number[]): ValuePath {\n return path as ValuePath;\n}\n\n/** Empty set ∅. */\nexport const EmptySetV = [];\n\n/** Compare two structured data without recursive calls. */\nexport function compare(v1: Value, v2: Value): number {\n const stack1: Value[] = [v1];\n const stack2: Value[] = [v2];\n\n while (stack1.length > 0 && stack2.length > 0) {\n const el1 = stack1.pop();\n const el2 = stack2.pop();\n if (el1 === el2) {\n continue;\n }\n\n const type1 = typeof el1;\n const type2 = typeof el2;\n if (type1 === 'number' && type2 === 'number') {\n const numDiff = (el1 as number) - (el2 as number);\n if (numDiff !== 0) return numDiff;\n continue;\n }\n\n const isArray1 = Array.isArray(el1);\n const isArray2 = Array.isArray(el2);\n if (!isArray1 || !isArray2) {\n throw new Error(`Cannot compare different types ${printValue(el1!)} and ${printValue(el2!)}`);\n }\n\n const arr1 = el1;\n const arr2 = el2;\n const len1 = arr1.length;\n const len2 = arr2.length;\n if (len1 !== len2) {\n return len1 - len2;\n }\n\n for (let i = len1 - 1; i >= 0; i--) {\n stack1.push(arr1[i]);\n stack2.push(arr2[i]);\n }\n }\n return 0;\n}\n\n/** Tuple from components. */\nexport function tuple(components: Value[]): Value {\n return [TUPLE_ID, ...components];\n}\n\n/** Set from elements (unique). Value[] - materialized. */\nexport function set(elements: Value[]): Value[] {\n const sorted = [...elements].sort(compare);\n for (let i = 1; i < sorted.length; ) {\n if (compare(sorted[i - 1], sorted[i]) === 0) {\n sorted.splice(i, 1);\n } else {\n i++;\n }\n }\n return sorted;\n}\n"],"mappings":";;;;;AAqBA,SAAgB,iBAAiB,SAAoC;CACnE,MAAM,cAAc,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;CAChE,IAAI,cAAA,KACF,OAAO;CAET,IAAI,gBAAgB,KAAK,QAAQ,WAAW,GAC1C,OAAO;CAGT,IAAI,cAAyB,CAAC,CAAC,CAAC;CAChC,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,OAAkB,CAAC;EACzB,KAAK,MAAM,UAAU,aACnB,KAAK,MAAM,SAAS,QAClB,KAAK,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC;EAGhC,cAAc;CAChB;CACA,OAAO,YAAY,IAAI,KAAK;AAC9B;;AAGA,SAAgB,QAAQ,MAA+B;CACrD,IAAI,KAAK,SAAA,IACP,OAAO;CAET,OAAO,SAAS,IAAI;AACtB;;AAGA,SAAS,SAAS,KAAkC;CAClD,MAAM,SAAoB,CAAC,CAAC,CAAC;CAC7B,IAAI,IAAI,WAAW,GACjB,OAAO;CAGT,IAAI,UAAqB,CAAC,CAAC,CAAC;CAC5B,IAAI,WAAqB,CAAC,EAAE;CAC5B,OAAO,QAAQ,SAAS,GAAG;EACzB,MAAM,OAAkB,CAAC;EACzB,MAAM,eAAyB,CAAC;EAChC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAClC,KAAK,IAAI,IAAI,SAAS,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK;GACjD,MAAM,SAAS,CAAC,GAAG,QAAQ,IAAI,IAAI,EAAE;GACrC,OAAO,KAAK,MAAM;GAClB,IAAI,IAAI,IAAI,SAAS,GAAG;IACtB,KAAK,KAAK,MAAM;IAChB,aAAa,KAAK,CAAC;GACrB;EACF;EAEF,UAAU;EACV,WAAW;CACb;CACA,OAAO;AACT;;AAGA,SAAgB,SAAS,SAAkB,SAAyB;CAClE,IAAI,OAAO;CACX,IAAI,QAAQ,QAAQ,SAAS;CAC7B,OAAO,QAAQ,OAAO;EACpB,MAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;EACzC,MAAM,MAAM,QAAQ,QAAQ,MAAM,OAAO;EACzC,IAAI,QAAQ,GACV,OAAO;OACF,IAAI,MAAM,GACf,OAAO,MAAM;OAEb,QAAQ,MAAM;CAElB;CACA,OAAO;AACT;;AAGA,SAAgB,aAAa,GAAY,GAAqB;CAC5D,IAAI,IAAI,GACN,IAAI;CACN,OAAO,IAAI,EAAE,UAAU,IAAI,EAAE,QAAQ;EACnC,MAAM,MAAM,QAAQ,EAAE,IAAI,EAAE,EAAE;EAC9B,IAAI,QAAQ,GAAG;GACb;GACA;EACF,OAAO,IAAI,MAAM,GACf;OAEA,OAAO;CAEX;CACA,OAAO,MAAM,EAAE;AACjB;;AAGA,SAAgB,OAAO,QAA4B;CACjD,MAAM,SAAkB,CAAC;CACzB,KAAK,MAAM,WAAW,QACpB,OAAO,KAAK,GAAG,OAAO;CAExB,OAAO,IAAI,MAAM;AACnB;;AAGA,SAAgB,SAAS,MAAe,MAAwB;CAC9D,MAAM,SAAkB,CAAC;CACzB,IAAI,IAAI,GACN,IAAI;CACN,OAAO,IAAI,KAAK,UAAU,IAAI,KAAK,QAAQ;EACzC,MAAM,MAAM,QAAQ,KAAK,IAAI,KAAK,EAAE;EACpC,IAAI,MAAM,GAAG;GACX,OAAO,KAAK,KAAK,EAAE;GACnB;EACF,OAAO,IAAI,MAAM,GAAG;GAClB,OAAO,KAAK,KAAK,EAAE;GACnB;EACF,OAAO;GACL,OAAO,KAAK,KAAK,EAAE;GACnB;GACA;EACF;CACF;CACA,OAAO,IAAI,KAAK,QAAQ;EACtB,OAAO,KAAK,KAAK,EAAE;EACnB;CACF;CACA,OAAO,IAAI,KAAK,QAAQ;EACtB,OAAO,KAAK,KAAK,EAAE;EACnB;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,gBAAgB,MAAe,MAAwB;CACrE,MAAM,SAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,KAAK,UAAU,IAAI,KAAK,SAAU;EAC3D,MAAM,MAAM,QAAQ,KAAK,IAAI,KAAK,EAAE;EACpC,IAAI,MAAM,GACR;OACK,IAAI,MAAM,GACf;OACK;GACL,OAAO,KAAK,KAAK,EAAE;GACnB;GACA;EACF;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,QAAQ,MAAe,MAAwB;CAC7D,MAAM,SAAkB,CAAC;CACzB,IAAI,IAAI,GACN,IAAI;CACN,OAAO,IAAI,KAAK,UAAU,IAAI,KAAK,QAAQ;EACzC,MAAM,MAAM,QAAQ,KAAK,IAAI,KAAK,EAAE;EACpC,IAAI,MAAM,GAAG;GACX,OAAO,KAAK,KAAK,EAAE;GACnB;EACF,OAAO,IAAI,MAAM,GACf;OACK;GACL;GACA;EACF;CACF;CACA,OAAO,IAAI,KAAK,QAAQ;EACtB,OAAO,KAAK,KAAK,EAAE;EACnB;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,WAAW,MAAe,MAAwB;CAChE,MAAM,SAAkB,CAAC;CACzB,IAAI,IAAI,GACN,IAAI;CACN,OAAO,IAAI,KAAK,UAAU,IAAI,KAAK,QAAQ;EACzC,MAAM,MAAM,QAAQ,KAAK,IAAI,KAAK,EAAE;EACpC,IAAI,MAAM,GAAG;GACX,OAAO,KAAK,KAAK,EAAE;GACnB;EACF,OAAO,IAAI,MAAM,GAAG;GAClB,OAAO,KAAK,KAAK,EAAE;GACnB;EACF,OAAO;GACL;GACA;EACF;CACF;CACA,OAAO,IAAI,KAAK,QAAQ;EACtB,OAAO,KAAK,KAAK,EAAE;EACnB;CACF;CACA,OAAO,IAAI,KAAK,QAAQ;EACtB,OAAO,KAAK,KAAK,EAAE;EACnB;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,WAAW,QAAmB,SAA4B;CAKxE,OAAO,IAJ4B,OAAO,KAAI,YAAW;EACvD,MAAM,gBAAgB,QAAQ,KAAI,QAAO,QAAQ,IAAI;EACrD,OAAO,QAAQ,WAAW,IAAI,cAAc,KAAK,MAAM,aAAa;CACtE,CACW,CAAiB;AAC9B;;AAGA,SAAgB,WAAW,MAA4B;CACrD,IAAI,CAAC,MAAM,QAAQ,IAAI,GACrB,OAAO,OAAO,IAAI;CAEpB,MAAM,MAAM,KAAK;CACjB,IAAI,KAAK,WAAW,GAClB,OAAO;CAGT,MAAM,UAAU,KAAK,OAAO;CAC5B,MAAM,QAAQ,UAAU,IAAI;CAE5B,IAAI,SAAS,UAAU,MAAM;CAC7B,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,KAAK;EAChC,IAAI,IAAI,OAAO,UAAU;EACzB,UAAU,WAAW,KAAK,EAAE;CAC9B;CACA,UAAU,UAAU,MAAM;CAC1B,OAAO;AACT;;AAGA,SAAgB,UAAU,OAA6B;CACrD,IAAI,SAAS,MACX,OAAO;CAGT,OAAO,aADK,WAAW,KACH,CAAG;AACzB;;AAGA,SAAgB,WAAW,MAAqC;CAC9D,OAAO,MAAM,QAAQ,IAAI,MAAM,KAAK,WAAW,KAAK,KAAK,OAAA;AAC3D;;AAGA,SAAgB,aAAa,MAAqC;CAChE,OAAO,MAAM,QAAQ,IAAI,KAAK,KAAK,SAAS,KAAK,KAAK,OAAA;AACxD;;AAGA,SAAgB,eAAe,MAAmB;CAChD,IAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GAC1C;CAGF,IAAI,KAAK,OAAA,MAAiB;EACxB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAC/B,eAAe,KAAK,EAAE;EAExB;CACF;CAEA,KAAK,MAAM,QAAQ,MACjB,eAAe,IAAI;CAGrB,KAAK,MAAM,GAAG,MAAM,QAAQ,GAAG,CAAC,CAAC;CACjC,IAAI,IAAI;CACR,OAAO,IAAI,KAAK,QACd,IAAI,QAAQ,KAAK,IAAI,IAAI,KAAK,EAAE,MAAM,GACpC,KAAK,OAAO,GAAG,CAAC;MAEhB;AAGN;;AAGA,SAAgB,cAAc,OAAc,MAAsB,QAA+B;CAC/F,QAAQ,KAAK,QAAb;EACE,KAAK,OAAO,SACV,OAAO,OAAO,UAAU;EAC1B,KAAK,OAAO;GACV,IAAI,OAAO,UAAU,UACnB,OAAO;GAET,OAAO,UAAA,KAAwB,UAAA;EAEjC,KAAK,OAAO,OAAO;GACjB,IAAI,OAAO,UAAU,UACnB,OAAO;GAET,MAAM,SAAS,OAAO,IAAI,KAAK,MAAM;GACrC,OAAO,CAAC,CAAC,UAAU,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,KAAK;EACnE;EAEA,KAAK,OAAO;GACV,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,KAAK,QAAQ,SAAS,KAAK,MAAM,OAAA,MAC7E,OAAO;GAET,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KACvC,IAAI,CAAC,cAAc,MAAM,IAAI,IAAI,KAAK,QAAQ,IAAI,MAAM,GACtD,OAAO;GAGX,OAAO;EAGT,KAAK,OAAO;GACV,IAAI,CAAC,WAAW,KAAK,GACnB,OAAO;GAET,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,cAAc,MAAM,KAAK,MAAM,MAAM,GACxC,OAAO;GAGX,OAAO;EAGT,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,OAAO,UACV,OAAO;CACX;AACF;;AAGA,SAAgB,kBAAkB,MAAiB,MAAqC;CACtF,MAAM,SAAmB,CAAC;CAC1B,IAAI,KAAK,WAAW,GAClB,OAAO;CAGT,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,OAAO,QAAQ,KAAK,QAClB,QAAQ,QAAQ,QAAhB;EACE,KAAK,OAAO;GACV,OAAO,KAAK,CAAC;GACb,UAAU,QAAQ;GAClB;GACA;EAEF,KAAK,OAAO,OAAO;GACjB,MAAM,WAAW,KAAK;GACtB,IAAI,OAAO,aAAa,YAAY,WAAW,KAAK,WAAW,QAAQ,QAAQ,QAC7E,OAAO;GAET,OAAO,KAAK,QAAQ;GACpB,UAAU,QAAQ,QAAQ,WAAW;GACrC;GACA;EACF;EACA,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,OAAO,iBACV,OAAO;CACX;CAEF,OAAO;AACT;;AAGA,SAAgB,aAAa,QAAe,MAA+B;CACzE,IAAI,UAAiB;CACrB,IAAI,IAAI;CACR,OAAO,IAAI,KAAK,QAAQ;EACtB,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,UAAU,KAAK,IACpD,OAAO;EAET,UAAU,QAAQ,KAAK;EACvB;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,iBAAiB,MAA2B;CAC1D,QAAQ,KAAK,QAAb;EACE,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,OAAO,OACV,OAAA;EACF,KAAK,OAAO,YACV,OAAO,CAAC;EACV,KAAK,OAAO,OACV,OAAO,MAAM,KAAK,QAAQ,KAAI,SAAQ,iBAAiB,IAAI,CAAC,CAAC;CACjE;AACF;;AAGA,SAAgB,eAAe,QAAsB,MAAiB,QAAsB;CAC1F,IAAI,KAAK,WAAW,GAClB,OAAO;CAET,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,MAAM,MAAM,MAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;CACnD,IAAI,QAAQ,eAAe,IAAI,OAAO,cAAc,IAAI,GAAG,MAAM;CACjE,OAAO;AACT;;AAGA,SAAgB,YAAY,OAAuB;CACjD,MAAM,QAAQ,CAAC,KAAK;CACpB,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,UAAU,MAAM,IAAI;EAC1B,IAAI,YAAA,IACF,OAAO;EAET,IAAI,MAAM,QAAQ,OAAO,GACvB,KAAK,MAAM,WAAW,SACpB,MAAM,KAAK,OAAO;CAGxB;CACA,OAAO;AACT;;;;AClbA,MAAa,WAAW;;AAGxB,MAAa,kBAAkB;;AAG/B,MAAa,aAAa;;AAG1B,MAAa,cAAc;;AAG3B,MAAa,eAAe;;AAG5B,MAAa,gBAAgB;;AAY7B,SAAgB,cAAc,MAA2B;CACvD,OAAO;AACT;;AAGA,MAAa,YAAY,CAAC;;AAG1B,SAAgB,QAAQ,IAAW,IAAmB;CACpD,MAAM,SAAkB,CAAC,EAAE;CAC3B,MAAM,SAAkB,CAAC,EAAE;CAE3B,OAAO,OAAO,SAAS,KAAK,OAAO,SAAS,GAAG;EAC7C,MAAM,MAAM,OAAO,IAAI;EACvB,MAAM,MAAM,OAAO,IAAI;EACvB,IAAI,QAAQ,KACV;EAKF,IAAI,OAFiB,QAEP,YAAY,OADL,QACe,UAAU;GAC5C,MAAM,UAAW,MAAkB;GACnC,IAAI,YAAY,GAAG,OAAO;GAC1B;EACF;EAIA,IAAI,CAFa,MAAM,QAAQ,GAE1B,KAAY,CADA,MAAM,QAAQ,GACb,GAChB,MAAM,IAAI,MAAM,kCAAkC,WAAW,GAAI,EAAE,OAAO,WAAW,GAAI,GAAG;EAG9F,MAAM,OAAO;EACb,MAAM,OAAO;EACb,MAAM,OAAO,KAAK;EAClB,MAAM,OAAO,KAAK;EAClB,IAAI,SAAS,MACX,OAAO,OAAO;EAGhB,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,GAAG,KAAK;GAClC,OAAO,KAAK,KAAK,EAAE;GACnB,OAAO,KAAK,KAAK,EAAE;EACrB;CACF;CACA,OAAO;AACT;;AAGA,SAAgB,MAAM,YAA4B;CAChD,OAAO,CAAC,UAAU,GAAG,UAAU;AACjC;;AAGA,SAAgB,IAAI,UAA4B;CAC9C,MAAM,SAAS,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,OAAO;CACzC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,SACzB,IAAI,QAAQ,OAAO,IAAI,IAAI,OAAO,EAAE,MAAM,GACxC,OAAO,OAAO,GAAG,CAAC;MAElB;CAGJ,OAAO;AACT"}
1
+ {"version":3,"file":"value-ybFBRuz6.js","names":[],"sources":["../src/rslang/eval/value-api.ts","../src/rslang/eval/value.ts"],"sourcesContent":["import { generateStub } from '../../shared';\nimport { type ExpressionType, TypeID, type TypePath, type Typification } from '../semantic/typification';\n\nimport {\n BOOL_INFINITY,\n compare,\n EmptySetV,\n INVALID_ELEMENT,\n makeValuePath,\n set,\n SET_INFINITY,\n tuple,\n TUPLE_ID,\n type Value,\n VALUE_FALSE,\n VALUE_TRUE,\n type ValueContext,\n type ValuePath\n} from './value';\n\n/** Cartesian product of factor sets. */\nexport function cartesianProduct(factors: Value[][]): Value[] | null {\n const cardinality = factors.reduce((acc, f) => acc * f.length, 1);\n if (cardinality > SET_INFINITY) {\n return null;\n }\n if (cardinality === 0 || factors.length === 0) {\n return EmptySetV;\n }\n\n let accumulator: Value[][] = [[]];\n for (const factor of factors) {\n const next: Value[][] = [];\n for (const prefix of accumulator) {\n for (const value of factor) {\n next.push([...prefix, value]);\n }\n }\n accumulator = next;\n }\n return accumulator.map(tuple);\n}\n\n/** Boolean power set ℬ(X). No cache - materialized. */\nexport function boolean(base: Value[]): Value[] | null {\n if (base.length > BOOL_INFINITY) {\n return null;\n }\n return powerset(base);\n}\n\n/** Powerset of array. */\nfunction powerset(arr: readonly Value[]): Value[][] {\n const result: Value[][] = [[]];\n if (arr.length === 0) {\n return result;\n }\n\n let current: Value[][] = [[]];\n let maxIndex: number[] = [-1];\n while (current.length > 0) {\n const next: Value[][] = [];\n const nextMaxIndex: number[] = [];\n for (let i = 0; i < current.length; i++) {\n for (let j = maxIndex[i] + 1; j < arr.length; j++) {\n const subset = [...current[i], arr[j]];\n result.push(subset);\n if (j < arr.length - 1) {\n next.push(subset);\n nextMaxIndex.push(j);\n }\n }\n }\n current = next;\n maxIndex = nextMaxIndex;\n }\n return result;\n}\n\n/** Check if set contains element. */\nexport function contains(setData: Value[], element: Value): boolean {\n let left = 0;\n let right = setData.length - 1;\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n const cmp = compare(setData[mid], element);\n if (cmp === 0) {\n return true;\n } else if (cmp < 0) {\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n return false;\n}\n\n/** Is A ⊆ B. */\nexport function isSubsetOrEq(a: Value[], b: Value[]): boolean {\n let i = 0,\n j = 0;\n while (i < a.length && j < b.length) {\n const cmp = compare(a[i], b[j]);\n if (cmp === 0) {\n i++;\n j++;\n } else if (cmp > 0) {\n j++;\n } else {\n return false;\n }\n }\n return i === a.length;\n}\n\n/** Reduce: flatten double boolean to single boolean. */\nexport function reduce(target: Value[][]): Value[] {\n const result: Value[] = [];\n for (const element of target) {\n result.push(...element);\n }\n return set(result);\n}\n\n/** Union A ∪ B. */\nexport function setUnion(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n let i = 0,\n j = 0;\n while (i < set1.length && j < set2.length) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n result.push(set1[i]);\n i++;\n } else if (cmp > 0) {\n result.push(set2[j]);\n j++;\n } else {\n result.push(set1[i]);\n i++;\n j++;\n }\n }\n while (i < set1.length) {\n result.push(set1[i]);\n i++;\n }\n while (j < set2.length) {\n result.push(set2[j]);\n j++;\n }\n return result;\n}\n\n/** Intersection A ∩ B. */\nexport function setIntersection(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n for (let i = 0, j = 0; i < set1.length && j < set2.length; ) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n i++;\n } else if (cmp > 0) {\n j++;\n } else {\n result.push(set1[i]);\n i++;\n j++;\n }\n }\n return result;\n}\n\n/** Difference A \\ B. */\nexport function setDiff(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n let i = 0,\n j = 0;\n while (i < set1.length && j < set2.length) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n result.push(set1[i]);\n i++;\n } else if (cmp > 0) {\n j++;\n } else {\n i++;\n j++;\n }\n }\n while (i < set1.length) {\n result.push(set1[i]);\n i++;\n }\n return result;\n}\n\n/** Symmetric difference A ∆ B. */\nexport function setSymDiff(set1: Value[], set2: Value[]): Value[] {\n const result: Value[] = [];\n let i = 0,\n j = 0;\n while (i < set1.length && j < set2.length) {\n const cmp = compare(set1[i], set2[j]);\n if (cmp < 0) {\n result.push(set1[i]);\n i++;\n } else if (cmp > 0) {\n result.push(set2[j]);\n j++;\n } else {\n i++;\n j++;\n }\n }\n while (i < set1.length) {\n result.push(set1[i]);\n i++;\n }\n while (j < set2.length) {\n result.push(set2[j]);\n j++;\n }\n return result;\n}\n\n/** Projection of set by indices (BigPr). */\nexport function projection(target: Value[][], indices: number[]): Value[] {\n const projectedElements: Value[] = target.map(element => {\n const newComponents = indices.map(idx => element[idx]);\n return indices.length === 1 ? newComponents[0] : tuple(newComponents);\n });\n return set(projectedElements);\n}\n\n/** Condensed string representation. */\nexport function printValue(data: Value | null): string {\n if (!Array.isArray(data)) {\n return String(data);\n }\n const len = data.length;\n if (data.length === 0) {\n return '{}';\n }\n\n const isTuple = data[0] === TUPLE_ID;\n const start = isTuple ? 1 : 0;\n\n let result = isTuple ? '(' : '{';\n for (let i = start; i < len; i++) {\n if (i > start) result += ', ';\n result += printValue(data[i]);\n }\n result += isTuple ? ')' : '}';\n return result;\n}\n\n/** Generates stub ID for value. */\nexport function valueStub(value: Value | null): string {\n if (value == null) {\n return '';\n }\n const str = printValue(value);\n return generateStub(str);\n}\n\n/** Checks if value is a set representation, not a tuple representation. */\nexport function isSetValue(data: Value | null): data is Value[] {\n return Array.isArray(data) && (data.length === 0 || data[0] !== TUPLE_ID);\n}\n\n/** Checks if value is a tuple representation. */\nexport function isTupleValue(data: Value | null): data is Value[] {\n return Array.isArray(data) && data.length > 1 && data[0] === TUPLE_ID;\n}\n\n/** Normalize unsorted array of values. */\nexport function normalizeValue(data: Value): void {\n if (!Array.isArray(data) || data.length === 0) {\n return;\n }\n\n if (data[0] === TUPLE_ID) {\n for (let i = 1; i < data.length; i++) {\n normalizeValue(data[i]);\n }\n return;\n }\n\n for (const item of data) {\n normalizeValue(item);\n }\n\n data.sort((a, b) => compare(a, b));\n let i = 1;\n while (i < data.length) {\n if (compare(data[i - 1], data[i]) === 0) {\n data.splice(i, 1);\n } else {\n i++;\n }\n }\n}\n\n/** Validates value for {@link ExpressionType} and value of basic sets. */\nexport function validateValue(value: Value, type: ExpressionType, basics: ValueContext): boolean {\n switch (type.typeID) {\n case TypeID.integer:\n return typeof value === 'number';\n case TypeID.logic: {\n if (typeof value !== 'number') {\n return false;\n }\n return value === VALUE_TRUE || value === VALUE_FALSE;\n }\n case TypeID.basic: {\n if (typeof value !== 'number') {\n return false;\n }\n const domain = basics.get(type.baseID);\n return !!domain && Array.isArray(domain) && domain.includes(value);\n }\n\n case TypeID.tuple: {\n if (!Array.isArray(value) || value.length !== type.factors.length + 1 || value[0] !== TUPLE_ID) {\n return false;\n }\n for (let i = 0; i < type.factors.length; i++) {\n if (!validateValue(value[i + 1], type.factors[i], basics)) {\n return false;\n }\n }\n return true;\n }\n\n case TypeID.collection: {\n if (!isSetValue(value)) {\n return false;\n }\n for (const item of value) {\n if (!validateValue(item, type.base, basics)) {\n return false;\n }\n }\n return true;\n }\n\n case TypeID.anyTypification:\n case TypeID.predicate:\n case TypeID.function:\n return false;\n }\n}\n\n/** Converts value path to type path. */\nexport function convertPathToType(path: ValuePath, type: Typification): TypePath | null {\n const result: number[] = [];\n if (path.length === 0) {\n return result as TypePath;\n }\n\n let curType = type;\n let index = 0;\n while (index < path.length) {\n switch (curType.typeID) {\n case TypeID.collection: {\n result.push(0);\n curType = curType.base;\n index++;\n break;\n }\n case TypeID.tuple: {\n const tupleIdx = path[index];\n if (typeof tupleIdx !== 'number' || tupleIdx < 1 || tupleIdx > curType.factors.length) {\n return null;\n }\n result.push(tupleIdx);\n curType = curType.factors[tupleIdx - 1];\n index++;\n break;\n }\n case TypeID.basic:\n case TypeID.integer:\n case TypeID.anyTypification:\n return null;\n }\n }\n return result as TypePath;\n}\n\n/** Extracts value from a target by path. */\nexport function extractValue(target: Value, path: ValuePath): Value | null {\n let current: Value = target;\n let i = 0;\n while (i < path.length) {\n if (!Array.isArray(current) || current.length <= path[i]) {\n return null;\n }\n current = current[path[i]];\n i++;\n }\n return current;\n}\n\n/** Makes default value for a type. */\nexport function makeDefaultValue(type: Typification): Value {\n switch (type.typeID) {\n case TypeID.anyTypification:\n case TypeID.integer:\n case TypeID.basic:\n return INVALID_ELEMENT;\n case TypeID.collection:\n return [];\n case TypeID.tuple:\n return tuple(type.factors.map(item => makeDefaultValue(item)));\n }\n}\n\n/** Perform immutable deep copy update. */\nexport function setNestedValue(target: Value | null, path: ValuePath, newVal: Value): Value {\n if (path.length === 0) {\n return newVal;\n }\n const [head, ...rest] = path;\n const arr = Array.isArray(target) ? [...target] : [];\n arr[head] = setNestedValue(arr[head], makeValuePath(rest), newVal);\n return arr;\n}\n\n/** Test if value contains invalid elements. */\nexport function testInvalid(value: Value): boolean {\n const stack = [value];\n while (stack.length > 0) {\n const current = stack.pop();\n if (current === INVALID_ELEMENT) {\n return true;\n }\n if (Array.isArray(current)) {\n for (const element of current) {\n stack.push(element);\n }\n }\n }\n return false;\n}\n","/**\n * Module: Structured data for RSLang expression evaluation.\n */\n\nimport { type Branded } from '../../shared';\n\nimport { printValue } from './value-api';\n\n/** Tuple ID for array distinction. */\nexport const TUPLE_ID = -111;\n\n/** Invalid value for structured data. */\nexport const INVALID_ELEMENT = -1;\n\n/** Boolean values: true. */\nexport const VALUE_TRUE = 1;\n\n/** Boolean values: false. */\nexport const VALUE_FALSE = 0;\n\n/** Cardinality threshold for \"infinite\" sets (e.g. Z). */\nexport const SET_INFINITY = 10_000_000;\n\n/** Cardinality threshold for Boolean power set. */\nexport const BOOL_INFINITY = 18;\n\n/** Expression evaluation result: structured data. */\nexport type Value = number | Value[];\n\n/** Values context. */\nexport type ValueContext = Map<string, Value>;\n\n/** Value extraction path. */\nexport type ValuePath = Branded<number[], 'ValuePath'>;\n\n/** Creates value path. */\nexport function makeValuePath(path: number[]): ValuePath {\n return path as ValuePath;\n}\n\n/** Empty set ∅. */\nexport const EmptySetV = [];\n\n/** Thrown when a runtime value operation cannot be applied to the given operands. */\nexport class CalcInvalidDataError extends Error {\n readonly left: string;\n readonly right: string;\n\n constructor(left: string, right: string) {\n super(`Cannot compare different types ${left} and ${right}`);\n this.name = 'CalcInvalidDataError';\n this.left = left;\n this.right = right;\n }\n}\n\n/** Compare two structured data without recursive calls. */\nexport function compare(v1: Value, v2: Value): number {\n const stack1: Value[] = [v1];\n const stack2: Value[] = [v2];\n\n while (stack1.length > 0 && stack2.length > 0) {\n const el1 = stack1.pop();\n const el2 = stack2.pop();\n if (el1 === el2) {\n continue;\n }\n\n const type1 = typeof el1;\n const type2 = typeof el2;\n if (type1 === 'number' && type2 === 'number') {\n const numDiff = (el1 as number) - (el2 as number);\n if (numDiff !== 0) return numDiff;\n continue;\n }\n\n const isArray1 = Array.isArray(el1);\n const isArray2 = Array.isArray(el2);\n if (!isArray1 || !isArray2) {\n throw new CalcInvalidDataError(printValue(el1!), printValue(el2!));\n }\n\n const arr1 = el1;\n const arr2 = el2;\n const len1 = arr1.length;\n const len2 = arr2.length;\n if (len1 !== len2) {\n return len1 - len2;\n }\n\n for (let i = len1 - 1; i >= 0; i--) {\n stack1.push(arr1[i]);\n stack2.push(arr2[i]);\n }\n }\n return 0;\n}\n\n/** Tuple from components. */\nexport function tuple(components: Value[]): Value {\n return [TUPLE_ID, ...components];\n}\n\n/** Set from elements (unique). Value[] - materialized. */\nexport function set(elements: Value[]): Value[] {\n const sorted = [...elements].sort(compare);\n for (let i = 1; i < sorted.length; ) {\n if (compare(sorted[i - 1], sorted[i]) === 0) {\n sorted.splice(i, 1);\n } else {\n i++;\n }\n }\n return sorted;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsconcept/domain",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Shared TypeScript domain for RS language, RSForm, RSModel, RSEngine, OSS, and concept-text helpers.",
5
5
  "license": "MIT",
6
6
  "author": "IRBorisov",
@@ -176,7 +176,7 @@
176
176
  "tsdown": "^0.22.2",
177
177
  "typescript": "^6.0.3",
178
178
  "typescript-eslint": "^8.61.0",
179
- "vitest": "^4.1.8"
179
+ "vitest": "^4.1.9"
180
180
  },
181
181
  "publishConfig": {
182
182
  "access": "public"
@@ -23,7 +23,6 @@ export interface RSEngineServices {
23
23
  export interface RSEngineNotifications {
24
24
  onInvalidSetValue: () => void;
25
25
  onCalculationSuccess: (timeSpent: string) => void;
26
- onEvaluationError: (message: string) => void;
27
26
  }
28
27
 
29
28
  /** Calculation engine for {@link RSModel}. */
@@ -274,26 +273,12 @@ export class RSEngine {
274
273
 
275
274
  /** Evaluates expression for {@link RSEngine}. */
276
275
  public evaluateExpression(expression: string, cstType: CstType): CalculatorResult {
277
- return getEvaluationFor(expression, cstType, this.schema!, this.calculator, message =>
278
- this.notifications?.onEvaluationError(message)
279
- );
276
+ return getEvaluationFor(expression, cstType, this.schema!, this.calculator);
280
277
  }
281
278
 
282
279
  /** Evaluates AST for {@link RSEngine}. */
283
280
  public evaluateAst(ast: AstNode, options?: CalculatorEvaluateOptions): CalculatorResult {
284
- try {
285
- const evaluation = this.calculator.evaluateFull(ast, options);
286
- return evaluation;
287
- } catch (error) {
288
- this.notifications?.onEvaluationError((error as Error).message);
289
- console.error(error);
290
- return {
291
- value: null,
292
- iterations: 0,
293
- cacheHits: 0,
294
- errors: []
295
- };
296
- }
281
+ return this.calculator.evaluateFull(ast, options);
297
282
  }
298
283
 
299
284
  /** Calculates value for {@link Constituenta}. */
@@ -307,9 +292,7 @@ export class RSEngine {
307
292
  const predecessors = this.schema.graph.expandAllInputs([cstID]);
308
293
  this.prepareEvaluation(predecessors);
309
294
  }
310
- const result = getEvaluationFor(cst.definition_formal, cst.cst_type, this.schema, this.calculator, message =>
311
- this.notifications?.onEvaluationError(message)
312
- );
295
+ const result = getEvaluationFor(cst.definition_formal, cst.cst_type, this.schema, this.calculator);
313
296
 
314
297
  if (result.value === null) {
315
298
  this.calculator.resetValue(cst.alias);
@@ -492,9 +475,7 @@ export class RSEngine {
492
475
  if (dependencies.includes(cstID)) {
493
476
  const cst = this.schema!.cstByID.get(cstID)!;
494
477
  if (isInferrable(cst.cst_type)) {
495
- const value = fastEvaluation(cst.definition_formal, cst.cst_type, this.schema!, this.calculator, message =>
496
- this.notifications?.onEvaluationError(message)
497
- );
478
+ const value = fastEvaluation(cst.definition_formal, cst.cst_type, this.schema!, this.calculator);
498
479
  if (value !== null) {
499
480
  this.calculator.setValue(cst.alias, value);
500
481
  } else {
@@ -537,8 +518,7 @@ function getEvaluationFor(
537
518
  expression: string,
538
519
  cstType: CstType,
539
520
  schema: RSForm,
540
- calculator: RSCalculator,
541
- onEvaluationError?: (message: string) => void
521
+ calculator: RSCalculator
542
522
  ): CalculatorResult {
543
523
  const parse = getAnalysisFor(expression, cstType, schema);
544
524
  if (!parse.success || !parse.ast) {
@@ -548,46 +528,21 @@ function getEvaluationFor(
548
528
  cacheHits: 0,
549
529
  errors: parse.errors
550
530
  };
551
- } else {
552
- try {
553
- const result = calculator.evaluateFull(parse.ast);
554
- return {
555
- value: result.value,
556
- iterations: result.iterations,
557
- cacheHits: result.cacheHits,
558
- errors: [...parse.errors, ...result.errors]
559
- };
560
- } catch (error) {
561
- onEvaluationError?.((error as Error).message);
562
- console.error(expression, error);
563
- return {
564
- value: null,
565
- iterations: 0,
566
- cacheHits: 0,
567
- errors: []
568
- };
569
- }
570
531
  }
532
+ const result = calculator.evaluateFull(parse.ast);
533
+ return {
534
+ value: result.value,
535
+ iterations: result.iterations,
536
+ cacheHits: result.cacheHits,
537
+ errors: [...parse.errors, ...result.errors]
538
+ };
571
539
  }
572
540
 
573
541
  /** Evaluates expression for {@link RSModel}. */
574
- function fastEvaluation(
575
- expression: string,
576
- cstType: CstType,
577
- schema: RSForm,
578
- calculator: RSCalculator,
579
- onEvaluationError?: (message: string) => void
580
- ): Value | null {
542
+ function fastEvaluation(expression: string, cstType: CstType, schema: RSForm, calculator: RSCalculator): Value | null {
581
543
  const parse = getAnalysisFor(expression, cstType, schema);
582
544
  if (!parse.success || !parse.ast) {
583
545
  return null;
584
- } else {
585
- try {
586
- return calculator.evaluateFast(parse.ast);
587
- } catch (error) {
588
- onEvaluationError?.((error as Error).message);
589
- console.error(expression, error);
590
- return null;
591
- }
592
546
  }
547
+ return calculator.evaluateFast(parse.ast);
593
548
  }
@@ -84,6 +84,7 @@ export const RSErrorCode = {
84
84
  calcInvalidDebool: 0x8105, // 35333
85
85
  iterateInfinity: 0x8106, // 35334
86
86
  calculationNotSupported: 0x8107, // 35335
87
+ calcInvalidData: 0x8108, // 35336
87
88
 
88
89
  cstEmptyDerived: 0x8861, // 34913
89
90
  definitionNotAllowed: 0x8862 // 34914
@@ -73,6 +73,14 @@ describe('RSCalculator', () => {
73
73
  expectCalcFull('X11', { expectErrorCode: RSErrorCode.calcGlobalMissing });
74
74
  });
75
75
 
76
+ it('returns error for undeclared local variable', () => {
77
+ expectCalcFull('∀a∈X1 b=b', { expectErrorCode: RSErrorCode.localUndeclared });
78
+ });
79
+
80
+ it('returns error for incompatible value comparison', () => {
81
+ expectCalcFull('X1=1', { expectErrorCode: RSErrorCode.calcInvalidData });
82
+ });
83
+
76
84
  it('returns error for infinite quantifier', () => {
77
85
  expectCalcFull('∀a∈Z a=a', { expectErrorCode: RSErrorCode.iterateInfinity });
78
86
  });
@@ -192,6 +192,7 @@ const correctValuesData = [
192
192
  const errorData = [
193
193
  ['[a∈ℬ(R1)] a=a', { code: RSErrorCode.calculationNotSupported, from: 0, to: 13 }],
194
194
  ['debool(X1)', { code: RSErrorCode.calcInvalidDebool, from: 7, to: 9 }],
195
+ ['Pr1(1)', { code: RSErrorCode.calcUnknownError, from: 0, to: 6 }],
195
196
  ['∀a∈Z a=a', { code: RSErrorCode.iterateInfinity, from: 3, to: 4 }],
196
197
  ['ℬℬ({1,2,3,4,5})', { code: RSErrorCode.booleanBaseLimit, from: 1, to: 15, params: [String(BOOL_INFINITY)] }],
197
198
  ['X1\\D1', { code: RSErrorCode.calcGlobalMissing, from: 3, to: 5, params: ['D1'] }],
@@ -227,7 +228,10 @@ const errorData = [
227
228
  ['R{a:=X1 | D1=D1 | a∪X1}', { code: RSErrorCode.calcGlobalMissing, from: 10, to: 12, params: ['D1'] }],
228
229
  ['I{(a,b) | a:∈D1; b:=a; b≠a}', { code: RSErrorCode.calcGlobalMissing, from: 13, to: 15, params: ['D1'] }],
229
230
  ['I{(a,b) | a:∈X1; b:=a; b≠D1}', { code: RSErrorCode.calcGlobalMissing, from: 25, to: 27, params: ['D1'] }],
230
- ['I{(a,b) | a:∈X1; b:=D1; b≠a}', { code: RSErrorCode.calcGlobalMissing, from: 20, to: 22, params: ['D1'] }]
231
+ ['I{(a,b) | a:∈X1; b:=D1; b≠a}', { code: RSErrorCode.calcGlobalMissing, from: 20, to: 22, params: ['D1'] }],
232
+ ['∀a∈X1 b=b', { code: RSErrorCode.localUndeclared, from: 6, to: 7, params: ['b'] }],
233
+ ['X1=1', { code: RSErrorCode.calcInvalidData, from: 0, to: 4, params: ['{1, 2, 3}', '1'] }],
234
+ ['X1=1 & 1=1', { code: RSErrorCode.calcInvalidData, from: 0, to: 4, params: ['{1, 2, 3}', '1'] }]
231
235
  ];
232
236
 
233
237
  describe('Calculator', () => {
@@ -10,6 +10,7 @@ import { TokenID } from '../parser/token';
10
10
  import { EvaluationCache, EvaluationMetadata } from './evaluation-cache';
11
11
  import {
12
12
  BOOL_INFINITY,
13
+ CalcInvalidDataError,
13
14
  compare,
14
15
  EmptySetV,
15
16
  set,
@@ -153,11 +154,19 @@ export class Evaluator {
153
154
  }
154
155
  }
155
156
 
156
- const result = this.dispatchVisitImpl(node);
157
- if (!this.disableCache && result !== null && info.cacheable && stamp !== null) {
158
- this.evalCache.store(info.structuralKey, stamp, result);
157
+ try {
158
+ const result = this.dispatchVisitImpl(node);
159
+ if (!this.disableCache && result !== null && info.cacheable && stamp !== null) {
160
+ this.evalCache.store(info.structuralKey, stamp, result);
161
+ }
162
+ return result;
163
+ } catch (error) {
164
+ if (error instanceof CalcInvalidDataError) {
165
+ return this.onError(RSErrorCode.calcInvalidData, node, [error.left, error.right]);
166
+ }
167
+ this.onError(RSErrorCode.calcUnknownError, node);
168
+ return null;
159
169
  }
160
- return result;
161
170
  }
162
171
 
163
172
  private dispatchVisitImpl(node: AstNode): Value | null {
@@ -280,8 +289,8 @@ export class Evaluator {
280
289
 
281
290
  private visitGlobal(node: AstNode): Value | null {
282
291
  const alias = getNodeText(node);
283
- const value = this.context.get(alias);
284
- if (value === undefined) {
292
+ const value = this.context.get(alias) ?? null;
293
+ if (value === null) {
285
294
  return this.onError(RSErrorCode.calcGlobalMissing, node, [alias]);
286
295
  }
287
296
  return value;
@@ -289,7 +298,11 @@ export class Evaluator {
289
298
 
290
299
  private visitLocal(node: AstNode): Value | null {
291
300
  const alias = getNodeText(node);
292
- return this.locals.getLocal(alias);
301
+ const value = this.locals.findLocal(alias);
302
+ if (value === null) {
303
+ return this.onError(RSErrorCode.localUndeclared, node, [alias]);
304
+ }
305
+ return value;
293
306
  }
294
307
 
295
308
  private visitFunctionCall(node: AstNode): Value | null {
@@ -910,12 +923,8 @@ class LocalContext {
910
923
  }
911
924
  }
912
925
 
913
- getLocal(alias: string): Value {
914
- const binding = this.data.get(alias);
915
- if (binding === undefined) {
916
- throw new Error(`Local variable "${alias}" not found`);
917
- }
918
- return binding.value;
926
+ findLocal(alias: string): Value | null {
927
+ return this.data.get(alias)?.value ?? null;
919
928
  }
920
929
 
921
930
  buildDependencyStamp(reads: ReadonlySet<string>): string | null {
@@ -41,6 +41,19 @@ export function makeValuePath(path: number[]): ValuePath {
41
41
  /** Empty set ∅. */
42
42
  export const EmptySetV = [];
43
43
 
44
+ /** Thrown when a runtime value operation cannot be applied to the given operands. */
45
+ export class CalcInvalidDataError extends Error {
46
+ readonly left: string;
47
+ readonly right: string;
48
+
49
+ constructor(left: string, right: string) {
50
+ super(`Cannot compare different types ${left} and ${right}`);
51
+ this.name = 'CalcInvalidDataError';
52
+ this.left = left;
53
+ this.right = right;
54
+ }
55
+ }
56
+
44
57
  /** Compare two structured data without recursive calls. */
45
58
  export function compare(v1: Value, v2: Value): number {
46
59
  const stack1: Value[] = [v1];
@@ -64,7 +77,7 @@ export function compare(v1: Value, v2: Value): number {
64
77
  const isArray1 = Array.isArray(el1);
65
78
  const isArray2 = Array.isArray(el2);
66
79
  if (!isArray1 || !isArray2) {
67
- throw new Error(`Cannot compare different types ${printValue(el1!)} and ${printValue(el2!)}`);
80
+ throw new CalcInvalidDataError(printValue(el1!), printValue(el2!));
68
81
  }
69
82
 
70
83
  const arr1 = el1;
@@ -7,7 +7,7 @@ import { normalizeAST } from '../parser/normalize';
7
7
  import { parser as rslangParser } from '../parser/parser';
8
8
 
9
9
  import { TypeAuditor } from './type-auditor';
10
- import { basic, bool, constant, LogicT, tuple, type TypeContext, TypeID } from './typification';
10
+ import { AnyTypificationT, basic, bool, constant, LogicT, tuple, type TypeContext, TypeID } from './typification';
11
11
 
12
12
  // Helper to build AST
13
13
  function buildAST(expression: string) {
@@ -299,6 +299,26 @@ describe('TypeAuditor', () => {
299
299
  });
300
300
  });
301
301
 
302
+ it('Templated function with R0 typification', () => {
303
+ typeContext.set('F3', {
304
+ typeID: TypeID.function,
305
+ result: bool(AnyTypificationT),
306
+ args: [{ alias: 'a', type: bool(AnyTypificationT) }]
307
+ });
308
+ expectType('F3[∅]', 'ℬ(R0)');
309
+ expectType('F3[X1]', 'ℬ(R0)');
310
+ });
311
+
312
+ it('Templated function with bare R0 argument', () => {
313
+ typeContext.set('F4', {
314
+ typeID: TypeID.function,
315
+ result: bool(basic('X1')),
316
+ args: [{ alias: 'a', type: AnyTypificationT }]
317
+ });
318
+ expectType('F4[X1]', 'ℬ(X1)');
319
+ expectType('F4[Z]', 'ℬ(X1)');
320
+ });
321
+
302
322
  it('Templated nesting', () => {
303
323
  typeContext.set('F2', {
304
324
  typeID: TypeID.function,
@@ -943,7 +943,8 @@ export class TypeAuditor {
943
943
  function mangleRadicals(funcName: string, type: Typification): Typification {
944
944
  switch (type.typeID) {
945
945
  default:
946
- throw new Error(`Unexpected type: ${type.typeID}`);
946
+ throw new Error(`Unexpected type for ${funcName}: ${JSON.stringify(type)}`);
947
+ case TypeID.anyTypification:
947
948
  case TypeID.integer:
948
949
  return type;
949
950
  case TypeID.basic: {
@@ -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 } from './typification';
5
- import { applyPath } from './typification-api';
4
+ import { AnyTypificationT, basic, bool, IntegerT, tuple, type Typification } from './typification';
5
+ import { applyPath, compareTemplated } from './typification-api';
6
6
 
7
7
  describe('applyPath', () => {
8
8
  function typePath(path: number[]): TypePath {
@@ -44,3 +44,12 @@ describe('applyPath', () => {
44
44
  expect(applyPath(nested, typePath([2, 1]))).toBeNull();
45
45
  });
46
46
  });
47
+
48
+ describe('compareTemplated', () => {
49
+ it('accepts R0 on either side', () => {
50
+ const substitutes = new Map<string, Typification>();
51
+ expect(compareTemplated(substitutes, AnyTypificationT, basic('X1'))).toBe(true);
52
+ expect(compareTemplated(substitutes, bool(basic('X1')), AnyTypificationT)).toBe(true);
53
+ expect(compareTemplated(substitutes, AnyTypificationT, AnyTypificationT)).toBe(true);
54
+ });
55
+ });
@@ -196,7 +196,7 @@ export function compareTemplated(
196
196
  return true;
197
197
  }
198
198
  }
199
- if (value.typeID === TypeID.anyTypification) {
199
+ if (arg.typeID === TypeID.anyTypification || value.typeID === TypeID.anyTypification) {
200
200
  return true;
201
201
  }
202
202
  if (