@rsconcept/domain 1.5.0 → 1.5.2

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 (32) hide show
  1. package/dist/{analyzer-54lGGg13.d.ts → analyzer-0kmNRqcr.d.ts} +2 -2
  2. package/dist/{ast-annotations-C0eMySxt.d.ts → ast-annotations-BnVekMjH.d.ts} +2 -2
  3. package/dist/{calculator-BQnE2gws.d.ts → calculator-OV-RNXre.d.ts} +2 -2
  4. package/dist/{error-CxIs0A7Y.d.ts → error-DYLkv4B3.d.ts} +6 -1
  5. package/dist/index.d.ts +4 -4
  6. package/dist/library/rsengine.d.ts +1 -1
  7. package/dist/library/rsform-api.d.ts +1 -1
  8. package/dist/library/rsform.d.ts +1 -1
  9. package/dist/rslang/ast-annotations.d.ts +1 -1
  10. package/dist/rslang/error.d.ts +1 -1
  11. package/dist/rslang/error.js +5 -0
  12. package/dist/rslang/error.js.map +1 -1
  13. package/dist/rslang/eval/calculator.d.ts +1 -1
  14. package/dist/rslang/eval/evaluator.d.ts +1 -1
  15. package/dist/rslang/index.d.ts +4 -4
  16. package/dist/rslang/parser/syntax-errors.d.ts +9 -3
  17. package/dist/rslang/parser/syntax-errors.js +58 -33
  18. package/dist/rslang/parser/syntax-errors.js.map +1 -1
  19. package/dist/rslang/semantic/analyzer.d.ts +1 -1
  20. package/dist/rslang/semantic/analyzer.js +1 -1
  21. package/dist/rslang/semantic/analyzer.js.map +1 -1
  22. package/dist/rslang/semantic/type-auditor.d.ts +1 -1
  23. package/dist/rslang/semantic/type-auditor.js +30 -6
  24. package/dist/rslang/semantic/type-auditor.js.map +1 -1
  25. package/dist/rslang/semantic/value-auditor.d.ts +1 -1
  26. package/package.json +1 -1
  27. package/src/rslang/error.ts +5 -0
  28. package/src/rslang/parser/parser.test.ts +21 -1
  29. package/src/rslang/parser/syntax-errors.ts +113 -48
  30. package/src/rslang/semantic/analyzer.ts +3 -1
  31. package/src/rslang/semantic/type-auditor.test.ts +36 -10
  32. package/src/rslang/semantic/type-auditor.ts +50 -3
@@ -1,6 +1,6 @@
1
1
  import { t as AstNode } from "./ast-C8sIpKdL.js";
2
2
  import { f as ExpressionType, g as TypeClass } from "./typification-Dk-fisgO.js";
3
- import { i as RSErrorDescription } from "./error-CxIs0A7Y.js";
3
+ import { i as RSErrorDescription } from "./error-DYLkv4B3.js";
4
4
  import { t as ValueClass } from "./value-class-CNI-lqXJ.js";
5
5
 
6
6
  //#region src/rslang/semantic/analyzer.d.ts
@@ -36,4 +36,4 @@ declare class RSLangAnalyzer {
36
36
  }
37
37
  //#endregion
38
38
  export { RSLangAnalyzer as a, AnalysisOptions as i, AnalysisFast as n, AnalysisFull as r, AnalysisBase as t };
39
- //# sourceMappingURL=analyzer-54lGGg13.d.ts.map
39
+ //# sourceMappingURL=analyzer-0kmNRqcr.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { t as AstNode } from "./ast-C8sIpKdL.js";
2
2
  import { f as ExpressionType } from "./typification-Dk-fisgO.js";
3
- import { a as RSErrorInfo, r as RSErrorCode } from "./error-CxIs0A7Y.js";
3
+ import { a as RSErrorInfo, r as RSErrorCode } from "./error-DYLkv4B3.js";
4
4
 
5
5
  //#region src/rslang/ast-annotations.d.ts
6
6
  /** Appends {@link ExpressionType} onto the node's `annotation.rsType`. */
