solve-engine 1.0.2 → 1.1.1

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 (237) hide show
  1. package/dist/{BytecodeBuilder-B0xskcv5.d.cts → BytecodeBuilder-Bp9xeTmX.d.cts} +4 -0
  2. package/dist/{BytecodeBuilder-B0xskcv5.d.ts → BytecodeBuilder-Bp9xeTmX.d.ts} +4 -0
  3. package/dist/{Configuration-B-G5gTRn.d.cts → Configuration-C9W8tJv_.d.cts} +53 -1
  4. package/dist/{Configuration-B-G5gTRn.d.ts → Configuration-C9W8tJv_.d.ts} +53 -1
  5. package/dist/{EngineError-LU7W7AgI.d.cts → EngineError-B61GS1jp.d.cts} +14 -0
  6. package/dist/{EngineError-LU7W7AgI.d.ts → EngineError-B61GS1jp.d.ts} +14 -0
  7. package/dist/FormattingSettings-CJHyxcYu.d.cts +27 -0
  8. package/dist/FormattingSettings-CJHyxcYu.d.ts +27 -0
  9. package/dist/{Lexer-DpjdaQ98.d.cts → Lexer-BOs7euZe.d.cts} +28 -1
  10. package/dist/{Lexer-CNmWxabg.d.ts → Lexer-CSI_lwbW.d.ts} +28 -1
  11. package/dist/PackageCompatibility-B-7rK1TD.d.cts +76 -0
  12. package/dist/PackageCompatibility-Dh59eF-X.d.ts +76 -0
  13. package/dist/{PackageRegistry-zuzqt51V.d.cts → PackageRegistry-BHWJP83F.d.cts} +449 -11
  14. package/dist/{PackageRegistry-ClIFXxAe.d.ts → PackageRegistry-_8rDlvxI.d.ts} +449 -11
  15. package/dist/{Parselet-BaySkMV3.d.ts → Parselet-BBT8riYh.d.ts} +12 -3
  16. package/dist/{Parselet-DuI1Pjiq.d.cts → Parselet-BHcgK9S7.d.cts} +12 -3
  17. package/dist/{ScopeManager-B6GzdhVG.d.cts → ScopeManager-8vf02dwj.d.cts} +56 -5
  18. package/dist/{ScopeManager-udv4Twwq.d.ts → ScopeManager-CxA24W5n.d.ts} +56 -5
  19. package/dist/{Token-BzG5G4ja.d.cts → Token-B1hdkedD.d.cts} +9 -0
  20. package/dist/{Token-BzG5G4ja.d.ts → Token-B1hdkedD.d.ts} +9 -0
  21. package/dist/{TokenNormalizer-t_GotBxr.d.ts → TokenNormalizer-C6VzZgHa.d.ts} +1 -1
  22. package/dist/{TokenNormalizer-DGVa24Q-.d.cts → TokenNormalizer-DRc1Js1V.d.cts} +1 -1
  23. package/dist/{VMCheckpoints-DwLjivM7.d.cts → VMCheckpoints-ELYqITdF.d.cts} +3 -3
  24. package/dist/{VMCheckpoints-BiaIlOOY.d.ts → VMCheckpoints-MK--EBH2.d.ts} +3 -3
  25. package/dist/{Value-CXJqDH9J.d.cts → Value-BUi1RA3S.d.cts} +124 -5
  26. package/dist/{Value-CXJqDH9J.d.ts → Value-BUi1RA3S.d.ts} +124 -5
  27. package/dist/WorkerError-_-RkoQ5P.d.ts +75 -0
  28. package/dist/WorkerError-gzmaopj2.d.cts +75 -0
  29. package/dist/{chunk-GQCOSXMG.js → chunk-267JPOTF.js} +43 -5
  30. package/dist/chunk-267JPOTF.js.map +1 -0
  31. package/dist/{chunk-JMXUNXQS.cjs → chunk-2TZKENDH.cjs} +51 -8
  32. package/dist/chunk-2TZKENDH.cjs.map +1 -0
  33. package/dist/chunk-3OWCDIPN.js +215 -0
  34. package/dist/chunk-3OWCDIPN.js.map +1 -0
  35. package/dist/{chunk-VB37OC6I.js → chunk-4D6NIHE2.js} +40 -3
  36. package/dist/chunk-4D6NIHE2.js.map +1 -0
  37. package/dist/{chunk-YXCTLWOH.js → chunk-4HQKTMWG.js} +1530 -57
  38. package/dist/chunk-4HQKTMWG.js.map +1 -0
  39. package/dist/{chunk-TY3TLZAW.cjs → chunk-536WPM2V.cjs} +18 -2
  40. package/dist/chunk-536WPM2V.cjs.map +1 -0
  41. package/dist/chunk-5HRB36DK.js +405 -0
  42. package/dist/chunk-5HRB36DK.js.map +1 -0
  43. package/dist/chunk-5ON7PUAZ.js +12 -0
  44. package/dist/chunk-5ON7PUAZ.js.map +1 -0
  45. package/dist/{chunk-KV7UW6T6.js → chunk-7KYSUDQO.js} +12 -5
  46. package/dist/chunk-7KYSUDQO.js.map +1 -0
  47. package/dist/{chunk-6WFMPTGB.cjs → chunk-7ZX6B7SY.cjs} +774 -528
  48. package/dist/chunk-7ZX6B7SY.cjs.map +1 -0
  49. package/dist/chunk-ALYRJ72W.cjs +434 -0
  50. package/dist/chunk-ALYRJ72W.cjs.map +1 -0
  51. package/dist/{chunk-5KMIY374.cjs → chunk-B4HBEFTB.cjs} +17 -2
  52. package/dist/chunk-B4HBEFTB.cjs.map +1 -0
  53. package/dist/chunk-B7NLZMQ3.cjs +74 -0
  54. package/dist/chunk-B7NLZMQ3.cjs.map +1 -0
  55. package/dist/{chunk-UQ3UIZJC.js → chunk-BLI4NIQY.js} +6 -2
  56. package/dist/chunk-BLI4NIQY.js.map +1 -0
  57. package/dist/{chunk-IP7ASJEW.js → chunk-BYJBUL7U.js} +5 -5
  58. package/dist/{chunk-IP7ASJEW.js.map → chunk-BYJBUL7U.js.map} +1 -1
  59. package/dist/{chunk-G535KJEG.js → chunk-CCBZZQAE.js} +2 -2
  60. package/dist/{chunk-G535KJEG.js.map → chunk-CCBZZQAE.js.map} +1 -1
  61. package/dist/chunk-CKQMXMHR.cjs +219 -0
  62. package/dist/chunk-CKQMXMHR.cjs.map +1 -0
  63. package/dist/{chunk-T556MJDZ.cjs → chunk-CUR2WLI4.cjs} +11 -11
  64. package/dist/{chunk-T556MJDZ.cjs.map → chunk-CUR2WLI4.cjs.map} +1 -1
  65. package/dist/{chunk-AA3KTWTX.js → chunk-DLEBSLF4.js} +4 -4
  66. package/dist/{chunk-AA3KTWTX.js.map → chunk-DLEBSLF4.js.map} +1 -1
  67. package/dist/{chunk-524F3ATQ.cjs → chunk-E23GZEWL.cjs} +15 -9
  68. package/dist/chunk-E23GZEWL.cjs.map +1 -0
  69. package/dist/{chunk-PFUESQTW.cjs → chunk-EJ3ILXX6.cjs} +48 -2
  70. package/dist/chunk-EJ3ILXX6.cjs.map +1 -0
  71. package/dist/{chunk-526PMQOA.js → chunk-ENKKJYD3.js} +10 -4
  72. package/dist/chunk-ENKKJYD3.js.map +1 -0
  73. package/dist/{chunk-5X2PTP6F.cjs → chunk-ENRIK36Q.cjs} +2 -12
  74. package/dist/chunk-ENRIK36Q.cjs.map +1 -0
  75. package/dist/{chunk-3D7V24DG.js → chunk-ERCOHGXD.js} +17 -2
  76. package/dist/chunk-ERCOHGXD.js.map +1 -0
  77. package/dist/{chunk-IF532O7C.js → chunk-FD5ZZHEU.js} +3 -12
  78. package/dist/chunk-FD5ZZHEU.js.map +1 -0
  79. package/dist/{chunk-7FSDNNNC.js → chunk-GLA4JXBO.js} +11 -5
  80. package/dist/chunk-GLA4JXBO.js.map +1 -0
  81. package/dist/{chunk-UM6BVY2S.cjs → chunk-HIQ5HSZL.cjs} +175 -43
  82. package/dist/chunk-HIQ5HSZL.cjs.map +1 -0
  83. package/dist/{chunk-HVQFNJKE.cjs → chunk-HVRVSI2Z.cjs} +104 -86
  84. package/dist/chunk-HVRVSI2Z.cjs.map +1 -0
  85. package/dist/{chunk-3LAEG75D.js → chunk-I4GAWIPW.js} +24 -6
  86. package/dist/chunk-I4GAWIPW.js.map +1 -0
  87. package/dist/{chunk-PA4VC73I.cjs → chunk-J45BCEZ4.cjs} +33 -27
  88. package/dist/chunk-J45BCEZ4.cjs.map +1 -0
  89. package/dist/{chunk-FQGX2PA2.js → chunk-JG6ZJ2WU.js} +128 -4
  90. package/dist/chunk-JG6ZJ2WU.js.map +1 -0
  91. package/dist/chunk-L2TE7PMO.cjs +14 -0
  92. package/dist/chunk-L2TE7PMO.cjs.map +1 -0
  93. package/dist/chunk-LHZ6VOA7.js +1764 -0
  94. package/dist/chunk-LHZ6VOA7.js.map +1 -0
  95. package/dist/{chunk-SESSWASV.cjs → chunk-MN3LHRGV.cjs} +1868 -393
  96. package/dist/chunk-MN3LHRGV.cjs.map +1 -0
  97. package/dist/{chunk-R3PY4G7J.js → chunk-MVTOCRV2.js} +48 -3
  98. package/dist/chunk-MVTOCRV2.js.map +1 -0
  99. package/dist/{chunk-FE23VSSA.cjs → chunk-N5NNW4VG.cjs} +6 -6
  100. package/dist/{chunk-FE23VSSA.cjs.map → chunk-N5NNW4VG.cjs.map} +1 -1
  101. package/dist/{chunk-Y7FT4IQT.js → chunk-NKW7LKYU.js} +266 -28
  102. package/dist/chunk-NKW7LKYU.js.map +1 -0
  103. package/dist/{chunk-O3ANBHSA.js → chunk-NNQ2TYDF.js} +123 -5
  104. package/dist/chunk-NNQ2TYDF.js.map +1 -0
  105. package/dist/{chunk-NG2JHZHE.js → chunk-NNZAEUDW.js} +1853 -2640
  106. package/dist/chunk-NNZAEUDW.js.map +1 -0
  107. package/dist/{chunk-5LI5EPGJ.cjs → chunk-QFTDTX6K.cjs} +40 -3
  108. package/dist/chunk-QFTDTX6K.cjs.map +1 -0
  109. package/dist/{chunk-HDP7VK3C.cjs → chunk-SRGQ72IR.cjs} +649 -349
  110. package/dist/chunk-SRGQ72IR.cjs.map +1 -0
  111. package/dist/{chunk-4B2CNWQU.cjs → chunk-SSV46KFA.cjs} +14 -7
  112. package/dist/chunk-SSV46KFA.cjs.map +1 -0
  113. package/dist/{chunk-HBVFFBRR.cjs → chunk-T6ZYQJ63.cjs} +1962 -2748
  114. package/dist/chunk-T6ZYQJ63.cjs.map +1 -0
  115. package/dist/{chunk-AJA6LUI7.js → chunk-UO6BUV6K.js} +18 -2
  116. package/dist/chunk-UO6BUV6K.js.map +1 -0
  117. package/dist/chunk-WWQEY7BV.js +67 -0
  118. package/dist/chunk-WWQEY7BV.js.map +1 -0
  119. package/dist/{chunk-5WVP4YHP.js → chunk-WXEHD6TT.js} +333 -33
  120. package/dist/chunk-WXEHD6TT.js.map +1 -0
  121. package/dist/{chunk-47LRVGOT.cjs → chunk-XA4CKRML.cjs} +2 -2
  122. package/dist/{chunk-47LRVGOT.cjs.map → chunk-XA4CKRML.cjs.map} +1 -1
  123. package/dist/{chunk-6KFYJ6TD.cjs → chunk-XIYYHA65.cjs} +6 -2
  124. package/dist/chunk-XIYYHA65.cjs.map +1 -0
  125. package/dist/chunk-YRIKITGF.cjs +1768 -0
  126. package/dist/chunk-YRIKITGF.cjs.map +1 -0
  127. package/dist/{chunk-TMA4RCEN.js → chunk-Z7XGGLI2.js} +3 -3
  128. package/dist/{chunk-TMA4RCEN.js.map → chunk-Z7XGGLI2.js.map} +1 -1
  129. package/dist/{chunk-R7YVBHCV.cjs → chunk-ZMW6NU2K.cjs} +197 -73
  130. package/dist/chunk-ZMW6NU2K.cjs.map +1 -0
  131. package/dist/{chunk-A2N2GFCG.cjs → chunk-ZVTWQLK4.cjs} +10 -10
  132. package/dist/{chunk-A2N2GFCG.cjs.map → chunk-ZVTWQLK4.cjs.map} +1 -1
  133. package/dist/constants.cjs +5 -5
  134. package/dist/constants.d.cts +1 -1
  135. package/dist/constants.d.ts +1 -1
  136. package/dist/constants.js +2 -2
  137. package/dist/engine.cjs +52 -35
  138. package/dist/engine.d.cts +13 -13
  139. package/dist/engine.d.ts +13 -13
  140. package/dist/engine.js +26 -21
  141. package/dist/errors.cjs +44 -19
  142. package/dist/errors.d.cts +3 -2
  143. package/dist/errors.d.ts +3 -2
  144. package/dist/errors.js +2 -1
  145. package/dist/format.cjs +19 -169
  146. package/dist/format.cjs.map +1 -1
  147. package/dist/format.d.cts +18 -26
  148. package/dist/format.d.ts +18 -26
  149. package/dist/format.js +7 -171
  150. package/dist/format.js.map +1 -1
  151. package/dist/index.cjs +250 -31
  152. package/dist/index.cjs.map +1 -1
  153. package/dist/index.d.cts +110 -74
  154. package/dist/index.d.ts +110 -74
  155. package/dist/index.js +228 -23
  156. package/dist/index.js.map +1 -1
  157. package/dist/language.cjs +9 -9
  158. package/dist/language.d.cts +12 -12
  159. package/dist/language.d.ts +12 -12
  160. package/dist/language.js +3 -3
  161. package/dist/lexer.cjs +16 -16
  162. package/dist/lexer.d.cts +3 -3
  163. package/dist/lexer.d.ts +3 -3
  164. package/dist/lexer.js +5 -5
  165. package/dist/normalizer.cjs +10 -10
  166. package/dist/normalizer.d.cts +3 -3
  167. package/dist/normalizer.d.ts +3 -3
  168. package/dist/normalizer.js +4 -4
  169. package/dist/packages.cjs +45 -36
  170. package/dist/packages.d.cts +135 -31
  171. package/dist/packages.d.ts +135 -31
  172. package/dist/packages.js +14 -13
  173. package/dist/parser.cjs +16 -16
  174. package/dist/parser.d.cts +6 -5
  175. package/dist/parser.d.ts +6 -5
  176. package/dist/parser.js +6 -6
  177. package/dist/{pipeline-BEb3hujr.d.cts → pipeline-CtfJtPQc.d.cts} +3 -3
  178. package/dist/{pipeline-B6k5lCB7.d.ts → pipeline-DCd5M6Gk.d.ts} +3 -3
  179. package/dist/resolvers.d.cts +3 -3
  180. package/dist/resolvers.d.ts +3 -3
  181. package/dist/testing.cjs +478 -0
  182. package/dist/testing.cjs.map +1 -0
  183. package/dist/testing.d.cts +271 -0
  184. package/dist/testing.d.ts +271 -0
  185. package/dist/testing.js +470 -0
  186. package/dist/testing.js.map +1 -0
  187. package/dist/uom.cjs +16 -16
  188. package/dist/uom.d.cts +3 -3
  189. package/dist/uom.d.ts +3 -3
  190. package/dist/uom.js +6 -6
  191. package/dist/utilities.cjs +6 -5
  192. package/dist/utilities.js +2 -1
  193. package/dist/vm.cjs +34 -34
  194. package/dist/vm.d.cts +8 -8
  195. package/dist/vm.d.ts +8 -8
  196. package/dist/vm.js +9 -9
  197. package/dist/worker.cjs +493 -0
  198. package/dist/worker.cjs.map +1 -0
  199. package/dist/worker.d.cts +509 -0
  200. package/dist/worker.d.ts +509 -0
  201. package/dist/worker.js +484 -0
  202. package/dist/worker.js.map +1 -0
  203. package/package.json +21 -1
  204. package/dist/chunk-3D7V24DG.js.map +0 -1
  205. package/dist/chunk-3LAEG75D.js.map +0 -1
  206. package/dist/chunk-4B2CNWQU.cjs.map +0 -1
  207. package/dist/chunk-524F3ATQ.cjs.map +0 -1
  208. package/dist/chunk-526PMQOA.js.map +0 -1
  209. package/dist/chunk-5KMIY374.cjs.map +0 -1
  210. package/dist/chunk-5LI5EPGJ.cjs.map +0 -1
  211. package/dist/chunk-5WVP4YHP.js.map +0 -1
  212. package/dist/chunk-5X2PTP6F.cjs.map +0 -1
  213. package/dist/chunk-6KFYJ6TD.cjs.map +0 -1
  214. package/dist/chunk-6WFMPTGB.cjs.map +0 -1
  215. package/dist/chunk-7FSDNNNC.js.map +0 -1
  216. package/dist/chunk-AJA6LUI7.js.map +0 -1
  217. package/dist/chunk-FQGX2PA2.js.map +0 -1
  218. package/dist/chunk-GQCOSXMG.js.map +0 -1
  219. package/dist/chunk-HBVFFBRR.cjs.map +0 -1
  220. package/dist/chunk-HDP7VK3C.cjs.map +0 -1
  221. package/dist/chunk-HVQFNJKE.cjs.map +0 -1
  222. package/dist/chunk-IF532O7C.js.map +0 -1
  223. package/dist/chunk-JMXUNXQS.cjs.map +0 -1
  224. package/dist/chunk-KV7UW6T6.js.map +0 -1
  225. package/dist/chunk-NG2JHZHE.js.map +0 -1
  226. package/dist/chunk-O3ANBHSA.js.map +0 -1
  227. package/dist/chunk-PA4VC73I.cjs.map +0 -1
  228. package/dist/chunk-PFUESQTW.cjs.map +0 -1
  229. package/dist/chunk-R3PY4G7J.js.map +0 -1
  230. package/dist/chunk-R7YVBHCV.cjs.map +0 -1
  231. package/dist/chunk-SESSWASV.cjs.map +0 -1
  232. package/dist/chunk-TY3TLZAW.cjs.map +0 -1
  233. package/dist/chunk-UM6BVY2S.cjs.map +0 -1
  234. package/dist/chunk-UQ3UIZJC.js.map +0 -1
  235. package/dist/chunk-VB37OC6I.js.map +0 -1
  236. package/dist/chunk-Y7FT4IQT.js.map +0 -1
  237. package/dist/chunk-YXCTLWOH.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,92 +1,128 @@
