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,107 @@
1
+ import { pairEquals } from '../engine/operators/equality.ts'
2
+ import { FhirPathTypeError } from '../errors.ts'
3
+ import { booleanSingleton, wrapBoolean } from '../values/collection.ts'
4
+ import { SYSTEM_BOOLEAN, SYSTEM_INTEGER, systemTypeOf, type TypedValue } from '../values/typed-value.ts'
5
+ import { perItem } from './iteration.ts'
6
+ import { argAt, registerFunction } from './registry.ts'
7
+
8
+ registerFunction('empty', {
9
+ minArity: 0,
10
+ maxArity: 0,
11
+ evaluate: (_context, input) => wrapBoolean(input.length === 0),
12
+ })
13
+
14
+ registerFunction('exists', {
15
+ minArity: 0,
16
+ maxArity: 1,
17
+ evaluate: (context, input, args, evaluateNode) => {
18
+ if (args.length === 0) {
19
+ return wrapBoolean(input.length > 0)
20
+ }
21
+ let found = false
22
+ perItem(context, input, argAt(args, 0), evaluateNode, (_item, result) => {
23
+ found = found || booleanSingleton(result) === true
24
+ })
25
+ return wrapBoolean(found)
26
+ },
27
+ })
28
+
29
+ registerFunction('all', {
30
+ minArity: 1,
31
+ maxArity: 1,
32
+ evaluate: (context, input, args, evaluateNode) => {
33
+ let all = true
34
+ perItem(context, input, argAt(args, 0), evaluateNode, (_item, result) => {
35
+ all = all && booleanSingleton(result) === true
36
+ })
37
+ return wrapBoolean(all)
38
+ },
39
+ })
40
+
41
+ function booleanAggregate(name: string, fold: (values: boolean[]) => boolean) {
42
+ registerFunction(name, {
43
+ minArity: 0,
44
+ maxArity: 0,
45
+ evaluate: (_context, input) => {
46
+ const values = input.map(item => {
47
+ if (systemTypeOf(item) !== SYSTEM_BOOLEAN) {
48
+ throw new FhirPathTypeError(`${name}() expects a collection of booleans, found ${item.type}`)
49
+ }
50
+ return item.value as boolean
51
+ })
52
+ return wrapBoolean(fold(values))
53
+ },
54
+ })
55
+ }
56
+
57
+ booleanAggregate('allTrue', values => values.every(value => value))
58
+ booleanAggregate('anyTrue', values => values.some(value => value))
59
+ booleanAggregate('allFalse', values => values.every(value => !value))
60
+ booleanAggregate('anyFalse', values => values.some(value => !value))
61
+
62
+ registerFunction('count', {
63
+ minArity: 0,
64
+ maxArity: 0,
65
+ evaluate: (_context, input) => [{ type: SYSTEM_INTEGER, value: input.length }],
66
+ })
67
+
68
+ /** Duplicate elimination with `=` semantics; shared with the `|` operator and isDistinct(). */
69
+ export function distinctItems(input: TypedValue[]): TypedValue[] {
70
+ const result: TypedValue[] = []
71
+ for (const item of input) {
72
+ if (!result.some(existing => pairEquals(existing, item) === true)) {
73
+ result.push(item)
74
+ }
75
+ }
76
+ return result
77
+ }
78
+
79
+ registerFunction('distinct', {
80
+ minArity: 0,
81
+ maxArity: 0,
82
+ evaluate: (_context, input) => distinctItems(input),
83
+ })
84
+
85
+ registerFunction('isDistinct', {
86
+ minArity: 0,
87
+ maxArity: 0,
88
+ evaluate: (_context, input) => wrapBoolean(distinctItems(input).length === input.length),
89
+ })
90
+
91
+ registerFunction('subsetOf', {
92
+ minArity: 1,
93
+ maxArity: 1,
94
+ evaluate: (context, input, args, evaluateNode) => {
95
+ const other = evaluateNode(argAt(args, 0), context, input)
96
+ return wrapBoolean(input.every(item => other.some(candidate => pairEquals(item, candidate) === true)))
97
+ },
98
+ })
99
+
100
+ registerFunction('supersetOf', {
101
+ minArity: 1,
102
+ maxArity: 1,
103
+ evaluate: (context, input, args, evaluateNode) => {
104
+ const other = evaluateNode(argAt(args, 0), context, input)
105
+ return wrapBoolean(other.every(item => input.some(candidate => pairEquals(item, candidate) === true)))
106
+ },
107
+ })
@@ -0,0 +1,247 @@
1
+ import { FhirPathRuntimeError, FhirPathTypeError } from '../errors.ts'
2
+ import { validateNarrative } from '../fhir/html-checks.ts'
3
+ import { singleton, wrapBoolean } from '../values/collection.ts'
4
+ import { calendarToUcumLoose, compareQuantities, promoteQuantity } from '../values/quantity.ts'
5
+ import { SYSTEM_QUANTITY, SYSTEM_STRING, systemTypeOf, toTypedValue, type TypedValue } from '../values/typed-value.ts'
6
+ import { argAt, registerFunction } from './registry.ts'
7
+
8
+ /** extension(url): extensions of each item, including primitive `_field` extensions. */
9
+ registerFunction('extension', {
10
+ minArity: 1,
11
+ maxArity: 1,
12
+ evaluate: (context, input, args, evaluateNode) => {
13
+ const urlValue = singleton(evaluateNode(argAt(args, 0), context, input))
14
+ if (urlValue === undefined) {
15
+ return []
16
+ }
17
+ if (systemTypeOf(urlValue) !== SYSTEM_STRING) {
18
+ throw new FhirPathTypeError('extension() expects a String url argument')
19
+ }
20
+ const url = urlValue.value as string
21
+ const result: TypedValue[] = []
22
+ for (const item of input) {
23
+ for (const extension of extensionsOf(item)) {
24
+ if ((extension as { url?: unknown }).url === url) {
25
+ result.push({ type: 'FHIR.Extension', value: extension })
26
+ }
27
+ }
28
+ }
29
+ return result
30
+ },
31
+ })
32
+
33
+ function extensionsOf(item: TypedValue): unknown[] {
34
+ const containers: unknown[] = [item.value, item.primitiveElement]
35
+ const result: unknown[] = []
36
+ for (const container of containers) {
37
+ if (typeof container === 'object' && container !== null) {
38
+ const extensions = (container as { extension?: unknown }).extension
39
+ if (Array.isArray(extensions)) {
40
+ result.push(...extensions)
41
+ }
42
+ }
43
+ }
44
+ return result
45
+ }
46
+
47
+ /**
48
+ * True when the input holds a single primitive with an actual value; a multi-item
49
+ * input is "not a single value" (FHIR spec wording), so false — not an error.
50
+ */
51
+ registerFunction('hasValue', {
52
+ minArity: 0,
53
+ maxArity: 0,
54
+ evaluate: (_context, input) => {
55
+ if (input.length === 0) {
56
+ return []
57
+ }
58
+ if (input.length > 1) {
59
+ return wrapBoolean(false)
60
+ }
61
+ const item = input[0] as TypedValue
62
+ return wrapBoolean(
63
+ systemTypeOf(item) !== undefined &&
64
+ item.type !== SYSTEM_QUANTITY &&
65
+ item.value !== undefined &&
66
+ item.value !== null
67
+ )
68
+ },
69
+ })
70
+
71
+ registerFunction('getValue', {
72
+ minArity: 0,
73
+ maxArity: 0,
74
+ evaluate: (_context, input) => {
75
+ if (input.length !== 1) {
76
+ return []
77
+ }
78
+ const item = input[0] as TypedValue
79
+ if (systemTypeOf(item) === undefined || item.value === undefined) {
80
+ return []
81
+ }
82
+ return [{ type: systemTypeOf(item) as string, value: item.value }]
83
+ },
84
+ })
85
+
86
+ /**
87
+ * Resolves contained references and Bundle entries against the evaluation root.
88
+ * External references return empty. A contained reference inside a Bundle entry
89
+ * also returns empty because resolution does not change root for each entry.
90
+ */
91
+ registerFunction('resolve', {
92
+ minArity: 0,
93
+ maxArity: 0,
94
+ evaluate: (context, input) => {
95
+ const result: TypedValue[] = []
96
+ const scope = context.root[0]?.value as ResolveScope | undefined
97
+ for (const item of input) {
98
+ const reference = referenceStringOf(item)
99
+ if (reference === undefined) {
100
+ continue
101
+ }
102
+ const resolved = resolveReference(reference, scope)
103
+ if (resolved !== undefined) {
104
+ result.push(toTypedValue(resolved))
105
+ }
106
+ }
107
+ return result
108
+ },
109
+ })
110
+
111
+ function referenceStringOf(item: TypedValue): string | undefined {
112
+ if (typeof item.value === 'string') {
113
+ return item.value
114
+ }
115
+ if (typeof item.value === 'object' && item.value !== null) {
116
+ const reference = (item.value as { reference?: unknown }).reference
117
+ return typeof reference === 'string' ? reference : undefined
118
+ }
119
+ return undefined
120
+ }
121
+
122
+ interface BundleEntry {
123
+ fullUrl?: unknown
124
+ resource?: { resourceType?: unknown; id?: unknown }
125
+ }
126
+
127
+ interface ResolveScope {
128
+ resourceType?: unknown
129
+ contained?: unknown
130
+ entry?: unknown
131
+ }
132
+
133
+ function resolveReference(reference: string, scope: ResolveScope | undefined): unknown {
134
+ if (!scope) {
135
+ return undefined
136
+ }
137
+ if (reference.startsWith('#')) {
138
+ const id = reference.slice(1)
139
+ if (id === '') {
140
+ return scope
141
+ }
142
+ if (Array.isArray(scope.contained)) {
143
+ return scope.contained.find(resource => (resource as { id?: unknown } | null)?.id === id)
144
+ }
145
+ return undefined
146
+ }
147
+ if (scope.resourceType === 'Bundle' && Array.isArray(scope.entry)) {
148
+ const isAbsolute = reference.includes('://') || reference.startsWith('urn:')
149
+ for (const entry of scope.entry) {
150
+ if (!isObject(entry)) {
151
+ continue
152
+ }
153
+ const { fullUrl, resource } = entry as BundleEntry
154
+ // Absolute references match a fullUrl exactly. Relative references
155
+ // (Type/id) match a resource's own type/id — a fullUrl suffix match alone
156
+ // would wrongly resolve Patient/123 against a different base whose resource
157
+ // id is not 123, so the resource must confirm the type/id.
158
+ if (isAbsolute && fullUrl === reference) {
159
+ return resource
160
+ }
161
+ if (resource && `${String(resource.resourceType)}/${String(resource.id)}` === reference) {
162
+ return resource
163
+ }
164
+ }
165
+ }
166
+ return undefined
167
+ }
168
+
169
+ function isObject(value: unknown): value is Record<string, unknown> {
170
+ return typeof value === 'object' && value !== null
171
+ }
172
+
173
+ /** Validate narrative xhtml against the FHIR rules (real implementation, not a stub). */
174
+ registerFunction('htmlChecks', {
175
+ minArity: 0,
176
+ maxArity: 0,
177
+ evaluate: (_context, input) => {
178
+ const item = singleton(input)
179
+ if (item === undefined) {
180
+ return []
181
+ }
182
+ return wrapBoolean(typeof item.value === 'string' && validateNarrative(item.value))
183
+ },
184
+ })
185
+
186
+ /** Quantities are comparable when their units share a dimension (FHIR R5 addition). */
187
+ registerFunction('comparable', {
188
+ minArity: 1,
189
+ maxArity: 1,
190
+ evaluate: (context, input, args, evaluateNode) => {
191
+ const left = singleton(input)
192
+ const right = singleton(evaluateNode(argAt(args, 0), context, input))
193
+ if (left === undefined || right === undefined) {
194
+ return []
195
+ }
196
+ const a = promoteQuantity(left)
197
+ const b = promoteQuantity(right)
198
+ if (!(a && b)) {
199
+ throw new FhirPathTypeError('comparable() expects Quantity operands')
200
+ }
201
+ // Dimensions decide comparability, so calendar durations count as their
202
+ // loose UCUM twins: 1 year.comparable(1 second) is true.
203
+ return wrapBoolean(compareQuantities(calendarToUcumLoose(a), calendarToUcumLoose(b)) !== undefined)
204
+ },
205
+ })
206
+
207
+ /**
208
+ * Base-StructureDefinition conformance only: the url must name a core resource type.
209
+ * Real profile validation is a deferred feature (README register).
210
+ */
211
+ registerFunction('conformsTo', {
212
+ minArity: 1,
213
+ maxArity: 1,
214
+ evaluate: (context, input, args, evaluateNode) => {
215
+ const item = singleton(input)
216
+ if (item === undefined) {
217
+ return []
218
+ }
219
+ const urlValue = singleton(evaluateNode(argAt(args, 0), context, input))
220
+ const url = typeof urlValue?.value === 'string' ? urlValue.value : ''
221
+ const match = /^http:\/\/hl7\.org\/fhir\/StructureDefinition\/([A-Za-z]+)$/.exec(url)
222
+ if (!match) {
223
+ throw new FhirPathRuntimeError(`conformsTo() only supports base StructureDefinition urls, got '${url}'`)
224
+ }
225
+ const resourceType = (item.value as { resourceType?: unknown } | undefined)?.resourceType
226
+ return wrapBoolean(resourceType === match[1])
227
+ },
228
+ })
229
+
230
+ /** Deferred features (see the README register): registered so they fail with a clear message. */
231
+ function unsupported(name: string, minArity: number, maxArity: number, reason: string): void {
232
+ registerFunction(name, {
233
+ minArity,
234
+ maxArity,
235
+ evaluate: () => {
236
+ throw new FhirPathRuntimeError(`${name}() is not supported in v1: ${reason}`)
237
+ },
238
+ })
239
+ }
240
+
241
+ unsupported('memberOf', 1, 1, 'terminology functions need a terminology service')
242
+ unsupported('subsumes', 1, 1, 'terminology functions need a terminology service')
243
+ unsupported('subsumedBy', 1, 1, 'terminology functions need a terminology service')
244
+ unsupported('slice', 2, 2, 'profile slicing needs profile definitions')
245
+ unsupported('elementDefinition', 0, 0, 'element definitions need profile definitions')
246
+ unsupported('checkModifiers', 0, 1, 'modifier checking needs profile definitions')
247
+ unsupported('weight', 0, 0, 'item weights need code-system lookups')
@@ -0,0 +1,120 @@
1
+ import { pairEquals } from '../engine/operators/equality.ts'
2
+ import { isKnownTypeName, itemMatchesType } from '../engine/type-matching.ts'
3
+ import { FhirPathRuntimeError } from '../errors.ts'
4
+ import { booleanSingleton, singleton, wrapBoolean } from '../values/collection.ts'
5
+ import type { TypedValue } from '../values/typed-value.ts'
6
+ import { perItem } from './iteration.ts'
7
+ import { argAt, registerFunction } from './registry.ts'
8
+ import { typePartsFromArgument } from './type-specifier.ts'
9
+
10
+ registerFunction('where', {
11
+ minArity: 1,
12
+ maxArity: 1,
13
+ evaluate: (context, input, args, evaluateNode) => {
14
+ const result: TypedValue[] = []
15
+ perItem(context, input, argAt(args, 0), evaluateNode, (item, criteria) => {
16
+ if (booleanSingleton(criteria) === true) {
17
+ result.push(item)
18
+ }
19
+ })
20
+ return result
21
+ },
22
+ })
23
+
24
+ registerFunction('select', {
25
+ minArity: 1,
26
+ maxArity: 1,
27
+ evaluate: (context, input, args, evaluateNode) => {
28
+ const result: TypedValue[] = []
29
+ perItem(context, input, argAt(args, 0), evaluateNode, (_item, projected) => {
30
+ result.push(...projected)
31
+ })
32
+ return result
33
+ },
34
+ })
35
+
36
+ registerFunction('repeat', {
37
+ minArity: 1,
38
+ maxArity: 1,
39
+ evaluate: (context, input, args, evaluateNode) => {
40
+ const expression = argAt(args, 0)
41
+ const collected: TypedValue[] = []
42
+ let current = input
43
+ while (current.length > 0) {
44
+ const produced: TypedValue[] = []
45
+ perItem(context, current, expression, evaluateNode, (_item, projected) => {
46
+ produced.push(...projected)
47
+ })
48
+ // Only never-seen items continue the loop (including duplicates produced in
49
+ // the same round), so cyclic data terminates and results stay distinct.
50
+ const fresh: typeof produced = []
51
+ for (const item of produced) {
52
+ if (!collected.some(existing => existing.value === item.value || pairEquals(existing, item) === true)) {
53
+ collected.push(item)
54
+ fresh.push(item)
55
+ }
56
+ }
57
+ current = fresh
58
+ }
59
+ return collected
60
+ },
61
+ })
62
+
63
+ /** coalesce(...) — ballot STU: the first argument that evaluates non-empty. */
64
+ registerFunction('coalesce', {
65
+ minArity: 0,
66
+ maxArity: 99,
67
+ evaluate: (context, input, args, evaluateNode) => {
68
+ for (const arg of args) {
69
+ const value = evaluateNode(arg, context, input)
70
+ if (value.length > 0) {
71
+ return value
72
+ }
73
+ }
74
+ return []
75
+ },
76
+ })
77
+
78
+ registerFunction('ofType', {
79
+ minArity: 1,
80
+ maxArity: 1,
81
+ evaluate: (context, input, args) => {
82
+ const parts = typePartsFromArgument('ofType', argAt(args, 0))
83
+ requireKnownType(context, 'ofType', parts)
84
+ return input.filter(item => itemMatchesType(context, item, parts, { exact: true }))
85
+ },
86
+ })
87
+
88
+ function requireKnownType(context: Parameters<typeof isKnownTypeName>[0], name: string, parts: string[]): void {
89
+ // Without a model there is no authority on type names; stay lenient.
90
+ if (context.model && !isKnownTypeName(context, parts)) {
91
+ throw new FhirPathRuntimeError(`${name}() received an unknown type name '${parts.join('.')}'`)
92
+ }
93
+ }
94
+
95
+ // Deprecated function forms of the `is` and `as` operators (spec §6.3).
96
+ registerFunction('is', {
97
+ minArity: 1,
98
+ maxArity: 1,
99
+ evaluate: (context, input, args) => {
100
+ const item = singleton(input)
101
+ if (item === undefined) {
102
+ return []
103
+ }
104
+ return wrapBoolean(itemMatchesType(context, item, typePartsFromArgument('is', argAt(args, 0))))
105
+ },
106
+ })
107
+
108
+ registerFunction('as', {
109
+ minArity: 1,
110
+ maxArity: 1,
111
+ evaluate: (context, input, args) => {
112
+ const parts = typePartsFromArgument('as', argAt(args, 0))
113
+ requireKnownType(context, 'as', parts)
114
+ const item = singleton(input)
115
+ if (item === undefined) {
116
+ return []
117
+ }
118
+ return itemMatchesType(context, item, parts, { exact: true }) ? [item] : []
119
+ },
120
+ })
@@ -0,0 +1,19 @@
1
+ // Importing this module registers the function library into the registry table.
2
+ // The evaluator imports it for its side effects; later phases append more modules.
3
+ import './aggregate.ts'
4
+ import './boundary.ts'
5
+ import './combining.ts'
6
+ import './conversion.ts'
7
+ import './date-components.ts'
8
+ import './control.ts'
9
+ import './existence.ts'
10
+ import './fhir.ts'
11
+ import './filtering.ts'
12
+ import './math.ts'
13
+ import './reflection.ts'
14
+ import './sort.ts'
15
+ import './string.ts'
16
+ import './subsetting.ts'
17
+ import './tree.ts'
18
+ import './variables.ts'
19
+ import './utility.ts'
@@ -0,0 +1,21 @@
1
+ import { type EvaluationContext, withFrame } from '../engine/context.ts'
2
+ import type { AstNode } from '../parser/ast.ts'
3
+ import type { TypedValue } from '../values/typed-value.ts'
4
+
5
+ export type NodeEvaluator = (node: AstNode, context: EvaluationContext, input: TypedValue[]) => TypedValue[]
6
+
7
+ /** Evaluate `expression` once per item with `$this` and `$index` bound. */
8
+ export function perItem(
9
+ context: EvaluationContext,
10
+ input: TypedValue[],
11
+ expression: AstNode,
12
+ evaluateNode: NodeEvaluator,
13
+ each: (item: TypedValue, result: TypedValue[], index: number) => void
14
+ ): void {
15
+ input.forEach((item, index) => {
16
+ const result = withFrame(context, { thisValue: [item], index }, frameContext =>
17
+ evaluateNode(expression, frameContext, [item])
18
+ )
19
+ each(item, result, index)
20
+ })
21
+ }
@@ -0,0 +1,167 @@
1
+ import { FhirPathTypeError } from '../errors.ts'
2
+ import { singleton } from '../values/collection.ts'
3
+ import { Decimal } from '../values/decimal.ts'
4
+ import { asNumeric, wrapNumeric } from '../values/numeric.ts'
5
+ import {
6
+ type QuantityValue,
7
+ SYSTEM_DECIMAL,
8
+ SYSTEM_INTEGER,
9
+ SYSTEM_QUANTITY,
10
+ type TypedValue,
11
+ } from '../values/typed-value.ts'
12
+ import { argAt, registerFunction } from './registry.ts'
13
+
14
+ function numericInput(name: string, input: TypedValue[]): { item: TypedValue; value: Decimal } | undefined {
15
+ const item = singleton(input)
16
+ if (item === undefined) {
17
+ return undefined
18
+ }
19
+ const numeric = asNumeric(item)
20
+ if (!numeric) {
21
+ throw new FhirPathTypeError(`${name}() is not defined for ${item.type}`)
22
+ }
23
+ return { item, value: numeric.value }
24
+ }
25
+
26
+ registerFunction('abs', {
27
+ minArity: 0,
28
+ maxArity: 0,
29
+ evaluate: (_context, input) => {
30
+ const item = singleton(input)
31
+ if (item === undefined) {
32
+ return []
33
+ }
34
+ if (item.type === SYSTEM_QUANTITY) {
35
+ const quantity = item.value as QuantityValue
36
+ return [{ type: SYSTEM_QUANTITY, value: { ...quantity, value: quantity.value.abs() } }]
37
+ }
38
+ const numeric = asNumeric(item)
39
+ if (!numeric) {
40
+ throw new FhirPathTypeError(`abs() is not defined for ${item.type}`)
41
+ }
42
+ return [wrapNumeric(numeric.value.abs(), numeric.kind)]
43
+ },
44
+ })
45
+
46
+ registerFunction('ceiling', {
47
+ minArity: 0,
48
+ maxArity: 0,
49
+ evaluate: (_context, input) => {
50
+ const numeric = numericInput('ceiling', input)
51
+ if (!numeric) {
52
+ return []
53
+ }
54
+ return [wrapNumeric(numeric.value.ceiling(), 'Integer')]
55
+ },
56
+ })
57
+
58
+ registerFunction('floor', {
59
+ minArity: 0,
60
+ maxArity: 0,
61
+ evaluate: (_context, input) => {
62
+ const numeric = numericInput('floor', input)
63
+ if (!numeric) {
64
+ return []
65
+ }
66
+ return [wrapNumeric(numeric.value.floor(), 'Integer')]
67
+ },
68
+ })
69
+
70
+ registerFunction('truncate', {
71
+ minArity: 0,
72
+ maxArity: 0,
73
+ evaluate: (_context, input) => {
74
+ const numeric = numericInput('truncate', input)
75
+ if (!numeric) {
76
+ return []
77
+ }
78
+ return [wrapNumeric(numeric.value.truncate(), 'Integer')]
79
+ },
80
+ })
81
+
82
+ registerFunction('round', {
83
+ minArity: 0,
84
+ maxArity: 1,
85
+ evaluate: (context, input, args, evaluateNode) => {
86
+ const numeric = numericInput('round', input)
87
+ if (!numeric) {
88
+ return []
89
+ }
90
+ let precision = 0
91
+ if (args.length === 1) {
92
+ const argument = singleton(evaluateNode(argAt(args, 0), context, input), SYSTEM_INTEGER)
93
+ if (argument === undefined || typeof argument.value !== 'number' || argument.value < 0) {
94
+ throw new FhirPathTypeError('round() expects a non-negative integer precision')
95
+ }
96
+ precision = argument.value
97
+ }
98
+ return [{ type: SYSTEM_DECIMAL, value: numeric.value.round(precision) }]
99
+ },
100
+ })
101
+
102
+ /** Number-backed transcendental; empty when the JS result is not finite (domain errors). */
103
+ function transcendental(name: string, compute: (value: number) => number): void {
104
+ registerFunction(name, {
105
+ minArity: 0,
106
+ maxArity: 0,
107
+ evaluate: (_context, input) => {
108
+ const numeric = numericInput(name, input)
109
+ if (!numeric) {
110
+ return []
111
+ }
112
+ const result = compute(numeric.value.toNumber())
113
+ const decimal = Decimal.fromNumber(result)
114
+ return decimal === undefined ? [] : [{ type: SYSTEM_DECIMAL, value: decimal }]
115
+ },
116
+ })
117
+ }
118
+
119
+ transcendental('exp', Math.exp)
120
+ transcendental('ln', Math.log)
121
+ transcendental('sqrt', Math.sqrt)
122
+
123
+ registerFunction('log', {
124
+ minArity: 1,
125
+ maxArity: 1,
126
+ evaluate: (context, input, args, evaluateNode) => {
127
+ const numeric = numericInput('log', input)
128
+ if (!numeric) {
129
+ return []
130
+ }
131
+ const baseInput = singleton(evaluateNode(argAt(args, 0), context, input))
132
+ const base = baseInput === undefined ? undefined : asNumeric(baseInput)
133
+ if (!base) {
134
+ return []
135
+ }
136
+ const result = Math.log(numeric.value.toNumber()) / Math.log(base.value.toNumber())
137
+ const decimal = Decimal.fromNumber(result)
138
+ // NaN and infinities (log of a non-positive value, base 1) become empty.
139
+ return decimal === undefined ? [] : [{ type: SYSTEM_DECIMAL, value: decimal }]
140
+ },
141
+ })
142
+
143
+ registerFunction('power', {
144
+ minArity: 1,
145
+ maxArity: 1,
146
+ evaluate: (context, input, args, evaluateNode) => {
147
+ const numeric = numericInput('power', input)
148
+ if (!numeric) {
149
+ return []
150
+ }
151
+ const exponentInput = singleton(evaluateNode(argAt(args, 0), context, input))
152
+ const exponent = exponentInput === undefined ? undefined : asNumeric(exponentInput)
153
+ if (!exponent) {
154
+ return []
155
+ }
156
+ const result = numeric.value.toNumber() ** exponent.value.toNumber()
157
+ const decimal = Decimal.fromNumber(result)
158
+ if (decimal === undefined) {
159
+ return []
160
+ }
161
+ // Integer ^ Integer stays an Integer when the result is whole (spec §5.7.7).
162
+ if (numeric.item.type === SYSTEM_INTEGER && exponentInput?.type === SYSTEM_INTEGER && decimal.isInteger()) {
163
+ return [wrapNumeric(decimal, 'Integer')]
164
+ }
165
+ return [{ type: SYSTEM_DECIMAL, value: decimal }]
166
+ },
167
+ })