@@ -13,4 +13,4 @@ declare function annotateError(node: AstNode, code: RSErrorCode, params?: readon
13
13
  declare function readErrorAnnotation(node: AstNode): RSErrorInfo | null;
14
14
  //#endregion
15
15
  export { readTypeAnnotation as i, annotateType as n, readErrorAnnotation as r, annotateError as t };
16
- //# sourceMappingURL=ast-annotations-C0eMySxt.d.ts.map
16
+ //# sourceMappingURL=ast-annotations-BnVekMjH.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { t as AstNode } from "./ast-C8sIpKdL.js";
2
2
  import { f as ExpressionType } from "./typification-Dk-fisgO.js";
3
- import { i as RSErrorDescription } from "./error-CxIs0A7Y.js";
3
+ import { i as RSErrorDescription } from "./error-DYLkv4B3.js";
4
4
  import { l as Value } from "./value-BduA_ZGp.js";
5
5
 
6
6
  //#region src/rslang/eval/calculator.d.ts
@@ -36,4 +36,4 @@ declare class RSCalculator {
36
36
  }
37
37
  //#endregion
38
38
  export { CalculatorResult as n, RSCalculator as r, CalculatorEvaluateOptions as t };
39
- //# sourceMappingURL=calculator-BQnE2gws.d.ts.map
39
+ //# sourceMappingURL=calculator-OV-RNXre.d.ts.map
@@ -29,6 +29,9 @@ declare const RSErrorCode: {
29
29
  readonly missingOpenBracket: 33803;
30
30
  readonly missingCloseBracket: 33804;
31
31
  readonly invalidFilterSyntax: 33815;
32
+ readonly expectedFunctionBody: 33816;
33
+ readonly expectedExpressionBody: 33817;
34
+ readonly expectedLogicBody: 33818;
32
35
  readonly expectedLocal: 33813;
33
36
  readonly expectedType: 33814;
34
37
  readonly localDoubleDeclare: 10241;
@@ -67,6 +70,8 @@ declare const RSErrorCode: {
67
70
  readonly invalidFilterParameterType: 34859;
68
71
  readonly invalidFilterIndex: 34860;
69
72
  readonly invalidFilterBooleanEchelon: 34861;
73
+ readonly localOutOfScopeParentheses: 34862;
74
+ readonly localUndeclaredInSubexpr: 34863;
70
75
  readonly globalNoValue: 34880;
71
76
  readonly invalidPropertyUsage: 34881;
72
77
  readonly calcUnknownError: 33024;
@@ -88,4 +93,4 @@ declare function getRSErrorPrefix(code: RSErrorCode): string;
88
93
  declare function isCritical(code: RSErrorCode): boolean;
89
94
  //#endregion
90
95
  export { RSErrorInfo as a, RSErrorDescription as i, RSErrorClass as n, getRSErrorPrefix as o, RSErrorCode as r, isCritical as s, ErrorReporter as t };
91
- //# sourceMappingURL=error-CxIs0A7Y.d.ts.map
96
+ //# sourceMappingURL=error-DYLkv4B3.d.ts.map
package/dist/index.d.ts CHANGED
@@ -9,15 +9,15 @@ import { a as TOKEN_ERROR, c as flattenAst, d as printAst, f as visitAstDFS, i a
9
9
  import { t as Branded } from "./branded-ZlzIcxzu.js";
10
10
  import { n as generateStub, t as applyHash_fnv1a } from "./hash-Y8I4c6Al.js";
11
11
  import { O as makeTypePath, b as Typification, d as EmptySetT, f as ExpressionType, g as TypeClass, m as LogicT, t as AnyTypificationT, v as TypeID, y as TypePath } from "./typification-Dk-fisgO.js";
12
- import { i as RSErrorDescription, r as RSErrorCode } from "./error-CxIs0A7Y.js";
13
- import { i as readTypeAnnotation, r as readErrorAnnotation } from "./ast-annotations-C0eMySxt.js";
12
+ import { i as RSErrorDescription, r as RSErrorCode } from "./error-DYLkv4B3.js";
13
+ import { i as readTypeAnnotation, r as readErrorAnnotation } from "./ast-annotations-BnVekMjH.js";
14
14
  import { d as ValuePath, l as Value, o as TUPLE_ID, p as makeValuePath } from "./value-BduA_ZGp.js";
15
- import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "./calculator-BQnE2gws.js";
15
+ import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "./calculator-OV-RNXre.js";
16
16
  import { d as printValue } from "./value-api-B6T6f4Ia.js";
17
17
  import { t as parser } from "./parser-Bwd8LxJ1.js";
18
18
  import { t as TokenID } from "./token-DeXAmzwr.js";
19
19
  import { t as ValueClass } from "./value-class-CNI-lqXJ.js";
20
- import { a as RSLangAnalyzer, n as AnalysisFast, r as AnalysisFull, t as AnalysisBase } from "./analyzer-54lGGg13.js";
20
+ import { a as RSLangAnalyzer, n as AnalysisFast, r as AnalysisFull, t as AnalysisBase } from "./analyzer-0kmNRqcr.js";
21
21
  import { n as ArgumentsType } from "./arguments-extractor-1acwjQNc.js";
22
22
  import { n as applyAsciiTypeSubstitutions, r as parseTypeText } from "./typification-parser-BBVx1RxP.js";
23
23
  import { n as TypificationNodeData, t as TypificationGraph } from "./typification-graph-6HcZ-rKH.js";
@@ -1,6 +1,6 @@
1
1
  import { t as AstNode } from "../ast-C8sIpKdL.js";
2
2
  import { l as Value } from "../value-BduA_ZGp.js";
3
- import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "../calculator-BQnE2gws.js";
3
+ import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "../calculator-OV-RNXre.js";
4
4
  import { CstType, RSForm } from "./rsform.js";
5
5
  import { BasicBinding, BasicsContext, EvalStatus, RSModel } from "./rsmodel.js";
6
6
 
@@ -1,7 +1,7 @@
1
1
  import { r as LibraryItem } from "../library-CYun28Xz.js";
2
2
  import { g as TypeClass, y as TypePath } from "../typification-Dk-fisgO.js";
3
3
  import { t as ValueClass } from "../value-class-CNI-lqXJ.js";
4
- import { r as AnalysisFull } from "../analyzer-54lGGg13.js";
4
+ import { r as AnalysisFull } from "../analyzer-0kmNRqcr.js";
5
5
  import { ArgumentValue, Constituenta, CstClass, CstStatus, CstType, RSForm, RSFormStats } from "./rsform.js";
6
6
 
7
7
  //#region src/library/rsform-api.d.ts
@@ -1,7 +1,7 @@
1
1
  import { t as Graph } from "../graph-DR8rL2o3.js";
2
2
  import { i as LibraryItemReference, n as CurrentVersion, r as LibraryItem, s as VersionInfo } from "../library-CYun28Xz.js";
3
3
  import { f as ExpressionType, y as TypePath } from "../typification-Dk-fisgO.js";
4
- import { a as RSLangAnalyzer, t as AnalysisBase } from "../analyzer-54lGGg13.js";
4
+ import { a as RSLangAnalyzer, t as AnalysisBase } from "../analyzer-0kmNRqcr.js";
5
5
  //#region src/library/rsform.d.ts
6
6
  /** Represents {@link Constituenta} type. */
7
7
  declare const CstType: {
@@ -1,2 +1,2 @@
1
- import { i as readTypeAnnotation, n as annotateType, r as readErrorAnnotation, t as annotateError } from "../ast-annotations-C0eMySxt.js";
1
+ import { i as readTypeAnnotation, n as annotateType, r as readErrorAnnotation, t as annotateError } from "../ast-annotations-BnVekMjH.js";
2
2
  export { annotateError, annotateType, readErrorAnnotation, readTypeAnnotation };
@@ -1,2 +1,2 @@
1
- import { a as RSErrorInfo, i as RSErrorDescription, n as RSErrorClass, o as getRSErrorPrefix, r as RSErrorCode, s as isCritical, t as ErrorReporter } from "../error-CxIs0A7Y.js";
1
+ import { a as RSErrorInfo, i as RSErrorDescription, n as RSErrorClass, o as getRSErrorPrefix, r as RSErrorCode, s as isCritical, t as ErrorReporter } from "../error-DYLkv4B3.js";
2
2
  export { ErrorReporter, RSErrorClass, RSErrorCode, RSErrorDescription, RSErrorInfo, getRSErrorPrefix, isCritical };
@@ -16,6 +16,9 @@ const RSErrorCode = {
16
16
  missingOpenBracket: 33803,
17
17
  missingCloseBracket: 33804,
18
18
  invalidFilterSyntax: 33815,
19
+ expectedFunctionBody: 33816,
20
+ expectedExpressionBody: 33817,
21
+ expectedLogicBody: 33818,
19
22
  expectedLocal: 33813,
20
23
  expectedType: 33814,
21
24
  localDoubleDeclare: 10241,
@@ -54,6 +57,8 @@ const RSErrorCode = {
54
57
  invalidFilterParameterType: 34859,
55
58
  invalidFilterIndex: 34860,
56
59
  invalidFilterBooleanEchelon: 34861,
60
+ localOutOfScopeParentheses: 34862,
61
+ localUndeclaredInSubexpr: 34863,
57
62
  globalNoValue: 34880,
58
63
  invalidPropertyUsage: 34881,
59
64
  calcUnknownError: 33024,
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","names":[],"sources":["../../src/rslang/error.ts"],"sourcesContent":["/** Module: Error types and functions. */\n\n/** Represents error class. */\nexport const RSErrorClass = {\n LEXER: 0,\n PARSER: 1,\n SEMANTIC: 2,\n EVALUATION: 3,\n UNKNOWN: 4\n} as const;\nexport type RSErrorClass = (typeof RSErrorClass)[keyof typeof RSErrorClass];\n\n/** Represents RSLang expression error information. */\nexport interface RSErrorInfo {\n code: RSErrorCode;\n params?: readonly string[];\n}\n\n/** Represents RSLang expression error description. */\nexport interface RSErrorDescription extends RSErrorInfo {\n from: number;\n to: number;\n}\n\n/** Error reporter function type. */\nexport type ErrorReporter = (error: RSErrorDescription) => void;\n\n/** Represents RSLang expression error types. */\nexport const RSErrorCode = {\n unknownSyntax: 0x8400, // 33792\n bracketMismatch: 0x8409, // 33801\n doubleParenthesis: 0x840a, // 33802\n missingOpenBracket: 0x840b, // 33803\n missingCloseBracket: 0x840c, // 33804\n invalidFilterSyntax: 0x8417, // 33815\n expectedLocal: 0x8415, // 33813\n expectedType: 0x8416, // 33814\n\n localDoubleDeclare: 0x2801, // 10241\n localNotUsed: 0x2802, // 10242\n\n localUndeclared: 0x8801, // 34817\n localShadowing: 0x8802, // 34818\n\n typesNotEqual: 0x8803, // 34819\n globalNotTyped: 0x8804, // 34820\n invalidDecart: 0x8805, // 34821\n invalidBoolean: 0x8806, // 34822\n invalidTypeOperation: 0x8807, // 34823\n invalidCard: 0x8808, // 34824\n invalidDebool: 0x8809, // 34825\n globalFuncWithoutArgs: 0x880b, // 34827\n invalidReduce: 0x8810, // 34832\n invalidProjectionTuple: 0x8811, // 34833\n invalidProjectionSet: 0x8812, // 34834\n invalidEnumeration: 0x8813, // 34835\n invalidCortegeDeclare: 0x8814, // 34836\n localOutOfScope: 0x8815, // 34837\n invalidElementPredicate: 0x8816, // 34838\n invalidEmptySetUsage: 0x8817, // 34839\n invalidArgsArity: 0x8818, // 34840\n invalidArgumentType: 0x8819, // 34841\n globalStructure: 0x881c, // 34844\n radicalUsage: 0x8821, // 34849\n invalidFilterArgumentType: 0x8822, // 34850\n invalidFilterArity: 0x8823, // 34851\n arithmeticNotSupported: 0x8824, // 34852\n typesNotCompatible: 0x8825, // 34853\n orderingNotSupported: 0x8826, // 34854\n expectedLogic: 0x8827, // 34855\n expectedSetexpr: 0x8828, // 34856\n invalidArgumentCortegeDeclare: 0x8829, // 34857\n invalidQuantifierDomain: 0x882a, // 34858\n invalidFilterParameterType: 0x882b, // 34859\n invalidFilterIndex: 0x882c, // 34860\n invalidFilterBooleanEchelon: 0x882d, // 34861\n\n globalNoValue: 0x8840, // 34880\n invalidPropertyUsage: 0x8841, // 34881\n\n // Value evaluation (runtime)\n calcUnknownError: 0x8100, // 35328\n setOverflow: 0x8101, // 35329\n booleanBaseLimit: 0x8102, // 35330\n calcGlobalMissing: 0x8103, // 35331\n iterationsLimit: 0x8104, // 35332\n calcInvalidDebool: 0x8105, // 35333\n iterateInfinity: 0x8106, // 35334\n calculationNotSupported: 0x8107, // 35335\n calcInvalidData: 0x8108, // 35336\n\n cstEmptyDerived: 0x8861, // 34913\n definitionNotAllowed: 0x8862 // 34914\n} as const;\nexport type RSErrorCode = (typeof RSErrorCode)[keyof typeof RSErrorCode];\n\nconst ERROR_EVALUATION_MASK = 0x0100;\nconst ERROR_LEXER_MASK = 0x0200;\nconst ERROR_PARSER_MASK = 0x0400;\nconst ERROR_SEMANTIC_MASK = 0x0800;\n\n/** Infers error class from error type (code). */\nfunction inferErrorClass(error: RSErrorCode): RSErrorClass {\n if ((error & ERROR_EVALUATION_MASK) !== 0) {\n return RSErrorClass.EVALUATION;\n } else if ((error & ERROR_LEXER_MASK) !== 0) {\n return RSErrorClass.LEXER;\n } else if ((error & ERROR_PARSER_MASK) !== 0) {\n return RSErrorClass.PARSER;\n } else if ((error & ERROR_SEMANTIC_MASK) !== 0) {\n return RSErrorClass.SEMANTIC;\n } else {\n return RSErrorClass.UNKNOWN;\n }\n}\n\n/** Generate ErrorID label. */\nexport function getRSErrorPrefix(code: RSErrorCode): string {\n const id = code.toString(16).toUpperCase();\n // prettier-ignore\n switch (inferErrorClass(code)) {\n case RSErrorClass.LEXER: return 'L' + id;\n case RSErrorClass.PARSER: return 'P' + id;\n case RSErrorClass.SEMANTIC: return 'S' + id;\n case RSErrorClass.EVALUATION: return 'E' + id;\n case RSErrorClass.UNKNOWN: return 'U' + id;\n }\n}\n\n/** Checks if error is critical. */\nexport function isCritical(code: RSErrorCode): boolean {\n return code !== RSErrorCode.localDoubleDeclare && code !== RSErrorCode.localNotUsed;\n}\n"],"mappings":";;;AAGA,MAAa,eAAe;CAC1B,OAAO;CACP,QAAQ;CACR,UAAU;CACV,YAAY;CACZ,SAAS;AACX;;AAmBA,MAAa,cAAc;CACzB,eAAe;CACf,iBAAiB;CACjB,mBAAmB;CACnB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,eAAe;CACf,cAAc;CAEd,oBAAoB;CACpB,cAAc;CAEd,iBAAiB;CACjB,gBAAgB;CAEhB,eAAe;CACf,gBAAgB;CAChB,eAAe;CACf,gBAAgB;CAChB,sBAAsB;CACtB,aAAa;CACb,eAAe;CACf,uBAAuB;CACvB,eAAe;CACf,wBAAwB;CACxB,sBAAsB;CACtB,oBAAoB;CACpB,uBAAuB;CACvB,iBAAiB;CACjB,yBAAyB;CACzB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,iBAAiB;CACjB,cAAc;CACd,2BAA2B;CAC3B,oBAAoB;CACpB,wBAAwB;CACxB,oBAAoB;CACpB,sBAAsB;CACtB,eAAe;CACf,iBAAiB;CACjB,+BAA+B;CAC/B,yBAAyB;CACzB,4BAA4B;CAC5B,oBAAoB;CACpB,6BAA6B;CAE7B,eAAe;CACf,sBAAsB;CAGtB,kBAAkB;CAClB,aAAa;CACb,kBAAkB;CAClB,mBAAmB;CACnB,iBAAiB;CACjB,mBAAmB;CACnB,iBAAiB;CACjB,yBAAyB;CACzB,iBAAiB;CAEjB,iBAAiB;CACjB,sBAAsB;AACxB;AAGA,MAAM,wBAAwB;AAC9B,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;;AAG5B,SAAS,gBAAgB,OAAkC;CACzD,KAAK,QAAQ,2BAA2B,GACtC,OAAO,aAAa;MACf,KAAK,QAAQ,sBAAsB,GACxC,OAAO,aAAa;MACf,KAAK,QAAQ,uBAAuB,GACzC,OAAO,aAAa;MACf,KAAK,QAAQ,yBAAyB,GAC3C,OAAO,aAAa;MAEpB,OAAO,aAAa;AAExB;;AAGA,SAAgB,iBAAiB,MAA2B;CAC1D,MAAM,KAAK,KAAK,SAAS,EAAE,CAAC,CAAC,YAAY;CAEzC,QAAQ,gBAAgB,IAAI,GAA5B;EACE,KAAK,aAAa,OAAO,OAAO,MAAM;EACtC,KAAK,aAAa,QAAQ,OAAO,MAAM;EACvC,KAAK,aAAa,UAAU,OAAO,MAAM;EACzC,KAAK,aAAa,YAAY,OAAO,MAAM;EAC3C,KAAK,aAAa,SAAS,OAAO,MAAM;CAC1C;AACF;;AAGA,SAAgB,WAAW,MAA4B;CACrD,OAAO,SAAS,YAAY,sBAAsB,SAAS,YAAY;AACzE"}
1
+ {"version":3,"file":"error.js","names":[],"sources":["../../src/rslang/error.ts"],"sourcesContent":["/** Module: Error types and functions. */\n\n/** Represents error class. */\nexport const RSErrorClass = {\n LEXER: 0,\n PARSER: 1,\n SEMANTIC: 2,\n EVALUATION: 3,\n UNKNOWN: 4\n} as const;\nexport type RSErrorClass = (typeof RSErrorClass)[keyof typeof RSErrorClass];\n\n/** Represents RSLang expression error information. */\nexport interface RSErrorInfo {\n code: RSErrorCode;\n params?: readonly string[];\n}\n\n/** Represents RSLang expression error description. */\nexport interface RSErrorDescription extends RSErrorInfo {\n from: number;\n to: number;\n}\n\n/** Error reporter function type. */\nexport type ErrorReporter = (error: RSErrorDescription) => void;\n\n/** Represents RSLang expression error types. */\nexport const RSErrorCode = {\n unknownSyntax: 0x8400, // 33792\n bracketMismatch: 0x8409, // 33801\n doubleParenthesis: 0x840a, // 33802\n missingOpenBracket: 0x840b, // 33803\n missingCloseBracket: 0x840c, // 33804\n invalidFilterSyntax: 0x8417, // 33815\n expectedFunctionBody: 0x8418, // 33816\n expectedExpressionBody: 0x8419, // 33817\n expectedLogicBody: 0x841a, // 33818\n expectedLocal: 0x8415, // 33813\n expectedType: 0x8416, // 33814\n\n localDoubleDeclare: 0x2801, // 10241\n localNotUsed: 0x2802, // 10242\n\n localUndeclared: 0x8801, // 34817\n localShadowing: 0x8802, // 34818\n\n typesNotEqual: 0x8803, // 34819\n globalNotTyped: 0x8804, // 34820\n invalidDecart: 0x8805, // 34821\n invalidBoolean: 0x8806, // 34822\n invalidTypeOperation: 0x8807, // 34823\n invalidCard: 0x8808, // 34824\n invalidDebool: 0x8809, // 34825\n globalFuncWithoutArgs: 0x880b, // 34827\n invalidReduce: 0x8810, // 34832\n invalidProjectionTuple: 0x8811, // 34833\n invalidProjectionSet: 0x8812, // 34834\n invalidEnumeration: 0x8813, // 34835\n invalidCortegeDeclare: 0x8814, // 34836\n localOutOfScope: 0x8815, // 34837\n invalidElementPredicate: 0x8816, // 34838\n invalidEmptySetUsage: 0x8817, // 34839\n invalidArgsArity: 0x8818, // 34840\n invalidArgumentType: 0x8819, // 34841\n globalStructure: 0x881c, // 34844\n radicalUsage: 0x8821, // 34849\n invalidFilterArgumentType: 0x8822, // 34850\n invalidFilterArity: 0x8823, // 34851\n arithmeticNotSupported: 0x8824, // 34852\n typesNotCompatible: 0x8825, // 34853\n orderingNotSupported: 0x8826, // 34854\n expectedLogic: 0x8827, // 34855\n expectedSetexpr: 0x8828, // 34856\n invalidArgumentCortegeDeclare: 0x8829, // 34857\n invalidQuantifierDomain: 0x882a, // 34858\n invalidFilterParameterType: 0x882b, // 34859\n invalidFilterIndex: 0x882c, // 34860\n invalidFilterBooleanEchelon: 0x882d, // 34861\n localOutOfScopeParentheses: 0x882e, // 34862\n localUndeclaredInSubexpr: 0x882f, // 34863\n\n globalNoValue: 0x8840, // 34880\n invalidPropertyUsage: 0x8841, // 34881\n\n // Value evaluation (runtime)\n calcUnknownError: 0x8100, // 35328\n setOverflow: 0x8101, // 35329\n booleanBaseLimit: 0x8102, // 35330\n calcGlobalMissing: 0x8103, // 35331\n iterationsLimit: 0x8104, // 35332\n calcInvalidDebool: 0x8105, // 35333\n iterateInfinity: 0x8106, // 35334\n calculationNotSupported: 0x8107, // 35335\n calcInvalidData: 0x8108, // 35336\n\n cstEmptyDerived: 0x8861, // 34913\n definitionNotAllowed: 0x8862 // 34914\n} as const;\nexport type RSErrorCode = (typeof RSErrorCode)[keyof typeof RSErrorCode];\n\nconst ERROR_EVALUATION_MASK = 0x0100;\nconst ERROR_LEXER_MASK = 0x0200;\nconst ERROR_PARSER_MASK = 0x0400;\nconst ERROR_SEMANTIC_MASK = 0x0800;\n\n/** Infers error class from error type (code). */\nfunction inferErrorClass(error: RSErrorCode): RSErrorClass {\n if ((error & ERROR_EVALUATION_MASK) !== 0) {\n return RSErrorClass.EVALUATION;\n } else if ((error & ERROR_LEXER_MASK) !== 0) {\n return RSErrorClass.LEXER;\n } else if ((error & ERROR_PARSER_MASK) !== 0) {\n return RSErrorClass.PARSER;\n } else if ((error & ERROR_SEMANTIC_MASK) !== 0) {\n return RSErrorClass.SEMANTIC;\n } else {\n return RSErrorClass.UNKNOWN;\n }\n}\n\n/** Generate ErrorID label. */\nexport function getRSErrorPrefix(code: RSErrorCode): string {\n const id = code.toString(16).toUpperCase();\n // prettier-ignore\n switch (inferErrorClass(code)) {\n case RSErrorClass.LEXER: return 'L' + id;\n case RSErrorClass.PARSER: return 'P' + id;\n case RSErrorClass.SEMANTIC: return 'S' + id;\n case RSErrorClass.EVALUATION: return 'E' + id;\n case RSErrorClass.UNKNOWN: return 'U' + id;\n }\n}\n\n/** Checks if error is critical. */\nexport function isCritical(code: RSErrorCode): boolean {\n return code !== RSErrorCode.localDoubleDeclare && code !== RSErrorCode.localNotUsed;\n}\n"],"mappings":";;;AAGA,MAAa,eAAe;CAC1B,OAAO;CACP,QAAQ;CACR,UAAU;CACV,YAAY;CACZ,SAAS;AACX;;AAmBA,MAAa,cAAc;CACzB,eAAe;CACf,iBAAiB;CACjB,mBAAmB;CACnB,oBAAoB;CACpB,qBAAqB;CACrB,qBAAqB;CACrB,sBAAsB;CACtB,wBAAwB;CACxB,mBAAmB;CACnB,eAAe;CACf,cAAc;CAEd,oBAAoB;CACpB,cAAc;CAEd,iBAAiB;CACjB,gBAAgB;CAEhB,eAAe;CACf,gBAAgB;CAChB,eAAe;CACf,gBAAgB;CAChB,sBAAsB;CACtB,aAAa;CACb,eAAe;CACf,uBAAuB;CACvB,eAAe;CACf,wBAAwB;CACxB,sBAAsB;CACtB,oBAAoB;CACpB,uBAAuB;CACvB,iBAAiB;CACjB,yBAAyB;CACzB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,iBAAiB;CACjB,cAAc;CACd,2BAA2B;CAC3B,oBAAoB;CACpB,wBAAwB;CACxB,oBAAoB;CACpB,sBAAsB;CACtB,eAAe;CACf,iBAAiB;CACjB,+BAA+B;CAC/B,yBAAyB;CACzB,4BAA4B;CAC5B,oBAAoB;CACpB,6BAA6B;CAC7B,4BAA4B;CAC5B,0BAA0B;CAE1B,eAAe;CACf,sBAAsB;CAGtB,kBAAkB;CAClB,aAAa;CACb,kBAAkB;CAClB,mBAAmB;CACnB,iBAAiB;CACjB,mBAAmB;CACnB,iBAAiB;CACjB,yBAAyB;CACzB,iBAAiB;CAEjB,iBAAiB;CACjB,sBAAsB;AACxB;AAGA,MAAM,wBAAwB;AAC9B,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;;AAG5B,SAAS,gBAAgB,OAAkC;CACzD,KAAK,QAAQ,2BAA2B,GACtC,OAAO,aAAa;MACf,KAAK,QAAQ,sBAAsB,GACxC,OAAO,aAAa;MACf,KAAK,QAAQ,uBAAuB,GACzC,OAAO,aAAa;MACf,KAAK,QAAQ,yBAAyB,GAC3C,OAAO,aAAa;MAEpB,OAAO,aAAa;AAExB;;AAGA,SAAgB,iBAAiB,MAA2B;CAC1D,MAAM,KAAK,KAAK,SAAS,EAAE,CAAC,CAAC,YAAY;CAEzC,QAAQ,gBAAgB,IAAI,GAA5B;EACE,KAAK,aAAa,OAAO,OAAO,MAAM;EACtC,KAAK,aAAa,QAAQ,OAAO,MAAM;EACvC,KAAK,aAAa,UAAU,OAAO,MAAM;EACzC,KAAK,aAAa,YAAY,OAAO,MAAM;EAC3C,KAAK,aAAa,SAAS,OAAO,MAAM;CAC1C;AACF;;AAGA,SAAgB,WAAW,MAA4B;CACrD,OAAO,SAAS,YAAY,sBAAsB,SAAS,YAAY;AACzE"}
@@ -1,2 +1,2 @@
1
- import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "../../calculator-BQnE2gws.js";
1
+ import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "../../calculator-OV-RNXre.js";
2
2
  export { CalculatorEvaluateOptions, CalculatorResult, RSCalculator };
@@ -1,5 +1,5 @@
1
1
  import { t as AstNode } from "../../ast-C8sIpKdL.js";
2
- import { t as ErrorReporter } from "../../error-CxIs0A7Y.js";
2
+ import { t as ErrorReporter } from "../../error-DYLkv4B3.js";
3
3
  import { l as Value, u as ValueContext } from "../../value-BduA_ZGp.js";
4
4
 
5
5
  //#region src/rslang/eval/evaluator.d.ts
@@ -1,13 +1,13 @@
1
1
  import { O as makeTypePath, b as Typification, d as EmptySetT, f as ExpressionType, g as TypeClass, m as LogicT, t as AnyTypificationT, v as TypeID, y as TypePath } from "../typification-Dk-fisgO.js";
2
- import { i as RSErrorDescription, r as RSErrorCode } from "../error-CxIs0A7Y.js";
3
- import { i as readTypeAnnotation, r as readErrorAnnotation } from "../ast-annotations-C0eMySxt.js";
2
+ import { i as RSErrorDescription, r as RSErrorCode } from "../error-DYLkv4B3.js";
3
+ import { i as readTypeAnnotation, r as readErrorAnnotation } from "../ast-annotations-BnVekMjH.js";
4
4
  import { d as ValuePath, l as Value, p as makeValuePath } from "../value-BduA_ZGp.js";
5
- import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "../calculator-BQnE2gws.js";
5
+ import { n as CalculatorResult, r as RSCalculator, t as CalculatorEvaluateOptions } from "../calculator-OV-RNXre.js";
6
6
  import { d as printValue } from "../value-api-B6T6f4Ia.js";
7
7
  import { t as parser } from "../parser-Bwd8LxJ1.js";
8
8
  import { t as TokenID } from "../token-DeXAmzwr.js";
9
9
  import { t as ValueClass } from "../value-class-CNI-lqXJ.js";
10
- import { a as RSLangAnalyzer, n as AnalysisFast, r as AnalysisFull, t as AnalysisBase } from "../analyzer-54lGGg13.js";
10
+ import { a as RSLangAnalyzer, n as AnalysisFast, r as AnalysisFull, t as AnalysisBase } from "../analyzer-0kmNRqcr.js";
11
11
  import { n as ArgumentsType } from "../arguments-extractor-1acwjQNc.js";
12
12
  import { n as applyAsciiTypeSubstitutions, r as parseTypeText } from "../typification-parser-BBVx1RxP.js";
13
13
  import { n as TypificationNodeData, t as TypificationGraph } from "../typification-graph-6HcZ-rKH.js";
@@ -1,8 +1,14 @@
1
1
  import { t as AstNode } from "../../ast-C8sIpKdL.js";
2
- import { t as ErrorReporter } from "../../error-CxIs0A7Y.js";
2
+ import { g as TypeClass } from "../../typification-Dk-fisgO.js";
3
+ import { t as ErrorReporter } from "../../error-DYLkv4B3.js";
3
4
 
4
5
  //#region src/rslang/parser/syntax-errors.d.ts
5
- declare function extractSyntaxErrors(ast: AstNode, expression: string, reporter: ErrorReporter, annotateErrors?: boolean): void;
6
+ /** Options for syntax error extraction. */
7
+ interface SyntaxErrorOptions {
8
+ expected?: TypeClass;
9
+ }
10
+ /** Extracts syntax errors from an AST. */
11
+ declare function extractSyntaxErrors(ast: AstNode, expression: string, reporter: ErrorReporter, annotateErrors?: boolean, options?: SyntaxErrorOptions): void;
6
12
  //#endregion
7
- export { extractSyntaxErrors };
13
+ export { SyntaxErrorOptions, extractSyntaxErrors };
8
14
  //# sourceMappingURL=syntax-errors.d.ts.map
@@ -3,40 +3,45 @@ import { RSErrorCode } from "../error.js";
3
3
  import { visitAstDFS } from "../../parsing/ast.js";
4
4
  import "../../parsing/index.js";
5
5
  import { TokenID } from "./token.js";
6
+ import { TypeClass } from "../semantic/typification.js";
6
7
  import "./parser.terms.js";
7
8
  //#region src/rslang/parser/syntax-errors.ts
8
9
  /**
9
10
  * Module: Syntactic errors reporting.
10
11
  */
11
- function extractSyntaxErrors(ast, expression, reporter, annotateErrors = false) {
12
+ /** Extracts syntax errors from an AST. */
13
+ function extractSyntaxErrors(ast, expression, reporter, annotateErrors = false, options) {
12
14
  const collected = [];
13
- const collect = (error) => {
15
+ const annotationTargets = /* @__PURE__ */ new Map();
16
+ const collect = (error, target) => {
14
17
  collected.push(error);
18
+ if (target !== void 0) annotationTargets.set(error, target);
15
19
  };
16
20
  const bracketError = extractBracketErrors(expression);
17
- if (bracketError !== null) {
18
- collect(bracketError);
19
- if (annotateErrors) annotateError(ast, bracketError.code, bracketError.params);
20
- }
21
+ if (bracketError !== null) collect(bracketError, ast);
21
22
  const hasBracketErrors = bracketError !== null;
22
- visitAstDFS(ast, (node) => extractInternal(node, expression, collect, annotateErrors, hasBracketErrors));
23
- for (const error of deduplicateErrors(collected)) reporter(error);
23
+ visitAstDFS(ast, (node) => extractInternal(node, expression, collect, hasBracketErrors, options));
24
+ for (const error of deduplicateErrors(collected)) {
25
+ reporter(error);
26
+ if (annotateErrors) {
27
+ const target = annotationTargets.get(error);
28
+ if (target !== void 0) annotateError(target, error.code, error.params);
29
+ }
30
+ }
24
31
  }
25
- function extractInternal(node, expression, reporter, annotateErrors, ignoreUnknownErrors) {
32
+ function extractInternal(node, expression, collect, ignoreUnknownErrors, options) {
26
33
  if (node.typeID !== TokenID.ERROR) return;
27
34
  function emit(target, code, params) {
28
- reporter({
35
+ collect({
29
36
  code,
30
37
  from: target.from,
31
38
  to: target.to,
32
39
  params
33
- });
34
- if (annotateErrors) annotateError(target, code, params);
40
+ }, target);
35
41
  }
36
- const classified = classifyParseError(node, expression);
42
+ const classified = classifyParseError(node, expression, options);
37
43
  if (classified !== null) {
38
- reporter(classified);
39
- if (annotateErrors) annotateError(node, classified.code, classified.params);
44
+ collect(classified, node);
40
45
  return;
41
46
  }
42
47
  const parent = node.parent;
@@ -47,11 +52,39 @@ function extractInternal(node, expression, reporter, annotateErrors, ignoreUnkno
47
52
  if (parent.typeID === 4) return emit(parent, RSErrorCode.expectedLocal);
48
53
  if (!ignoreUnknownErrors) emit(node.from === node.to ? parent : node, RSErrorCode.unknownSyntax);
49
54
  }
50
- function classifyParseError(node, expression) {
55
+ function classifyParseError(node, expression, options) {
56
+ const incompleteFunctionDecl = detectIncompleteFunctionDecl(node, expression, options?.expected);
57
+ if (incompleteFunctionDecl !== null) return incompleteFunctionDecl;
51
58
  const filterParen = detectFilterParenMismatch(node, expression);
52
59
  if (filterParen !== null) return filterParen;
53
60
  return detectGlobalFuncWithoutArgs(node, expression);
54
61
  }
62
+ function detectIncompleteFunctionDecl(node, expression, expected) {
63
+ const funcDecl = findAncestor(node, isFunctionDeclNode);
64
+ if (funcDecl === null) return null;
65
+ const bodyChild = funcDecl.children[funcDecl.children.length - 1];
66
+ if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) return null;
67
+ const argsNode = funcDecl.children.find((child) => child.typeID === 77 || child.typeID === TokenID.NT_ARGUMENTS);
68
+ if (argsNode === void 0 || subtreeHasError(argsNode)) return null;
69
+ if (expression.slice(funcDecl.to).trim().length > 0) return null;
70
+ return {
71
+ code: incompleteFormalExpressionCode(expected),
72
+ from: bodyChild.from,
73
+ to: bodyChild.to
74
+ };
75
+ }
76
+ function incompleteFormalExpressionCode(expected) {
77
+ switch (expected) {
78
+ case TypeClass.function: return RSErrorCode.expectedExpressionBody;
79
+ case TypeClass.predicate:
80
+ case TypeClass.logic: return RSErrorCode.expectedLogicBody;
81
+ default: return RSErrorCode.expectedFunctionBody;
82
+ }
83
+ }
84
+ function subtreeHasError(node) {
85
+ if (node.typeID === TokenID.ERROR) return true;
86
+ return node.children.some(subtreeHasError);
87
+ }
55
88
  function detectFilterParenMismatch(node, expression) {
56
89
  const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);
57
90
  if (filterNode === null) return null;
@@ -78,29 +111,18 @@ function findRelatedNode(node, predicate) {
78
111
  function classifyFuncWithoutArgs(funcNode, expression) {
79
112
  const name = expression.slice(funcNode.from, funcNode.to);
80
113
  const rest = expression.slice(funcNode.to);
81
- if (!/^\s*\[/.test(rest)) return {
82
- code: RSErrorCode.globalFuncWithoutArgs,
83
- from: funcNode.from,
84
- to: funcNode.to,
85
- params: [name]
86
- };
87
- if (/^\s*\[\s*\]/.test(rest)) return {
114
+ const withoutArgs = {
88
115
  code: RSErrorCode.globalFuncWithoutArgs,
89
116
  from: funcNode.from,
90
117
  to: funcNode.to,
91
118
  params: [name]
92
119
  };
120
+ if (/^\s*$/.test(rest)) return withoutArgs;
93
121
  const openBracket = /^\s*\[/.exec(rest);
94
- if (openBracket !== null) {
95
- const closeIdx = findMatchingCloseBracket(rest, openBracket[0].length - 1);
96
- if (closeIdx >= 0) {
97
- if (rest.slice(openBracket[0].length, closeIdx).trim().length === 0) return {
98
- code: RSErrorCode.globalFuncWithoutArgs,
99
- from: funcNode.from,
100
- to: funcNode.to,
101
- params: [name]
102
- };
103
- }
122
+ if (openBracket === null) return null;
123
+ const closeIdx = findMatchingCloseBracket(rest, openBracket[0].length - 1);
124
+ if (closeIdx >= 0) {
125
+ if (rest.slice(openBracket[0].length, closeIdx).trim().length === 0) return withoutArgs;
104
126
  }
105
127
  return null;
106
128
  }
@@ -112,6 +134,9 @@ function findAncestor(node, predicate) {
112
134
  }
113
135
  return null;
114
136
  }
137
+ function isFunctionDeclNode(node) {
138
+ return node.typeID === 76 || node.typeID === TokenID.NT_FUNC_DEFINITION;
139
+ }
115
140
  function isFunctionNode(node) {
116
141
  return node.typeID === 69 || node.typeID === TokenID.ID_FUNCTION;
117
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"syntax-errors.js","names":[],"sources":["../../../src/rslang/parser/syntax-errors.ts"],"sourcesContent":["/**\n * Module: Syntactic errors reporting.\n */\n\nimport { type AstNode, visitAstDFS } from '../../parsing';\nimport { annotateError } from '../ast-annotations';\nimport { type ErrorReporter, RSErrorCode, type RSErrorDescription } from '../error';\n\nimport { Filter, Function, Predicate, Variable } from './parser.terms';\nimport { TokenID } from './token';\n\nexport function extractSyntaxErrors(\n ast: AstNode,\n expression: string,\n reporter: ErrorReporter,\n annotateErrors: boolean = false\n) {\n const collected: RSErrorDescription[] = [];\n const collect = (error: RSErrorDescription) => {\n collected.push(error);\n };\n\n const bracketError = extractBracketErrors(expression);\n if (bracketError !== null) {\n collect(bracketError);\n if (annotateErrors) {\n annotateError(ast, bracketError.code, bracketError.params);\n }\n }\n const hasBracketErrors = bracketError !== null;\n visitAstDFS(ast, node => extractInternal(node, expression, collect, annotateErrors, hasBracketErrors));\n\n for (const error of deduplicateErrors(collected)) {\n reporter(error);\n }\n}\n\n// ====== Internals =========\nfunction extractInternal(\n node: AstNode,\n expression: string,\n reporter: ErrorReporter,\n annotateErrors: boolean,\n ignoreUnknownErrors: boolean\n) {\n if (node.typeID !== TokenID.ERROR) {\n return;\n }\n\n function emit(target: AstNode, code: RSErrorCode, params?: readonly string[]) {\n reporter({ code: code, from: target.from, to: target.to, params });\n if (annotateErrors) {\n annotateError(target, code, params);\n }\n }\n\n const classified = classifyParseError(node, expression);\n if (classified !== null) {\n reporter(classified);\n if (annotateErrors) {\n annotateError(node, classified.code, classified.params);\n }\n return;\n }\n\n const parent = node.parent;\n if (parent === null) {\n if (!ignoreUnknownErrors) {\n return emit(node, RSErrorCode.unknownSyntax);\n }\n return;\n }\n\n if (parent.typeID === Variable) {\n return emit(parent, RSErrorCode.expectedLocal);\n }\n\n if (!ignoreUnknownErrors) {\n emit(node.from === node.to ? parent : node, RSErrorCode.unknownSyntax);\n }\n}\n\nfunction classifyParseError(node: AstNode, expression: string): RSErrorDescription | null {\n const filterParen = detectFilterParenMismatch(node, expression);\n if (filterParen !== null) {\n return filterParen;\n }\n\n return detectGlobalFuncWithoutArgs(node, expression);\n}\n\nfunction detectFilterParenMismatch(node: AstNode, expression: string): RSErrorDescription | null {\n const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);\n if (filterNode === null) {\n return null;\n }\n\n const nextChar = expression[filterNode.to];\n if (nextChar === '(') {\n return {\n code: RSErrorCode.invalidFilterSyntax,\n from: filterNode.from,\n to: filterNode.to + 1\n };\n }\n return null;\n}\n\nfunction detectGlobalFuncWithoutArgs(node: AstNode, expression: string): RSErrorDescription | null {\n const funcNode =\n findAncestor(node, n => isFunctionNode(n) || isPredicateNode(n)) ??\n findRelatedNode(node, n => isFunctionNode(n) || isPredicateNode(n));\n if (funcNode === null) {\n return null;\n }\n return classifyFuncWithoutArgs(funcNode, expression);\n}\n\nfunction findRelatedNode(node: AstNode, predicate: (target: AstNode) => boolean): AstNode | null {\n let current: AstNode | null = node.parent;\n while (current !== null) {\n for (const child of current.children) {\n if (predicate(child)) {\n return child;\n }\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction classifyFuncWithoutArgs(funcNode: AstNode, expression: string): RSErrorDescription | null {\n const name = expression.slice(funcNode.from, funcNode.to);\n const rest = expression.slice(funcNode.to);\n\n if (!/^\\s*\\[/.test(rest)) {\n return {\n code: RSErrorCode.globalFuncWithoutArgs,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n }\n\n if (/^\\s*\\[\\s*\\]/.test(rest)) {\n return {\n code: RSErrorCode.globalFuncWithoutArgs,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n }\n\n const openBracket = /^\\s*\\[/.exec(rest);\n if (openBracket !== null) {\n const closeIdx = findMatchingCloseBracket(rest, openBracket[0].length - 1);\n if (closeIdx >= 0) {\n const inner = rest.slice(openBracket[0].length, closeIdx).trim();\n if (inner.length === 0) {\n return {\n code: RSErrorCode.globalFuncWithoutArgs,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n }\n }\n }\n\n return null;\n}\n\nfunction findAncestor(node: AstNode, predicate: (node: AstNode) => boolean): AstNode | null {\n let current: AstNode | null = node;\n while (current !== null) {\n if (predicate(current)) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction isFunctionNode(node: AstNode): boolean {\n return node.typeID === Function || node.typeID === TokenID.ID_FUNCTION;\n}\n\nfunction isPredicateNode(node: AstNode): boolean {\n return node.typeID === Predicate || node.typeID === TokenID.ID_PREDICATE;\n}\n\nfunction isFilterNode(node: AstNode): boolean {\n return node.typeID === Filter || node.typeID === TokenID.FILTER;\n}\n\nfunction findMatchingCloseBracket(expression: string, openPos: number): number {\n const open = expression[openPos];\n if (open !== '[') {\n return -1;\n }\n\n let depth = 0;\n for (let index = openPos; index < expression.length; index++) {\n const symbol = expression[index];\n if (symbol === '[') {\n depth++;\n } else if (symbol === ']') {\n depth--;\n if (depth === 0) {\n return index;\n }\n }\n }\n return -1;\n}\n\nfunction deduplicateErrors(errors: RSErrorDescription[]): RSErrorDescription[] {\n const result: RSErrorDescription[] = [];\n\n for (const error of errors) {\n const duplicate = result.some(\n existing => existing.code === error.code && existing.from === error.from && existing.to === error.to\n );\n if (duplicate) {\n continue;\n }\n\n if (error.code !== RSErrorCode.unknownSyntax) {\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index].code === RSErrorCode.unknownSyntax && rangesOverlap(error, result[index])) {\n result.splice(index, 1);\n }\n }\n }\n\n result.push(error);\n }\n\n const specific = result.filter(error => error.code !== RSErrorCode.unknownSyntax);\n return result.filter(\n error => error.code !== RSErrorCode.unknownSyntax || !specific.some(item => rangesOverlap(error, item))\n );\n}\n\nfunction rangesOverlap(a: RSErrorDescription, b: RSErrorDescription): boolean {\n return a.from < b.to && b.from < a.to;\n}\n\ntype OpenBracket = '(' | '[' | '{';\ntype CloseBracket = ')' | ']' | '}';\n\ninterface BracketFrame {\n bracket: OpenBracket;\n index: number;\n}\n\nfunction extractBracketErrors(expression: string): RSErrorDescription | null {\n const stack: BracketFrame[] = [];\n\n for (let pos = 0; pos < expression.length; pos++) {\n const symbol = expression[pos];\n if (isOpenBracket(symbol)) {\n if (isDoubleParenthesis(expression, pos)) {\n return {\n code: RSErrorCode.doubleParenthesis,\n from: pos,\n to: pos + 2\n };\n }\n stack.push({ bracket: symbol, index: pos });\n continue;\n }\n if (!isCloseBracket(symbol)) {\n continue;\n }\n\n const expectedOpen = closeToOpen(symbol);\n const top = stack[stack.length - 1];\n if (top === undefined) {\n return {\n code: RSErrorCode.missingOpenBracket,\n from: pos,\n to: pos + 1,\n params: [symbol]\n };\n }\n\n if (top.bracket !== expectedOpen) {\n return {\n code: RSErrorCode.bracketMismatch,\n from: pos,\n to: pos + 1,\n params: [openToClose(top.bracket), symbol]\n };\n }\n\n stack.pop();\n }\n\n if (stack.length > 0) {\n const unclosed = stack[0];\n return {\n code: RSErrorCode.missingCloseBracket,\n from: unclosed.index,\n to: unclosed.index + 1,\n params: [unclosed.bracket]\n };\n }\n\n return null;\n}\n\nfunction isOpenBracket(symbol: string): symbol is OpenBracket {\n return symbol === '(' || symbol === '[' || symbol === '{';\n}\n\nfunction isCloseBracket(symbol: string): symbol is CloseBracket {\n return symbol === ')' || symbol === ']' || symbol === '}';\n}\n\nfunction openToClose(symbol: OpenBracket): CloseBracket {\n switch (symbol) {\n case '(':\n return ')';\n case '[':\n return ']';\n case '{':\n return '}';\n }\n}\n\nfunction closeToOpen(symbol: CloseBracket): OpenBracket {\n switch (symbol) {\n case ')':\n return '(';\n case ']':\n return '[';\n case '}':\n return '{';\n }\n}\n\nfunction isDoubleParenthesis(expression: string, pos: number): boolean {\n const isOpenDoubleParenthesis = expression[pos] === '(' && expression[pos + 1] === '(';\n if (!isOpenDoubleParenthesis) {\n return false;\n }\n\n const outerClose = findMatchingCloseParen(expression, pos);\n const innerClose = findMatchingCloseParen(expression, pos + 1);\n if (outerClose < 0 || innerClose < 0) {\n return false;\n }\n\n return outerClose === innerClose + 1;\n}\n\nfunction findMatchingCloseParen(expression: string, openPos: number): number {\n if (expression[openPos] !== '(') {\n return -1;\n }\n\n const stack: OpenBracket[] = [];\n for (let index = openPos; index < expression.length; index++) {\n const symbol = expression[index];\n if (isOpenBracket(symbol)) {\n stack.push(symbol);\n continue;\n }\n if (!isCloseBracket(symbol)) {\n continue;\n }\n const top = stack.pop();\n if (top === undefined || top !== closeToOpen(symbol)) {\n return -1;\n }\n if (stack.length === 0) {\n return index;\n }\n }\n\n return -1;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"syntax-errors.js","names":["TypeClassEnum"],"sources":["../../../src/rslang/parser/syntax-errors.ts"],"sourcesContent":["/**\n * Module: Syntactic errors reporting.\n */\n\nimport { type AstNode, visitAstDFS } from '../../parsing';\nimport { annotateError } from '../ast-annotations';\nimport { type ErrorReporter, RSErrorCode, type RSErrorDescription } from '../error';\nimport { type TypeClass, TypeClass as TypeClassEnum } from '../semantic/typification';\n\nimport { Arguments, Filter, Function, Function_decl, Predicate, Variable } from './parser.terms';\nimport { TokenID } from './token';\n\n/** Options for syntax error extraction. */\nexport interface SyntaxErrorOptions {\n expected?: TypeClass;\n}\n\n/** Extracts syntax errors from an AST. */\nexport function extractSyntaxErrors(\n ast: AstNode,\n expression: string,\n reporter: ErrorReporter,\n annotateErrors: boolean = false,\n options?: SyntaxErrorOptions\n) {\n const collected: RSErrorDescription[] = [];\n const annotationTargets = new Map<RSErrorDescription, AstNode>();\n const collect = (error: RSErrorDescription, target?: AstNode) => {\n collected.push(error);\n if (target !== undefined) {\n annotationTargets.set(error, target);\n }\n };\n\n const bracketError = extractBracketErrors(expression);\n if (bracketError !== null) {\n collect(bracketError, ast);\n }\n const hasBracketErrors = bracketError !== null;\n visitAstDFS(ast, node => extractInternal(node, expression, collect, hasBracketErrors, options));\n\n for (const error of deduplicateErrors(collected)) {\n reporter(error);\n if (annotateErrors) {\n const target = annotationTargets.get(error);\n if (target !== undefined) {\n annotateError(target, error.code, error.params);\n }\n }\n }\n}\n\n// ====== Internals =========\nfunction extractInternal(\n node: AstNode,\n expression: string,\n collect: (error: RSErrorDescription, target: AstNode) => void,\n ignoreUnknownErrors: boolean,\n options?: SyntaxErrorOptions\n) {\n if (node.typeID !== TokenID.ERROR) {\n return;\n }\n\n function emit(target: AstNode, code: RSErrorCode, params?: readonly string[]) {\n collect({ code: code, from: target.from, to: target.to, params }, target);\n }\n\n const classified = classifyParseError(node, expression, options);\n if (classified !== null) {\n collect(classified, node);\n return;\n }\n\n const parent = node.parent;\n if (parent === null) {\n if (!ignoreUnknownErrors) {\n return emit(node, RSErrorCode.unknownSyntax);\n }\n return;\n }\n\n if (parent.typeID === Variable) {\n return emit(parent, RSErrorCode.expectedLocal);\n }\n\n if (!ignoreUnknownErrors) {\n emit(node.from === node.to ? parent : node, RSErrorCode.unknownSyntax);\n }\n}\n\nfunction classifyParseError(\n node: AstNode,\n expression: string,\n options?: SyntaxErrorOptions\n): RSErrorDescription | null {\n const incompleteFunctionDecl = detectIncompleteFunctionDecl(node, expression, options?.expected);\n if (incompleteFunctionDecl !== null) {\n return incompleteFunctionDecl;\n }\n\n const filterParen = detectFilterParenMismatch(node, expression);\n if (filterParen !== null) {\n return filterParen;\n }\n\n return detectGlobalFuncWithoutArgs(node, expression);\n}\n\nfunction detectIncompleteFunctionDecl(\n node: AstNode,\n expression: string,\n expected?: TypeClass\n): RSErrorDescription | null {\n const funcDecl = findAncestor(node, isFunctionDeclNode);\n if (funcDecl === null) {\n return null;\n }\n\n const bodyChild = funcDecl.children[funcDecl.children.length - 1];\n if (bodyChild?.typeID !== TokenID.ERROR || node !== bodyChild) {\n return null;\n }\n\n const argsNode = funcDecl.children.find(child => child.typeID === Arguments || child.typeID === TokenID.NT_ARGUMENTS);\n if (argsNode === undefined || subtreeHasError(argsNode)) {\n return null;\n }\n\n if (expression.slice(funcDecl.to).trim().length > 0) {\n return null;\n }\n\n return {\n code: incompleteFormalExpressionCode(expected),\n from: bodyChild.from,\n to: bodyChild.to\n };\n}\n\nfunction incompleteFormalExpressionCode(expected?: TypeClass): RSErrorCode {\n switch (expected) {\n case TypeClassEnum.function:\n return RSErrorCode.expectedExpressionBody;\n case TypeClassEnum.predicate:\n case TypeClassEnum.logic:\n return RSErrorCode.expectedLogicBody;\n default:\n return RSErrorCode.expectedFunctionBody;\n }\n}\n\nfunction subtreeHasError(node: AstNode): boolean {\n if (node.typeID === TokenID.ERROR) {\n return true;\n }\n return node.children.some(subtreeHasError);\n}\n\nfunction detectFilterParenMismatch(node: AstNode, expression: string): RSErrorDescription | null {\n const filterNode = findAncestor(node, isFilterNode) ?? findRelatedNode(node, isFilterNode);\n if (filterNode === null) {\n return null;\n }\n\n const nextChar = expression[filterNode.to];\n if (nextChar === '(') {\n return {\n code: RSErrorCode.invalidFilterSyntax,\n from: filterNode.from,\n to: filterNode.to + 1\n };\n }\n return null;\n}\n\nfunction detectGlobalFuncWithoutArgs(node: AstNode, expression: string): RSErrorDescription | null {\n const funcNode =\n findAncestor(node, n => isFunctionNode(n) || isPredicateNode(n)) ??\n findRelatedNode(node, n => isFunctionNode(n) || isPredicateNode(n));\n if (funcNode === null) {\n return null;\n }\n return classifyFuncWithoutArgs(funcNode, expression);\n}\n\nfunction findRelatedNode(node: AstNode, predicate: (target: AstNode) => boolean): AstNode | null {\n let current: AstNode | null = node.parent;\n while (current !== null) {\n for (const child of current.children) {\n if (predicate(child)) {\n return child;\n }\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction classifyFuncWithoutArgs(funcNode: AstNode, expression: string): RSErrorDescription | null {\n const name = expression.slice(funcNode.from, funcNode.to);\n const rest = expression.slice(funcNode.to);\n\n const withoutArgs: RSErrorDescription = {\n code: RSErrorCode.globalFuncWithoutArgs,\n from: funcNode.from,\n to: funcNode.to,\n params: [name]\n };\n\n // Function with nothing (or only whitespace) after it is genuinely called without arguments.\n if (/^\\s*$/.test(rest)) {\n return withoutArgs;\n }\n\n // Anything other than a bracketed argument form (e.g. parentheses or braces) is malformed call\n // syntax: defer to the bracket/syntax error handling instead of reporting a missing-arguments error.\n const openBracket = /^\\s*\\[/.exec(rest);\n if (openBracket === null) {\n return null;\n }\n\n const closeIdx = findMatchingCloseBracket(rest, openBracket[0].length - 1);\n if (closeIdx >= 0) {\n const inner = rest.slice(openBracket[0].length, closeIdx).trim();\n if (inner.length === 0) {\n return withoutArgs;\n }\n }\n\n return null;\n}\n\nfunction findAncestor(node: AstNode, predicate: (node: AstNode) => boolean): AstNode | null {\n let current: AstNode | null = node;\n while (current !== null) {\n if (predicate(current)) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\nfunction isFunctionDeclNode(node: AstNode): boolean {\n return node.typeID === Function_decl || node.typeID === TokenID.NT_FUNC_DEFINITION;\n}\n\nfunction isFunctionNode(node: AstNode): boolean {\n return node.typeID === Function || node.typeID === TokenID.ID_FUNCTION;\n}\n\nfunction isPredicateNode(node: AstNode): boolean {\n return node.typeID === Predicate || node.typeID === TokenID.ID_PREDICATE;\n}\n\nfunction isFilterNode(node: AstNode): boolean {\n return node.typeID === Filter || node.typeID === TokenID.FILTER;\n}\n\nfunction findMatchingCloseBracket(expression: string, openPos: number): number {\n const open = expression[openPos];\n if (open !== '[') {\n return -1;\n }\n\n let depth = 0;\n for (let index = openPos; index < expression.length; index++) {\n const symbol = expression[index];\n if (symbol === '[') {\n depth++;\n } else if (symbol === ']') {\n depth--;\n if (depth === 0) {\n return index;\n }\n }\n }\n return -1;\n}\n\nfunction deduplicateErrors(errors: RSErrorDescription[]): RSErrorDescription[] {\n const result: RSErrorDescription[] = [];\n\n for (const error of errors) {\n const duplicate = result.some(\n existing => existing.code === error.code && existing.from === error.from && existing.to === error.to\n );\n if (duplicate) {\n continue;\n }\n\n if (error.code !== RSErrorCode.unknownSyntax) {\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index].code === RSErrorCode.unknownSyntax && rangesOverlap(error, result[index])) {\n result.splice(index, 1);\n }\n }\n }\n\n result.push(error);\n }\n\n const specific = result.filter(error => error.code !== RSErrorCode.unknownSyntax);\n return result.filter(\n error => error.code !== RSErrorCode.unknownSyntax || !specific.some(item => rangesOverlap(error, item))\n );\n}\n\nfunction rangesOverlap(a: RSErrorDescription, b: RSErrorDescription): boolean {\n return a.from < b.to && b.from < a.to;\n}\n\ntype OpenBracket = '(' | '[' | '{';\ntype CloseBracket = ')' | ']' | '}';\n\ninterface BracketFrame {\n bracket: OpenBracket;\n index: number;\n}\n\nfunction extractBracketErrors(expression: string): RSErrorDescription | null {\n const stack: BracketFrame[] = [];\n\n for (let pos = 0; pos < expression.length; pos++) {\n const symbol = expression[pos];\n if (isOpenBracket(symbol)) {\n if (isDoubleParenthesis(expression, pos)) {\n return {\n code: RSErrorCode.doubleParenthesis,\n from: pos,\n to: pos + 2\n };\n }\n stack.push({ bracket: symbol, index: pos });\n continue;\n }\n if (!isCloseBracket(symbol)) {\n continue;\n }\n\n const expectedOpen = closeToOpen(symbol);\n const top = stack[stack.length - 1];\n if (top === undefined) {\n return {\n code: RSErrorCode.missingOpenBracket,\n from: pos,\n to: pos + 1,\n params: [symbol]\n };\n }\n\n if (top.bracket !== expectedOpen) {\n return {\n code: RSErrorCode.bracketMismatch,\n from: pos,\n to: pos + 1,\n params: [openToClose(top.bracket), symbol]\n };\n }\n\n stack.pop();\n }\n\n if (stack.length > 0) {\n const unclosed = stack[0];\n return {\n code: RSErrorCode.missingCloseBracket,\n from: unclosed.index,\n to: unclosed.index + 1,\n params: [unclosed.bracket]\n };\n }\n\n return null;\n}\n\nfunction isOpenBracket(symbol: string): symbol is OpenBracket {\n return symbol === '(' || symbol === '[' || symbol === '{';\n}\n\nfunction isCloseBracket(symbol: string): symbol is CloseBracket {\n return symbol === ')' || symbol === ']' || symbol === '}';\n}\n\nfunction openToClose(symbol: OpenBracket): CloseBracket {\n switch (symbol) {\n case '(':\n return ')';\n case '[':\n return ']';\n case '{':\n return '}';\n }\n}\n\nfunction closeToOpen(symbol: CloseBracket): OpenBracket {\n switch (symbol) {\n case ')':\n return '(';\n case ']':\n return '[';\n case '}':\n return '{';\n }\n}\n\nfunction isDoubleParenthesis(expression: string, pos: number): boolean {\n const isOpenDoubleParenthesis = expression[pos] === '(' && expression[pos + 1] === '(';\n if (!isOpenDoubleParenthesis) {\n return false;\n }\n\n const outerClose = findMatchingCloseParen(expression, pos);\n const innerClose = findMatchingCloseParen(expression, pos + 1);\n if (outerClose < 0 || innerClose < 0) {\n return false;\n }\n\n return outerClose === innerClose + 1;\n}\n\nfunction findMatchingCloseParen(expression: string, openPos: number): number {\n if (expression[openPos] !== '(') {\n return -1;\n }\n\n const stack: OpenBracket[] = [];\n for (let index = openPos; index < expression.length; index++) {\n const symbol = expression[index];\n if (isOpenBracket(symbol)) {\n stack.push(symbol);\n continue;\n }\n if (!isCloseBracket(symbol)) {\n continue;\n }\n const top = stack.pop();\n if (top === undefined || top !== closeToOpen(symbol)) {\n return -1;\n }\n if (stack.length === 0) {\n return index;\n }\n }\n\n return -1;\n}\n"],"mappings":";;;;;;;;;;;;AAkBA,SAAgB,oBACd,KACA,YACA,UACA,iBAA0B,OAC1B,SACA;CACA,MAAM,YAAkC,CAAC;CACzC,MAAM,oCAAoB,IAAI,IAAiC;CAC/D,MAAM,WAAW,OAA2B,WAAqB;EAC/D,UAAU,KAAK,KAAK;EACpB,IAAI,WAAW,QACb,kBAAkB,IAAI,OAAO,MAAM;CAEvC;CAEA,MAAM,eAAe,qBAAqB,UAAU;CACpD,IAAI,iBAAiB,MACnB,QAAQ,cAAc,GAAG;CAE3B,MAAM,mBAAmB,iBAAiB;CAC1C,YAAY,MAAK,SAAQ,gBAAgB,MAAM,YAAY,SAAS,kBAAkB,OAAO,CAAC;CAE9F,KAAK,MAAM,SAAS,kBAAkB,SAAS,GAAG;EAChD,SAAS,KAAK;EACd,IAAI,gBAAgB;GAClB,MAAM,SAAS,kBAAkB,IAAI,KAAK;GAC1C,IAAI,WAAW,QACb,cAAc,QAAQ,MAAM,MAAM,MAAM,MAAM;EAElD;CACF;AACF;AAGA,SAAS,gBACP,MACA,YACA,SACA,qBACA,SACA;CACA,IAAI,KAAK,WAAW,QAAQ,OAC1B;CAGF,SAAS,KAAK,QAAiB,MAAmB,QAA4B;EAC5E,QAAQ;GAAQ;GAAM,MAAM,OAAO;GAAM,IAAI,OAAO;GAAI;EAAO,GAAG,MAAM;CAC1E;CAEA,MAAM,aAAa,mBAAmB,MAAM,YAAY,OAAO;CAC/D,IAAI,eAAe,MAAM;EACvB,QAAQ,YAAY,IAAI;EACxB;CACF;CAEA,MAAM,SAAS,KAAK;CACpB,IAAI,WAAW,MAAM;EACnB,IAAI,CAAC,qBACH,OAAO,KAAK,MAAM,YAAY,aAAa;EAE7C;CACF;CAEA,IAAI,OAAO,WAAA,GACT,OAAO,KAAK,QAAQ,YAAY,aAAa;CAG/C,IAAI,CAAC,qBACH,KAAK,KAAK,SAAS,KAAK,KAAK,SAAS,MAAM,YAAY,aAAa;AAEzE;AAEA,SAAS,mBACP,MACA,YACA,SAC2B;CAC3B,MAAM,yBAAyB,6BAA6B,MAAM,YAAY,SAAS,QAAQ;CAC/F,IAAI,2BAA2B,MAC7B,OAAO;CAGT,MAAM,cAAc,0BAA0B,MAAM,UAAU;CAC9D,IAAI,gBAAgB,MAClB,OAAO;CAGT,OAAO,4BAA4B,MAAM,UAAU;AACrD;AAEA,SAAS,6BACP,MACA,YACA,UAC2B;CAC3B,MAAM,WAAW,aAAa,MAAM,kBAAkB;CACtD,IAAI,aAAa,MACf,OAAO;CAGT,MAAM,YAAY,SAAS,SAAS,SAAS,SAAS,SAAS;CAC/D,IAAI,WAAW,WAAW,QAAQ,SAAS,SAAS,WAClD,OAAO;CAGT,MAAM,WAAW,SAAS,SAAS,MAAK,UAAS,MAAM,WAAA,MAAwB,MAAM,WAAW,QAAQ,YAAY;CACpH,IAAI,aAAa,UAAa,gBAAgB,QAAQ,GACpD,OAAO;CAGT,IAAI,WAAW,MAAM,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GAChD,OAAO;CAGT,OAAO;EACL,MAAM,+BAA+B,QAAQ;EAC7C,MAAM,UAAU;EAChB,IAAI,UAAU;CAChB;AACF;AAEA,SAAS,+BAA+B,UAAmC;CACzE,QAAQ,UAAR;EACE,KAAKA,UAAc,UACjB,OAAO,YAAY;EACrB,KAAKA,UAAc;EACnB,KAAKA,UAAc,OACjB,OAAO,YAAY;EACrB,SACE,OAAO,YAAY;CACvB;AACF;AAEA,SAAS,gBAAgB,MAAwB;CAC/C,IAAI,KAAK,WAAW,QAAQ,OAC1B,OAAO;CAET,OAAO,KAAK,SAAS,KAAK,eAAe;AAC3C;AAEA,SAAS,0BAA0B,MAAe,YAA+C;CAC/F,MAAM,aAAa,aAAa,MAAM,YAAY,KAAK,gBAAgB,MAAM,YAAY;CACzF,IAAI,eAAe,MACjB,OAAO;CAIT,IADiB,WAAW,WAAW,QACtB,KACf,OAAO;EACL,MAAM,YAAY;EAClB,MAAM,WAAW;EACjB,IAAI,WAAW,KAAK;CACtB;CAEF,OAAO;AACT;AAEA,SAAS,4BAA4B,MAAe,YAA+C;CACjG,MAAM,WACJ,aAAa,OAAM,MAAK,eAAe,CAAC,KAAK,gBAAgB,CAAC,CAAC,KAC/D,gBAAgB,OAAM,MAAK,eAAe,CAAC,KAAK,gBAAgB,CAAC,CAAC;CACpE,IAAI,aAAa,MACf,OAAO;CAET,OAAO,wBAAwB,UAAU,UAAU;AACrD;AAEA,SAAS,gBAAgB,MAAe,WAAyD;CAC/F,IAAI,UAA0B,KAAK;CACnC,OAAO,YAAY,MAAM;EACvB,KAAK,MAAM,SAAS,QAAQ,UAC1B,IAAI,UAAU,KAAK,GACjB,OAAO;EAGX,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAS,wBAAwB,UAAmB,YAA+C;CACjG,MAAM,OAAO,WAAW,MAAM,SAAS,MAAM,SAAS,EAAE;CACxD,MAAM,OAAO,WAAW,MAAM,SAAS,EAAE;CAEzC,MAAM,cAAkC;EACtC,MAAM,YAAY;EAClB,MAAM,SAAS;EACf,IAAI,SAAS;EACb,QAAQ,CAAC,IAAI;CACf;CAGA,IAAI,QAAQ,KAAK,IAAI,GACnB,OAAO;CAKT,MAAM,cAAc,SAAS,KAAK,IAAI;CACtC,IAAI,gBAAgB,MAClB,OAAO;CAGT,MAAM,WAAW,yBAAyB,MAAM,YAAY,EAAE,CAAC,SAAS,CAAC;CACzE,IAAI,YAAY,GAEd;MADc,KAAK,MAAM,YAAY,EAAE,CAAC,QAAQ,QAAQ,CAAC,CAAC,KACtD,CAAA,CAAM,WAAW,GACnB,OAAO;CACT;CAGF,OAAO;AACT;AAEA,SAAS,aAAa,MAAe,WAAuD;CAC1F,IAAI,UAA0B;CAC9B,OAAO,YAAY,MAAM;EACvB,IAAI,UAAU,OAAO,GACnB,OAAO;EAET,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,SAAS,mBAAmB,MAAwB;CAClD,OAAO,KAAK,WAAA,MAA4B,KAAK,WAAW,QAAQ;AAClE;AAEA,SAAS,eAAe,MAAwB;CAC9C,OAAO,KAAK,WAAA,MAAuB,KAAK,WAAW,QAAQ;AAC7D;AAEA,SAAS,gBAAgB,MAAwB;CAC/C,OAAO,KAAK,WAAA,MAAwB,KAAK,WAAW,QAAQ;AAC9D;AAEA,SAAS,aAAa,MAAwB;CAC5C,OAAO,KAAK,WAAA,MAAqB,KAAK,WAAW,QAAQ;AAC3D;AAEA,SAAS,yBAAyB,YAAoB,SAAyB;CAE7E,IADa,WAAW,aACX,KACX,OAAO;CAGT,IAAI,QAAQ;CACZ,KAAK,IAAI,QAAQ,SAAS,QAAQ,WAAW,QAAQ,SAAS;EAC5D,MAAM,SAAS,WAAW;EAC1B,IAAI,WAAW,KACb;OACK,IAAI,WAAW,KAAK;GACzB;GACA,IAAI,UAAU,GACZ,OAAO;EAEX;CACF;CACA,OAAO;AACT;AAEA,SAAS,kBAAkB,QAAoD;CAC7E,MAAM,SAA+B,CAAC;CAEtC,KAAK,MAAM,SAAS,QAAQ;EAI1B,IAHkB,OAAO,MACvB,aAAY,SAAS,SAAS,MAAM,QAAQ,SAAS,SAAS,MAAM,QAAQ,SAAS,OAAO,MAAM,EAEhG,GACF;EAGF,IAAI,MAAM,SAAS,YAAY,eAC7B;QAAK,IAAI,QAAQ,OAAO,SAAS,GAAG,SAAS,GAAG,SAC9C,IAAI,OAAO,MAAM,CAAC,SAAS,YAAY,iBAAiB,cAAc,OAAO,OAAO,MAAM,GACxF,OAAO,OAAO,OAAO,CAAC;EAE1B;EAGF,OAAO,KAAK,KAAK;CACnB;CAEA,MAAM,WAAW,OAAO,QAAO,UAAS,MAAM,SAAS,YAAY,aAAa;CAChF,OAAO,OAAO,QACZ,UAAS,MAAM,SAAS,YAAY,iBAAiB,CAAC,SAAS,MAAK,SAAQ,cAAc,OAAO,IAAI,CAAC,CACxG;AACF;AAEA,SAAS,cAAc,GAAuB,GAAgC;CAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;AACrC;AAUA,SAAS,qBAAqB,YAA+C;CAC3E,MAAM,QAAwB,CAAC;CAE/B,KAAK,IAAI,MAAM,GAAG,MAAM,WAAW,QAAQ,OAAO;EAChD,MAAM,SAAS,WAAW;EAC1B,IAAI,cAAc,MAAM,GAAG;GACzB,IAAI,oBAAoB,YAAY,GAAG,GACrC,OAAO;IACL,MAAM,YAAY;IAClB,MAAM;IACN,IAAI,MAAM;GACZ;GAEF,MAAM,KAAK;IAAE,SAAS;IAAQ,OAAO;GAAI,CAAC;GAC1C;EACF;EACA,IAAI,CAAC,eAAe,MAAM,GACxB;EAGF,MAAM,eAAe,YAAY,MAAM;EACvC,MAAM,MAAM,MAAM,MAAM,SAAS;EACjC,IAAI,QAAQ,QACV,OAAO;GACL,MAAM,YAAY;GAClB,MAAM;GACN,IAAI,MAAM;GACV,QAAQ,CAAC,MAAM;EACjB;EAGF,IAAI,IAAI,YAAY,cAClB,OAAO;GACL,MAAM,YAAY;GAClB,MAAM;GACN,IAAI,MAAM;GACV,QAAQ,CAAC,YAAY,IAAI,OAAO,GAAG,MAAM;EAC3C;EAGF,MAAM,IAAI;CACZ;CAEA,IAAI,MAAM,SAAS,GAAG;EACpB,MAAM,WAAW,MAAM;EACvB,OAAO;GACL,MAAM,YAAY;GAClB,MAAM,SAAS;GACf,IAAI,SAAS,QAAQ;GACrB,QAAQ,CAAC,SAAS,OAAO;EAC3B;CACF;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,QAAuC;CAC5D,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW;AACxD;AAEA,SAAS,eAAe,QAAwC;CAC9D,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW;AACxD;AAEA,SAAS,YAAY,QAAmC;CACtD,QAAQ,QAAR;EACE,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;CACX;AACF;AAEA,SAAS,YAAY,QAAmC;CACtD,QAAQ,QAAR;EACE,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;EACT,KAAK,KACH,OAAO;CACX;AACF;AAEA,SAAS,oBAAoB,YAAoB,KAAsB;CAErE,IAAI,EAD4B,WAAW,SAAS,OAAO,WAAW,MAAM,OAAO,MAEjF,OAAO;CAGT,MAAM,aAAa,uBAAuB,YAAY,GAAG;CACzD,MAAM,aAAa,uBAAuB,YAAY,MAAM,CAAC;CAC7D,IAAI,aAAa,KAAK,aAAa,GACjC,OAAO;CAGT,OAAO,eAAe,aAAa;AACrC;AAEA,SAAS,uBAAuB,YAAoB,SAAyB;CAC3E,IAAI,WAAW,aAAa,KAC1B,OAAO;CAGT,MAAM,QAAuB,CAAC;CAC9B,KAAK,IAAI,QAAQ,SAAS,QAAQ,WAAW,QAAQ,SAAS;EAC5D,MAAM,SAAS,WAAW;EAC1B,IAAI,cAAc,MAAM,GAAG;GACzB,MAAM,KAAK,MAAM;GACjB;EACF;EACA,IAAI,CAAC,eAAe,MAAM,GACxB;EAEF,MAAM,MAAM,MAAM,IAAI;EACtB,IAAI,QAAQ,UAAa,QAAQ,YAAY,MAAM,GACjD,OAAO;EAET,IAAI,MAAM,WAAW,GACnB,OAAO;CAEX;CAEA,OAAO;AACT"}
@@ -1,2 +1,2 @@
1
- import { a as RSLangAnalyzer, i as AnalysisOptions, n as AnalysisFast, r as AnalysisFull, t as AnalysisBase } from "../../analyzer-54lGGg13.js";
1
+ import { a as RSLangAnalyzer, i as AnalysisOptions, n as AnalysisFast, r as AnalysisFull, t as AnalysisBase } from "../../analyzer-0kmNRqcr.js";
2
2
  export { AnalysisBase, AnalysisFast, AnalysisFull, AnalysisOptions, RSLangAnalyzer };
@@ -102,7 +102,7 @@ var RSLangAnalyzer = class {
102
102
  }
103
103
  const ast = this.parse(expression);
104
104
  if (ast.hasError) {
105
- extractSyntaxErrors(ast, expression, reporter, options?.annotateErrors ?? false);
105
+ extractSyntaxErrors(ast, expression, reporter, options?.annotateErrors ?? false, { expected: options?.expected });
106
106
  return {
107
107
  success: false,
108
108
  type: null,
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","names":["rslangParser"],"sources":["../../../src/rslang/semantic/analyzer.ts"],"sourcesContent":["import { type AstNode, buildTree } from '../../parsing';\nimport { annotateError } from '../ast-annotations';\nimport { RSErrorCode, type RSErrorDescription } from '../error';\nimport { normalizeAST } from '../parser/normalize';\nimport { parser as rslangParser } from '../parser/parser';\nimport { extractSyntaxErrors } from '../parser/syntax-errors';\nimport { TokenID } from '../parser/token';\n\nimport { TypeAuditor } from './type-auditor';\nimport {\n basic,\n bool,\n constant,\n debool,\n type ExpressionType,\n type TypeClass,\n type TypeContext,\n TypeID\n} from './typification';\nimport { getTypeClass } from './typification-api';\nimport { ValueAuditor } from './value-auditor';\nimport { ValueClass, type ValueClassContext } from './value-class';\n\nexport interface AnalysisBase {\n success: boolean;\n type: ExpressionType | null;\n valueClass: ValueClass | null;\n}\n\nexport interface AnalysisFast extends AnalysisBase {\n ast: AstNode | null;\n}\n\nexport interface AnalysisFull extends AnalysisBase {\n ast: AstNode | null;\n errors: RSErrorDescription[];\n}\n\nexport interface AnalysisOptions {\n expected?: TypeClass;\n isDomain?: boolean;\n annotateTypes?: boolean;\n annotateErrors?: boolean;\n}\n\nexport class RSLangAnalyzer {\n private typeContext: TypeContext = new Map<string, ExpressionType>();\n private valueContext: ValueClassContext = new Map<string, ValueClass>();\n private typeAuditor: TypeAuditor = new TypeAuditor(this.typeContext);\n private valueAuditor: ValueAuditor = new ValueAuditor(this.valueContext);\n\n public addBase(alias: string, isNumeric: boolean = false, valueClass: ValueClass = ValueClass.VALUE): void {\n if (isNumeric) {\n this.typeContext.set(alias, bool(constant(alias)));\n this.valueContext.set(alias, valueClass);\n } else {\n this.typeContext.set(alias, bool(basic(alias)));\n this.valueContext.set(alias, valueClass);\n }\n }\n\n public setGlobal(alias: string, type: ExpressionType | null, value: ValueClass | null): void {\n if (type) {\n this.typeContext.set(alias, type);\n }\n if (value) {\n this.valueContext.set(alias, value);\n }\n }\n\n public getType(alias: string): ExpressionType | null {\n return this.typeContext.get(alias) ?? null;\n }\n\n public checkFast(expression: string, options?: AnalysisOptions): AnalysisFast {\n if (expression.length === 0) {\n return { success: false, type: null, valueClass: null, ast: null };\n }\n const ast = this.parse(expression);\n if (ast.hasError) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n const type = this.typeAuditor.run(ast, options?.annotateTypes ?? false);\n if (type === null) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n\n if (options?.isDomain) {\n if (!isStructureDomain(ast) || type.typeID !== TypeID.collection) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n return { success: true, type: debool(type), valueClass: ValueClass.VALUE, ast: ast };\n }\n if (options?.expected && getTypeClass(type.typeID) !== options.expected) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n\n return {\n success: true,\n type: type,\n valueClass: options?.isDomain ? ValueClass.VALUE : this.valueAuditor.run(ast),\n ast: ast\n };\n }\n\n public checkFull(expression: string, options?: AnalysisOptions): AnalysisFull {\n const errors: RSErrorDescription[] = [];\n const reporter = (error: RSErrorDescription) => {\n errors.push(error);\n };\n if (expression.length === 0) {\n reporter({ code: RSErrorCode.cstEmptyDerived, from: 0, to: 0 });\n return { success: false, type: null, valueClass: null, errors: errors, ast: null };\n }\n const ast = this.parse(expression);\n if (ast.hasError) {\n extractSyntaxErrors(ast, expression, reporter, options?.annotateErrors ?? false);\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n\n const type = this.typeAuditor.run(ast, options?.annotateTypes ?? false, reporter, options?.annotateErrors ?? false);\n if (type === null) {\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n\n if (options?.isDomain) {\n if (!isStructureDomain(ast) || type.typeID !== TypeID.collection) {\n reporter({ code: RSErrorCode.globalStructure, from: ast.from, to: ast.to });\n if (options?.annotateErrors) {\n annotateError(ast, RSErrorCode.globalStructure);\n }\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n return { success: true, type: debool(type), valueClass: ValueClass.VALUE, errors, ast };\n }\n if (options?.expected && getTypeClass(type.typeID) !== options.expected) {\n reporter({\n code: RSErrorCode.expectedType,\n from: ast.from,\n to: ast.to\n });\n if (options?.annotateErrors) {\n annotateError(ast, RSErrorCode.expectedType);\n }\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n const valueClass = options?.isDomain\n ? ValueClass.VALUE\n : this.valueAuditor.run(ast, reporter, options?.annotateErrors ?? false);\n return { success: true, type, valueClass, errors, ast };\n }\n\n private parse(expression: string): AstNode {\n const tree = rslangParser.parse(expression);\n const ast = buildTree(tree.cursor());\n normalizeAST(ast, expression);\n return ast;\n }\n}\n\n// ======= Internals ========\nfunction isStructureDomain(node: AstNode): boolean {\n switch (node.typeID) {\n case TokenID.LIT_WHOLE_NUMBERS:\n case TokenID.ID_GLOBAL:\n case TokenID.BOOLEAN:\n case TokenID.DECART:\n case TokenID.NT_ENUMERATION:\n break;\n default:\n return false;\n }\n for (const child of node.children) {\n if (!isStructureDomain(child)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.js","names":["rslangParser"],"sources":["../../../src/rslang/semantic/analyzer.ts"],"sourcesContent":["import { type AstNode, buildTree } from '../../parsing';\nimport { annotateError } from '../ast-annotations';\nimport { RSErrorCode, type RSErrorDescription } from '../error';\nimport { normalizeAST } from '../parser/normalize';\nimport { parser as rslangParser } from '../parser/parser';\nimport { extractSyntaxErrors } from '../parser/syntax-errors';\nimport { TokenID } from '../parser/token';\n\nimport { TypeAuditor } from './type-auditor';\nimport {\n basic,\n bool,\n constant,\n debool,\n type ExpressionType,\n type TypeClass,\n type TypeContext,\n TypeID\n} from './typification';\nimport { getTypeClass } from './typification-api';\nimport { ValueAuditor } from './value-auditor';\nimport { ValueClass, type ValueClassContext } from './value-class';\n\nexport interface AnalysisBase {\n success: boolean;\n type: ExpressionType | null;\n valueClass: ValueClass | null;\n}\n\nexport interface AnalysisFast extends AnalysisBase {\n ast: AstNode | null;\n}\n\nexport interface AnalysisFull extends AnalysisBase {\n ast: AstNode | null;\n errors: RSErrorDescription[];\n}\n\nexport interface AnalysisOptions {\n expected?: TypeClass;\n isDomain?: boolean;\n annotateTypes?: boolean;\n annotateErrors?: boolean;\n}\n\nexport class RSLangAnalyzer {\n private typeContext: TypeContext = new Map<string, ExpressionType>();\n private valueContext: ValueClassContext = new Map<string, ValueClass>();\n private typeAuditor: TypeAuditor = new TypeAuditor(this.typeContext);\n private valueAuditor: ValueAuditor = new ValueAuditor(this.valueContext);\n\n public addBase(alias: string, isNumeric: boolean = false, valueClass: ValueClass = ValueClass.VALUE): void {\n if (isNumeric) {\n this.typeContext.set(alias, bool(constant(alias)));\n this.valueContext.set(alias, valueClass);\n } else {\n this.typeContext.set(alias, bool(basic(alias)));\n this.valueContext.set(alias, valueClass);\n }\n }\n\n public setGlobal(alias: string, type: ExpressionType | null, value: ValueClass | null): void {\n if (type) {\n this.typeContext.set(alias, type);\n }\n if (value) {\n this.valueContext.set(alias, value);\n }\n }\n\n public getType(alias: string): ExpressionType | null {\n return this.typeContext.get(alias) ?? null;\n }\n\n public checkFast(expression: string, options?: AnalysisOptions): AnalysisFast {\n if (expression.length === 0) {\n return { success: false, type: null, valueClass: null, ast: null };\n }\n const ast = this.parse(expression);\n if (ast.hasError) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n const type = this.typeAuditor.run(ast, options?.annotateTypes ?? false);\n if (type === null) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n\n if (options?.isDomain) {\n if (!isStructureDomain(ast) || type.typeID !== TypeID.collection) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n return { success: true, type: debool(type), valueClass: ValueClass.VALUE, ast: ast };\n }\n if (options?.expected && getTypeClass(type.typeID) !== options.expected) {\n return { success: false, type: null, valueClass: null, ast: ast };\n }\n\n return {\n success: true,\n type: type,\n valueClass: options?.isDomain ? ValueClass.VALUE : this.valueAuditor.run(ast),\n ast: ast\n };\n }\n\n public checkFull(expression: string, options?: AnalysisOptions): AnalysisFull {\n const errors: RSErrorDescription[] = [];\n const reporter = (error: RSErrorDescription) => {\n errors.push(error);\n };\n if (expression.length === 0) {\n reporter({ code: RSErrorCode.cstEmptyDerived, from: 0, to: 0 });\n return { success: false, type: null, valueClass: null, errors: errors, ast: null };\n }\n const ast = this.parse(expression);\n if (ast.hasError) {\n extractSyntaxErrors(ast, expression, reporter, options?.annotateErrors ?? false, {\n expected: options?.expected\n });\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n\n const type = this.typeAuditor.run(ast, options?.annotateTypes ?? false, reporter, options?.annotateErrors ?? false);\n if (type === null) {\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n\n if (options?.isDomain) {\n if (!isStructureDomain(ast) || type.typeID !== TypeID.collection) {\n reporter({ code: RSErrorCode.globalStructure, from: ast.from, to: ast.to });\n if (options?.annotateErrors) {\n annotateError(ast, RSErrorCode.globalStructure);\n }\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n return { success: true, type: debool(type), valueClass: ValueClass.VALUE, errors, ast };\n }\n if (options?.expected && getTypeClass(type.typeID) !== options.expected) {\n reporter({\n code: RSErrorCode.expectedType,\n from: ast.from,\n to: ast.to\n });\n if (options?.annotateErrors) {\n annotateError(ast, RSErrorCode.expectedType);\n }\n return { success: false, type: null, valueClass: null, errors, ast };\n }\n const valueClass = options?.isDomain\n ? ValueClass.VALUE\n : this.valueAuditor.run(ast, reporter, options?.annotateErrors ?? false);\n return { success: true, type, valueClass, errors, ast };\n }\n\n private parse(expression: string): AstNode {\n const tree = rslangParser.parse(expression);\n const ast = buildTree(tree.cursor());\n normalizeAST(ast, expression);\n return ast;\n }\n}\n\n// ======= Internals ========\nfunction isStructureDomain(node: AstNode): boolean {\n switch (node.typeID) {\n case TokenID.LIT_WHOLE_NUMBERS:\n case TokenID.ID_GLOBAL:\n case TokenID.BOOLEAN:\n case TokenID.DECART:\n case TokenID.NT_ENUMERATION:\n break;\n default:\n return false;\n }\n for (const child of node.children) {\n if (!isStructureDomain(child)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as AstNode } from "../../ast-C8sIpKdL.js";
2
2
  import { _ as TypeContext, f as ExpressionType } from "../../typification-Dk-fisgO.js";
3
- import { t as ErrorReporter } from "../../error-CxIs0A7Y.js";
3
+ import { t as ErrorReporter } from "../../error-DYLkv4B3.js";
4
4
 
5
5
  //#region src/rslang/semantic/type-auditor.d.ts
6
6
  /** Type auditor for AST type checking. */
@@ -497,11 +497,7 @@ var TypeAuditor = class TypeAuditor {
497
497
  }
498
498
  reportFilterParameterError(node, childIndex, param, expected, operator) {
499
499
  const wrapped = bool(param);
500
- if (checkEquality(wrapped, expected) || checkCompatibility(wrapped, expected)) return this.onError(RSErrorCode.invalidFilterBooleanEchelon, node.children[childIndex], [
501
- operator,
502
- labelType(param),
503
- labelType(expected)
504
- ]);
500
+ if (checkEquality(wrapped, expected) || checkCompatibility(wrapped, expected)) return this.onError(RSErrorCode.invalidFilterBooleanEchelon, node.children[childIndex], [operator, labelType(param)]);
505
501
  return this.onError(RSErrorCode.invalidFilterParameterType, node.children[childIndex], [
506
502
  labelType(param),
507
503
  labelType(expected),
@@ -588,7 +584,7 @@ var TypeAuditor = class TypeAuditor {
588
584
  return false;
589
585
  }
590
586
  checkFuncArguments(node, alias, type) {
591
- if (node.children.length - 1 !== type.args.length) return this.onError(RSErrorCode.invalidArgsArity, node.children[1], [String(type.args.length), String(node.children.length - 1)]);
587
+ if (node.children.length - 1 !== type.args.length) return this.onError(RSErrorCode.invalidArgsArity, node, [String(type.args.length), String(node.children.length - 1)]);
592
588
  const substitutes = /* @__PURE__ */ new Map();
593
589
  for (let child = 1; child < node.children.length; child++) {
594
590
  const childType = this.childTypification(node, child);
@@ -627,6 +623,29 @@ function mangleRadicals(funcName, type) {
627
623
  }
628
624
  }
629
625
  }
626
+ function isLogicBinaryNode(typeID) {
627
+ return typeID === TokenID.LOGIC_AND || typeID === TokenID.LOGIC_OR || typeID === TokenID.LOGIC_IMPLICATION || typeID === TokenID.LOGIC_EQUIVALENT;
628
+ }
629
+ function isQuantifierNode(typeID) {
630
+ return typeID === TokenID.QUANTOR_UNIVERSAL || typeID === TokenID.QUANTOR_EXISTS;
631
+ }
632
+ function subtreeContainsQuantifier(node) {
633
+ if (isQuantifierNode(node.typeID)) return true;
634
+ for (const child of node.children) if (subtreeContainsQuantifier(child)) return true;
635
+ return false;
636
+ }
637
+ /** Right operand subtree of the innermost logic binary containing `node`. */
638
+ function findRightLogicOperandRoot(node) {
639
+ let current = node;
640
+ while (current !== null && current.parent !== null) {
641
+ const parent = current.parent;
642
+ if (isLogicBinaryNode(parent.typeID)) {
643
+ if (parent.children.indexOf(current) > 0) return current;
644
+ }
645
+ current = parent;
646
+ }
647
+ return null;
648
+ }
630
649
  /** Local variables context. */
631
650
  var LocalContext = class {
632
651
  onError;
@@ -672,6 +691,11 @@ var LocalContext = class {
672
691
  this.onError(RSErrorCode.localUndeclared, node, [alias]);
673
692
  return null;
674
693
  } else if (local.level < 1) {
694
+ const subexprRoot = findRightLogicOperandRoot(node);
695
+ if (subexprRoot !== null) {
696
+ if (subtreeContainsQuantifier(subexprRoot)) return this.onError(RSErrorCode.localUndeclaredInSubexpr, node, [alias, labelType(local.type)]);
697
+ return this.onError(RSErrorCode.localOutOfScopeParentheses, node, [alias]);
698
+ }
675
699
  this.onError(RSErrorCode.localOutOfScope, node, [alias]);
676
700
  return null;
677
701
  } else {