1
- import { I as IEnginePackage } from './PackageRegistry-zuzqt51V.cjs';
2
- export { E as EvalResults, a as ExpressionEngine, b as IPackageRegistry, L as LineEvaluation, P as PackageRegistry, p as packageRegistry } from './PackageRegistry-zuzqt51V.cjs';
1
+ import { I as IEnginePackage } from './PackageRegistry-BHWJP83F.cjs';
2
+ export { a as EngineRestoreOptions, b as EngineSnapshot, c as EvalResults, d as Explanation, e as ExplanationStep, E as ExpressionEngine, f as IPackageRegistry, L as LineEvaluation, P as PackageRegistry, S as SNAPSHOT_FORMAT, g as SNAPSHOT_VERSION, h as SerializedAnonymousBody, i as SerializedBytecode, j as SerializedDecimal, k as SerializedLineCacheEntry, l as SerializedNumber, m as SerializedRational, n as SerializedUserFunction, o as SerializedValue, p as SnapshotErrorCodes, q as packageRegistry } from './PackageRegistry-BHWJP83F.cjs';
3
+ export { a as CompatibilityConflict, b as CompatibilityConflictKind, C as CompatibilityReport, c as CompatibilitySeverity, d as checkPackageCompatibility } from './PackageCompatibility-B-7rK1TD.cjs';
3
4
  export { ENGINE_VERSION } from './constants.cjs';
