fhirpath-ts 0.0.0-bootstrap.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.
- package/LICENSE +201 -0
- package/README.md +391 -0
- package/THIRD-PARTY-NOTICES.md +296 -0
- package/dist/analyzer/analyze-dto.d.ts +45 -0
- package/dist/analyzer/analyze-dto.d.ts.map +1 -0
- package/dist/analyzer/analyze-dto.js +147 -0
- package/dist/analyzer/analyze-dto.js.map +1 -0
- package/dist/analyzer/analyze.d.ts +98 -0
- package/dist/analyzer/analyze.d.ts.map +1 -0
- package/dist/analyzer/analyze.js +925 -0
- package/dist/analyzer/analyze.js.map +1 -0
- package/dist/analyzer/expression-policy.d.ts +210 -0
- package/dist/analyzer/expression-policy.d.ts.map +1 -0
- package/dist/analyzer/expression-policy.js +254 -0
- package/dist/analyzer/expression-policy.js.map +1 -0
- package/dist/analyzer/index.d.ts +3 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +6 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/regex-safety.d.ts +10 -0
- package/dist/analyzer/regex-safety.d.ts.map +1 -0
- package/dist/analyzer/regex-safety.js +84 -0
- package/dist/analyzer/regex-safety.js.map +1 -0
- package/dist/analyzer/signatures.d.ts +72 -0
- package/dist/analyzer/signatures.d.ts.map +1 -0
- package/dist/analyzer/signatures.js +195 -0
- package/dist/analyzer/signatures.js.map +1 -0
- package/dist/api/bundle.d.ts +29 -0
- package/dist/api/bundle.d.ts.map +1 -0
- package/dist/api/bundle.js +108 -0
- package/dist/api/bundle.js.map +1 -0
- package/dist/api/cache.d.ts +10 -0
- package/dist/api/cache.d.ts.map +1 -0
- package/dist/api/cache.js +38 -0
- package/dist/api/cache.js.map +1 -0
- package/dist/api/column-signature.d.ts +53 -0
- package/dist/api/column-signature.d.ts.map +1 -0
- package/dist/api/column-signature.js +43 -0
- package/dist/api/column-signature.js.map +1 -0
- package/dist/api/compile.d.ts +120 -0
- package/dist/api/compile.d.ts.map +1 -0
- package/dist/api/compile.js +167 -0
- package/dist/api/compile.js.map +1 -0
- package/dist/api/constraints.d.ts +48 -0
- package/dist/api/constraints.d.ts.map +1 -0
- package/dist/api/constraints.js +52 -0
- package/dist/api/constraints.js.map +1 -0
- package/dist/api/dto.d.ts +134 -0
- package/dist/api/dto.d.ts.map +1 -0
- package/dist/api/dto.js +295 -0
- package/dist/api/dto.js.map +1 -0
- package/dist/api/engine.d.ts +136 -0
- package/dist/api/engine.d.ts.map +1 -0
- package/dist/api/engine.js +183 -0
- package/dist/api/engine.js.map +1 -0
- package/dist/api/evaluate.d.ts +7 -0
- package/dist/api/evaluate.d.ts.map +1 -0
- package/dist/api/evaluate.js +10 -0
- package/dist/api/evaluate.js.map +1 -0
- package/dist/api/project.d.ts +89 -0
- package/dist/api/project.d.ts.map +1 -0
- package/dist/api/project.js +150 -0
- package/dist/api/project.js.map +1 -0
- package/dist/api/tagged.d.ts +14 -0
- package/dist/api/tagged.d.ts.map +1 -0
- package/dist/api/tagged.js +13 -0
- package/dist/api/tagged.js.map +1 -0
- package/dist/cli/dto-check.d.ts +25 -0
- package/dist/cli/dto-check.d.ts.map +1 -0
- package/dist/cli/dto-check.js +77 -0
- package/dist/cli/dto-check.js.map +1 -0
- package/dist/cli/fhirpath-check.d.ts +3 -0
- package/dist/cli/fhirpath-check.d.ts.map +1 -0
- package/dist/cli/fhirpath-check.js +149 -0
- package/dist/cli/fhirpath-check.js.map +1 -0
- package/dist/cli/ts-loader.d.mts +3 -0
- package/dist/cli/ts-loader.d.mts.map +1 -0
- package/dist/cli/ts-loader.mjs +48 -0
- package/dist/cli/ts-loader.mjs.map +1 -0
- package/dist/engine/context.d.ts +173 -0
- package/dist/engine/context.d.ts.map +1 -0
- package/dist/engine/context.js +118 -0
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/evaluator.d.ts +7 -0
- package/dist/engine/evaluator.d.ts.map +1 -0
- package/dist/engine/evaluator.js +196 -0
- package/dist/engine/evaluator.js.map +1 -0
- package/dist/engine/navigation.d.ts +11 -0
- package/dist/engine/navigation.d.ts.map +1 -0
- package/dist/engine/navigation.js +102 -0
- package/dist/engine/navigation.js.map +1 -0
- package/dist/engine/operators/collections.d.ts +12 -0
- package/dist/engine/operators/collections.d.ts.map +1 -0
- package/dist/engine/operators/collections.js +31 -0
- package/dist/engine/operators/collections.js.map +1 -0
- package/dist/engine/operators/comparison.d.ts +13 -0
- package/dist/engine/operators/comparison.d.ts.map +1 -0
- package/dist/engine/operators/comparison.js +77 -0
- package/dist/engine/operators/comparison.js.map +1 -0
- package/dist/engine/operators/equality.d.ts +19 -0
- package/dist/engine/operators/equality.d.ts.map +1 -0
- package/dist/engine/operators/equality.js +203 -0
- package/dist/engine/operators/equality.js.map +1 -0
- package/dist/engine/operators/index.d.ts +18 -0
- package/dist/engine/operators/index.d.ts.map +1 -0
- package/dist/engine/operators/index.js +30 -0
- package/dist/engine/operators/index.js.map +1 -0
- package/dist/engine/operators/logic.d.ts +8 -0
- package/dist/engine/operators/logic.d.ts.map +1 -0
- package/dist/engine/operators/logic.js +38 -0
- package/dist/engine/operators/logic.js.map +1 -0
- package/dist/engine/operators/math.d.ts +13 -0
- package/dist/engine/operators/math.d.ts.map +1 -0
- package/dist/engine/operators/math.js +198 -0
- package/dist/engine/operators/math.js.map +1 -0
- package/dist/engine/operators/strings.d.ts +8 -0
- package/dist/engine/operators/strings.d.ts.map +1 -0
- package/dist/engine/operators/strings.js +22 -0
- package/dist/engine/operators/strings.js.map +1 -0
- package/dist/engine/operators/types.d.ts +3 -0
- package/dist/engine/operators/types.d.ts.map +1 -0
- package/dist/engine/operators/types.js +15 -0
- package/dist/engine/operators/types.js.map +1 -0
- package/dist/engine/type-matching.d.ts +20 -0
- package/dist/engine/type-matching.d.ts.map +1 -0
- package/dist/engine/type-matching.js +122 -0
- package/dist/engine/type-matching.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +21 -0
- package/dist/errors.js.map +1 -0
- package/dist/eslint/index.d.ts +12 -0
- package/dist/eslint/index.d.ts.map +1 -0
- package/dist/eslint/index.js +316 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/fhir/html-checks.d.ts +7 -0
- package/dist/fhir/html-checks.d.ts.map +1 -0
- package/dist/fhir/html-checks.js +256 -0
- package/dist/fhir/html-checks.js.map +1 -0
- package/dist/fhir/model-navigation.d.ts +11 -0
- package/dist/fhir/model-navigation.d.ts.map +1 -0
- package/dist/fhir/model-navigation.js +142 -0
- package/dist/fhir/model-navigation.js.map +1 -0
- package/dist/functions/aggregate.d.ts +2 -0
- package/dist/functions/aggregate.d.ts.map +1 -0
- package/dist/functions/aggregate.js +127 -0
- package/dist/functions/aggregate.js.map +1 -0
- package/dist/functions/boundary.d.ts +2 -0
- package/dist/functions/boundary.d.ts.map +1 -0
- package/dist/functions/boundary.js +189 -0
- package/dist/functions/boundary.js.map +1 -0
- package/dist/functions/combining.d.ts +2 -0
- package/dist/functions/combining.d.ts.map +1 -0
- package/dist/functions/combining.js +13 -0
- package/dist/functions/combining.js.map +1 -0
- package/dist/functions/control.d.ts +2 -0
- package/dist/functions/control.d.ts.map +1 -0
- package/dist/functions/control.js +25 -0
- package/dist/functions/control.js.map +1 -0
- package/dist/functions/conversion.d.ts +3 -0
- package/dist/functions/conversion.d.ts.map +1 -0
- package/dist/functions/conversion.js +316 -0
- package/dist/functions/conversion.js.map +1 -0
- package/dist/functions/date-components.d.ts +2 -0
- package/dist/functions/date-components.d.ts.map +1 -0
- package/dist/functions/date-components.js +81 -0
- package/dist/functions/date-components.js.map +1 -0
- package/dist/functions/existence.d.ts +4 -0
- package/dist/functions/existence.d.ts.map +1 -0
- package/dist/functions/existence.js +97 -0
- package/dist/functions/existence.js.map +1 -0
- package/dist/functions/fhir.d.ts +2 -0
- package/dist/functions/fhir.d.ts.map +1 -0
- package/dist/functions/fhir.js +222 -0
- package/dist/functions/fhir.js.map +1 -0
- package/dist/functions/filtering.d.ts +2 -0
- package/dist/functions/filtering.d.ts.map +1 -0
- package/dist/functions/filtering.js +112 -0
- package/dist/functions/filtering.js.map +1 -0
- package/dist/functions/install.d.ts +18 -0
- package/dist/functions/install.d.ts.map +1 -0
- package/dist/functions/install.js +20 -0
- package/dist/functions/install.js.map +1 -0
- package/dist/functions/iteration.d.ts +7 -0
- package/dist/functions/iteration.d.ts.map +1 -0
- package/dist/functions/iteration.js +9 -0
- package/dist/functions/iteration.js.map +1 -0
- package/dist/functions/math.d.ts +2 -0
- package/dist/functions/math.d.ts.map +1 -0
- package/dist/functions/math.js +152 -0
- package/dist/functions/math.js.map +1 -0
- package/dist/functions/reflection.d.ts +2 -0
- package/dist/functions/reflection.d.ts.map +1 -0
- package/dist/functions/reflection.js +23 -0
- package/dist/functions/reflection.js.map +1 -0
- package/dist/functions/registry.d.ts +28 -0
- package/dist/functions/registry.d.ts.map +1 -0
- package/dist/functions/registry.js +46 -0
- package/dist/functions/registry.js.map +1 -0
- package/dist/functions/sort.d.ts +2 -0
- package/dist/functions/sort.d.ts.map +1 -0
- package/dist/functions/sort.js +48 -0
- package/dist/functions/sort.js.map +1 -0
- package/dist/functions/string.d.ts +2 -0
- package/dist/functions/string.d.ts.map +1 -0
- package/dist/functions/string.js +353 -0
- package/dist/functions/string.js.map +1 -0
- package/dist/functions/subsetting.d.ts +2 -0
- package/dist/functions/subsetting.d.ts.map +1 -0
- package/dist/functions/subsetting.js +72 -0
- package/dist/functions/subsetting.js.map +1 -0
- package/dist/functions/tree.d.ts +8 -0
- package/dist/functions/tree.d.ts.map +1 -0
- package/dist/functions/tree.js +109 -0
- package/dist/functions/tree.js.map +1 -0
- package/dist/functions/type-specifier.d.ts +8 -0
- package/dist/functions/type-specifier.d.ts.map +1 -0
- package/dist/functions/type-specifier.js +27 -0
- package/dist/functions/type-specifier.js.map +1 -0
- package/dist/functions/utility.d.ts +2 -0
- package/dist/functions/utility.d.ts.map +1 -0
- package/dist/functions/utility.js +76 -0
- package/dist/functions/utility.js.map +1 -0
- package/dist/functions/variables.d.ts +2 -0
- package/dist/functions/variables.d.ts.map +1 -0
- package/dist/functions/variables.js +35 -0
- package/dist/functions/variables.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/lexer/lexer.d.ts +4 -0
- package/dist/lexer/lexer.d.ts.map +1 -0
- package/dist/lexer/lexer.js +318 -0
- package/dist/lexer/lexer.js.map +1 -0
- package/dist/lexer/tokens.d.ts +23 -0
- package/dist/lexer/tokens.d.ts.map +1 -0
- package/dist/lexer/tokens.js +40 -0
- package/dist/lexer/tokens.js.map +1 -0
- package/dist/model/provider.d.ts +36 -0
- package/dist/model/provider.d.ts.map +1 -0
- package/dist/model/provider.js +2 -0
- package/dist/model/provider.js.map +1 -0
- package/dist/parser/ast.d.ts +104 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +2 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/parser.d.ts +4 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +299 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/parser/precedence.d.ts +24 -0
- package/dist/parser/precedence.d.ts.map +1 -0
- package/dist/parser/precedence.js +52 -0
- package/dist/parser/precedence.js.map +1 -0
- package/dist/parser/printer.d.ts +4 -0
- package/dist/parser/printer.d.ts.map +1 -0
- package/dist/parser/printer.js +112 -0
- package/dist/parser/printer.js.map +1 -0
- package/dist/r4/generated/resources-data.d.ts +3 -0
- package/dist/r4/generated/resources-data.d.ts.map +1 -0
- package/dist/r4/generated/resources-data.js +28628 -0
- package/dist/r4/generated/resources-data.js.map +1 -0
- package/dist/r4/generated/type-maps.d.ts +43153 -0
- package/dist/r4/generated/type-maps.d.ts.map +1 -0
- package/dist/r4/generated/type-maps.js +4 -0
- package/dist/r4/generated/type-maps.js.map +1 -0
- package/dist/r4/generated/types-data.d.ts +3 -0
- package/dist/r4/generated/types-data.d.ts.map +1 -0
- package/dist/r4/generated/types-data.js +2205 -0
- package/dist/r4/generated/types-data.js.map +1 -0
- package/dist/r4/index.d.ts +9 -0
- package/dist/r4/index.d.ts.map +1 -0
- package/dist/r4/index.js +94 -0
- package/dist/r4/index.js.map +1 -0
- package/dist/r4/model-data.d.ts +17 -0
- package/dist/r4/model-data.d.ts.map +1 -0
- package/dist/r4/model-data.js +2 -0
- package/dist/r4/model-data.js.map +1 -0
- package/dist/sites/index.d.ts +31 -0
- package/dist/sites/index.d.ts.map +1 -0
- package/dist/sites/index.js +205 -0
- package/dist/sites/index.js.map +1 -0
- package/dist/typed/infer.d.ts +234 -0
- package/dist/typed/infer.d.ts.map +1 -0
- package/dist/typed/infer.js +85 -0
- package/dist/typed/infer.js.map +1 -0
- package/dist/typed/perf-fixture.types.d.ts +136 -0
- package/dist/typed/perf-fixture.types.d.ts.map +1 -0
- package/dist/typed/perf-fixture.types.js +2 -0
- package/dist/typed/perf-fixture.types.js.map +1 -0
- package/dist/values/collection.d.ts +24 -0
- package/dist/values/collection.d.ts.map +1 -0
- package/dist/values/collection.js +51 -0
- package/dist/values/collection.js.map +1 -0
- package/dist/values/datetime.d.ts +54 -0
- package/dist/values/datetime.d.ts.map +1 -0
- package/dist/values/datetime.js +226 -0
- package/dist/values/datetime.js.map +1 -0
- package/dist/values/decimal.d.ts +48 -0
- package/dist/values/decimal.d.ts.map +1 -0
- package/dist/values/decimal.js +188 -0
- package/dist/values/decimal.js.map +1 -0
- package/dist/values/numeric.d.ts +24 -0
- package/dist/values/numeric.d.ts.map +1 -0
- package/dist/values/numeric.js +53 -0
- package/dist/values/numeric.js.map +1 -0
- package/dist/values/quantity.d.ts +49 -0
- package/dist/values/quantity.d.ts.map +1 -0
- package/dist/values/quantity.js +297 -0
- package/dist/values/quantity.js.map +1 -0
- package/dist/values/temporal-arithmetic.d.ts +17 -0
- package/dist/values/temporal-arithmetic.d.ts.map +1 -0
- package/dist/values/temporal-arithmetic.js +183 -0
- package/dist/values/temporal-arithmetic.js.map +1 -0
- package/dist/values/temporal-compare.d.ts +9 -0
- package/dist/values/temporal-compare.d.ts.map +1 -0
- package/dist/values/temporal-compare.js +59 -0
- package/dist/values/temporal-compare.js.map +1 -0
- package/dist/values/type-compat.d.ts +47 -0
- package/dist/values/type-compat.d.ts.map +1 -0
- package/dist/values/type-compat.js +100 -0
- package/dist/values/type-compat.js.map +1 -0
- package/dist/values/typed-value.d.ts +48 -0
- package/dist/values/typed-value.d.ts.map +1 -0
- package/dist/values/typed-value.js +117 -0
- package/dist/values/typed-value.js.map +1 -0
- package/dist/values/ucum.d.ts +14 -0
- package/dist/values/ucum.d.ts.map +1 -0
- package/dist/values/ucum.js +146 -0
- package/dist/values/ucum.js.map +1 -0
- package/package.json +137 -0
- package/src/analyzer/analyze-dto.ts +195 -0
- package/src/analyzer/analyze.ts +1181 -0
- package/src/analyzer/expression-policy.ts +434 -0
- package/src/analyzer/index.ts +23 -0
- package/src/analyzer/regex-safety.ts +85 -0
- package/src/analyzer/signatures.ts +260 -0
- package/src/api/bundle.ts +132 -0
- package/src/api/cache.ts +40 -0
- package/src/api/column-signature.ts +71 -0
- package/src/api/compile.ts +308 -0
- package/src/api/constraints.ts +104 -0
- package/src/api/dto.ts +445 -0
- package/src/api/engine.ts +328 -0
- package/src/api/evaluate.ts +11 -0
- package/src/api/project.ts +255 -0
- package/src/api/tagged.ts +35 -0
- package/src/cli/dto-check.ts +94 -0
- package/src/cli/fhirpath-check.ts +168 -0
- package/src/cli/ts-loader.mjs +49 -0
- package/src/engine/context.ts +282 -0
- package/src/engine/evaluator.ts +246 -0
- package/src/engine/navigation.ts +106 -0
- package/src/engine/operators/collections.ts +34 -0
- package/src/engine/operators/comparison.ts +82 -0
- package/src/engine/operators/equality.ts +232 -0
- package/src/engine/operators/index.ts +65 -0
- package/src/engine/operators/logic.ts +53 -0
- package/src/engine/operators/math.ts +225 -0
- package/src/engine/operators/strings.ts +25 -0
- package/src/engine/operators/types.ts +16 -0
- package/src/engine/type-matching.ts +148 -0
- package/src/errors.ts +33 -0
- package/src/eslint/index.ts +388 -0
- package/src/fhir/html-checks.ts +266 -0
- package/src/fhir/model-navigation.ts +148 -0
- package/src/functions/aggregate.ts +136 -0
- package/src/functions/boundary.ts +209 -0
- package/src/functions/combining.ts +15 -0
- package/src/functions/control.ts +25 -0
- package/src/functions/conversion.ts +349 -0
- package/src/functions/date-components.ts +88 -0
- package/src/functions/existence.ts +107 -0
- package/src/functions/fhir.ts +247 -0
- package/src/functions/filtering.ts +120 -0
- package/src/functions/install.ts +19 -0
- package/src/functions/iteration.ts +21 -0
- package/src/functions/math.ts +167 -0
- package/src/functions/reflection.ts +24 -0
- package/src/functions/registry.ts +72 -0
- package/src/functions/sort.ts +68 -0
- package/src/functions/string.ts +413 -0
- package/src/functions/subsetting.ts +89 -0
- package/src/functions/tree.ts +112 -0
- package/src/functions/type-specifier.ts +29 -0
- package/src/functions/utility.ts +82 -0
- package/src/functions/variables.ts +36 -0
- package/src/index.ts +30 -0
- package/src/lexer/lexer.ts +341 -0
- package/src/lexer/tokens.ts +69 -0
- package/src/model/provider.ts +36 -0
- package/src/parser/ast.ts +164 -0
- package/src/parser/parser.ts +321 -0
- package/src/parser/precedence.ts +52 -0
- package/src/parser/printer.ts +114 -0
- package/src/r4/generated/resources-data.ts +28631 -0
- package/src/r4/generated/type-maps.ts +22145 -0
- package/src/r4/generated/types-data.ts +2208 -0
- package/src/r4/index.ts +107 -0
- package/src/r4/model-data.ts +17 -0
- package/src/sites/index.ts +285 -0
- package/src/typed/infer.ts +433 -0
- package/src/typed/perf-fixture.types.ts +143 -0
- package/src/values/collection.ts +57 -0
- package/src/values/datetime.ts +285 -0
- package/src/values/decimal.ts +213 -0
- package/src/values/numeric.ts +63 -0
- package/src/values/quantity.ts +358 -0
- package/src/values/temporal-arithmetic.ts +231 -0
- package/src/values/temporal-compare.ts +65 -0
- package/src/values/type-compat.ts +133 -0
- package/src/values/typed-value.ts +151 -0
- package/src/values/ucum.ts +181 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import '../functions/install.ts'
|
|
2
|
+
|
|
3
|
+
import { FhirPathRuntimeError, FhirPathTypeError } from '../errors.ts'
|
|
4
|
+
import { describeArity, lookupFunction } from '../functions/registry.ts'
|
|
5
|
+
import type { AstNode } from '../parser/ast.ts'
|
|
6
|
+
import { criteriaBoolean, singleton, wrapBoolean } from '../values/collection.ts'
|
|
7
|
+
import { Temporal } from '../values/datetime.ts'
|
|
8
|
+
import { Decimal } from '../values/decimal.ts'
|
|
9
|
+
import { wrapNumeric } from '../values/numeric.ts'
|
|
10
|
+
import {
|
|
11
|
+
SYSTEM_BOOLEAN,
|
|
12
|
+
SYSTEM_DATE,
|
|
13
|
+
SYSTEM_DATETIME,
|
|
14
|
+
SYSTEM_DECIMAL,
|
|
15
|
+
SYSTEM_INTEGER,
|
|
16
|
+
SYSTEM_LONG,
|
|
17
|
+
SYSTEM_QUANTITY,
|
|
18
|
+
SYSTEM_STRING,
|
|
19
|
+
SYSTEM_TIME,
|
|
20
|
+
toCollection,
|
|
21
|
+
type TypedValue,
|
|
22
|
+
unwrap,
|
|
23
|
+
} from '../values/typed-value.ts'
|
|
24
|
+
import {
|
|
25
|
+
type EvaluationContext,
|
|
26
|
+
forkVariables,
|
|
27
|
+
type HostFunction,
|
|
28
|
+
resolveEnvironmentVariable,
|
|
29
|
+
withEnvOverlay,
|
|
30
|
+
withFrame,
|
|
31
|
+
} from './context.ts'
|
|
32
|
+
import { navigateIdentifier } from './navigation.ts'
|
|
33
|
+
import { evaluateBinary, evaluateTypeOp, evaluateUnary } from './operators/index.ts'
|
|
34
|
+
import { resolveHostCall } from './type-matching.ts'
|
|
35
|
+
|
|
36
|
+
function evaluateArgument(node: AstNode, context: EvaluationContext, _input: TypedValue[]): TypedValue[] {
|
|
37
|
+
// Arguments evaluate against $this (the current context item), not the function's
|
|
38
|
+
// input collection: `name.given.combine(name.family)` resolves name.family on the
|
|
39
|
+
// Patient. Lambda-style functions bind their own frame first, so they see each item.
|
|
40
|
+
const forked = forkVariables(context)
|
|
41
|
+
return evaluateNode(node, forked, forked.frame.thisValue)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Calls a host function after focus-type dispatch. Expression functions keep
|
|
46
|
+
* typed values, use the call focus as `$this`, and apply their local environment.
|
|
47
|
+
* Native functions receive eagerly evaluated plain JavaScript values.
|
|
48
|
+
*/
|
|
49
|
+
function evaluateHostFunction(
|
|
50
|
+
name: string,
|
|
51
|
+
entry: HostFunction,
|
|
52
|
+
args: AstNode[],
|
|
53
|
+
context: EvaluationContext,
|
|
54
|
+
input: TypedValue[]
|
|
55
|
+
): TypedValue[] {
|
|
56
|
+
const host = resolveHostCall(name, entry, context, input)
|
|
57
|
+
if ('ast' in host) {
|
|
58
|
+
if (args.length > 0) {
|
|
59
|
+
throw new FhirPathTypeError(`Function '${name}' expects ${describeArity(0, 0)}, got ${args.length} arguments`)
|
|
60
|
+
}
|
|
61
|
+
if (context.activeExpressionFunctions.has(name)) {
|
|
62
|
+
throw new FhirPathRuntimeError(
|
|
63
|
+
`Expression-defined function '${name}' calls itself, directly or through another function`
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
context.activeExpressionFunctions.add(name)
|
|
67
|
+
try {
|
|
68
|
+
// Keep the function's environment local and recursion detection active.
|
|
69
|
+
const scoped = host.env === undefined ? context : withEnvOverlay(context, host.env)
|
|
70
|
+
// withFrame rebinds $this to the input and forks variables, so the
|
|
71
|
+
// body's defineVariable() bindings stay local to the body.
|
|
72
|
+
const result = withFrame(scoped, { thisValue: input }, forked => evaluateNode(host.ast, forked, input))
|
|
73
|
+
// Inside the try, so a body that returns several items still removes its
|
|
74
|
+
// name from activeExpressionFunctions on the way out.
|
|
75
|
+
return host.criteria === true ? wrapBoolean(criteriaBoolean(result)) : result
|
|
76
|
+
} finally {
|
|
77
|
+
context.activeExpressionFunctions.delete(name)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const minArity = host.minArity ?? 0
|
|
81
|
+
const maxArity = host.maxArity ?? Number.POSITIVE_INFINITY
|
|
82
|
+
if (args.length < minArity || args.length > maxArity) {
|
|
83
|
+
throw new FhirPathTypeError(
|
|
84
|
+
`Function '${name}' expects ${describeArity(minArity, maxArity)}, got ${args.length} arguments`
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
const argValues = args.map(node => evaluateArgument(node, context, input).map(unwrap))
|
|
88
|
+
return toCollection(host.fn(input.map(unwrap), ...argValues))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Evaluate one AST node against an input collection. */
|
|
92
|
+
export function evaluateNode(node: AstNode, context: EvaluationContext, input: TypedValue[]): TypedValue[] {
|
|
93
|
+
switch (node.kind) {
|
|
94
|
+
case 'null':
|
|
95
|
+
return []
|
|
96
|
+
case 'boolean':
|
|
97
|
+
return [{ type: SYSTEM_BOOLEAN, value: node.value }]
|
|
98
|
+
case 'string':
|
|
99
|
+
return [{ type: SYSTEM_STRING, value: node.value }]
|
|
100
|
+
case 'number':
|
|
101
|
+
return [
|
|
102
|
+
node.isLong === true
|
|
103
|
+
? { type: SYSTEM_LONG, value: BigInt(node.text) }
|
|
104
|
+
: evaluateNumberLiteral(node.text, node.isDecimal),
|
|
105
|
+
]
|
|
106
|
+
case 'date':
|
|
107
|
+
return [{ type: SYSTEM_DATE, value: parseTemporalLiteral('date', node.text) }]
|
|
108
|
+
case 'dateTime':
|
|
109
|
+
return [{ type: SYSTEM_DATETIME, value: parseTemporalLiteral('dateTime', node.text) }]
|
|
110
|
+
case 'time':
|
|
111
|
+
return [{ type: SYSTEM_TIME, value: parseTemporalLiteral('time', node.text) }]
|
|
112
|
+
case 'quantity':
|
|
113
|
+
return [evaluateQuantityLiteral(node.value, node.unit, node.unitKind)]
|
|
114
|
+
case 'identifier':
|
|
115
|
+
return navigateIdentifier(context, node.name, input)
|
|
116
|
+
case 'special':
|
|
117
|
+
return evaluateSpecialVariable(node.name, context)
|
|
118
|
+
case 'external':
|
|
119
|
+
return resolveEnvironmentVariable(context, node.name)
|
|
120
|
+
case 'dot':
|
|
121
|
+
return evaluateNode(node.right, context, evaluateNode(node.left, context, input))
|
|
122
|
+
case 'indexer':
|
|
123
|
+
return evaluateIndexer(node.target, node.index, context, input)
|
|
124
|
+
case 'call': {
|
|
125
|
+
const host = context.functions.get(node.name)
|
|
126
|
+
if (host !== undefined) {
|
|
127
|
+
return evaluateHostFunction(node.name, host, node.args, context, input)
|
|
128
|
+
}
|
|
129
|
+
// Each function argument evaluates in its own defineVariable() scope.
|
|
130
|
+
return lookupFunction(node.name, node.args.length).evaluate(context, input, node.args, evaluateArgument)
|
|
131
|
+
}
|
|
132
|
+
case 'unary':
|
|
133
|
+
return evaluateUnary(context, node.operator, evaluateNode(node.operand, context, input))
|
|
134
|
+
case 'binary':
|
|
135
|
+
// Operator operands are separate chains; variables defined in one are not
|
|
136
|
+
// visible in the other (locked by the official defineVariable tests).
|
|
137
|
+
return evaluateBinary(
|
|
138
|
+
context,
|
|
139
|
+
node.operator,
|
|
140
|
+
evaluateNode(node.left, forkVariables(context), input),
|
|
141
|
+
evaluateNode(node.right, forkVariables(context), input)
|
|
142
|
+
)
|
|
143
|
+
case 'typeOp':
|
|
144
|
+
return evaluateTypeOp(context, node.operator, evaluateNode(node.operand, context, input), node.type)
|
|
145
|
+
/* v8 ignore start -- exhaustive fallback, unreachable for real ASTs */
|
|
146
|
+
default: {
|
|
147
|
+
const unreachable: never = node
|
|
148
|
+
throw new FhirPathRuntimeError(`Unhandled node ${String(unreachable)}`)
|
|
149
|
+
}
|
|
150
|
+
/* v8 ignore stop */
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function evaluateNumberLiteral(text: string, isDecimal: boolean): TypedValue {
|
|
155
|
+
if (isDecimal) {
|
|
156
|
+
return { type: SYSTEM_DECIMAL, value: parseDecimalLiteral(text) }
|
|
157
|
+
}
|
|
158
|
+
// The grammar's NUMBER rule has no digit-count limit, so an integer literal can
|
|
159
|
+
// exceed 32 bits (or even 64). Widen through wrapNumeric the same way arithmetic
|
|
160
|
+
// results do, rather than truncating through a JS double (Number.parseInt loses
|
|
161
|
+
// precision above 2^53 and never reports the overflow).
|
|
162
|
+
return wrapNumeric(parseDecimalLiteral(text), 'Integer')
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function parseDecimalLiteral(text: string): Decimal {
|
|
166
|
+
const parsed = Decimal.fromString(text)
|
|
167
|
+
/* v8 ignore next 3 -- the lexer only emits parseable decimal literals */
|
|
168
|
+
if (parsed === undefined) {
|
|
169
|
+
throw new FhirPathRuntimeError(`Invalid decimal literal ${text}`)
|
|
170
|
+
}
|
|
171
|
+
return parsed
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function parseTemporalLiteral(kind: 'date' | 'dateTime' | 'time', text: string): Temporal {
|
|
175
|
+
const parsed =
|
|
176
|
+
kind === 'date'
|
|
177
|
+
? Temporal.parseDate(text)
|
|
178
|
+
: kind === 'dateTime'
|
|
179
|
+
? Temporal.parseDateTime(text)
|
|
180
|
+
: Temporal.parseTime(text)
|
|
181
|
+
if (!parsed) {
|
|
182
|
+
throw new FhirPathRuntimeError(`Invalid ${kind} literal @${kind === 'time' ? 'T' : ''}${text}`)
|
|
183
|
+
}
|
|
184
|
+
return parsed
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function evaluateQuantityLiteral(value: string, unit: string, unitKind: 'ucum' | 'calendar'): TypedValue {
|
|
188
|
+
return {
|
|
189
|
+
type: SYSTEM_QUANTITY,
|
|
190
|
+
value: {
|
|
191
|
+
value: parseDecimalLiteral(value),
|
|
192
|
+
unit,
|
|
193
|
+
calendar: unitKind === 'calendar',
|
|
194
|
+
},
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function evaluateSpecialVariable(name: 'this' | 'index' | 'total', context: EvaluationContext): TypedValue[] {
|
|
199
|
+
const frame = context.frame
|
|
200
|
+
switch (name) {
|
|
201
|
+
case 'this':
|
|
202
|
+
return frame.thisValue
|
|
203
|
+
case 'index': {
|
|
204
|
+
let current: typeof frame | undefined = frame
|
|
205
|
+
while (current && current.index === undefined) {
|
|
206
|
+
current = current.parent
|
|
207
|
+
}
|
|
208
|
+
if (!current || current.index === undefined) {
|
|
209
|
+
throw new FhirPathTypeError('$index is only defined inside iteration functions')
|
|
210
|
+
}
|
|
211
|
+
return [{ type: SYSTEM_INTEGER, value: current.index }]
|
|
212
|
+
}
|
|
213
|
+
case 'total': {
|
|
214
|
+
let current: typeof frame | undefined = frame
|
|
215
|
+
while (current && current.total === undefined) {
|
|
216
|
+
current = current.parent
|
|
217
|
+
}
|
|
218
|
+
if (!current || current.total === undefined) {
|
|
219
|
+
throw new FhirPathTypeError('$total is only defined inside aggregate()')
|
|
220
|
+
}
|
|
221
|
+
return current.total
|
|
222
|
+
}
|
|
223
|
+
/* v8 ignore start -- the parser only produces the three names above */
|
|
224
|
+
default:
|
|
225
|
+
return []
|
|
226
|
+
/* v8 ignore stop */
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function evaluateIndexer(
|
|
231
|
+
target: AstNode,
|
|
232
|
+
indexNode: AstNode,
|
|
233
|
+
context: EvaluationContext,
|
|
234
|
+
input: TypedValue[]
|
|
235
|
+
): TypedValue[] {
|
|
236
|
+
const collection = evaluateNode(target, context, input)
|
|
237
|
+
const index = singleton(evaluateNode(indexNode, context, input), SYSTEM_INTEGER)
|
|
238
|
+
if (index === undefined) {
|
|
239
|
+
return []
|
|
240
|
+
}
|
|
241
|
+
// The singleton check already guarantees an Integer, and out-of-range (including
|
|
242
|
+
// negative) array access yields undefined, which is the spec's empty result.
|
|
243
|
+
const item = collection[index.value as number]
|
|
244
|
+
/* v8 ignore next -- both halves run across the suites; v8 misattributes this line */
|
|
245
|
+
return item === undefined ? [] : [item]
|
|
246
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { FhirPathTypeError } from '../errors.ts'
|
|
2
|
+
import { readModelProperty } from '../fhir/model-navigation.ts'
|
|
3
|
+
import { OBJECT_TYPE, toTypedValue, type TypedValue } from '../values/typed-value.ts'
|
|
4
|
+
import type { EvaluationContext } from './context.ts'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Evaluate a bare identifier against the input. The spec's root rule (§10.1) applies
|
|
8
|
+
* first: an identifier naming the item's own type yields the item itself, which is
|
|
9
|
+
* how `Patient.name` works when the context is a Patient.
|
|
10
|
+
*/
|
|
11
|
+
export function navigateIdentifier(context: EvaluationContext, name: string, input: TypedValue[]): TypedValue[] {
|
|
12
|
+
const results: TypedValue[] = []
|
|
13
|
+
for (const item of input) {
|
|
14
|
+
if (matchesTypeName(context, item, name)) {
|
|
15
|
+
results.push(item)
|
|
16
|
+
} else if (context.model && item.type.startsWith(`${context.model.namespace}.`)) {
|
|
17
|
+
const modelRead = readModelProperty(context.model, item, name)
|
|
18
|
+
if (modelRead === undefined) {
|
|
19
|
+
// Choice elements go by stem name; a suffixed key like Observation.valueQuantity
|
|
20
|
+
// is the one unknown-element shape the official suites require to error at
|
|
21
|
+
// runtime. Everything else is the static analyzer's job (spec §11) — plain
|
|
22
|
+
// unknown elements navigate to empty, and types the model has never heard of
|
|
23
|
+
// (custom resourceTypes) read like raw JSON.
|
|
24
|
+
// See: https://hl7.org/fhirpath/en/index.html#type-safety-and-strict-evaluation
|
|
25
|
+
if (isChoiceKeyMisuse(context, item.type, name)) {
|
|
26
|
+
throw new FhirPathTypeError(
|
|
27
|
+
`Element '${name}' is not defined on ${item.type}; choice elements use their stem name`
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
if (
|
|
31
|
+
name === 'resourceType' ||
|
|
32
|
+
(context.model.listElements !== undefined && context.model.listElements(item.type) === undefined)
|
|
33
|
+
) {
|
|
34
|
+
results.push(...getProperty(item, name))
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
results.push(...modelRead)
|
|
38
|
+
}
|
|
39
|
+
} else if (context.model) {
|
|
40
|
+
const modelRead = readModelProperty(context.model, item, name)
|
|
41
|
+
results.push(...(modelRead ?? getProperty(item, name)))
|
|
42
|
+
} else {
|
|
43
|
+
results.push(...getProperty(item, name))
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return results
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** True for `valueQuantity`-style keys whose stem is a choice element of the type. */
|
|
50
|
+
function isChoiceKeyMisuse(context: EvaluationContext, type: string, name: string): boolean {
|
|
51
|
+
const model = context.model as NonNullable<EvaluationContext['model']>
|
|
52
|
+
for (let position = 1; position < name.length; position++) {
|
|
53
|
+
if (!/[A-Z]/.test(name[position] as string)) {
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
const stem = name.slice(0, position)
|
|
57
|
+
if (model.getElement(type, stem)?.isChoice === true) {
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function matchesTypeName(context: EvaluationContext, item: TypedValue, name: string): boolean {
|
|
65
|
+
// Only the namespace strips off: the backbone type FHIR.ValueSet.expansion.contains
|
|
66
|
+
// must not answer to the element name 'contains'. Lowercase primitive type names
|
|
67
|
+
// (FHIR.code) never self-match either — `children().code` means the element.
|
|
68
|
+
if (!/^[A-Z]/.test(name)) {
|
|
69
|
+
// Lowercase names are always elements: `children().code` never filters by the
|
|
70
|
+
// primitive type FHIR.code.
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
const separator = item.type.indexOf('.')
|
|
74
|
+
const local = separator === -1 ? item.type : item.type.slice(separator + 1)
|
|
75
|
+
if (local === name && item.type !== OBJECT_TYPE) {
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
if (context.model) {
|
|
79
|
+
const canonical = context.model.resolveType(name)
|
|
80
|
+
if (canonical !== undefined) {
|
|
81
|
+
return context.model.isSubtypeOf(item.type, canonical)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Read one child element from a complex value, flattening arrays. Missing → empty. */
|
|
88
|
+
export function getProperty(item: TypedValue, name: string): TypedValue[] {
|
|
89
|
+
const value = item.value
|
|
90
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
91
|
+
return []
|
|
92
|
+
}
|
|
93
|
+
// Own properties only: `Patient.constructor` or `x.toString` must be empty, not
|
|
94
|
+
// an inherited member leaking off Object.prototype.
|
|
95
|
+
if (!Object.hasOwn(value, name)) {
|
|
96
|
+
return []
|
|
97
|
+
}
|
|
98
|
+
const child = (value as Record<string, unknown>)[name]
|
|
99
|
+
if (child === undefined || child === null) {
|
|
100
|
+
return []
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(child)) {
|
|
103
|
+
return child.filter(element => element !== null && element !== undefined).map(element => toTypedValue(element))
|
|
104
|
+
}
|
|
105
|
+
return [toTypedValue(child)]
|
|
106
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FhirPathRuntimeError } from '../../errors.ts'
|
|
2
|
+
import { SYSTEM_BOOLEAN, type TypedValue } from '../../values/typed-value.ts'
|
|
3
|
+
import { pairEquals } from './equality.ts'
|
|
4
|
+
import type { BinaryOperatorTable } from './index.ts'
|
|
5
|
+
|
|
6
|
+
/** Merge with duplicate elimination using `=` semantics (spec §6.4.1 / `union()`). */
|
|
7
|
+
export function unionCollections(left: TypedValue[], right: TypedValue[]): TypedValue[] {
|
|
8
|
+
const result: TypedValue[] = []
|
|
9
|
+
for (const item of [...left, ...right]) {
|
|
10
|
+
if (!result.some(existing => pairEquals(existing, item) === true)) {
|
|
11
|
+
result.push(item)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return result
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** `in`: left singleton membership; empty left → empty, empty right → false. */
|
|
18
|
+
function inOperator(_context: unknown, left: TypedValue[], right: TypedValue[]): TypedValue[] {
|
|
19
|
+
if (left.length === 0) {
|
|
20
|
+
return []
|
|
21
|
+
}
|
|
22
|
+
if (left.length > 1) {
|
|
23
|
+
throw new FhirPathRuntimeError("The left operand of 'in' must have at most one item")
|
|
24
|
+
}
|
|
25
|
+
const item = left[0] as TypedValue
|
|
26
|
+
const found = right.some(candidate => pairEquals(item, candidate) === true)
|
|
27
|
+
return [{ type: SYSTEM_BOOLEAN, value: found }]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const collectionOperators = {
|
|
31
|
+
'|': (_context, left, right) => unionCollections(left, right),
|
|
32
|
+
in: inOperator,
|
|
33
|
+
contains: (context, left, right) => inOperator(context, right, left),
|
|
34
|
+
} satisfies BinaryOperatorTable
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { FhirPathTypeError } from '../../errors.ts'
|
|
2
|
+
import { singleton } from '../../values/collection.ts'
|
|
3
|
+
import { Temporal } from '../../values/datetime.ts'
|
|
4
|
+
import { asNumeric } from '../../values/numeric.ts'
|
|
5
|
+
import { coerceQuantityPair, compareQuantities } from '../../values/quantity.ts'
|
|
6
|
+
import { compareTemporal } from '../../values/temporal-compare.ts'
|
|
7
|
+
import { SYSTEM_BOOLEAN, SYSTEM_STRING, systemTypeOf, type TypedValue } from '../../values/typed-value.ts'
|
|
8
|
+
import type { BinaryOperatorTable } from './index.ts'
|
|
9
|
+
|
|
10
|
+
type ComparisonOperator = '<' | '>' | '<=' | '>='
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Order two singleton values (spec §6.2). Undefined means empty: an empty operand,
|
|
14
|
+
* a date/time precision mismatch, or units that cannot be compared.
|
|
15
|
+
*/
|
|
16
|
+
export function compareValues(a: TypedValue, b: TypedValue): number | undefined {
|
|
17
|
+
const numericA = asNumeric(a)
|
|
18
|
+
const numericB = asNumeric(b)
|
|
19
|
+
if (numericA && numericB) {
|
|
20
|
+
return numericA.value.compare(numericB.value)
|
|
21
|
+
}
|
|
22
|
+
if (systemTypeOf(a) === SYSTEM_STRING && systemTypeOf(b) === SYSTEM_STRING) {
|
|
23
|
+
const left = a.value as string
|
|
24
|
+
const right = b.value as string
|
|
25
|
+
if (left < right) {
|
|
26
|
+
return -1
|
|
27
|
+
}
|
|
28
|
+
return left > right ? 1 : 0
|
|
29
|
+
}
|
|
30
|
+
if (a.value instanceof Temporal && b.value instanceof Temporal) {
|
|
31
|
+
const comparison = compareTemporal(a.value, b.value)
|
|
32
|
+
if (comparison === 'differentPrecision') {
|
|
33
|
+
return undefined
|
|
34
|
+
}
|
|
35
|
+
if (comparison === 'incompatible') {
|
|
36
|
+
throw new FhirPathTypeError('Cannot compare a time with a date or dateTime')
|
|
37
|
+
}
|
|
38
|
+
return comparison
|
|
39
|
+
}
|
|
40
|
+
const quantityPair = coerceQuantityPair(a, b)
|
|
41
|
+
if (quantityPair) {
|
|
42
|
+
return compareQuantities(quantityPair[0], quantityPair[1])
|
|
43
|
+
}
|
|
44
|
+
throw new FhirPathTypeError(`Cannot compare ${a.type} with ${b.type}`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function comparisonOperator(operator: ComparisonOperator) {
|
|
48
|
+
return (_context: unknown, left: TypedValue[], right: TypedValue[]): TypedValue[] => {
|
|
49
|
+
const a = singleton(left)
|
|
50
|
+
const b = singleton(right)
|
|
51
|
+
if (a === undefined || b === undefined) {
|
|
52
|
+
return []
|
|
53
|
+
}
|
|
54
|
+
const comparison = compareValues(a, b)
|
|
55
|
+
if (comparison === undefined) {
|
|
56
|
+
return []
|
|
57
|
+
}
|
|
58
|
+
let value: boolean
|
|
59
|
+
switch (operator) {
|
|
60
|
+
case '<':
|
|
61
|
+
value = comparison < 0
|
|
62
|
+
break
|
|
63
|
+
case '>':
|
|
64
|
+
value = comparison > 0
|
|
65
|
+
break
|
|
66
|
+
case '<=':
|
|
67
|
+
value = comparison <= 0
|
|
68
|
+
break
|
|
69
|
+
default:
|
|
70
|
+
value = comparison >= 0
|
|
71
|
+
break
|
|
72
|
+
}
|
|
73
|
+
return [{ type: SYSTEM_BOOLEAN, value }]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const comparisonOperators = {
|
|
78
|
+
'<': comparisonOperator('<'),
|
|
79
|
+
'>': comparisonOperator('>'),
|
|
80
|
+
'<=': comparisonOperator('<='),
|
|
81
|
+
'>=': comparisonOperator('>='),
|
|
82
|
+
} satisfies BinaryOperatorTable
|