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.
Files changed (414) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +391 -0
  3. package/THIRD-PARTY-NOTICES.md +296 -0
  4. package/dist/analyzer/analyze-dto.d.ts +45 -0
  5. package/dist/analyzer/analyze-dto.d.ts.map +1 -0
  6. package/dist/analyzer/analyze-dto.js +147 -0
  7. package/dist/analyzer/analyze-dto.js.map +1 -0
  8. package/dist/analyzer/analyze.d.ts +98 -0
  9. package/dist/analyzer/analyze.d.ts.map +1 -0
  10. package/dist/analyzer/analyze.js +925 -0
  11. package/dist/analyzer/analyze.js.map +1 -0
  12. package/dist/analyzer/expression-policy.d.ts +210 -0
  13. package/dist/analyzer/expression-policy.d.ts.map +1 -0
  14. package/dist/analyzer/expression-policy.js +254 -0
  15. package/dist/analyzer/expression-policy.js.map +1 -0
  16. package/dist/analyzer/index.d.ts +3 -0
  17. package/dist/analyzer/index.d.ts.map +1 -0
  18. package/dist/analyzer/index.js +6 -0
  19. package/dist/analyzer/index.js.map +1 -0
  20. package/dist/analyzer/regex-safety.d.ts +10 -0
  21. package/dist/analyzer/regex-safety.d.ts.map +1 -0
  22. package/dist/analyzer/regex-safety.js +84 -0
  23. package/dist/analyzer/regex-safety.js.map +1 -0
  24. package/dist/analyzer/signatures.d.ts +72 -0
  25. package/dist/analyzer/signatures.d.ts.map +1 -0
  26. package/dist/analyzer/signatures.js +195 -0
  27. package/dist/analyzer/signatures.js.map +1 -0
  28. package/dist/api/bundle.d.ts +29 -0
  29. package/dist/api/bundle.d.ts.map +1 -0
  30. package/dist/api/bundle.js +108 -0
  31. package/dist/api/bundle.js.map +1 -0
  32. package/dist/api/cache.d.ts +10 -0
  33. package/dist/api/cache.d.ts.map +1 -0
  34. package/dist/api/cache.js +38 -0
  35. package/dist/api/cache.js.map +1 -0
  36. package/dist/api/column-signature.d.ts +53 -0
  37. package/dist/api/column-signature.d.ts.map +1 -0
  38. package/dist/api/column-signature.js +43 -0
  39. package/dist/api/column-signature.js.map +1 -0
  40. package/dist/api/compile.d.ts +120 -0
  41. package/dist/api/compile.d.ts.map +1 -0
  42. package/dist/api/compile.js +167 -0
  43. package/dist/api/compile.js.map +1 -0
  44. package/dist/api/constraints.d.ts +48 -0
  45. package/dist/api/constraints.d.ts.map +1 -0
  46. package/dist/api/constraints.js +52 -0
  47. package/dist/api/constraints.js.map +1 -0
  48. package/dist/api/dto.d.ts +134 -0
  49. package/dist/api/dto.d.ts.map +1 -0
  50. package/dist/api/dto.js +295 -0
  51. package/dist/api/dto.js.map +1 -0
  52. package/dist/api/engine.d.ts +136 -0
  53. package/dist/api/engine.d.ts.map +1 -0
  54. package/dist/api/engine.js +183 -0
  55. package/dist/api/engine.js.map +1 -0
  56. package/dist/api/evaluate.d.ts +7 -0
  57. package/dist/api/evaluate.d.ts.map +1 -0
  58. package/dist/api/evaluate.js +10 -0
  59. package/dist/api/evaluate.js.map +1 -0
  60. package/dist/api/project.d.ts +89 -0
  61. package/dist/api/project.d.ts.map +1 -0
  62. package/dist/api/project.js +150 -0
  63. package/dist/api/project.js.map +1 -0
  64. package/dist/api/tagged.d.ts +14 -0
  65. package/dist/api/tagged.d.ts.map +1 -0
  66. package/dist/api/tagged.js +13 -0
  67. package/dist/api/tagged.js.map +1 -0
  68. package/dist/cli/dto-check.d.ts +25 -0
  69. package/dist/cli/dto-check.d.ts.map +1 -0
  70. package/dist/cli/dto-check.js +77 -0
  71. package/dist/cli/dto-check.js.map +1 -0
  72. package/dist/cli/fhirpath-check.d.ts +3 -0
  73. package/dist/cli/fhirpath-check.d.ts.map +1 -0
  74. package/dist/cli/fhirpath-check.js +149 -0
  75. package/dist/cli/fhirpath-check.js.map +1 -0
  76. package/dist/cli/ts-loader.d.mts +3 -0
  77. package/dist/cli/ts-loader.d.mts.map +1 -0
  78. package/dist/cli/ts-loader.mjs +48 -0
  79. package/dist/cli/ts-loader.mjs.map +1 -0
  80. package/dist/engine/context.d.ts +173 -0
  81. package/dist/engine/context.d.ts.map +1 -0
  82. package/dist/engine/context.js +118 -0
  83. package/dist/engine/context.js.map +1 -0
  84. package/dist/engine/evaluator.d.ts +7 -0
  85. package/dist/engine/evaluator.d.ts.map +1 -0
  86. package/dist/engine/evaluator.js +196 -0
  87. package/dist/engine/evaluator.js.map +1 -0
  88. package/dist/engine/navigation.d.ts +11 -0
  89. package/dist/engine/navigation.d.ts.map +1 -0
  90. package/dist/engine/navigation.js +102 -0
  91. package/dist/engine/navigation.js.map +1 -0
  92. package/dist/engine/operators/collections.d.ts +12 -0
  93. package/dist/engine/operators/collections.d.ts.map +1 -0
  94. package/dist/engine/operators/collections.js +31 -0
  95. package/dist/engine/operators/collections.js.map +1 -0
  96. package/dist/engine/operators/comparison.d.ts +13 -0
  97. package/dist/engine/operators/comparison.d.ts.map +1 -0
  98. package/dist/engine/operators/comparison.js +77 -0
  99. package/dist/engine/operators/comparison.js.map +1 -0
  100. package/dist/engine/operators/equality.d.ts +19 -0
  101. package/dist/engine/operators/equality.d.ts.map +1 -0
  102. package/dist/engine/operators/equality.js +203 -0
  103. package/dist/engine/operators/equality.js.map +1 -0
  104. package/dist/engine/operators/index.d.ts +18 -0
  105. package/dist/engine/operators/index.d.ts.map +1 -0
  106. package/dist/engine/operators/index.js +30 -0
  107. package/dist/engine/operators/index.js.map +1 -0
  108. package/dist/engine/operators/logic.d.ts +8 -0
  109. package/dist/engine/operators/logic.d.ts.map +1 -0
  110. package/dist/engine/operators/logic.js +38 -0
  111. package/dist/engine/operators/logic.js.map +1 -0
  112. package/dist/engine/operators/math.d.ts +13 -0
  113. package/dist/engine/operators/math.d.ts.map +1 -0
  114. package/dist/engine/operators/math.js +198 -0
  115. package/dist/engine/operators/math.js.map +1 -0
  116. package/dist/engine/operators/strings.d.ts +8 -0
  117. package/dist/engine/operators/strings.d.ts.map +1 -0
  118. package/dist/engine/operators/strings.js +22 -0
  119. package/dist/engine/operators/strings.js.map +1 -0
  120. package/dist/engine/operators/types.d.ts +3 -0
  121. package/dist/engine/operators/types.d.ts.map +1 -0
  122. package/dist/engine/operators/types.js +15 -0
  123. package/dist/engine/operators/types.js.map +1 -0
  124. package/dist/engine/type-matching.d.ts +20 -0
  125. package/dist/engine/type-matching.d.ts.map +1 -0
  126. package/dist/engine/type-matching.js +122 -0
  127. package/dist/engine/type-matching.js.map +1 -0
  128. package/dist/errors.d.ts +25 -0
  129. package/dist/errors.d.ts.map +1 -0
  130. package/dist/errors.js +21 -0
  131. package/dist/errors.js.map +1 -0
  132. package/dist/eslint/index.d.ts +12 -0
  133. package/dist/eslint/index.d.ts.map +1 -0
  134. package/dist/eslint/index.js +316 -0
  135. package/dist/eslint/index.js.map +1 -0
  136. package/dist/fhir/html-checks.d.ts +7 -0
  137. package/dist/fhir/html-checks.d.ts.map +1 -0
  138. package/dist/fhir/html-checks.js +256 -0
  139. package/dist/fhir/html-checks.js.map +1 -0
  140. package/dist/fhir/model-navigation.d.ts +11 -0
  141. package/dist/fhir/model-navigation.d.ts.map +1 -0
  142. package/dist/fhir/model-navigation.js +142 -0
  143. package/dist/fhir/model-navigation.js.map +1 -0
  144. package/dist/functions/aggregate.d.ts +2 -0
  145. package/dist/functions/aggregate.d.ts.map +1 -0
  146. package/dist/functions/aggregate.js +127 -0
  147. package/dist/functions/aggregate.js.map +1 -0
  148. package/dist/functions/boundary.d.ts +2 -0
  149. package/dist/functions/boundary.d.ts.map +1 -0
  150. package/dist/functions/boundary.js +189 -0
  151. package/dist/functions/boundary.js.map +1 -0
  152. package/dist/functions/combining.d.ts +2 -0
  153. package/dist/functions/combining.d.ts.map +1 -0
  154. package/dist/functions/combining.js +13 -0
  155. package/dist/functions/combining.js.map +1 -0
  156. package/dist/functions/control.d.ts +2 -0
  157. package/dist/functions/control.d.ts.map +1 -0
  158. package/dist/functions/control.js +25 -0
  159. package/dist/functions/control.js.map +1 -0
  160. package/dist/functions/conversion.d.ts +3 -0
  161. package/dist/functions/conversion.d.ts.map +1 -0
  162. package/dist/functions/conversion.js +316 -0
  163. package/dist/functions/conversion.js.map +1 -0
  164. package/dist/functions/date-components.d.ts +2 -0
  165. package/dist/functions/date-components.d.ts.map +1 -0
  166. package/dist/functions/date-components.js +81 -0
  167. package/dist/functions/date-components.js.map +1 -0
  168. package/dist/functions/existence.d.ts +4 -0
  169. package/dist/functions/existence.d.ts.map +1 -0
  170. package/dist/functions/existence.js +97 -0
  171. package/dist/functions/existence.js.map +1 -0
  172. package/dist/functions/fhir.d.ts +2 -0
  173. package/dist/functions/fhir.d.ts.map +1 -0
  174. package/dist/functions/fhir.js +222 -0
  175. package/dist/functions/fhir.js.map +1 -0
  176. package/dist/functions/filtering.d.ts +2 -0
  177. package/dist/functions/filtering.d.ts.map +1 -0
  178. package/dist/functions/filtering.js +112 -0
  179. package/dist/functions/filtering.js.map +1 -0
  180. package/dist/functions/install.d.ts +18 -0
  181. package/dist/functions/install.d.ts.map +1 -0
  182. package/dist/functions/install.js +20 -0
  183. package/dist/functions/install.js.map +1 -0
  184. package/dist/functions/iteration.d.ts +7 -0
  185. package/dist/functions/iteration.d.ts.map +1 -0
  186. package/dist/functions/iteration.js +9 -0
  187. package/dist/functions/iteration.js.map +1 -0
  188. package/dist/functions/math.d.ts +2 -0
  189. package/dist/functions/math.d.ts.map +1 -0
  190. package/dist/functions/math.js +152 -0
  191. package/dist/functions/math.js.map +1 -0
  192. package/dist/functions/reflection.d.ts +2 -0
  193. package/dist/functions/reflection.d.ts.map +1 -0
  194. package/dist/functions/reflection.js +23 -0
  195. package/dist/functions/reflection.js.map +1 -0
  196. package/dist/functions/registry.d.ts +28 -0
  197. package/dist/functions/registry.d.ts.map +1 -0
  198. package/dist/functions/registry.js +46 -0
  199. package/dist/functions/registry.js.map +1 -0
  200. package/dist/functions/sort.d.ts +2 -0
  201. package/dist/functions/sort.d.ts.map +1 -0
  202. package/dist/functions/sort.js +48 -0
  203. package/dist/functions/sort.js.map +1 -0
  204. package/dist/functions/string.d.ts +2 -0
  205. package/dist/functions/string.d.ts.map +1 -0
  206. package/dist/functions/string.js +353 -0
  207. package/dist/functions/string.js.map +1 -0
  208. package/dist/functions/subsetting.d.ts +2 -0
  209. package/dist/functions/subsetting.d.ts.map +1 -0
  210. package/dist/functions/subsetting.js +72 -0
  211. package/dist/functions/subsetting.js.map +1 -0
  212. package/dist/functions/tree.d.ts +8 -0
  213. package/dist/functions/tree.d.ts.map +1 -0
  214. package/dist/functions/tree.js +109 -0
  215. package/dist/functions/tree.js.map +1 -0
  216. package/dist/functions/type-specifier.d.ts +8 -0
  217. package/dist/functions/type-specifier.d.ts.map +1 -0
  218. package/dist/functions/type-specifier.js +27 -0
  219. package/dist/functions/type-specifier.js.map +1 -0
  220. package/dist/functions/utility.d.ts +2 -0
  221. package/dist/functions/utility.d.ts.map +1 -0
  222. package/dist/functions/utility.js +76 -0
  223. package/dist/functions/utility.js.map +1 -0
  224. package/dist/functions/variables.d.ts +2 -0
  225. package/dist/functions/variables.d.ts.map +1 -0
  226. package/dist/functions/variables.js +35 -0
  227. package/dist/functions/variables.js.map +1 -0
  228. package/dist/index.d.ts +25 -0
  229. package/dist/index.d.ts.map +1 -0
  230. package/dist/index.js +11 -0
  231. package/dist/index.js.map +1 -0
  232. package/dist/lexer/lexer.d.ts +4 -0
  233. package/dist/lexer/lexer.d.ts.map +1 -0
  234. package/dist/lexer/lexer.js +318 -0
  235. package/dist/lexer/lexer.js.map +1 -0
  236. package/dist/lexer/tokens.d.ts +23 -0
  237. package/dist/lexer/tokens.d.ts.map +1 -0
  238. package/dist/lexer/tokens.js +40 -0
  239. package/dist/lexer/tokens.js.map +1 -0
  240. package/dist/model/provider.d.ts +36 -0
  241. package/dist/model/provider.d.ts.map +1 -0
  242. package/dist/model/provider.js +2 -0
  243. package/dist/model/provider.js.map +1 -0
  244. package/dist/parser/ast.d.ts +104 -0
  245. package/dist/parser/ast.d.ts.map +1 -0
  246. package/dist/parser/ast.js +2 -0
  247. package/dist/parser/ast.js.map +1 -0
  248. package/dist/parser/parser.d.ts +4 -0
  249. package/dist/parser/parser.d.ts.map +1 -0
  250. package/dist/parser/parser.js +299 -0
  251. package/dist/parser/parser.js.map +1 -0
  252. package/dist/parser/precedence.d.ts +24 -0
  253. package/dist/parser/precedence.d.ts.map +1 -0
  254. package/dist/parser/precedence.js +52 -0
  255. package/dist/parser/precedence.js.map +1 -0
  256. package/dist/parser/printer.d.ts +4 -0
  257. package/dist/parser/printer.d.ts.map +1 -0
  258. package/dist/parser/printer.js +112 -0
  259. package/dist/parser/printer.js.map +1 -0
  260. package/dist/r4/generated/resources-data.d.ts +3 -0
  261. package/dist/r4/generated/resources-data.d.ts.map +1 -0
  262. package/dist/r4/generated/resources-data.js +28628 -0
  263. package/dist/r4/generated/resources-data.js.map +1 -0
  264. package/dist/r4/generated/type-maps.d.ts +43153 -0
  265. package/dist/r4/generated/type-maps.d.ts.map +1 -0
  266. package/dist/r4/generated/type-maps.js +4 -0
  267. package/dist/r4/generated/type-maps.js.map +1 -0
  268. package/dist/r4/generated/types-data.d.ts +3 -0
  269. package/dist/r4/generated/types-data.d.ts.map +1 -0
  270. package/dist/r4/generated/types-data.js +2205 -0
  271. package/dist/r4/generated/types-data.js.map +1 -0
  272. package/dist/r4/index.d.ts +9 -0
  273. package/dist/r4/index.d.ts.map +1 -0
  274. package/dist/r4/index.js +94 -0
  275. package/dist/r4/index.js.map +1 -0
  276. package/dist/r4/model-data.d.ts +17 -0
  277. package/dist/r4/model-data.d.ts.map +1 -0
  278. package/dist/r4/model-data.js +2 -0
  279. package/dist/r4/model-data.js.map +1 -0
  280. package/dist/sites/index.d.ts +31 -0
  281. package/dist/sites/index.d.ts.map +1 -0
  282. package/dist/sites/index.js +205 -0
  283. package/dist/sites/index.js.map +1 -0
  284. package/dist/typed/infer.d.ts +234 -0
  285. package/dist/typed/infer.d.ts.map +1 -0
  286. package/dist/typed/infer.js +85 -0
  287. package/dist/typed/infer.js.map +1 -0
  288. package/dist/typed/perf-fixture.types.d.ts +136 -0
  289. package/dist/typed/perf-fixture.types.d.ts.map +1 -0
  290. package/dist/typed/perf-fixture.types.js +2 -0
  291. package/dist/typed/perf-fixture.types.js.map +1 -0
  292. package/dist/values/collection.d.ts +24 -0
  293. package/dist/values/collection.d.ts.map +1 -0
  294. package/dist/values/collection.js +51 -0
  295. package/dist/values/collection.js.map +1 -0
  296. package/dist/values/datetime.d.ts +54 -0
  297. package/dist/values/datetime.d.ts.map +1 -0
  298. package/dist/values/datetime.js +226 -0
  299. package/dist/values/datetime.js.map +1 -0
  300. package/dist/values/decimal.d.ts +48 -0
  301. package/dist/values/decimal.d.ts.map +1 -0
  302. package/dist/values/decimal.js +188 -0
  303. package/dist/values/decimal.js.map +1 -0
  304. package/dist/values/numeric.d.ts +24 -0
  305. package/dist/values/numeric.d.ts.map +1 -0
  306. package/dist/values/numeric.js +53 -0
  307. package/dist/values/numeric.js.map +1 -0
  308. package/dist/values/quantity.d.ts +49 -0
  309. package/dist/values/quantity.d.ts.map +1 -0
  310. package/dist/values/quantity.js +297 -0
  311. package/dist/values/quantity.js.map +1 -0
  312. package/dist/values/temporal-arithmetic.d.ts +17 -0
  313. package/dist/values/temporal-arithmetic.d.ts.map +1 -0
  314. package/dist/values/temporal-arithmetic.js +183 -0
  315. package/dist/values/temporal-arithmetic.js.map +1 -0
  316. package/dist/values/temporal-compare.d.ts +9 -0
  317. package/dist/values/temporal-compare.d.ts.map +1 -0
  318. package/dist/values/temporal-compare.js +59 -0
  319. package/dist/values/temporal-compare.js.map +1 -0
  320. package/dist/values/type-compat.d.ts +47 -0
  321. package/dist/values/type-compat.d.ts.map +1 -0
  322. package/dist/values/type-compat.js +100 -0
  323. package/dist/values/type-compat.js.map +1 -0
  324. package/dist/values/typed-value.d.ts +48 -0
  325. package/dist/values/typed-value.d.ts.map +1 -0
  326. package/dist/values/typed-value.js +117 -0
  327. package/dist/values/typed-value.js.map +1 -0
  328. package/dist/values/ucum.d.ts +14 -0
  329. package/dist/values/ucum.d.ts.map +1 -0
  330. package/dist/values/ucum.js +146 -0
  331. package/dist/values/ucum.js.map +1 -0
  332. package/package.json +137 -0
  333. package/src/analyzer/analyze-dto.ts +195 -0
  334. package/src/analyzer/analyze.ts +1181 -0
  335. package/src/analyzer/expression-policy.ts +434 -0
  336. package/src/analyzer/index.ts +23 -0
  337. package/src/analyzer/regex-safety.ts +85 -0
  338. package/src/analyzer/signatures.ts +260 -0
  339. package/src/api/bundle.ts +132 -0
  340. package/src/api/cache.ts +40 -0
  341. package/src/api/column-signature.ts +71 -0
  342. package/src/api/compile.ts +308 -0
  343. package/src/api/constraints.ts +104 -0
  344. package/src/api/dto.ts +445 -0
  345. package/src/api/engine.ts +328 -0
  346. package/src/api/evaluate.ts +11 -0
  347. package/src/api/project.ts +255 -0
  348. package/src/api/tagged.ts +35 -0
  349. package/src/cli/dto-check.ts +94 -0
  350. package/src/cli/fhirpath-check.ts +168 -0
  351. package/src/cli/ts-loader.mjs +49 -0
  352. package/src/engine/context.ts +282 -0
  353. package/src/engine/evaluator.ts +246 -0
  354. package/src/engine/navigation.ts +106 -0
  355. package/src/engine/operators/collections.ts +34 -0
  356. package/src/engine/operators/comparison.ts +82 -0
  357. package/src/engine/operators/equality.ts +232 -0
  358. package/src/engine/operators/index.ts +65 -0
  359. package/src/engine/operators/logic.ts +53 -0
  360. package/src/engine/operators/math.ts +225 -0
  361. package/src/engine/operators/strings.ts +25 -0
  362. package/src/engine/operators/types.ts +16 -0
  363. package/src/engine/type-matching.ts +148 -0
  364. package/src/errors.ts +33 -0
  365. package/src/eslint/index.ts +388 -0
  366. package/src/fhir/html-checks.ts +266 -0
  367. package/src/fhir/model-navigation.ts +148 -0
  368. package/src/functions/aggregate.ts +136 -0
  369. package/src/functions/boundary.ts +209 -0
  370. package/src/functions/combining.ts +15 -0
  371. package/src/functions/control.ts +25 -0
  372. package/src/functions/conversion.ts +349 -0
  373. package/src/functions/date-components.ts +88 -0
  374. package/src/functions/existence.ts +107 -0
  375. package/src/functions/fhir.ts +247 -0
  376. package/src/functions/filtering.ts +120 -0
  377. package/src/functions/install.ts +19 -0
  378. package/src/functions/iteration.ts +21 -0
  379. package/src/functions/math.ts +167 -0
  380. package/src/functions/reflection.ts +24 -0
  381. package/src/functions/registry.ts +72 -0
  382. package/src/functions/sort.ts +68 -0
  383. package/src/functions/string.ts +413 -0
  384. package/src/functions/subsetting.ts +89 -0
  385. package/src/functions/tree.ts +112 -0
  386. package/src/functions/type-specifier.ts +29 -0
  387. package/src/functions/utility.ts +82 -0
  388. package/src/functions/variables.ts +36 -0
  389. package/src/index.ts +30 -0
  390. package/src/lexer/lexer.ts +341 -0
  391. package/src/lexer/tokens.ts +69 -0
  392. package/src/model/provider.ts +36 -0
  393. package/src/parser/ast.ts +164 -0
  394. package/src/parser/parser.ts +321 -0
  395. package/src/parser/precedence.ts +52 -0
  396. package/src/parser/printer.ts +114 -0
  397. package/src/r4/generated/resources-data.ts +28631 -0
  398. package/src/r4/generated/type-maps.ts +22145 -0
  399. package/src/r4/generated/types-data.ts +2208 -0
  400. package/src/r4/index.ts +107 -0
  401. package/src/r4/model-data.ts +17 -0
  402. package/src/sites/index.ts +285 -0
  403. package/src/typed/infer.ts +433 -0
  404. package/src/typed/perf-fixture.types.ts +143 -0
  405. package/src/values/collection.ts +57 -0
  406. package/src/values/datetime.ts +285 -0
  407. package/src/values/decimal.ts +213 -0
  408. package/src/values/numeric.ts +63 -0
  409. package/src/values/quantity.ts +358 -0
  410. package/src/values/temporal-arithmetic.ts +231 -0
  411. package/src/values/temporal-compare.ts +65 -0
  412. package/src/values/type-compat.ts +133 -0
  413. package/src/values/typed-value.ts +151 -0
  414. 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