4
- import './Parselet-DuI1Pjiq.cjs';
5
- import './BytecodeBuilder-B0xskcv5.cjs';
6
- import './Token-BzG5G4ja.cjs';
7
- import './pipeline-BEb3hujr.cjs';
8
- import './Value-CXJqDH9J.cjs';
5
+ import './Parselet-BHcgK9S7.cjs';
6
+ import './BytecodeBuilder-Bp9xeTmX.cjs';
7
+ import './Token-B1hdkedD.cjs';
8
+ import './pipeline-CtfJtPQc.cjs';
9
+ import './Value-BUi1RA3S.cjs';
9
10
  import './variables.cjs';
10
- import './Lexer-DpjdaQ98.cjs';
11
+ import './Lexer-BOs7euZe.cjs';
11
12
  import './resolvers.cjs';
12
13
  import '@tanstack/query-core';
13
- import './TokenNormalizer-DGVa24Q-.cjs';
14
- import './ScopeManager-B6GzdhVG.cjs';
15
- import './EngineError-LU7W7AgI.cjs';
16
- import './Configuration-B-G5gTRn.cjs';
14
+ import './TokenNormalizer-DRc1Js1V.cjs';
15
+ import './ScopeManager-8vf02dwj.cjs';
16
+ import './EngineError-B61GS1jp.cjs';
17
+ import './Configuration-C9W8tJv_.cjs';
17
18
 
18
19
  /**
19
- * Package load-time compatibility checking, the "detect overlapping
20
- * logic between packages" SDK surface.
20
+ * A higher-level, declarative way to contribute a single `name(args)`
21
+ * function, sitting ON TOP OF the package contract rather than replacing it.
21
22
  *
22
- * This engine's package system (`IEnginePackage`) has always had SOME
23
- * collision visibility, but it's inconsistent and scattered: `ParseletRegistry`
24
- * warns on a token-type overwrite, `asConverterRegistry` warns on a converter
25
- * name overwrite, and `PhraseTrie` warns on... nothing at all, a second
26
- * package fusing the exact same multi-word phrase to a different token type
27
- * silently wins with zero signal, the same class of gap
28
- * `ParseletRegistry.registerPrefix()`'s collision-visibility fix closed for
29
- * parselets specifically (see `ARCHITECTURE.md`'s punch list). And none of
30
- * these existing checks can be run BEFORE registration, they only fire at
31
- * the moment a collision actually happens, deep inside a live engine.
32
- *
33
- * `checkPackageCompatibility()` is a single, pure, side-effect-free function
34
- * that statically compares one candidate package's declared descriptor
35
- * against a list of already-registered packages' descriptors, across every
36
- * collision-capable field `IEnginePackage` has, callable standalone (a host
37
- * building a plugin marketplace could run it before ever constructing an
38
- * engine) or wired into registration itself (see
39
- * `ExpressionEngine.registerPackage()`, which calls this automatically and
40
- * logs every conflict found, the "load-up resiliency" half of this
41
- * mechanism).
42
- *
43
- * A real, concrete motivating bug (found the same session this module was
44
- * built): the currency package's real `IEnginePackage` descriptor
45
- * (`CurrencyPackage.ts`) and its parallel test-harness registration helper
46
- * (`parselets/index.ts`'s `registerCurrencyParselets()`) drifted out of sync
47
- *, new currency-symbol token types were wired into one but not the other
48
- * caught only by a test happening to exercise the stale path. This module
49
- * doesn't catch THAT specific class of bug (two hand-written registration
50
- * functions for the same logical package diverging is a source-consistency
51
- * problem, not a runtime collision), but it DOES catch the more common and
52
- * more dangerous sibling: two DIFFERENT, independently-authored packages
53
- * unknowingly claiming the same token type, phrase, converter name, plugin
54
- * function index, or lexer keyword.
23
+ * The low-level contract (allocate a plugin function index, write a parselet,
24
+ * emit `CALL_PLUGIN`) stays exactly as it was and remains the way to add
25
+ * anything that needs custom parsing. This module derives that same wiring
26
+ * from a declaration for the common case, a function called with parenthesised
27
+ * arguments, so adding `vat(x)` costs a spec object rather than an
28
+ * understanding of the parser and the VM. See `defineFunction`.
55
29
  */
56
- /** How serious a detected conflict is. */
57
- type CompatibilitySeverity = "error" | "warning" | "info";
58
- /** The category of overlap detected between two packages. */
59
- type CompatibilityConflictKind = "prefixParseletTokenType" | "infixParseletTokenType" | "phrase" | "converterName" | "pluginFunctionIndex" | "lexerKeyword" | "lexerOperator" | "asyncResolverNamespace" | "tokenCategory";
60
- /** One way two packages collide, for example claiming the same keyword. */
61
- interface CompatibilityConflict {
62
- kind: CompatibilityConflictKind;
63
- severity: CompatibilitySeverity;
64
- /** Human-readable description, safe to log directly. */
65
- detail: string;
66
- /** The two package names involved, [existing, candidate]. */
67
- packages: [string, string];
30
+ /** The value types a declared argument or return may take. */
31
+ type FunctionValueType = "number" | "string" | "boolean";
32
+ /** The JavaScript type a {@link FunctionValueType} maps to at the `call` boundary. */
33
+ type JsValue<T extends FunctionValueType> = T extends "number" ? number : T extends "string" ? string : boolean;
34
+ /** One declared parameter: a name (for error messages) and a value type. */
35
+ interface FunctionArg {
36
+ /** Parameter name, used only in the generated type-mismatch messages. */
37
+ name: string;
38
+ /** The value type this parameter accepts. */
39
+ type: FunctionValueType;
68
40
  }
69
- /** Every conflict found between a candidate package and those already registered. */
70
- interface CompatibilityReport {
71
- /** `false` iff at least one "error"-severity conflict was found. */
72
- compatible: boolean;
73
- conflicts: CompatibilityConflict[];
41
+ /** Map a tuple of {@link FunctionArg} specs to the tuple of JS values `call` receives. */
42
+ type CallArgs<A extends readonly FunctionArg[]> = {
43
+ [K in keyof A]: JsValue<A[K]["type"]>;
44
+ };
45
+ /**
46
+ * A declarative function definition.
47
+ *
48
+ * `A` and `R` are inferred from the literal `args`/`returns` (via
49
+ * `defineFunction`'s `const` type parameter), so `call`'s parameters and
50
+ * return are typed from the declaration with no annotations: an
51
+ * `{ type: "number" }` argument arrives as a `number`, and a `returns:
52
+ * "string"` demands a `string` back.
53
+ */
54
+ interface FunctionSpec<A extends readonly FunctionArg[] = readonly FunctionArg[], R extends FunctionValueType = FunctionValueType> {
55
+ /**
56
+ * The call name, a single identifier (`/^[a-z_][a-z0-9_]*$/i`). Registered
57
+ * as a lexer keyword, so it is matched case-insensitively and cannot collide
58
+ * with a built-in keyword (that collision throws at registration time).
59
+ */
60
+ name: string;
61
+ /** The parameters, in order. A fixed-length list: variadic and optional args are out of scope (see {@link defineFunction}). */
62
+ args: A;
63
+ /** The value type the function returns. */
64
+ returns: R;
65
+ /** The implementation, receiving plain JS values and returning one. Must be synchronous (see {@link defineFunction}). */
66
+ call: (...args: CallArgs<A>) => JsValue<R>;
74
67
  }
75
68
  /**
76
- * Statically check `candidate` against every package in `existing` for
77
- * overlapping/conflicting declarations, across every collision-capable
78
- * field `IEnginePackage` has. Pure and side-effect-free, does not touch
79
- * any shared registry, does not require a live `ExpressionEngine`.
69
+ * Error codes the declarative function API raises. Kept as a co-located const
70
+ * (the convention `errors/ErrorCode.ts` documents for a domain's own codes) so
71
+ * the strings have one source of truth.
72
+ */
73
+ declare const DefineFunctionErrorCodes: {
74
+ /** The spec's `name` is not a single identifier. Thrown by `defineFunction`, before any engine sees it. */
75
+ readonly DEFINE_FUNCTION_INVALID_NAME: "DEFINE_FUNCTION_INVALID_NAME";
76
+ /** The spec is otherwise malformed (bad `args`, unsupported type, missing `call`). Thrown by `defineFunction`. */
77
+ readonly DEFINE_FUNCTION_INVALID_SPEC: "DEFINE_FUNCTION_INVALID_SPEC";
78
+ /** The call site passed the wrong number of arguments. Raised at evaluation time. */
79
+ readonly DEFINE_FUNCTION_ARITY_MISMATCH: "DEFINE_FUNCTION_ARITY_MISMATCH";
80
+ /** An argument was the wrong value type. Raised at evaluation time. */
81
+ readonly DEFINE_FUNCTION_ARGUMENT_TYPE: "DEFINE_FUNCTION_ARGUMENT_TYPE";
82
+ /** The `call` implementation returned a value that did not match `returns`. Raised at evaluation time, an authoring bug rather than a user one. */
83
+ readonly DEFINE_FUNCTION_RETURN_TYPE: "DEFINE_FUNCTION_RETURN_TYPE";
84
+ };
85
+ /**
86
+ * Turn a declarative {@link FunctionSpec} into a ready-to-register
87
+ * {@link IEnginePackage}.
88
+ *
89
+ * This is the higher-level API from issue #102. It derives, from the
90
+ * declaration alone, everything the low-level contract asks an author to write
91
+ * by hand: a plugin function index ({@link allocatePluginFunctionIndex}), a
92
+ * lexer keyword so the name tokenises, a call-syntax parselet emitting
93
+ * `CALL_PLUGIN`, and a handler that checks arity and argument types (yielding
94
+ * the engine's own structured errors) before invoking `call` and wrapping its
95
+ * result. Anything needing custom parsing keeps writing a raw parselet exactly
96
+ * as before, this sits on top of that contract and does not change it.
80
97
  *
81
98
  * @example
82
99
  * ```ts
83
- * const report = checkPackageCompatibility(myNewPackage, BUILTIN_PACKAGES);
84
- * if (!report.compatible) {
85
- * for (const c of report.conflicts) console.error(c.detail);
86
- * }
100
+ * const engine = new ExpressionEngine("en", false, undefined, undefined, [
101
+ * ...BUILTIN_PACKAGES,
102
+ * defineFunction({
103
+ * name: "vat",
104
+ * args: [{ name: "amount", type: "number" }],
105
+ * returns: "number",
106
+ * call: (amount) => amount * 1.2,
107
+ * }),
108
+ * ]);
109
+ * engine.evaluateExpression("vat(100)"); // 120
87
110
  * ```
111
+ *
112
+ * The returned package is self-contained and composes with any others through
113
+ * the engine's `packages` array; register several functions by passing several
114
+ * packages. Its name is `solve-fn-<name>`.
115
+ *
116
+ * Scope: arguments are a fixed-length list of `number`/`string`/`boolean`, and
117
+ * `call` is synchronous. Variadic and optional arguments, other value types
118
+ * (units, percentages, dates, matrices), and async work are deliberately out
119
+ * of scope, a function needing any of those keeps using the low-level
120
+ * contract, whose parselets and async resolvers are unchanged.
121
+ *
122
+ * @throws {EngineError} (category CONFIG) if the spec is malformed, at the
123
+ * point `defineFunction` is called, before the package reaches an engine.
88
124
  */
89
- declare function checkPackageCompatibility(candidate: IEnginePackage, existing: IEnginePackage[]): CompatibilityReport;
125
+ declare function defineFunction<const A extends readonly FunctionArg[], R extends FunctionValueType>(spec: FunctionSpec<A, R>): IEnginePackage;
90
126
 
91
127
  /**
92
128
  * Engine-version package compatibility gating, the "reject a package built
@@ -149,4 +185,4 @@ declare function checkEngineVersionCompatibility(pkg: IEnginePackage, engineVers
149
185
  */
150
186
  declare function assertEngineVersionCompatible(pkg: IEnginePackage, engineVersion?: string): void;
151
187
 
152
- export { type CompatibilityConflict, type CompatibilityConflictKind, type CompatibilityReport, type CompatibilitySeverity, type EngineVersionCheckResult, IEnginePackage, assertEngineVersionCompatible, checkEngineVersionCompatibility, checkPackageCompatibility };
188
+ export { DefineFunctionErrorCodes, type EngineVersionCheckResult, type FunctionArg, type FunctionSpec, type FunctionValueType, IEnginePackage, assertEngineVersionCompatible, checkEngineVersionCompatibility, defineFunction };
package/dist/index.d.ts CHANGED
@@ -1,92 +1,128 @@
1
- import { I as IEnginePackage } from './PackageRegistry-ClIFXxAe.js';
2
- export { E as EvalResults, a as ExpressionEngine, b as IPackageRegistry, L as LineEvaluation, P as PackageRegistry, p as packageRegistry } from './PackageRegistry-ClIFXxAe.js';
1
+ import { I as IEnginePackage } from './PackageRegistry-_8rDlvxI.js';
2
+ export { a as EngineRestoreOptions, b as EngineSnapshot, c as EvalResults, d as Explanation, e as ExplanationStep, E as ExpressionEngine, f as IPackageRegistry, L as LineEvaluation, P as PackageRegistry, S as SNAPSHOT_FORMAT, g as SNAPSHOT_VERSION, h as SerializedAnonymousBody, i as SerializedBytecode, j as SerializedDecimal, k as SerializedLineCacheEntry, l as SerializedNumber, m as SerializedRational, n as SerializedUserFunction, o as SerializedValue, p as SnapshotErrorCodes, q as packageRegistry } from './PackageRegistry-_8rDlvxI.js';
3
+ export { a as CompatibilityConflict, b as CompatibilityConflictKind, C as CompatibilityReport, c as CompatibilitySeverity, d as checkPackageCompatibility } from './PackageCompatibility-Dh59eF-X.js';
3
4
  export { ENGINE_VERSION } from './constants.js';
4
- import './Parselet-BaySkMV3.js';
5
- import './BytecodeBuilder-B0xskcv5.js';
6
- import './Token-BzG5G4ja.js';
7
- import './pipeline-B6k5lCB7.js';
8
- import './Value-CXJqDH9J.js';
5
+ import './Parselet-BBT8riYh.js';
6
+ import './BytecodeBuilder-Bp9xeTmX.js';
7
+ import './Token-B1hdkedD.js';
8
+ import './pipeline-DCd5M6Gk.js';
9
+ import './Value-BUi1RA3S.js';
9
10
  import './variables.js';
10
- import './Lexer-CNmWxabg.js';
11
+ import './Lexer-CSI_lwbW.js';
11
12
  import './resolvers.js';
12
13
  import '@tanstack/query-core';
13
- import './TokenNormalizer-t_GotBxr.js';
14
- import './ScopeManager-udv4Twwq.js';
15
- import './EngineError-LU7W7AgI.js';
16
- import './Configuration-B-G5gTRn.js';
14
+ import './TokenNormalizer-C6VzZgHa.js';
15
+ import './ScopeManager-CxA24W5n.js';
16
+ import './EngineError-B61GS1jp.js';
17
+ import './Configuration-C9W8tJv_.js';
17
18
 
18
19
  /**
19
- * Package load-time compatibility checking, the "detect overlapping
20
- * logic between packages" SDK surface.
20
+ * A higher-level, declarative way to contribute a single `name(args)`
21
+ * function, sitting ON TOP OF the package contract rather than replacing it.
21
22
  *
22
- * This engine's package system (`IEnginePackage`) has always had SOME
23
- * collision visibility, but it's inconsistent and scattered: `ParseletRegistry`
24
- * warns on a token-type overwrite, `asConverterRegistry` warns on a converter
25
- * name overwrite, and `PhraseTrie` warns on... nothing at all, a second
26
- * package fusing the exact same multi-word phrase to a different token type
27
- * silently wins with zero signal, the same class of gap
28
- * `ParseletRegistry.registerPrefix()`'s collision-visibility fix closed for
29
- * parselets specifically (see `ARCHITECTURE.md`'s punch list). And none of
30
- * these existing checks can be run BEFORE registration, they only fire at
31
- * the moment a collision actually happens, deep inside a live engine.
32
- *
33
- * `checkPackageCompatibility()` is a single, pure, side-effect-free function
34
- * that statically compares one candidate package's declared descriptor
35
- * against a list of already-registered packages' descriptors, across every
36
- * collision-capable field `IEnginePackage` has, callable standalone (a host
37
- * building a plugin marketplace could run it before ever constructing an
38
- * engine) or wired into registration itself (see
39
- * `ExpressionEngine.registerPackage()`, which calls this automatically and
40
- * logs every conflict found, the "load-up resiliency" half of this
41
- * mechanism).
42
- *
43
- * A real, concrete motivating bug (found the same session this module was
44
- * built): the currency package's real `IEnginePackage` descriptor
45
- * (`CurrencyPackage.ts`) and its parallel test-harness registration helper
46
- * (`parselets/index.ts`'s `registerCurrencyParselets()`) drifted out of sync
47
- *, new currency-symbol token types were wired into one but not the other
48
- * caught only by a test happening to exercise the stale path. This module
49
- * doesn't catch THAT specific class of bug (two hand-written registration
50
- * functions for the same logical package diverging is a source-consistency
51
- * problem, not a runtime collision), but it DOES catch the more common and
52
- * more dangerous sibling: two DIFFERENT, independently-authored packages
53
- * unknowingly claiming the same token type, phrase, converter name, plugin
54
- * function index, or lexer keyword.
23
+ * The low-level contract (allocate a plugin function index, write a parselet,
24
+ * emit `CALL_PLUGIN`) stays exactly as it was and remains the way to add
25
+ * anything that needs custom parsing. This module derives that same wiring
26
+ * from a declaration for the common case, a function called with parenthesised
27
+ * arguments, so adding `vat(x)` costs a spec object rather than an
28
+ * understanding of the parser and the VM. See `defineFunction`.
55
29
  */
56
- /** How serious a detected conflict is. */
57
- type CompatibilitySeverity = "error" | "warning" | "info";
58
- /** The category of overlap detected between two packages. */
59
- type CompatibilityConflictKind = "prefixParseletTokenType" | "infixParseletTokenType" | "phrase" | "converterName" | "pluginFunctionIndex" | "lexerKeyword" | "lexerOperator" | "asyncResolverNamespace" | "tokenCategory";
60
- /** One way two packages collide, for example claiming the same keyword. */
61
- interface CompatibilityConflict {
62
- kind: CompatibilityConflictKind;
63
- severity: CompatibilitySeverity;
64
- /** Human-readable description, safe to log directly. */
65
- detail: string;
66
- /** The two package names involved, [existing, candidate]. */
67
- packages: [string, string];
30
+ /** The value types a declared argument or return may take. */
31
+ type FunctionValueType = "number" | "string" | "boolean";
32
+ /** The JavaScript type a {@link FunctionValueType} maps to at the `call` boundary. */
33
+ type JsValue<T extends FunctionValueType> = T extends "number" ? number : T extends "string" ? string : boolean;
34
+ /** One declared parameter: a name (for error messages) and a value type. */
35
+ interface FunctionArg {
36
+ /** Parameter name, used only in the generated type-mismatch messages. */
37
+ name: string;
38
+ /** The value type this parameter accepts. */
39
+ type: FunctionValueType;
68
40
  }
69
- /** Every conflict found between a candidate package and those already registered. */
70
- interface CompatibilityReport {
71
- /** `false` iff at least one "error"-severity conflict was found. */
72
- compatible: boolean;
73
- conflicts: CompatibilityConflict[];
41
+ /** Map a tuple of {@link FunctionArg} specs to the tuple of JS values `call` receives. */
42
+ type CallArgs<A extends readonly FunctionArg[]> = {
43
+ [K in keyof A]: JsValue<A[K]["type"]>;
44
+ };
45
+ /**
46
+ * A declarative function definition.
47
+ *
48
+ * `A` and `R` are inferred from the literal `args`/`returns` (via
49
+ * `defineFunction`'s `const` type parameter), so `call`'s parameters and
50
+ * return are typed from the declaration with no annotations: an
51
+ * `{ type: "number" }` argument arrives as a `number`, and a `returns:
52
+ * "string"` demands a `string` back.
53
+ */
54
+ interface FunctionSpec<A extends readonly FunctionArg[] = readonly FunctionArg[], R extends FunctionValueType = FunctionValueType> {
55
+ /**
56
+ * The call name, a single identifier (`/^[a-z_][a-z0-9_]*$/i`). Registered
57
+ * as a lexer keyword, so it is matched case-insensitively and cannot collide
58
+ * with a built-in keyword (that collision throws at registration time).
59
+ */
60
+ name: string;
61
+ /** The parameters, in order. A fixed-length list: variadic and optional args are out of scope (see {@link defineFunction}). */
62
+ args: A;
63
+ /** The value type the function returns. */
64
+ returns: R;
65
+ /** The implementation, receiving plain JS values and returning one. Must be synchronous (see {@link defineFunction}). */
66
+ call: (...args: CallArgs<A>) => JsValue<R>;
74
67
  }
75
68
  /**
76
- * Statically check `candidate` against every package in `existing` for
77
- * overlapping/conflicting declarations, across every collision-capable
78
- * field `IEnginePackage` has. Pure and side-effect-free, does not touch
79
- * any shared registry, does not require a live `ExpressionEngine`.
69
+ * Error codes the declarative function API raises. Kept as a co-located const
70
+ * (the convention `errors/ErrorCode.ts` documents for a domain's own codes) so
71
+ * the strings have one source of truth.
72
+ */
73
+ declare const DefineFunctionErrorCodes: {
74
+ /** The spec's `name` is not a single identifier. Thrown by `defineFunction`, before any engine sees it. */
75
+ readonly DEFINE_FUNCTION_INVALID_NAME: "DEFINE_FUNCTION_INVALID_NAME";
76
+ /** The spec is otherwise malformed (bad `args`, unsupported type, missing `call`). Thrown by `defineFunction`. */
77
+ readonly DEFINE_FUNCTION_INVALID_SPEC: "DEFINE_FUNCTION_INVALID_SPEC";
78
+ /** The call site passed the wrong number of arguments. Raised at evaluation time. */
79
+ readonly DEFINE_FUNCTION_ARITY_MISMATCH: "DEFINE_FUNCTION_ARITY_MISMATCH";
80
+ /** An argument was the wrong value type. Raised at evaluation time. */
81
+ readonly DEFINE_FUNCTION_ARGUMENT_TYPE: "DEFINE_FUNCTION_ARGUMENT_TYPE";
82
+ /** The `call` implementation returned a value that did not match `returns`. Raised at evaluation time, an authoring bug rather than a user one. */
83
+ readonly DEFINE_FUNCTION_RETURN_TYPE: "DEFINE_FUNCTION_RETURN_TYPE";
84
+ };
85
+ /**
86
+ * Turn a declarative {@link FunctionSpec} into a ready-to-register
87
+ * {@link IEnginePackage}.
88
+ *
89
+ * This is the higher-level API from issue #102. It derives, from the
90
+ * declaration alone, everything the low-level contract asks an author to write
91
+ * by hand: a plugin function index ({@link allocatePluginFunctionIndex}), a
92
+ * lexer keyword so the name tokenises, a call-syntax parselet emitting
93
+ * `CALL_PLUGIN`, and a handler that checks arity and argument types (yielding
94
+ * the engine's own structured errors) before invoking `call` and wrapping its
95
+ * result. Anything needing custom parsing keeps writing a raw parselet exactly
96
+ * as before, this sits on top of that contract and does not change it.
80
97
  *
81
98
  * @example
82
99
  * ```ts
83
- * const report = checkPackageCompatibility(myNewPackage, BUILTIN_PACKAGES);
84
- * if (!report.compatible) {
85
- * for (const c of report.conflicts) console.error(c.detail);
86
- * }
100
+ * const engine = new ExpressionEngine("en", false, undefined, undefined, [
101
+ * ...BUILTIN_PACKAGES,
102
+ * defineFunction({
103
+ * name: "vat",
104
+ * args: [{ name: "amount", type: "number" }],
105
+ * returns: "number",
106
+ * call: (amount) => amount * 1.2,
107
+ * }),
108
+ * ]);
109
+ * engine.evaluateExpression("vat(100)"); // 120
87
110
  * ```
111
+ *
112
+ * The returned package is self-contained and composes with any others through
113
+ * the engine's `packages` array; register several functions by passing several
114
+ * packages. Its name is `solve-fn-<name>`.
115
+ *
116
+ * Scope: arguments are a fixed-length list of `number`/`string`/`boolean`, and
117
+ * `call` is synchronous. Variadic and optional arguments, other value types
118
+ * (units, percentages, dates, matrices), and async work are deliberately out
119
+ * of scope, a function needing any of those keeps using the low-level
120
+ * contract, whose parselets and async resolvers are unchanged.
121
+ *
122
+ * @throws {EngineError} (category CONFIG) if the spec is malformed, at the
123
+ * point `defineFunction` is called, before the package reaches an engine.
88
124
  */
89
- declare function checkPackageCompatibility(candidate: IEnginePackage, existing: IEnginePackage[]): CompatibilityReport;
125
+ declare function defineFunction<const A extends readonly FunctionArg[], R extends FunctionValueType>(spec: FunctionSpec<A, R>): IEnginePackage;
90
126
 
91
127
  /**
92
128
  * Engine-version package compatibility gating, the "reject a package built
@@ -149,4 +185,4 @@ declare function checkEngineVersionCompatibility(pkg: IEnginePackage, engineVers
149
185
  */
150
186
  declare function assertEngineVersionCompatible(pkg: IEnginePackage, engineVersion?: string): void;
151
187
 
152
- export { type CompatibilityConflict, type CompatibilityConflictKind, type CompatibilityReport, type CompatibilitySeverity, type EngineVersionCheckResult, IEnginePackage, assertEngineVersionCompatible, checkEngineVersionCompatibility, checkPackageCompatibility };
188
+ export { DefineFunctionErrorCodes, type EngineVersionCheckResult, type FunctionArg, type FunctionSpec, type FunctionValueType, IEnginePackage, assertEngineVersionCompatible, checkEngineVersionCompatibility, defineFunction };