solve-engine 1.0.2 → 1.1.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 (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-TY3TLZAW.cjs → chunk-536WPM2V.cjs} +18 -2
  38. package/dist/chunk-536WPM2V.cjs.map +1 -0
  39. package/dist/chunk-5HRB36DK.js +405 -0
  40. package/dist/chunk-5HRB36DK.js.map +1 -0
  41. package/dist/chunk-5ON7PUAZ.js +12 -0
  42. package/dist/chunk-5ON7PUAZ.js.map +1 -0
  43. package/dist/{chunk-KV7UW6T6.js → chunk-7KYSUDQO.js} +12 -5
  44. package/dist/chunk-7KYSUDQO.js.map +1 -0
  45. package/dist/{chunk-6WFMPTGB.cjs → chunk-7ZX6B7SY.cjs} +774 -528
  46. package/dist/chunk-7ZX6B7SY.cjs.map +1 -0
  47. package/dist/chunk-ALYRJ72W.cjs +434 -0
  48. package/dist/chunk-ALYRJ72W.cjs.map +1 -0
  49. package/dist/{chunk-5KMIY374.cjs → chunk-B4HBEFTB.cjs} +17 -2
  50. package/dist/chunk-B4HBEFTB.cjs.map +1 -0
  51. package/dist/chunk-B7NLZMQ3.cjs +74 -0
  52. package/dist/chunk-B7NLZMQ3.cjs.map +1 -0
  53. package/dist/{chunk-UQ3UIZJC.js → chunk-BLI4NIQY.js} +6 -2
  54. package/dist/chunk-BLI4NIQY.js.map +1 -0
  55. package/dist/{chunk-T556MJDZ.cjs → chunk-C75AFGVD.cjs} +11 -11
  56. package/dist/{chunk-T556MJDZ.cjs.map → chunk-C75AFGVD.cjs.map} +1 -1
  57. package/dist/{chunk-G535KJEG.js → chunk-CCBZZQAE.js} +2 -2
  58. package/dist/{chunk-G535KJEG.js.map → chunk-CCBZZQAE.js.map} +1 -1
  59. package/dist/chunk-CKQMXMHR.cjs +219 -0
  60. package/dist/chunk-CKQMXMHR.cjs.map +1 -0
  61. package/dist/{chunk-PFUESQTW.cjs → chunk-EJ3ILXX6.cjs} +48 -2
  62. package/dist/chunk-EJ3ILXX6.cjs.map +1 -0
  63. package/dist/{chunk-526PMQOA.js → chunk-ENKKJYD3.js} +10 -4
  64. package/dist/chunk-ENKKJYD3.js.map +1 -0
  65. package/dist/{chunk-5X2PTP6F.cjs → chunk-ENRIK36Q.cjs} +2 -12
  66. package/dist/chunk-ENRIK36Q.cjs.map +1 -0
  67. package/dist/{chunk-3D7V24DG.js → chunk-ERCOHGXD.js} +17 -2
  68. package/dist/chunk-ERCOHGXD.js.map +1 -0
  69. package/dist/{chunk-IF532O7C.js → chunk-FD5ZZHEU.js} +3 -12
  70. package/dist/chunk-FD5ZZHEU.js.map +1 -0
  71. package/dist/{chunk-7FSDNNNC.js → chunk-G7Z4HJQA.js} +11 -5
  72. package/dist/chunk-G7Z4HJQA.js.map +1 -0
  73. package/dist/{chunk-FQGX2PA2.js → chunk-GQMUHVE3.js} +115 -4
  74. package/dist/chunk-GQMUHVE3.js.map +1 -0
  75. package/dist/chunk-GUG7SNSV.js +1764 -0
  76. package/dist/chunk-GUG7SNSV.js.map +1 -0
  77. package/dist/{chunk-UM6BVY2S.cjs → chunk-HIQ5HSZL.cjs} +175 -43
  78. package/dist/chunk-HIQ5HSZL.cjs.map +1 -0
  79. package/dist/{chunk-HVQFNJKE.cjs → chunk-HVRVSI2Z.cjs} +104 -86
  80. package/dist/chunk-HVRVSI2Z.cjs.map +1 -0
  81. package/dist/{chunk-3LAEG75D.js → chunk-I4GAWIPW.js} +24 -6
  82. package/dist/chunk-I4GAWIPW.js.map +1 -0
  83. package/dist/{chunk-PA4VC73I.cjs → chunk-J45BCEZ4.cjs} +33 -27
  84. package/dist/chunk-J45BCEZ4.cjs.map +1 -0
  85. package/dist/{chunk-NG2JHZHE.js → chunk-JIPATHVY.js} +1853 -2640
  86. package/dist/chunk-JIPATHVY.js.map +1 -0
  87. package/dist/{chunk-IP7ASJEW.js → chunk-JJIXHXFQ.js} +5 -5
  88. package/dist/{chunk-IP7ASJEW.js.map → chunk-JJIXHXFQ.js.map} +1 -1
  89. package/dist/chunk-L2TE7PMO.cjs +14 -0
  90. package/dist/chunk-L2TE7PMO.cjs.map +1 -0
  91. package/dist/{chunk-HBVFFBRR.cjs → chunk-MG6Q3DUO.cjs} +1962 -2748
  92. package/dist/chunk-MG6Q3DUO.cjs.map +1 -0
  93. package/dist/{chunk-R3PY4G7J.js → chunk-MVTOCRV2.js} +48 -3
  94. package/dist/chunk-MVTOCRV2.js.map +1 -0
  95. package/dist/{chunk-Y7FT4IQT.js → chunk-NKW7LKYU.js} +266 -28
  96. package/dist/chunk-NKW7LKYU.js.map +1 -0
  97. package/dist/{chunk-O3ANBHSA.js → chunk-NNQ2TYDF.js} +123 -5
  98. package/dist/chunk-NNQ2TYDF.js.map +1 -0
  99. package/dist/{chunk-AA3KTWTX.js → chunk-OADDUPT3.js} +4 -4
  100. package/dist/{chunk-AA3KTWTX.js.map → chunk-OADDUPT3.js.map} +1 -1
  101. package/dist/{chunk-SESSWASV.cjs → chunk-OTN6SZOD.cjs} +1868 -393
  102. package/dist/chunk-OTN6SZOD.cjs.map +1 -0
  103. package/dist/{chunk-5LI5EPGJ.cjs → chunk-QFTDTX6K.cjs} +40 -3
  104. package/dist/chunk-QFTDTX6K.cjs.map +1 -0
  105. package/dist/{chunk-YXCTLWOH.js → chunk-RRLHC37V.js} +1530 -57
  106. package/dist/chunk-RRLHC37V.js.map +1 -0
  107. package/dist/chunk-SNHVVOJK.cjs +1768 -0
  108. package/dist/chunk-SNHVVOJK.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-AJA6LUI7.js → chunk-UO6BUV6K.js} +18 -2
  114. package/dist/chunk-UO6BUV6K.js.map +1 -0
  115. package/dist/chunk-WWQEY7BV.js +67 -0
  116. package/dist/chunk-WWQEY7BV.js.map +1 -0
  117. package/dist/{chunk-5WVP4YHP.js → chunk-WXEHD6TT.js} +333 -33
  118. package/dist/chunk-WXEHD6TT.js.map +1 -0
  119. package/dist/{chunk-47LRVGOT.cjs → chunk-XA4CKRML.cjs} +2 -2
  120. package/dist/{chunk-47LRVGOT.cjs.map → chunk-XA4CKRML.cjs.map} +1 -1
  121. package/dist/{chunk-6KFYJ6TD.cjs → chunk-XIYYHA65.cjs} +6 -2
  122. package/dist/chunk-XIYYHA65.cjs.map +1 -0
  123. package/dist/{chunk-FE23VSSA.cjs → chunk-XJGJCF2R.cjs} +6 -6
  124. package/dist/{chunk-FE23VSSA.cjs.map → chunk-XJGJCF2R.cjs.map} +1 -1
  125. package/dist/{chunk-R7YVBHCV.cjs → chunk-YTIYVHL7.cjs} +184 -73
  126. package/dist/chunk-YTIYVHL7.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-A2N2GFCG.cjs → chunk-ZVTWQLK4.cjs} +10 -10
  130. package/dist/{chunk-A2N2GFCG.cjs.map → chunk-ZVTWQLK4.cjs.map} +1 -1
  131. package/dist/{chunk-524F3ATQ.cjs → chunk-ZXCESUJS.cjs} +15 -9
  132. package/dist/chunk-ZXCESUJS.cjs.map +1 -0
  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
@@ -312,5 +312,5 @@ var DiagnosticEventType = {
312
312
  exports.DiagnosticEventType = DiagnosticEventType;
313
313
  exports.DiagnosticPipeline = DiagnosticPipeline;
314
314
  exports.TimelineDiagnosticCollector = TimelineDiagnosticCollector;
315
- //# sourceMappingURL=chunk-47LRVGOT.cjs.map
316
- //# sourceMappingURL=chunk-47LRVGOT.cjs.map
315
+ //# sourceMappingURL=chunk-XA4CKRML.cjs.map
316
+ //# sourceMappingURL=chunk-XA4CKRML.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/diagnostics/pipeline.ts","../src/diagnostics/collector.ts","../src/diagnostics/timeline-collector.ts","../src/diagnostics/events.ts"],"names":[],"mappings":"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","file":"chunk-47LRVGOT.cjs","sourcesContent":["import { DiagnosticCollector } from \"./collector\";\nimport { DiagnosticEvent } from \"./events\";\nimport { DiagnosticReport } from \"./events\";\n\n/**\n * Dispatches diagnostic events to all registered collectors.\n *\n * Performance guarantee: when no collectors are registered (production mode),\n * every dispatch method is a branch on `this.collectors.length === 0` which\n * modern JS engines will predict and eliminate. The overhead is a single\n * comparison per call, effectively zero.\n */\nexport class DiagnosticPipeline {\n private collectors: DiagnosticCollector[] = [];\n\n register(collector: DiagnosticCollector): void {\n this.collectors.push(collector);\n }\n\n unregister(collector: DiagnosticCollector): void {\n const idx = this.collectors.indexOf(collector);\n if (idx !== -1) this.collectors.splice(idx, 1);\n }\n\n clear(): void {\n this.collectors = [];\n }\n\n get hasCollectors(): boolean {\n return this.collectors.length > 0;\n }\n\n get collectorCount(): number {\n return this.collectors.length;\n }\n\n // Inline-optimized dispatchers, each checks length once then loops.\n // When collectors.length === 0, the JIT eliminates the entire method body.\n\n firePipelineStart(event: DiagnosticEvent & { type: \"pipeline_start\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onPipelineStart?.(event);\n }\n\n fireTokenEmitted(event: DiagnosticEvent & { type: \"token_emitted\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onTokenEmitted?.(event);\n }\n\n fireNormalizerStart(event: DiagnosticEvent & { type: \"normalizer_start\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onNormalizerStart?.(event);\n }\n\n fireTokenFused(event: DiagnosticEvent & { type: \"token_fused\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onTokenFused?.(event);\n }\n\n fireNormalizerEnd(event: DiagnosticEvent & { type: \"normalizer_end\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onNormalizerEnd?.(event);\n }\n\n fireParseletMatched(event: DiagnosticEvent & { type: \"parselet_matched\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onParseletMatched?.(event);\n }\n\n fireBytecodeBuilt(event: DiagnosticEvent & { type: \"bytecode_built\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onBytecodeBuilt?.(event);\n }\n\n fireVmStep(event: DiagnosticEvent & { type: \"vm_step\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onVmStep?.(event);\n }\n\n fireVmHalt(event: DiagnosticEvent & { type: \"vm_halt\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onVmHalt?.(event);\n }\n\n fireCacheHit(event: DiagnosticEvent & { type: \"cache_hit\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onCacheHit?.(event);\n }\n\n fireCacheMiss(event: DiagnosticEvent & { type: \"cache_miss\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onCacheMiss?.(event);\n }\n\n firePipelineEnd(event: DiagnosticEvent & { type: \"pipeline_end\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onPipelineEnd?.(event);\n }\n\n collectReports(): DiagnosticReport[] {\n const reports: DiagnosticReport[] = [];\n for (const c of this.collectors) {\n const report = c.getReport();\n if (report) reports.push(report);\n }\n return reports;\n }\n\n reset(): void {\n for (const c of this.collectors) c.reset();\n }\n}","import { DiagnosticEvent } from \"./events\";\nimport { DiagnosticReport } from \"./events\";\n\n/**\n * Interface for collecting diagnostic data during pipeline execution.\n *\n * All methods are implemented as concrete no-ops so subclasses only\n * need to override the ones they care about. This avoids optional\n * method issues with TypeScript's strict mode.\n *\n * The parameters are named `_event` because these base implementations\n * deliberately ignore them. Overrides are free to name theirs `event` and use\n * it; TypeScript does not match parameter names when checking overrides.\n */\nexport abstract class DiagnosticCollector {\n onPipelineStart(_event: DiagnosticEvent & { type: \"pipeline_start\" }): void {}\n onTokenEmitted(_event: DiagnosticEvent & { type: \"token_emitted\" }): void {}\n onNormalizerStart(_event: DiagnosticEvent & { type: \"normalizer_start\" }): void {}\n onTokenFused(_event: DiagnosticEvent & { type: \"token_fused\" }): void {}\n onNormalizerEnd(_event: DiagnosticEvent & { type: \"normalizer_end\" }): void {}\n onParseletMatched(_event: DiagnosticEvent & { type: \"parselet_matched\" }): void {}\n onBytecodeBuilt(_event: DiagnosticEvent & { type: \"bytecode_built\" }): void {}\n onVmStep(_event: DiagnosticEvent & { type: \"vm_step\" }): void {}\n onVmHalt(_event: DiagnosticEvent & { type: \"vm_halt\" }): void {}\n onCacheHit(_event: DiagnosticEvent & { type: \"cache_hit\" }): void {}\n onCacheMiss(_event: DiagnosticEvent & { type: \"cache_miss\" }): void {}\n onPipelineEnd(_event: DiagnosticEvent & { type: \"pipeline_end\" }): void {}\n\n abstract getReport(): DiagnosticReport | undefined;\n abstract reset(): void;\n}","import { DiagnosticCollector } from \"./collector\";\nimport { DiagnosticReport, DiagnosticReportJSON, DiagnosticEvent, CategorizedParselet } from \"./events\";\n\n/**\n * Collects all pipeline events with high-resolution timestamps.\n *\n * Overrides the zero-filled `elapsedNs` on every incoming event with a\n * real `performance.now()` delta from `onPipelineStart`. This enables\n * per-stage timing extraction from the event timeline (lexer/parser/\n * compiler/VM breakdown) rather than relying on a single total elapsed.\n *\n * Produces a complete DiagnosticReport at the end of evaluation.\n */\nexport class TimelineDiagnosticCollector extends DiagnosticCollector {\n private events: DiagnosticEvent[] = [];\n private startNs: number = 0;\n private parseletEntries: Map<string, { category: string; count: number }> = new Map();\n\n // Incrementally-maintained summary state. See getReport()'s doc comment\n // for why these exist. Each mirrors exactly what getReport() used to\n // recompute by rescanning the full `events` array on every call.\n private totalTokens = 0;\n private cacheHitSeen = false;\n private vmStepSeen = false;\n private hasBytecodeBuilt = false;\n private firstBytecodeOpcodesLength = 0;\n private parseletMatches: CategorizedParselet[] = [];\n private lastExpression = \"\";\n private lastInputType = \"\";\n\n /**\n * Current cumulative count of `parselet_matched` events seen since\n * construction (or the last `reset()`), a cheap peek that doesn't build\n * the full report (`getReport()` copies the whole `parseletMatches`\n * array). Used by `ExpressionEngine.evaluateExpressionWithDiagnostic()`\n * to capture a \"before\" baseline per line, since `parseletMatches` itself\n * is deliberately cumulative across an entire document pass (see\n * `onPipelineStart`'s doc comment) rather than reset per line.\n */\n get parseletMatchCount(): number {\n return this.parseletMatches.length;\n }\n\n reset(): void {\n this.events = [];\n this.parseletEntries.clear();\n this.startNs = 0;\n this.totalTokens = 0;\n this.cacheHitSeen = false;\n this.vmStepSeen = false;\n this.hasBytecodeBuilt = false;\n this.firstBytecodeOpcodesLength = 0;\n this.parseletMatches = [];\n this.lastExpression = \"\";\n this.lastInputType = \"\";\n }\n\n /** Stamp the real wall-clock `elapsedNs` onto an event before storing it. */\n private stamp<T extends DiagnosticEvent>(event: T): T {\n const elapsedNs = this.startNs !== 0\n ? performance.now() * 1e6 - this.startNs\n : 0;\n return { ...event, elapsedNs } as T;\n }\n\n onPipelineStart(event: DiagnosticEvent & { type: \"pipeline_start\" }): void {\n // Set once per collector lifetime (until an explicit reset()), not on\n // every pipeline, a multi-line evaluation pass fires pipeline_start\n // once per line, all appending to the SAME `events` array (see\n // buildLineStats() in the playground, which relies on that shared,\n // ever-growing array to slice out each line's own events via\n // cumulative-length diffing). Resetting the origin on every line meant\n // every individual line's own timestamps were self-consistent, but\n // nothing tied one line's clock to another's, any code trying to\n // compare or span timestamps ACROSS lines (e.g. \"how far into this\n // pass are we\") had no stable reference point to do it with.\n if (this.startNs === 0) {\n this.startNs = performance.now() * 1e6;\n }\n // Tracked incrementally (most-recent wins) so getReport()'s `metadata`\n // describes the line THIS report is actually about, reading\n // `events[0]` instead (the old code) froze `expression`/`inputType` on\n // the very first line ever evaluated in the session, forever, which is\n // wrong regardless of whether a field is meant to be cumulative or\n // per-line: nothing downstream ever wanted \"line 1's expression\" once\n // the document had moved on to line 50.\n this.lastExpression = event.expression;\n this.lastInputType = event.inputType;\n this.events.push(this.stamp(event));\n }\n\n onTokenEmitted(event: DiagnosticEvent & { type: \"token_emitted\" }): void {\n this.events.push(this.stamp(event));\n this.totalTokens++;\n }\n\n onNormalizerStart(event: DiagnosticEvent & { type: \"normalizer_start\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onTokenFused(event: DiagnosticEvent & { type: \"token_fused\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onNormalizerEnd(event: DiagnosticEvent & { type: \"normalizer_end\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onParseletMatched(event: DiagnosticEvent & { type: \"parselet_matched\" }): void {\n this.events.push(this.stamp(event));\n\n const entry = this.parseletEntries.get(event.parseletCategory);\n if (entry) {\n entry.count++;\n } else {\n this.parseletEntries.set(event.parseletCategory, {\n category: event.parseletCategory,\n count: 1,\n });\n }\n\n this.parseletMatches.push({\n tokenType: event.tokenType,\n tokenValue: event.tokenValue,\n parseletCategory: event.parseletCategory,\n parseletType: event.parseletType,\n isPrefix: event.isPrefix,\n bindingPower: event.bindingPower,\n tokenOffset: event.tokenOffset,\n });\n }\n\n onBytecodeBuilt(event: DiagnosticEvent & { type: \"bytecode_built\" }): void {\n this.events.push(this.stamp(event));\n // Matches getReport()'s original behavior: the FIRST bytecode_built\n // event ever seen (not the most recent) wins, preserved as-is here\n // this rewrite only changes HOW that value is computed, not what it is.\n if (!this.hasBytecodeBuilt) {\n this.hasBytecodeBuilt = true;\n this.firstBytecodeOpcodesLength = event.opcodesLength;\n }\n }\n\n onVmStep(event: DiagnosticEvent & { type: \"vm_step\" }): void {\n this.events.push(this.stamp(event));\n this.vmStepSeen = true;\n }\n\n onVmHalt(event: DiagnosticEvent & { type: \"vm_halt\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onCacheHit(event: DiagnosticEvent & { type: \"cache_hit\" }): void {\n this.events.push(this.stamp(event));\n this.cacheHitSeen = true;\n }\n\n onCacheMiss(event: DiagnosticEvent & { type: \"cache_miss\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onPipelineEnd(event: DiagnosticEvent & { type: \"pipeline_end\" }): void {\n this.events.push(this.stamp(event));\n }\n\n/**\n * Build the summary/metadata/parselets report from this collector's\n * running state.\n *\n * These fields used to be recomputed by rescanning the FULL `events`\n * array on every single call (`.some()`/`.filter()`/a manual scan), since\n * `events` is never cleared except by an explicit `reset()` (which nothing\n * in `ExpressionEngine` currently calls, the cumulative-across-the-whole-\n * document design is deliberate, see `onPipelineStart`'s comment and the\n * playground's `buildLineStats()`, which slices per-line events out of\n * this ever-growing array via cumulative-length diffing), that meant\n * per-call cost grew linearly with total prior calls: O(n²) diagnostic-mode\n * evaluation over a document's lifetime. Fixed by maintaining each of these\n * incrementally as events arrive (see the `on*` handlers above), the same\n * pattern already used for `parseletEntries`. Every value produced here is\n * identical to what the old rescanning code produced, including its\n * existing \"first bytecode_built event wins\" quirk. This is a performance\n * fix, not a behavior change.\n */\ngetReport(): DiagnosticReport | undefined {\n if (this.events.length === 0) return undefined;\n\n const elapsedNs = performance.now() * 1e6 - this.startNs;\n\n const parseCategories = new Map<string, number>();\n for (const [, entry] of this.parseletEntries) {\n parseCategories.set(entry.category, entry.count);\n }\n\n const totalOpcodes = this.firstBytecodeOpcodesLength;\n const cacheHit = this.cacheHitSeen;\n const totalTokens = this.totalTokens;\n\n const report: DiagnosticReport = {\n events: this.events,\n parselets: this.parseletMatches.map((e) => ({ ...e })),\n summary: {\n totalTokens,\n totalParselets: parseCategories.size,\n totalOpcodes,\n cacheHit,\n elapsedNs,\n parseCategories,\n },\n metadata: {\n expression: this.lastExpression,\n inputType: this.lastInputType,\n timestamp: Date.now(),\n vmTraceEnabled: this.vmStepSeen,\n },\n toJSON(): DiagnosticReportJSON {\n return {\n events: report.events,\n parselets: report.parselets,\n summary: {\n totalTokens: report.summary.totalTokens,\n totalParselets: report.summary.totalParselets,\n totalOpcodes: report.summary.totalOpcodes,\n cacheHit: report.summary.cacheHit,\n elapsedNs: report.summary.elapsedNs,\n parseCategories: Object.fromEntries(report.summary.parseCategories),\n },\n metadata: { ...report.metadata },\n };\n },\n };\n\n return report;\n }\n}","\n\nimport type { MatrixData, RangeData } from \"@solve-js/vm/Value\";\nimport type { SymbolicNode } from \"@solve-js/symbolic\";\n\n/**\n * Diagnostic event types as string constants (not const enum, for cross-module compatibility with isolatedModules)\n */\nexport const DiagnosticEventType = {\n TokenEmitted: \"token_emitted\",\n NormalizerStart: \"normalizer_start\",\n TokenFused: \"token_fused\",\n NormalizerEnd: \"normalizer_end\",\n ParseletMatched: \"parselet_matched\",\n BytecodeBuilt: \"bytecode_built\",\n VmStep: \"vm_step\",\n VmHalt: \"vm_halt\",\n CacheHit: \"cache_hit\",\n CacheMiss: \"cache_miss\",\n PipelineStart: \"pipeline_start\",\n PipelineEnd: \"pipeline_end\",\n} as const;\n\n/** Discriminator naming which pipeline event a diagnostic record describes. */\nexport type EventType = (typeof DiagnosticEventType)[keyof typeof DiagnosticEventType];\n\n/** Base event, all events include a timestamp relative to pipeline start */\nexport interface BaseEvent {\n readonly type: string;\n readonly elapsedNs: number;\n readonly expression: string;\n}\n\n/** Emitted after each token is produced by the lexer */\nexport interface TokenEmittedEvent extends BaseEvent {\n readonly type: \"token_emitted\";\n readonly token: {\n readonly type: string;\n readonly value: string;\n readonly offset: number;\n readonly line: number;\n readonly col: number;\n };\n}\n\n/** Emitted when the parser resolves a parselet for a token */\nexport interface ParseletMatchedEvent extends BaseEvent {\n readonly type: \"parselet_matched\";\n readonly tokenType: string;\n readonly tokenValue: string;\n readonly parseletCategory: string;\n readonly parseletType: string;\n readonly isPrefix: boolean;\n readonly bindingPower?: number;\n readonly tokenOffset: number;\n}\n\n/** Emitted after bytecode is built */\nexport interface BytecodeBuiltEvent extends BaseEvent {\n readonly type: \"bytecode_built\";\n readonly opcodesLength: number;\n readonly numbersLength: number;\n readonly stringsLength: number;\n readonly isCached: boolean;\n}\n\n/** Emitted after each VM opcode execution (only when vmTrace is enabled) */\nexport interface VmStepEvent extends BaseEvent {\n readonly type: \"vm_step\";\n readonly opcode: number;\n readonly opcodeName: string;\n readonly ip: number;\n readonly stackDepth: number;\n readonly instructionNumber: number;\n readonly stack: ReadonlyArray<{\n readonly type: number;\n readonly value: number | bigint | string | boolean | MatrixData | RangeData | SymbolicNode;\n readonly unit?: string;\n }>;\n}\n\n/** Emitted when the VM halts with a result */\nexport interface VmHaltEvent extends BaseEvent {\n readonly type: \"vm_halt\";\n readonly result?: {\n readonly type: number;\n readonly value: number | bigint | string | boolean | MatrixData | RangeData | SymbolicNode;\n readonly unit?: string;\n };\n}\n\n/** Emitted on cache hit */\nexport interface CacheHitEvent extends BaseEvent {\n readonly type: \"cache_hit\";\n readonly cache: \"bytecode\" | \"line\";\n readonly key: string;\n}\n\n/** Emitted on cache miss */\nexport interface CacheMissEvent extends BaseEvent {\n readonly type: \"cache_miss\";\n readonly cache: \"bytecode\" | \"line\";\n readonly key: string;\n}\n\n/** Emitted when a pipeline evaluation begins */\nexport interface PipelineStartEvent extends BaseEvent {\n readonly type: \"pipeline_start\";\n readonly inputType: string;\n}\n\n/** Emitted when a pipeline evaluation completes */\nexport interface PipelineEndEvent extends BaseEvent {\n readonly type: \"pipeline_end\";\n readonly success: boolean;\n readonly error?: string;\n readonly totalTokens: number;\n readonly totalOpcodes: number;\n}\n\n/** Emitted when the normalizer begins its pass */\nexport interface NormalizerStartEvent extends BaseEvent {\n readonly type: \"normalizer_start\";\n readonly inputTokenCount: number;\n}\n\n/** Emitted when the normalizer fuses tokens */\nexport interface TokenFusedEvent extends BaseEvent {\n readonly type: \"token_fused\";\n readonly ruleName: string;\n readonly sourceTokenCount: number;\n readonly fusedTokenType: string;\n readonly fusedTokenValue: string;\n}\n\n/** Emitted when the normalizer completes its pass */\nexport interface NormalizerEndEvent extends BaseEvent {\n readonly type: \"normalizer_end\";\n readonly outputTokenCount: number;\n readonly fusionsCount: number;\n}\n\n/** Union of all event types */\nexport type DiagnosticEvent =\n | TokenEmittedEvent\n | NormalizerStartEvent\n | TokenFusedEvent\n | NormalizerEndEvent\n | ParseletMatchedEvent\n | BytecodeBuiltEvent\n | VmStepEvent\n | VmHaltEvent\n | CacheHitEvent\n | CacheMissEvent\n | PipelineStartEvent\n | PipelineEndEvent;\n\n/** Categorized parselet info */\nexport interface CategorizedParselet {\n readonly tokenType: string;\n readonly tokenValue: string;\n readonly parseletCategory: string;\n readonly parseletType: string;\n readonly isPrefix: boolean;\n readonly bindingPower?: number;\n readonly tokenOffset: number;\n}\n\n/** JSON-serializable representation of a DiagnosticReport */\nexport interface DiagnosticReportJSON {\n readonly events: readonly DiagnosticEvent[];\n readonly parselets: readonly CategorizedParselet[];\n readonly summary: {\n readonly totalTokens: number;\n readonly totalParselets: number;\n readonly totalOpcodes: number;\n readonly cacheHit: boolean;\n readonly elapsedNs: number;\n readonly parseCategories: Record<string, number>;\n };\n readonly metadata: {\n readonly expression: string;\n readonly inputType: string;\n readonly timestamp: number;\n readonly vmTraceEnabled: boolean;\n };\n}\n\n/** Structured diagnostic report */\nexport interface DiagnosticReport {\n readonly events: readonly DiagnosticEvent[];\n readonly parselets: readonly CategorizedParselet[];\n readonly summary: {\n readonly totalTokens: number;\n readonly totalParselets: number;\n readonly totalOpcodes: number;\n readonly cacheHit: boolean;\n readonly elapsedNs: number;\n readonly parseCategories: ReadonlyMap<string, number>;\n };\n readonly metadata: {\n readonly expression: string;\n readonly inputType: string;\n readonly timestamp: number;\n readonly vmTraceEnabled: boolean;\n };\n\n /** Serialize to a JSON-safe plain object */\n toJSON(): DiagnosticReportJSON;\n}\n\n/** JSON-serializable representation of a DiagnosticReport */\nexport interface DiagnosticReportJSON {\n readonly events: readonly DiagnosticEvent[];\n readonly parselets: readonly CategorizedParselet[];\n readonly summary: {\n readonly totalTokens: number;\n readonly totalParselets: number;\n readonly totalOpcodes: number;\n readonly cacheHit: boolean;\n readonly elapsedNs: number;\n readonly parseCategories: Record<string, number>;\n };\n readonly metadata: {\n readonly expression: string;\n readonly inputType: string;\n readonly timestamp: number;\n readonly vmTraceEnabled: boolean;\n };\n}"]}
1
+ {"version":3,"sources":["../src/diagnostics/pipeline.ts","../src/diagnostics/collector.ts","../src/diagnostics/timeline-collector.ts","../src/diagnostics/events.ts"],"names":[],"mappings":"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","file":"chunk-XA4CKRML.cjs","sourcesContent":["import { DiagnosticCollector } from \"./collector\";\nimport { DiagnosticEvent } from \"./events\";\nimport { DiagnosticReport } from \"./events\";\n\n/**\n * Dispatches diagnostic events to all registered collectors.\n *\n * Performance guarantee: when no collectors are registered (production mode),\n * every dispatch method is a branch on `this.collectors.length === 0` which\n * modern JS engines will predict and eliminate. The overhead is a single\n * comparison per call, effectively zero.\n */\nexport class DiagnosticPipeline {\n private collectors: DiagnosticCollector[] = [];\n\n register(collector: DiagnosticCollector): void {\n this.collectors.push(collector);\n }\n\n unregister(collector: DiagnosticCollector): void {\n const idx = this.collectors.indexOf(collector);\n if (idx !== -1) this.collectors.splice(idx, 1);\n }\n\n clear(): void {\n this.collectors = [];\n }\n\n get hasCollectors(): boolean {\n return this.collectors.length > 0;\n }\n\n get collectorCount(): number {\n return this.collectors.length;\n }\n\n // Inline-optimized dispatchers, each checks length once then loops.\n // When collectors.length === 0, the JIT eliminates the entire method body.\n\n firePipelineStart(event: DiagnosticEvent & { type: \"pipeline_start\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onPipelineStart?.(event);\n }\n\n fireTokenEmitted(event: DiagnosticEvent & { type: \"token_emitted\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onTokenEmitted?.(event);\n }\n\n fireNormalizerStart(event: DiagnosticEvent & { type: \"normalizer_start\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onNormalizerStart?.(event);\n }\n\n fireTokenFused(event: DiagnosticEvent & { type: \"token_fused\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onTokenFused?.(event);\n }\n\n fireNormalizerEnd(event: DiagnosticEvent & { type: \"normalizer_end\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onNormalizerEnd?.(event);\n }\n\n fireParseletMatched(event: DiagnosticEvent & { type: \"parselet_matched\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onParseletMatched?.(event);\n }\n\n fireBytecodeBuilt(event: DiagnosticEvent & { type: \"bytecode_built\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onBytecodeBuilt?.(event);\n }\n\n fireVmStep(event: DiagnosticEvent & { type: \"vm_step\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onVmStep?.(event);\n }\n\n fireVmHalt(event: DiagnosticEvent & { type: \"vm_halt\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onVmHalt?.(event);\n }\n\n fireCacheHit(event: DiagnosticEvent & { type: \"cache_hit\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onCacheHit?.(event);\n }\n\n fireCacheMiss(event: DiagnosticEvent & { type: \"cache_miss\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onCacheMiss?.(event);\n }\n\n firePipelineEnd(event: DiagnosticEvent & { type: \"pipeline_end\" }): void {\n if (this.collectors.length === 0) return;\n for (const c of this.collectors) c.onPipelineEnd?.(event);\n }\n\n collectReports(): DiagnosticReport[] {\n const reports: DiagnosticReport[] = [];\n for (const c of this.collectors) {\n const report = c.getReport();\n if (report) reports.push(report);\n }\n return reports;\n }\n\n reset(): void {\n for (const c of this.collectors) c.reset();\n }\n}","import { DiagnosticEvent } from \"./events\";\nimport { DiagnosticReport } from \"./events\";\n\n/**\n * Interface for collecting diagnostic data during pipeline execution.\n *\n * All methods are implemented as concrete no-ops so subclasses only\n * need to override the ones they care about. This avoids optional\n * method issues with TypeScript's strict mode.\n *\n * The parameters are named `_event` because these base implementations\n * deliberately ignore them. Overrides are free to name theirs `event` and use\n * it; TypeScript does not match parameter names when checking overrides.\n */\nexport abstract class DiagnosticCollector {\n onPipelineStart(_event: DiagnosticEvent & { type: \"pipeline_start\" }): void {}\n onTokenEmitted(_event: DiagnosticEvent & { type: \"token_emitted\" }): void {}\n onNormalizerStart(_event: DiagnosticEvent & { type: \"normalizer_start\" }): void {}\n onTokenFused(_event: DiagnosticEvent & { type: \"token_fused\" }): void {}\n onNormalizerEnd(_event: DiagnosticEvent & { type: \"normalizer_end\" }): void {}\n onParseletMatched(_event: DiagnosticEvent & { type: \"parselet_matched\" }): void {}\n onBytecodeBuilt(_event: DiagnosticEvent & { type: \"bytecode_built\" }): void {}\n onVmStep(_event: DiagnosticEvent & { type: \"vm_step\" }): void {}\n onVmHalt(_event: DiagnosticEvent & { type: \"vm_halt\" }): void {}\n onCacheHit(_event: DiagnosticEvent & { type: \"cache_hit\" }): void {}\n onCacheMiss(_event: DiagnosticEvent & { type: \"cache_miss\" }): void {}\n onPipelineEnd(_event: DiagnosticEvent & { type: \"pipeline_end\" }): void {}\n\n abstract getReport(): DiagnosticReport | undefined;\n abstract reset(): void;\n}","import { DiagnosticCollector } from \"./collector\";\nimport { DiagnosticReport, DiagnosticReportJSON, DiagnosticEvent, CategorizedParselet } from \"./events\";\n\n/**\n * Collects all pipeline events with high-resolution timestamps.\n *\n * Overrides the zero-filled `elapsedNs` on every incoming event with a\n * real `performance.now()` delta from `onPipelineStart`. This enables\n * per-stage timing extraction from the event timeline (lexer/parser/\n * compiler/VM breakdown) rather than relying on a single total elapsed.\n *\n * Produces a complete DiagnosticReport at the end of evaluation.\n */\nexport class TimelineDiagnosticCollector extends DiagnosticCollector {\n private events: DiagnosticEvent[] = [];\n private startNs: number = 0;\n private parseletEntries: Map<string, { category: string; count: number }> = new Map();\n\n // Incrementally-maintained summary state. See getReport()'s doc comment\n // for why these exist. Each mirrors exactly what getReport() used to\n // recompute by rescanning the full `events` array on every call.\n private totalTokens = 0;\n private cacheHitSeen = false;\n private vmStepSeen = false;\n private hasBytecodeBuilt = false;\n private firstBytecodeOpcodesLength = 0;\n private parseletMatches: CategorizedParselet[] = [];\n private lastExpression = \"\";\n private lastInputType = \"\";\n\n /**\n * Current cumulative count of `parselet_matched` events seen since\n * construction (or the last `reset()`), a cheap peek that doesn't build\n * the full report (`getReport()` copies the whole `parseletMatches`\n * array). Used by `ExpressionEngine.evaluateExpressionWithDiagnostic()`\n * to capture a \"before\" baseline per line, since `parseletMatches` itself\n * is deliberately cumulative across an entire document pass (see\n * `onPipelineStart`'s doc comment) rather than reset per line.\n */\n get parseletMatchCount(): number {\n return this.parseletMatches.length;\n }\n\n reset(): void {\n this.events = [];\n this.parseletEntries.clear();\n this.startNs = 0;\n this.totalTokens = 0;\n this.cacheHitSeen = false;\n this.vmStepSeen = false;\n this.hasBytecodeBuilt = false;\n this.firstBytecodeOpcodesLength = 0;\n this.parseletMatches = [];\n this.lastExpression = \"\";\n this.lastInputType = \"\";\n }\n\n /** Stamp the real wall-clock `elapsedNs` onto an event before storing it. */\n private stamp<T extends DiagnosticEvent>(event: T): T {\n const elapsedNs = this.startNs !== 0\n ? performance.now() * 1e6 - this.startNs\n : 0;\n return { ...event, elapsedNs } as T;\n }\n\n onPipelineStart(event: DiagnosticEvent & { type: \"pipeline_start\" }): void {\n // Set once per collector lifetime (until an explicit reset()), not on\n // every pipeline, a multi-line evaluation pass fires pipeline_start\n // once per line, all appending to the SAME `events` array (see\n // buildLineStats() in the playground, which relies on that shared,\n // ever-growing array to slice out each line's own events via\n // cumulative-length diffing). Resetting the origin on every line meant\n // every individual line's own timestamps were self-consistent, but\n // nothing tied one line's clock to another's, any code trying to\n // compare or span timestamps ACROSS lines (e.g. \"how far into this\n // pass are we\") had no stable reference point to do it with.\n if (this.startNs === 0) {\n this.startNs = performance.now() * 1e6;\n }\n // Tracked incrementally (most-recent wins) so getReport()'s `metadata`\n // describes the line THIS report is actually about, reading\n // `events[0]` instead (the old code) froze `expression`/`inputType` on\n // the very first line ever evaluated in the session, forever, which is\n // wrong regardless of whether a field is meant to be cumulative or\n // per-line: nothing downstream ever wanted \"line 1's expression\" once\n // the document had moved on to line 50.\n this.lastExpression = event.expression;\n this.lastInputType = event.inputType;\n this.events.push(this.stamp(event));\n }\n\n onTokenEmitted(event: DiagnosticEvent & { type: \"token_emitted\" }): void {\n this.events.push(this.stamp(event));\n this.totalTokens++;\n }\n\n onNormalizerStart(event: DiagnosticEvent & { type: \"normalizer_start\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onTokenFused(event: DiagnosticEvent & { type: \"token_fused\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onNormalizerEnd(event: DiagnosticEvent & { type: \"normalizer_end\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onParseletMatched(event: DiagnosticEvent & { type: \"parselet_matched\" }): void {\n this.events.push(this.stamp(event));\n\n const entry = this.parseletEntries.get(event.parseletCategory);\n if (entry) {\n entry.count++;\n } else {\n this.parseletEntries.set(event.parseletCategory, {\n category: event.parseletCategory,\n count: 1,\n });\n }\n\n this.parseletMatches.push({\n tokenType: event.tokenType,\n tokenValue: event.tokenValue,\n parseletCategory: event.parseletCategory,\n parseletType: event.parseletType,\n isPrefix: event.isPrefix,\n bindingPower: event.bindingPower,\n tokenOffset: event.tokenOffset,\n });\n }\n\n onBytecodeBuilt(event: DiagnosticEvent & { type: \"bytecode_built\" }): void {\n this.events.push(this.stamp(event));\n // Matches getReport()'s original behavior: the FIRST bytecode_built\n // event ever seen (not the most recent) wins, preserved as-is here\n // this rewrite only changes HOW that value is computed, not what it is.\n if (!this.hasBytecodeBuilt) {\n this.hasBytecodeBuilt = true;\n this.firstBytecodeOpcodesLength = event.opcodesLength;\n }\n }\n\n onVmStep(event: DiagnosticEvent & { type: \"vm_step\" }): void {\n this.events.push(this.stamp(event));\n this.vmStepSeen = true;\n }\n\n onVmHalt(event: DiagnosticEvent & { type: \"vm_halt\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onCacheHit(event: DiagnosticEvent & { type: \"cache_hit\" }): void {\n this.events.push(this.stamp(event));\n this.cacheHitSeen = true;\n }\n\n onCacheMiss(event: DiagnosticEvent & { type: \"cache_miss\" }): void {\n this.events.push(this.stamp(event));\n }\n\n onPipelineEnd(event: DiagnosticEvent & { type: \"pipeline_end\" }): void {\n this.events.push(this.stamp(event));\n }\n\n/**\n * Build the summary/metadata/parselets report from this collector's\n * running state.\n *\n * These fields used to be recomputed by rescanning the FULL `events`\n * array on every single call (`.some()`/`.filter()`/a manual scan), since\n * `events` is never cleared except by an explicit `reset()` (which nothing\n * in `ExpressionEngine` currently calls, the cumulative-across-the-whole-\n * document design is deliberate, see `onPipelineStart`'s comment and the\n * playground's `buildLineStats()`, which slices per-line events out of\n * this ever-growing array via cumulative-length diffing), that meant\n * per-call cost grew linearly with total prior calls: O(n²) diagnostic-mode\n * evaluation over a document's lifetime. Fixed by maintaining each of these\n * incrementally as events arrive (see the `on*` handlers above), the same\n * pattern already used for `parseletEntries`. Every value produced here is\n * identical to what the old rescanning code produced, including its\n * existing \"first bytecode_built event wins\" quirk. This is a performance\n * fix, not a behavior change.\n */\ngetReport(): DiagnosticReport | undefined {\n if (this.events.length === 0) return undefined;\n\n const elapsedNs = performance.now() * 1e6 - this.startNs;\n\n const parseCategories = new Map<string, number>();\n for (const [, entry] of this.parseletEntries) {\n parseCategories.set(entry.category, entry.count);\n }\n\n const totalOpcodes = this.firstBytecodeOpcodesLength;\n const cacheHit = this.cacheHitSeen;\n const totalTokens = this.totalTokens;\n\n const report: DiagnosticReport = {\n events: this.events,\n parselets: this.parseletMatches.map((e) => ({ ...e })),\n summary: {\n totalTokens,\n totalParselets: parseCategories.size,\n totalOpcodes,\n cacheHit,\n elapsedNs,\n parseCategories,\n },\n metadata: {\n expression: this.lastExpression,\n inputType: this.lastInputType,\n timestamp: Date.now(),\n vmTraceEnabled: this.vmStepSeen,\n },\n toJSON(): DiagnosticReportJSON {\n return {\n events: report.events,\n parselets: report.parselets,\n summary: {\n totalTokens: report.summary.totalTokens,\n totalParselets: report.summary.totalParselets,\n totalOpcodes: report.summary.totalOpcodes,\n cacheHit: report.summary.cacheHit,\n elapsedNs: report.summary.elapsedNs,\n parseCategories: Object.fromEntries(report.summary.parseCategories),\n },\n metadata: { ...report.metadata },\n };\n },\n };\n\n return report;\n }\n}","\n\nimport type { MatrixData, RangeData, ColourData } from \"@solve-js/vm/Value\";\nimport type { SymbolicNode } from \"@solve-js/symbolic\";\n\n/**\n * Diagnostic event types as string constants (not const enum, for cross-module compatibility with isolatedModules)\n */\nexport const DiagnosticEventType = {\n TokenEmitted: \"token_emitted\",\n NormalizerStart: \"normalizer_start\",\n TokenFused: \"token_fused\",\n NormalizerEnd: \"normalizer_end\",\n ParseletMatched: \"parselet_matched\",\n BytecodeBuilt: \"bytecode_built\",\n VmStep: \"vm_step\",\n VmHalt: \"vm_halt\",\n CacheHit: \"cache_hit\",\n CacheMiss: \"cache_miss\",\n PipelineStart: \"pipeline_start\",\n PipelineEnd: \"pipeline_end\",\n} as const;\n\n/** Discriminator naming which pipeline event a diagnostic record describes. */\nexport type EventType = (typeof DiagnosticEventType)[keyof typeof DiagnosticEventType];\n\n/** Base event, all events include a timestamp relative to pipeline start */\nexport interface BaseEvent {\n readonly type: string;\n readonly elapsedNs: number;\n readonly expression: string;\n}\n\n/** Emitted after each token is produced by the lexer */\nexport interface TokenEmittedEvent extends BaseEvent {\n readonly type: \"token_emitted\";\n readonly token: {\n readonly type: string;\n readonly value: string;\n readonly offset: number;\n readonly line: number;\n readonly col: number;\n };\n}\n\n/** Emitted when the parser resolves a parselet for a token */\nexport interface ParseletMatchedEvent extends BaseEvent {\n readonly type: \"parselet_matched\";\n readonly tokenType: string;\n readonly tokenValue: string;\n readonly parseletCategory: string;\n readonly parseletType: string;\n readonly isPrefix: boolean;\n readonly bindingPower?: number;\n readonly tokenOffset: number;\n}\n\n/** Emitted after bytecode is built */\nexport interface BytecodeBuiltEvent extends BaseEvent {\n readonly type: \"bytecode_built\";\n readonly opcodesLength: number;\n readonly numbersLength: number;\n readonly stringsLength: number;\n readonly isCached: boolean;\n}\n\n/** Emitted after each VM opcode execution (only when vmTrace is enabled) */\nexport interface VmStepEvent extends BaseEvent {\n readonly type: \"vm_step\";\n readonly opcode: number;\n readonly opcodeName: string;\n readonly ip: number;\n readonly stackDepth: number;\n readonly instructionNumber: number;\n readonly stack: ReadonlyArray<{\n readonly type: number;\n readonly value: number | bigint | string | boolean | MatrixData | RangeData | ColourData | SymbolicNode;\n readonly unit?: string;\n }>;\n}\n\n/** Emitted when the VM halts with a result */\nexport interface VmHaltEvent extends BaseEvent {\n readonly type: \"vm_halt\";\n readonly result?: {\n readonly type: number;\n readonly value: number | bigint | string | boolean | MatrixData | RangeData | ColourData | SymbolicNode;\n readonly unit?: string;\n };\n}\n\n/** Emitted on cache hit */\nexport interface CacheHitEvent extends BaseEvent {\n readonly type: \"cache_hit\";\n readonly cache: \"bytecode\" | \"line\";\n readonly key: string;\n}\n\n/** Emitted on cache miss */\nexport interface CacheMissEvent extends BaseEvent {\n readonly type: \"cache_miss\";\n readonly cache: \"bytecode\" | \"line\";\n readonly key: string;\n}\n\n/** Emitted when a pipeline evaluation begins */\nexport interface PipelineStartEvent extends BaseEvent {\n readonly type: \"pipeline_start\";\n readonly inputType: string;\n}\n\n/** Emitted when a pipeline evaluation completes */\nexport interface PipelineEndEvent extends BaseEvent {\n readonly type: \"pipeline_end\";\n readonly success: boolean;\n readonly error?: string;\n readonly totalTokens: number;\n readonly totalOpcodes: number;\n}\n\n/** Emitted when the normalizer begins its pass */\nexport interface NormalizerStartEvent extends BaseEvent {\n readonly type: \"normalizer_start\";\n readonly inputTokenCount: number;\n}\n\n/** Emitted when the normalizer fuses tokens */\nexport interface TokenFusedEvent extends BaseEvent {\n readonly type: \"token_fused\";\n readonly ruleName: string;\n readonly sourceTokenCount: number;\n readonly fusedTokenType: string;\n readonly fusedTokenValue: string;\n}\n\n/** Emitted when the normalizer completes its pass */\nexport interface NormalizerEndEvent extends BaseEvent {\n readonly type: \"normalizer_end\";\n readonly outputTokenCount: number;\n readonly fusionsCount: number;\n}\n\n/** Union of all event types */\nexport type DiagnosticEvent =\n | TokenEmittedEvent\n | NormalizerStartEvent\n | TokenFusedEvent\n | NormalizerEndEvent\n | ParseletMatchedEvent\n | BytecodeBuiltEvent\n | VmStepEvent\n | VmHaltEvent\n | CacheHitEvent\n | CacheMissEvent\n | PipelineStartEvent\n | PipelineEndEvent;\n\n/** Categorized parselet info */\nexport interface CategorizedParselet {\n readonly tokenType: string;\n readonly tokenValue: string;\n readonly parseletCategory: string;\n readonly parseletType: string;\n readonly isPrefix: boolean;\n readonly bindingPower?: number;\n readonly tokenOffset: number;\n}\n\n/** JSON-serializable representation of a DiagnosticReport */\nexport interface DiagnosticReportJSON {\n readonly events: readonly DiagnosticEvent[];\n readonly parselets: readonly CategorizedParselet[];\n readonly summary: {\n readonly totalTokens: number;\n readonly totalParselets: number;\n readonly totalOpcodes: number;\n readonly cacheHit: boolean;\n readonly elapsedNs: number;\n readonly parseCategories: Record<string, number>;\n };\n readonly metadata: {\n readonly expression: string;\n readonly inputType: string;\n readonly timestamp: number;\n readonly vmTraceEnabled: boolean;\n };\n}\n\n/** Structured diagnostic report */\nexport interface DiagnosticReport {\n readonly events: readonly DiagnosticEvent[];\n readonly parselets: readonly CategorizedParselet[];\n readonly summary: {\n readonly totalTokens: number;\n readonly totalParselets: number;\n readonly totalOpcodes: number;\n readonly cacheHit: boolean;\n readonly elapsedNs: number;\n readonly parseCategories: ReadonlyMap<string, number>;\n };\n readonly metadata: {\n readonly expression: string;\n readonly inputType: string;\n readonly timestamp: number;\n readonly vmTraceEnabled: boolean;\n };\n\n /** Serialize to a JSON-safe plain object */\n toJSON(): DiagnosticReportJSON;\n}\n\n/** JSON-serializable representation of a DiagnosticReport */\nexport interface DiagnosticReportJSON {\n readonly events: readonly DiagnosticEvent[];\n readonly parselets: readonly CategorizedParselet[];\n readonly summary: {\n readonly totalTokens: number;\n readonly totalParselets: number;\n readonly totalOpcodes: number;\n readonly cacheHit: boolean;\n readonly elapsedNs: number;\n readonly parseCategories: Record<string, number>;\n };\n readonly metadata: {\n readonly expression: string;\n readonly inputType: string;\n readonly timestamp: number;\n readonly vmTraceEnabled: boolean;\n };\n}"]}
@@ -12,6 +12,7 @@ var OpCode = /* @__PURE__ */ ((OpCode2) => {
12
12
  OpCode2[OpCode2["PUSH_STRING"] = 13] = "PUSH_STRING";
13
13
  OpCode2[OpCode2["PUSH_BOOLEAN"] = 14] = "PUSH_BOOLEAN";
14
14
  OpCode2[OpCode2["PUSH_VARIABLE"] = 15] = "PUSH_VARIABLE";
15
+ OpCode2[OpCode2["PUSH_DECIMAL"] = 16] = "PUSH_DECIMAL";
15
16
  OpCode2[OpCode2["ADD"] = 20] = "ADD";
16
17
  OpCode2[OpCode2["SUB"] = 21] = "SUB";
17
18
  OpCode2[OpCode2["MUL"] = 22] = "MUL";
@@ -20,6 +21,7 @@ var OpCode = /* @__PURE__ */ ((OpCode2) => {
20
21
  OpCode2[OpCode2["EXP"] = 25] = "EXP";
21
22
  OpCode2[OpCode2["NEG"] = 26] = "NEG";
22
23
  OpCode2[OpCode2["POS"] = 27] = "POS";
24
+ OpCode2[OpCode2["MAKE_UNCERTAIN"] = 28] = "MAKE_UNCERTAIN";
23
25
  OpCode2[OpCode2["LSHIFT"] = 30] = "LSHIFT";
24
26
  OpCode2[OpCode2["RSHIFT"] = 31] = "RSHIFT";
25
27
  OpCode2[OpCode2["URSHIFT"] = 32] = "URSHIFT";
@@ -55,6 +57,8 @@ var OpCode = /* @__PURE__ */ ((OpCode2) => {
55
57
  OpCode2[OpCode2["DATE_NEXT_WEEKDAY"] = 93] = "DATE_NEXT_WEEKDAY";
56
58
  OpCode2[OpCode2["DATE_LAST_WEEKDAY"] = 94] = "DATE_LAST_WEEKDAY";
57
59
  OpCode2[OpCode2["DATE_LITERAL"] = 95] = "DATE_LITERAL";
60
+ OpCode2[OpCode2["DATE_WORKDAY_OFFSET"] = 96] = "DATE_WORKDAY_OFFSET";
61
+ OpCode2[OpCode2["DATE_WORKDAYS_BETWEEN"] = 97] = "DATE_WORKDAYS_BETWEEN";
58
62
  OpCode2[OpCode2["RATE_DIV"] = 110] = "RATE_DIV";
59
63
  OpCode2[OpCode2["RATE_MUL"] = 111] = "RATE_MUL";
60
64
  OpCode2[OpCode2["RATE_CONVERT"] = 112] = "RATE_CONVERT";
@@ -93,5 +97,5 @@ function getOpCodeName(op) {
93
97
 
94
98
  exports.OpCode = OpCode;
95
99
  exports.getOpCodeName = getOpCodeName;
96
- //# sourceMappingURL=chunk-6KFYJ6TD.cjs.map
97
- //# sourceMappingURL=chunk-6KFYJ6TD.cjs.map
100
+ //# sourceMappingURL=chunk-XIYYHA65.cjs.map
101
+ //# sourceMappingURL=chunk-XIYYHA65.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parser/OpCode.ts"],"names":["OpCode"],"mappings":"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","file":"chunk-XIYYHA65.cjs","sourcesContent":["/**\n * The VM's bytecode instruction set.\n *\n * Emitted by parselets (via {@link BytecodeBuilder}) during parsing and\n * consumed by the VM's dispatch loop during execution. Values are grouped\n * into numeric bands by category (0-9 stack ops, 10-19 push-literal, 20-29\n * arithmetic, ...) purely for readability, the VM dispatches on the exact\n * numeric value, not the band.\n *\n * Third-party packages emit `CALL_PLUGIN` (with a plugin-function index\n * from {@link allocatePluginFunctionIndex}) to invoke their own logic\n * see `IEnginePackage.pluginFunctions`. The other opcodes are used\n * internally by the built-in packages' parselets.\n */\nexport enum OpCode {\n\t// Stack operations\n\tNOP = 0,\n\tHALT = 1,\n\tSWAP = 2,\n\tDUP = 3,\n\n\t// Push literals\n\tPUSH_NUMBER = 10,\n\tPUSH_BIGINT = 11,\n\tPUSH_HEX = 12,\n\tPUSH_STRING = 13,\n\tPUSH_BOOLEAN = 14,\n\tPUSH_VARIABLE = 15,\n\t// A decimal-point literal, pushed with the exact base-ten value it was\n\t// written as alongside the nearest double. The operand is a string-pool\n\t// index holding the normalized \".\" decimal text (thousands grouping already\n\t// stripped), read back into a Number-typed Value whose `exact` sidecar makes\n\t// money that combines with it exact. See vm/Value.ts's numberValueExact().\n\tPUSH_DECIMAL = 16,\n\n\t// Arithmetic (BinaryOperator)\n\tADD = 20,\n\tSUB = 21,\n\tMUL = 22,\n\tDIV = 23,\n\tMOD = 24,\n\tEXP = 25,\n\tNEG = 26,\n\tPOS = 27,\n\t// `a ± b` (or the ASCII `a +/- b`): pops the spread then the center off the\n\t// stack and pushes a Number carrying a one-sigma uncertainty (`vm/Value.ts`'s\n\t// numberValueUncertain). Takes no operand byte, like the other arithmetic\n\t// ops. See packages/uncertainty/ for the parselet that emits it and\n\t// vm/VMConversion.ts's uncertainOp for how the four arithmetic ops propagate.\n\tMAKE_UNCERTAIN = 28,\n\n\t// Bitwise\n\tLSHIFT = 30,\n\tRSHIFT = 31,\n\tURSHIFT = 32,\n\tBIT_AND = 33,\n\tBIT_OR = 34,\n\tBIT_XOR = 35,\n\tBIT_NOT = 36,\n\n\t// Comparison\n\tEQ = 40,\n\tNEQ = 41,\n\tLT = 42,\n\tLTE = 43,\n\tGT = 44,\n\tGTE = 45,\n\n\t// Functions\n\tCALL_PLUGIN = 50, // Plugin-registered functions (may be async — pre-resolved by orchestrator)\n\tCALL_BUILTIN = 51, // Sync built-in functions (sqrt, sin, diceRoll, matmul)\n\tRETURN = 52, // Reserved for future user-defined functions\n\n\t// Variables\n\tLOAD_VAR = 60,\n\tSTORE_VAR = 61,\n\tLOAD_GLOBAL_VAR = 62, // Reads from the process-wide GlobalVariableStore, not the VM's local scope\n\tSTORE_GLOBAL_VAR = 63, // Writes to the process-wide GlobalVariableStore, visible to every document\n\n\t// Type conversion\n\tTO_NUMBER = 70,\n\tTO_HEX = 71,\n\tTO_PERCENTAGE = 74,\n\n\t// UoM\n\tUOM_CONVERT = 80,\n\tUOM_CONVERT_TO = 81,\n\tUOM_GET_VALUE = 82,\n\tUOM_BEST = 83,\n\tUOM_CONVERT_IN = 84,\n\tUOM_POSSIBILITIES = 85, // \"sourceUnit to ?\" — list units convertible from sourceUnit\n\n\t// Datetime\n\tDATE_NOW = 90,\n\tDATE_ADD = 91,\n\tDATE_SUB = 92,\n\tDATE_NEXT_WEEKDAY = 93, // \"next <Weekday>\" — the next occurrence strictly after now\n\tDATE_LAST_WEEKDAY = 94, // \"last <Weekday>\" — the previous occurrence strictly before now\n\tDATE_LITERAL = 95, // Push a datetime literal whose epoch-ms was already resolved at parse time (see DateLiteralParselet)\n\tDATE_WORKDAY_OFFSET = 96, // \"N working days after/before/from <date>\" — a business-day walk from the anchor date. One operand byte: 0 forward, 1 backward. Same walk as `<date> + N workdays` (vm/VM.ts's addBusinessDays). See WorkdayOffsetParselet.\n\tDATE_WORKDAYS_BETWEEN = 97, // \"working days between <date> and <date>\" — the count of working days in the inclusive span. See WorkdaysBetweenParselet and vm/BusinessDays.ts's countBusinessDaysBetween.\n\n\t// Rate, \"quantity per unit of something\" ($99/week, 30 fps). See\n\t// vm/Value.ts's rateValue()/isRateUnit()/splitRateUnit() for the\n\t// representation these opcodes operate on.\n\tRATE_DIV = 110, // Uom ÷ Uom (different measures) -> Rate — the construction op\n\tRATE_MUL = 111, // Rate × Uom (same measure as denominator) -> plain Uom (denominator cancels)\n\tRATE_CONVERT = 112, // Rate -> Rate with a rescaled denominator unit (keeps the same real-world rate)\n\n\t// Time, clock-time-of-day, lap times, video timecode (distinct from\n\t// the Datetime band's calendar-date arithmetic).\n\tCLOCK_TIME_TODAY = 120, // minutes-since-midnight -> Datetime anchored to today's calendar date\n\n\t// Conditionals, boolean logic and eager-evaluated ternary selection.\n\t// EQ/NEQ/LT/LTE/GT/GTE (40-45, above) already existed as dead opcodes\n\t// before this band was wired up; see vm/VM.ts for their handlers.\n\tLOGICAL_AND = 130, // Boolean && Boolean -> Boolean\n\tLOGICAL_OR = 131, // Boolean || Boolean -> Boolean\n\tSELECT = 132, // (thenVal, elseVal, condition) -> thenVal if condition else elseVal — EAGER (both\n\t // branches already evaluated by the time this runs; no real branching/short-circuit,\n\t // a deliberate simplification for a side-effect-free expression language, see\n\t // packages/conditionals/parselets/IfThenElseParselet.ts)\n\n\t// Converters, the general \"as <type>\" mechanism. TO_NUMBER/TO_HEX/\n\t// TO_PERCENTAGE (70/71/74, above) cover the simplest cases; these cover\n\t// the ones with no existing opcode. CALL_AS_CONVERTER is the SDK\n\t// extension point. See IEnginePackage.asConverters and\n\t// vm/VMBuiltins.ts's asConverterRegistry.\n\tTO_FRACTION = 140, // Number -> String, simplified fraction (\"0.5\" -> \"1/2\")\n\tTO_MULTIPLIER = 141, // Number -> String, \"1 + n\" growth multiplier (\"0.5\" -> \"1.5x\")\n\tTO_SCI = 142, // Number -> String, scientific notation (\"1500000\" -> \"1.5e+6\")\n\tTO_BINARY = 143, // Number -> String, base-2 display (\"10\" -> \"0b1010\")\n\tTO_OCTAL = 144, // Number -> String, base-8 display (\"10\" -> \"0o12\")\n\tCALL_AS_CONVERTER = 145, // (value, name) -> runtime asConverterRegistry lookup + call\n\n\t// User-defined, parameterized, reusable functions (f(x) = expr, then\n\t// f(5). See parser/PrecedenceParser.ts's IDENT_ID case\n\t// parser/BytecodeBuilder.ts's UserFunctionDef/emitUserFunctionBody, and\n\t// vm/VM.ts's VM.userFunctions/callFrames). Parameter references inside a\n\t// function body are ORDINARY LOAD_VAR opcodes, not a dedicated\n\t// parameter-load opcode, CALL_USER_FUNCTION binds arguments into a\n\t// name-keyed call frame at runtime, and LOAD_VAR checks the innermost\n\t// call frame before the flat variable store (see VM.getVar()).\n\tDEFINE_USER_FUNCTION = 150, // (operand = index into bytecode.userFunctionBodies) -> register name/params/program into vm.userFunctions. Registration happens at VM-EXECUTION time, not parse time, so a diagnostic/lookahead parse that compiles but never executes a definition line has no side effect on the shared registry.\n\tCALL_USER_FUNCTION = 151, // (N arg values already on stack) -> pop N args, bind by NAME into a new call frame, execute the named function's stored body (reentrant executeBytecode), push its result\n\n\t// Matrix (Calca-parity, replaces the old ARR_* vector-only opcodes\n\t// which were never emitted by any registered parselet; see\n\t// vm/MatrixOps.ts for the shared column-major storage helpers this band\n\t// operates on, and vm/Value.ts's MatrixData for the representation).\n\tMAT_NEW = 152, // (rows, cols operands; rows*cols values already on stack, ROW-MAJOR push order) -> pop rows*cols values, transpose to column-major, push a Matrix\n\tMAT_INDEX1 = 153, // (matrix, index already on stack) -> column-major single-index read `a[i]`\n\tMAT_INDEX2 = 154, // (matrix, row, col already on stack) -> `a[row, col]` read\n\tMAT_SLICE = 155, // (matrix, rowRange, colRange already on stack) -> sub-matrix via two Range values\n\tRANGE_NEW = 156, // (min, max already on stack) -> push a Range value `min:max`\n\tMAP_INVOKE = 157, // map(...) — see parser/BytecodeBuilder.ts's `anonymousBodies` side-table\n\tREDUCE_INVOKE = 158, // reduce(...) — same anonymousBodies mechanism as MAP_INVOKE\n\t// An algebra verb's expression argument, evaluated with the verb's own\n\t// named unknown bound to itself (`der(x^2, x)` reads `x` as the unknown\n\t// even where the document also has a value for it). Operand = an index\n\t// into `anonymousBodies`, whose `params[0]` carries the name to bind, the\n\t// same side-table and the same call-frame shadowing MAP_INVOKE uses for a\n\t// transform body's parameters. See vm/VM.ts's handler.\n\tBIND_UNKNOWN = 159,\n\t// 159 and 160 were THEREFORE_SOLVE and STORE_EQUATION_OR_ASSIGNMENT, declared\n\t// but never emitted by any parselet nor handled in the VM switch. Both shapes\n\t// have effects (a stored equation, a direct vm.setVar()) that a cached\n\t// bytecode program cannot represent, so engine/ExpressionEngine.ts intercepts\n\t// them before compilation and always will. 159 has since been reused above;\n\t// 160 is still free.\n}\n\n// Reverse lookup built once at module load, getOpCodeName() is called once\n// per VM instruction whenever a diagnostic collector is attached (VM.ts's\n// trace path), so a per-call linear scan of every enum entry (TS numeric\n// enums are bidirectional at runtime, so Object.entries(OpCode) yields both\n// \"NOP\" -> 0 and \"0\" -> \"NOP\" style entries) would otherwise redo the same\n// scan every single traced instruction. Only the numeric-valued entries are\n// kept, the string-valued reverse entries TS also generates aren't needed\n// here.\nconst OP_CODE_NAMES: ReadonlyMap<number, string> = (() => {\n\tconst map = new Map<number, string>();\n\tfor (const [key, value] of Object.entries(OpCode)) {\n\t\tif (typeof value === \"number\") map.set(value, key);\n\t}\n\treturn map;\n})();\n\n/**\n * Gets the name of an OpCode as a string.\n * @param op The OpCode value\n * @returns The enum name as a string, or \"UNKNOWN_<value>\" if not found\n */\nexport function getOpCodeName(op: number): string {\n\treturn OP_CODE_NAMES.get(op) ?? `UNKNOWN_${op}`;\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkTY3TLZAW_cjs = require('./chunk-TY3TLZAW.cjs');
4
- var chunkR7YVBHCV_cjs = require('./chunk-R7YVBHCV.cjs');
3
+ var chunk536WPM2V_cjs = require('./chunk-536WPM2V.cjs');
4
+ var chunkYTIYVHL7_cjs = require('./chunk-YTIYVHL7.cjs');
5
5
  var chunkOUHT5Z36_cjs = require('./chunk-OUHT5Z36.cjs');
6
6
  var chunkAQNHHJMJ_cjs = require('./chunk-AQNHHJMJ.cjs');
7
7
 
@@ -28,7 +28,7 @@ var Lexer = class {
28
28
  // next()/peek() streaming access.
29
29
  this.tokens = [];
30
30
  this.tokenIdx = 0;
31
- this.expressionLexer = new chunkR7YVBHCV_cjs.ExpressionLexer(localeCode, tokenLookup);
31
+ this.expressionLexer = new chunkYTIYVHL7_cjs.ExpressionLexer(localeCode, tokenLookup);
32
32
  }
33
33
  reset(input, state) {
34
34
  const newState = state ?? "main" /* Main */;
@@ -184,7 +184,7 @@ var Lexer = class {
184
184
  // differ for a string literal, whose value is the payload while its
185
185
  // text still carries the quote characters the reader typed.
186
186
  length: token.text.length,
187
- category: chunkTY3TLZAW_cjs.getTokenCategory(token.type)
187
+ category: chunk536WPM2V_cjs.getTokenCategory(token.type)
188
188
  }));
189
189
  }
190
190
  };
@@ -337,5 +337,5 @@ exports.Lexer = Lexer;
337
337
  exports.LexerState = LexerState;
338
338
  exports.buildTokenLookup = buildTokenLookup;
339
339
  exports.sharedLexer = sharedLexer;
340
- //# sourceMappingURL=chunk-FE23VSSA.cjs.map
341
- //# sourceMappingURL=chunk-FE23VSSA.cjs.map
340
+ //# sourceMappingURL=chunk-XJGJCF2R.cjs.map
341
+ //# sourceMappingURL=chunk-XJGJCF2R.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lexer/LexerState.ts","../src/lexer/Lexer.ts","../src/lexer/TokenClassRegistry.ts","../src/lexer/tokenRegistration.ts"],"names":["LexerState","ExpressionLexer","getTokenCategory","getLocale","knownUnits"],"mappings":"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","file":"chunk-FE23VSSA.cjs","sourcesContent":["/**\n * Lexer state machine modes.\n * - Main: document-level scanning with markdown classification\n * - Inline: expression embedded in markdown inline solve (`s\\`...\\``)\n * - String: inside a double-quoted string literal\n */\nexport enum LexerState {\n\tMain = \"main\",\n\tInline = \"inline\",\n\tString = \"string\",\n}\n","import { ExpressionLexer, LineClassification, LexerVocabulary, type ScanLineResult } from \"./ExpressionLexer\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { LexerState } from \"@solve-js/lexer/LexerState\";\nimport { getTokenCategory } from \"@solve-js/language/TokenCategoryMap\";\nimport type { TokenCategory } from \"@solve-js/language/TokenCategory\";\nimport type { TokenLookup } from \"@solve-js/lexer/TokenClassRegistry\";\n\n/**\n * Public tokenizer wrapper around {@link ExpressionLexer}.\n *\n * `ExpressionLexer` does the actual character-by-character scanning;\n * `Lexer` adds a materialized-token-array streaming interface\n * (`next()`/`peek()`) plus line-classification state (`reset()`) so\n * callers can iterate a line's tokens without re-scanning on each peek.\n *\n * Each `ExpressionEngine` instance owns its own `Lexer`, and packages\n * extend it via {@link registerVocabulary} (keywords, operators, units)\n * see `IEnginePackage.lexerVocabulary`.\n */\nexport class Lexer {\n /** Expression-mode lexer (Phase A: V8-optimized, replaces moo) */\n private expressionLexer: ExpressionLexer;\n private currentState: LexerState = LexerState.Main;\n private peekedToken: Token | undefined;\n private hasPeeked = false;\n\n // Materialized token array from the last reset() call, used for\n // next()/peek() streaming access.\n private tokens: Token[] = [];\n private tokenIdx: number = 0;\n\n /**\n * @param localeCode - Locale code (e.g., \"en\", \"de\"). Defaults to \"en\".\n * @param tokenLookup - Optional TokenLookup from TokenClassRegistry.\n * When provided, configures ExpressionLexer to use registry-built\n * keyword/unit/phrase lookups instead of internal instance maps.\n */\n constructor(localeCode = \"en\", tokenLookup?: TokenLookup) {\n // Pass the lookup directly to ExpressionLexer's constructor, it's an\n // instance field now, not a static. Each Lexer instance gets its own\n // isolated lookup, preventing cross-instance corruption.\n this.expressionLexer = new ExpressionLexer(localeCode, tokenLookup);\n }\n\n reset(input: string, state?: LexerState): void {\n const newState = state ?? LexerState.Main;\n this.currentState = newState;\n this.hasPeeked = false;\n this.peekedToken = undefined;\n\n // Phase B: Main state classifies the line with the markdown scanner.\n // Skip lines (headings, fences, HRs, etc.) produce empty token arrays.\n // Expression lines and lines with inline solves are tokenized normally.\n if (newState === LexerState.Main) {\n const classification = this.expressionLexer.classifyLine(input);\n if (classification.skip) {\n this.tokens = [];\n this.tokenIdx = 0;\n return;\n }\n // Expression line or markdown line with inline solves, tokenize.\n this.expressionLexer.reset(input);\n this.tokens = this.expressionLexer.tokenizeAll();\n this.tokenIdx = 0;\n } else {\n // Non-main states (Inline, String), expression tokenization.\n this.expressionLexer.reset(input);\n this.tokens = this.expressionLexer.tokenizeAll();\n this.tokenIdx = 0;\n }\n }\n\n /**\n * Classify a single line of markdown text (Phase B).\n * Delegates to the ExpressionLexer's character-by-character scanner.\n */\n classifyLine(lineText: string): LineClassification {\n return this.expressionLexer.classifyLine(lineText);\n }\n\n /**\n * Find all inline solve markers in a line (Phase B).\n * Delegates to the ExpressionLexer's character-by-character scanner.\n */\n findInlineSolves(lineText: string) {\n return this.expressionLexer.findInlineSolves(lineText);\n }\n\n /**\n * Every keyword this lexer currently recognizes (locale + plugin-contributed),\n * mapped to the token type it lexes to. Delegates to the ExpressionLexer.\n */\n getKeywords(): Record<string, string> {\n return this.expressionLexer.getKeywords();\n }\n\n next(): Token | undefined {\n if (this.hasPeeked) {\n this.hasPeeked = false;\n return this.peekedToken;\n }\n // Materialized token array (ExpressionLexer path).\n if (this.tokenIdx < this.tokens.length) {\n return this.tokens[this.tokenIdx++];\n }\n return undefined;\n }\n\n peek(): Token | undefined {\n if (this.hasPeeked) return this.peekedToken;\n this.peekedToken = this.next();\n this.hasPeeked = true;\n return this.peekedToken;\n }\n\n [Symbol.iterator](): Iterator<Token> {\n return this.tokens[Symbol.iterator]();\n }\n\n /**\n * Register a plugin to extend the lexer with custom tokens.\n * Delegates to the underlying ExpressionLexer.\n *\n * @see LexerVocabulary for the supported extension points.\n */\n registerVocabulary(plugin: LexerVocabulary): void {\n this.expressionLexer.registerVocabulary(plugin);\n }\n\n /**\n * Unregister a plugin, removing its custom tokens from the lexer.\n * Delegates to the underlying ExpressionLexer.\n */\n unregisterVocabulary(plugin: LexerVocabulary): void {\n this.expressionLexer.unregisterVocabulary(plugin);\n }\n\n /**\n * Reset the lexer for expression-only text, skips the classifyLine()\n * overhead in reset() for callers that already know the input is an\n * evaluable expression (e.g., after isEmptyLine() confirmed non-skip).\n */\n resetExpression(input: string): void {\n this.currentState = LexerState.Main;\n this.hasPeeked = false;\n this.peekedToken = undefined;\n this.expressionLexer.reset(input);\n this.tokens = this.expressionLexer.tokenizeAll();\n this.tokenIdx = 0;\n }\n\n /**\n * Scan a full document in one pass, classifying each line and\n * tokenizing non-skipped lines. Delegates to ExpressionLexer.\n *\n * @returns ScanLineResult[], one per line, with classification + tokens.\n */\n scanDocument(text: string): ScanLineResult[] {\n return this.expressionLexer.scanDocument(text);\n }\n\n getState(): LexerState {\n return this.currentState;\n }\n\n setState(state: LexerState): void {\n this.currentState = state;\n }\n\n getHighlightTokens(lineText: string): {type: string; value: string; offset: number; col: number; length: number; category: TokenCategory | undefined}[] {\n const classification = this.expressionLexer.classifyLine(lineText);\n\n // For blockquote lines, strip the \"> \" prefix and tokenize the expression content.\n // This lets expressions inside blockquotes (e.g., \"> 1 + 2\") get syntax highlighted\n // while pure structural lines (headings, code fences) remain unhighlighted.\n if (classification.skip && lineText.startsWith(\"> \")) {\n return this.collectHighlightTokens(lineText.slice(2));\n }\n\n if (classification.skip) {\n return [];\n }\n\n return this.collectHighlightTokens(lineText);\n }\n\n /**\n * The same tokens {@link getHighlightTokens} reduces, before reduction.\n *\n * Exists because normalization operates on tokens, not on the flattened\n * shape, and a consumer that wants phrase-fused highlighting has to run the\n * normalizer between the two. See `LanguageService.getSemanticTokens`.\n *\n * @param lineText - One line of source.\n * @returns Every token on the line that is worth painting, unreduced.\n */\n getHighlightTokenObjects(lineText: string): Token[] {\n const classification = this.expressionLexer.classifyLine(lineText);\n if (classification.skip && lineText.startsWith(\"> \")) {\n return this.collectTokenObjects(lineText.slice(2));\n }\n if (classification.skip) return [];\n return this.collectTokenObjects(lineText);\n }\n\n private collectTokenObjects(lineText: string): Token[] {\n this.resetExpression(lineText);\n const result: Token[] = [];\n for (const token of this) {\n if (token.type === \"WS\" || token.type === \"NEWLINE\") continue;\n if (token.type.startsWith(\"MD_\")) continue;\n if (token.type === \"INLINE_SOLVE_START\" || token.type === \"BACKTICK_CLOSE\") continue;\n result.push(token);\n }\n return result;\n }\n\n private collectHighlightTokens(lineText: string): {type: string; value: string; offset: number; col: number; length: number; category: TokenCategory | undefined}[] {\n return this.collectTokenObjects(lineText).map(token => ({\n type: token.type,\n value: token.value,\n offset: token.offset,\n col: token.col,\n // `text`, not `value`: this is a span into the source, and the two\n // differ for a string literal, whose value is the payload while its\n // text still carries the quote characters the reader typed.\n length: token.text.length,\n category: getTokenCategory(token.type),\n }));\n }\n}\n\n/**\n * A lexer for operations that do not depend on registered vocabulary.\n *\n * Line classification and inline-solve detection read characters looking for\n * headings, comment markers, fences and backtick spans, and never consult the\n * keyword, unit or operator tables. Every lexer therefore returns the same\n * answer, so the callers that have no engine to ask can use this one. Checked\n * by `__tests__/lexer/LineClassificationIsVocabularyIndependent.spec.ts`.\n *\n * Do not tokenize with this. An engine's own lexer carries the vocabulary its\n * packages registered; this one carries none.\n */\nexport const sharedLexer = new Lexer(\"en\", undefined);","/**\n * TokenClass, Plugin-extensible keyword registration for the Lexer.\n *\n * Providers call `registry.register(tokenClass)` to teach the lexer about\n * their keywords. The registry merges locale keywords, provider keywords,\n * phrase mappings, and unit names into an optimized TokenLookup structure\n * consumed by the Lexer.\n *\n * @example\n * registry.register({\n * tokenType: 'CARET',\n * keywords: {},\n * phrases: { 'to the power of': true, 'power of': true },\n * priority: 10,\n * description: 'Exponentiation operators (x^y)',\n * });\n */\nexport interface TokenClass {\n /** The token type string produced by the lexer (e.g., \"FUNC\", \"PI\", \"CARET\").\n * Must match a token type that a ParseletRegistry has a parselet for. */\n tokenType: string;\n\n /** Single-word keywords (case-insensitive). The lexer lowercases input\n * before lookup, so these should be lowercase. Example:\n * { sqrt: true, abs: true, sin: true, cos: true } for tokenType \"FUNC\" */\n keywords: Record<string, boolean>;\n\n /** Multi-word phrases (case-insensitive). Matched by the built-in PhraseMatcher\n * via the phrase trie. Example:\n * { \"to the power of\": true, \"power of\": true } for tokenType \"CARET\" */\n phrases?: Record<string, boolean>;\n\n /** Priority for conflict resolution. When two TokenClasses register\n * the same keyword, the higher-priority class wins. Locale keywords\n * have priority 0 (set via setLocale). Providers should use\n * priority >= 10 to override locale defaults. Default: 0 */\n priority?: number;\n\n /** Human-readable description for debugging and introspection */\n description?: string;\n}\n\n// ── Phrase Trie ──────────────────────────────────────────────────────────────\n\n/** Trie node for multi-word phrase matching. */\nexport interface PhraseNode {\n /** Complete phrase token type (null = intermediate node) */\n type?: string;\n children: Map<string, PhraseNode>;\n}\n\n// ── TokenLookup, Optimized lookup structure for the Lexer ──────────────────\n\n/**\n * The optimized lookup structure built by TokenClassRegistry.build().\n * Consumed by the Lexer for O(1) keyword → token type lookups and\n * O(word-count) phrase matching.\n */\nexport interface TokenLookup {\n /** Lowercase keyword → token type. O(1) Map lookup. */\n keywordToType: Map<string, string>;\n\n /** Phrase trie for multi-word matching. Root node with children maps.\n * Null if no phrases registered. */\n phraseTrie: PhraseNode | null;\n\n /** Set of lowercase first-words of all registered phrases.\n * Used by the lexer to emit IDENT (not a phrase keyword) for words\n * that start multi-word phrases, deferring to the PhraseMatcher.\n *\n * Example: \"to\" is in phraseStartWords because \"to the power of\" is a phrase.\n * When the lexer sees \"to\", it emits IDENT and lets the phrase matcher\n * combine \"to the power of\" into a single CARET token.\n *\n * This prevents plugins from accidentally overriding phrase-start words.\n */\n phraseStartWords: Set<string>;\n\n /** Case-sensitive unit names for UNIT fallback after keyword lookup fails. */\n unitNames: ReadonlySet<string>;\n}\n\n// ── TokenClassRegistry ───────────────────────────────────────────────────────\n\n/**\n * Central registry for keyword→token-type mappings.\n *\n * Providers register TokenClasses; locales provide keyword maps;\n * units provide a name set. `build()` merges all sources into an\n * optimized TokenLookup consumed by the Lexer.\n *\n * Merge order (later overrides earlier):\n * 1. Locale keywords (priority 0)\n * 2. Provider keywords (sorted by priority ascending, higher priority wins)\n *\n * Unit names are stored separately (checked AFTER keyword lookup fails).\n * Phrases are stored in a trie for O(phrase-length) matching.\n */\nexport class TokenClassRegistry {\n private classes: TokenClass[] = [];\n private localeKeywordMap: Record<string, string> | null = null;\n private localePhraseMap: Record<string, string> | null = null;\n private unitNames: ReadonlySet<string> | null = null;\n\n /**\n * Register a provider's TokenClass. Must be called BEFORE build().\n * Can be called multiple times to add more entries.\n *\n * Built-in token types CANNOT be overridden, throws a EngineError\n * if the TokenClass attempts to register a keyword that conflicts\n * with an already-registered token type.\n */\n register(tokenClass: TokenClass): void {\n this.classes.push(tokenClass);\n }\n\n /**\n * Unregister all TokenClasses for a given token type.\n * Useful for plugin unload. Requires rebuild() to take effect.\n */\n unregister(tokenType: string): void {\n this.classes = this.classes.filter(c => c.tokenType !== tokenType);\n }\n\n /**\n * Set the locale's keyword→type map and optional phrase map.\n * Called on locale change. Priority 0 (cannot override providers with higher priority).\n */\n setLocale(keywordMap: Record<string, string>, phraseMap?: Record<string, string>): void {\n this.localeKeywordMap = keywordMap;\n this.localePhraseMap = phraseMap ?? null;\n }\n\n /**\n * Set the unit name set. Called when unit list changes.\n * Units are stored separately (checked AFTER keyword lookup fails).\n *\n * Takes a ReadonlySet because the caller's set is derived from the\n * conversion tables and must not be mutated; this class only ever reads it.\n */\n setUnits(unitNames: ReadonlySet<string>): void {\n this.unitNames = unitNames;\n }\n\n /**\n * Build the optimized TokenLookup from all registered sources.\n *\n * Merge order (later overrides earlier):\n * 1. Locale keywords (priority 0)\n * 2. Provider classes (sorted by priority ascending)\n *\n * Returns a frozen TokenLookup that the Lexer consumes.\n * Call build() again after register()/setLocale()/setUnits() changes.\n */\n build(): TokenLookup {\n const keywordToType = new Map<string, string>();\n\n // Layer 1: Locale keywords (priority 0, lowest)\n if (this.localeKeywordMap) {\n for (const [keyword, tokenType] of Object.entries(this.localeKeywordMap)) {\n keywordToType.set(keyword.toLowerCase(), tokenType);\n }\n }\n\n // Layer 2: Provider keywords (sorted by priority ascending, higher wins)\n const sorted = [...this.classes].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));\n for (const tc of sorted) {\n for (const keyword of Object.keys(tc.keywords)) {\n keywordToType.set(keyword.toLowerCase(), tc.tokenType);\n }\n }\n\n // Build phrase trie from locale + provider phrases\n const phraseTrie = this.buildPhraseTrie();\n\n // Build phraseStartWords set (first word of every phrase)\n const phraseStartWords = this.buildPhraseStartWords();\n\n return {\n keywordToType,\n phraseTrie,\n phraseStartWords,\n unitNames: this.unitNames ?? new Set(),\n };\n }\n\n // ── Private helpers ─────────────────────────────────────────────────────\n\n private buildPhraseTrie(): PhraseNode | null {\n const root: PhraseNode = { children: new Map() };\n\n // Layer 1: Locale phrases\n if (this.localePhraseMap) {\n for (const [phrase, tokenType] of Object.entries(this.localePhraseMap)) {\n this.insertPhrase(root, phrase.toLowerCase(), tokenType);\n }\n }\n\n // Layer 2: Provider phrases\n for (const tc of this.classes) {\n if (!tc.phrases) continue;\n for (const phrase of Object.keys(tc.phrases)) {\n this.insertPhrase(root, phrase.toLowerCase(), tc.tokenType);\n }\n }\n\n return root.children.size > 0 ? root : null;\n }\n\n private insertPhrase(root: PhraseNode, phrase: string, tokenType: string): void {\n const words = phrase.split(' ');\n let node = root;\n for (const word of words) {\n if (!node.children.has(word)) {\n node.children.set(word, { children: new Map() });\n }\n node = node.children.get(word)!;\n }\n // Only set type if not already set, first-registered (locale) wins\n if (!node.type) {\n node.type = tokenType;\n }\n }\n\n private buildPhraseStartWords(): Set<string> {\n const startWords = new Set<string>();\n\n // Locale phrase first words\n if (this.localePhraseMap) {\n for (const phrase of Object.keys(this.localePhraseMap)) {\n const first = phrase.split(' ')[0].toLowerCase();\n startWords.add(first);\n }\n }\n\n // Provider phrase first words\n for (const tc of this.classes) {\n if (!tc.phrases) continue;\n for (const phrase of Object.keys(tc.phrases)) {\n const first = phrase.split(' ')[0].toLowerCase();\n startWords.add(first);\n }\n }\n\n return startWords;\n }\n}","/**\n * tokenRegistration.ts, Bootstrap for building TokenLookup from locale, units, and phrases.\n *\n * This module centralizes the assembly of the TokenLookup consumed by ExpressionLexer.\n * It merges:\n * 1. Locale keywords (from ILocale.keywordMap)\n * 2. Built-in phrase patterns (to the power of, increase by, etc.)\n * 3. Known unit names (from units.ts)\n *\n * The resulting TokenLookup is frozen and passed to ExpressionLexer.configuredLookup\n * at construction time, enabling data-driven keyword/unit/phrase resolution.\n */\nimport { TokenClassRegistry } from '@solve-js/lexer/TokenClassRegistry';\nimport type { TokenLookup } from '@solve-js/lexer/TokenClassRegistry';\nimport { getLocale, type ILocale } from '@solve-js/constants/locales';\nimport { knownUnits } from '@solve-js/lexer/units';\n\n// ── Built-in phrase map ───────────────────────────────────────────────────\n// These are the multi-word expressions handled as compound tokens.\n// Matched by the PhraseMatcher (trie-based) in ExpressionLexer.tryMatchPhrase().\nconst BUILTIN_PHRASES: Record<string, string> = {\n 'to the power of': 'CARET',\n 'power of': 'CARET',\n 'increase by': 'INCREASE_BY',\n 'decrease by': 'DECREASE_BY',\n 'times by': 'TIMES_BY',\n 'multiply by': 'MULTIPLY_BY',\n 'multiplied by': 'MULTIPLY_BY',\n 'divide by': 'DIVIDE_BY',\n};\n\n/**\n * Build a TokenLookup from locale keywords, known units, and built-in phrases.\n *\n * Merge order (later overrides earlier):\n * 1. Locale keywords (priority 0, lowest, can be overridden by providers)\n * 2. Built-in phrases (via locale phraseMap)\n * 3. Known units (checked AFTER keyword lookup fails, via unitNames set)\n *\n * The resulting TokenLookup replaces the internal keyword map, unit set,\n * phrase trie, and phraseStartWords in ExpressionLexer when set via\n * ExpressionLexer.configuredLookup.\n *\n * @param localeCode - The locale code (e.g., \"en\", \"de\"). Defaults to \"en\".\n * @returns A frozen TokenLookup ready for consumption by the lexer.\n */\nexport function buildTokenLookup(localeCode = 'en'): TokenLookup {\n const locale: ILocale = getLocale(localeCode);\n const registry = new TokenClassRegistry();\n\n // Layer 1: Locale keywords (priority 0, lowest)\n registry.setLocale(locale.keywordMap, BUILTIN_PHRASES);\n\n // Layer 2: Known units (checked after keyword lookup)\n registry.setUnits(knownUnits);\n\n // Build and return the lookup\n return registry.build();\n}\n"]}
1
+ {"version":3,"sources":["../src/lexer/LexerState.ts","../src/lexer/Lexer.ts","../src/lexer/TokenClassRegistry.ts","../src/lexer/tokenRegistration.ts"],"names":["LexerState","ExpressionLexer","getTokenCategory","getLocale","knownUnits"],"mappings":"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","file":"chunk-XJGJCF2R.cjs","sourcesContent":["/**\n * Lexer state machine modes.\n * - Main: document-level scanning with markdown classification\n * - Inline: expression embedded in markdown inline solve (`s\\`...\\``)\n * - String: inside a double-quoted string literal\n */\nexport enum LexerState {\n\tMain = \"main\",\n\tInline = \"inline\",\n\tString = \"string\",\n}\n","import { ExpressionLexer, LineClassification, LexerVocabulary, type ScanLineResult } from \"./ExpressionLexer\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { LexerState } from \"@solve-js/lexer/LexerState\";\nimport { getTokenCategory } from \"@solve-js/language/TokenCategoryMap\";\nimport type { TokenCategory } from \"@solve-js/language/TokenCategory\";\nimport type { TokenLookup } from \"@solve-js/lexer/TokenClassRegistry\";\n\n/**\n * Public tokenizer wrapper around {@link ExpressionLexer}.\n *\n * `ExpressionLexer` does the actual character-by-character scanning;\n * `Lexer` adds a materialized-token-array streaming interface\n * (`next()`/`peek()`) plus line-classification state (`reset()`) so\n * callers can iterate a line's tokens without re-scanning on each peek.\n *\n * Each `ExpressionEngine` instance owns its own `Lexer`, and packages\n * extend it via {@link registerVocabulary} (keywords, operators, units)\n * see `IEnginePackage.lexerVocabulary`.\n */\nexport class Lexer {\n /** Expression-mode lexer (Phase A: V8-optimized, replaces moo) */\n private expressionLexer: ExpressionLexer;\n private currentState: LexerState = LexerState.Main;\n private peekedToken: Token | undefined;\n private hasPeeked = false;\n\n // Materialized token array from the last reset() call, used for\n // next()/peek() streaming access.\n private tokens: Token[] = [];\n private tokenIdx: number = 0;\n\n /**\n * @param localeCode - Locale code (e.g., \"en\", \"de\"). Defaults to \"en\".\n * @param tokenLookup - Optional TokenLookup from TokenClassRegistry.\n * When provided, configures ExpressionLexer to use registry-built\n * keyword/unit/phrase lookups instead of internal instance maps.\n */\n constructor(localeCode = \"en\", tokenLookup?: TokenLookup) {\n // Pass the lookup directly to ExpressionLexer's constructor, it's an\n // instance field now, not a static. Each Lexer instance gets its own\n // isolated lookup, preventing cross-instance corruption.\n this.expressionLexer = new ExpressionLexer(localeCode, tokenLookup);\n }\n\n reset(input: string, state?: LexerState): void {\n const newState = state ?? LexerState.Main;\n this.currentState = newState;\n this.hasPeeked = false;\n this.peekedToken = undefined;\n\n // Phase B: Main state classifies the line with the markdown scanner.\n // Skip lines (headings, fences, HRs, etc.) produce empty token arrays.\n // Expression lines and lines with inline solves are tokenized normally.\n if (newState === LexerState.Main) {\n const classification = this.expressionLexer.classifyLine(input);\n if (classification.skip) {\n this.tokens = [];\n this.tokenIdx = 0;\n return;\n }\n // Expression line or markdown line with inline solves, tokenize.\n this.expressionLexer.reset(input);\n this.tokens = this.expressionLexer.tokenizeAll();\n this.tokenIdx = 0;\n } else {\n // Non-main states (Inline, String), expression tokenization.\n this.expressionLexer.reset(input);\n this.tokens = this.expressionLexer.tokenizeAll();\n this.tokenIdx = 0;\n }\n }\n\n /**\n * Classify a single line of markdown text (Phase B).\n * Delegates to the ExpressionLexer's character-by-character scanner.\n */\n classifyLine(lineText: string): LineClassification {\n return this.expressionLexer.classifyLine(lineText);\n }\n\n /**\n * Find all inline solve markers in a line (Phase B).\n * Delegates to the ExpressionLexer's character-by-character scanner.\n */\n findInlineSolves(lineText: string) {\n return this.expressionLexer.findInlineSolves(lineText);\n }\n\n /**\n * Every keyword this lexer currently recognizes (locale + plugin-contributed),\n * mapped to the token type it lexes to. Delegates to the ExpressionLexer.\n */\n getKeywords(): Record<string, string> {\n return this.expressionLexer.getKeywords();\n }\n\n next(): Token | undefined {\n if (this.hasPeeked) {\n this.hasPeeked = false;\n return this.peekedToken;\n }\n // Materialized token array (ExpressionLexer path).\n if (this.tokenIdx < this.tokens.length) {\n return this.tokens[this.tokenIdx++];\n }\n return undefined;\n }\n\n peek(): Token | undefined {\n if (this.hasPeeked) return this.peekedToken;\n this.peekedToken = this.next();\n this.hasPeeked = true;\n return this.peekedToken;\n }\n\n [Symbol.iterator](): Iterator<Token> {\n return this.tokens[Symbol.iterator]();\n }\n\n /**\n * Register a plugin to extend the lexer with custom tokens.\n * Delegates to the underlying ExpressionLexer.\n *\n * @see LexerVocabulary for the supported extension points.\n */\n registerVocabulary(plugin: LexerVocabulary): void {\n this.expressionLexer.registerVocabulary(plugin);\n }\n\n /**\n * Unregister a plugin, removing its custom tokens from the lexer.\n * Delegates to the underlying ExpressionLexer.\n */\n unregisterVocabulary(plugin: LexerVocabulary): void {\n this.expressionLexer.unregisterVocabulary(plugin);\n }\n\n /**\n * Reset the lexer for expression-only text, skips the classifyLine()\n * overhead in reset() for callers that already know the input is an\n * evaluable expression (e.g., after isEmptyLine() confirmed non-skip).\n */\n resetExpression(input: string): void {\n this.currentState = LexerState.Main;\n this.hasPeeked = false;\n this.peekedToken = undefined;\n this.expressionLexer.reset(input);\n this.tokens = this.expressionLexer.tokenizeAll();\n this.tokenIdx = 0;\n }\n\n /**\n * Scan a full document in one pass, classifying each line and\n * tokenizing non-skipped lines. Delegates to ExpressionLexer.\n *\n * @returns ScanLineResult[], one per line, with classification + tokens.\n */\n scanDocument(text: string): ScanLineResult[] {\n return this.expressionLexer.scanDocument(text);\n }\n\n getState(): LexerState {\n return this.currentState;\n }\n\n setState(state: LexerState): void {\n this.currentState = state;\n }\n\n getHighlightTokens(lineText: string): {type: string; value: string; offset: number; col: number; length: number; category: TokenCategory | undefined}[] {\n const classification = this.expressionLexer.classifyLine(lineText);\n\n // For blockquote lines, strip the \"> \" prefix and tokenize the expression content.\n // This lets expressions inside blockquotes (e.g., \"> 1 + 2\") get syntax highlighted\n // while pure structural lines (headings, code fences) remain unhighlighted.\n if (classification.skip && lineText.startsWith(\"> \")) {\n return this.collectHighlightTokens(lineText.slice(2));\n }\n\n if (classification.skip) {\n return [];\n }\n\n return this.collectHighlightTokens(lineText);\n }\n\n /**\n * The same tokens {@link getHighlightTokens} reduces, before reduction.\n *\n * Exists because normalization operates on tokens, not on the flattened\n * shape, and a consumer that wants phrase-fused highlighting has to run the\n * normalizer between the two. See `LanguageService.getSemanticTokens`.\n *\n * @param lineText - One line of source.\n * @returns Every token on the line that is worth painting, unreduced.\n */\n getHighlightTokenObjects(lineText: string): Token[] {\n const classification = this.expressionLexer.classifyLine(lineText);\n if (classification.skip && lineText.startsWith(\"> \")) {\n return this.collectTokenObjects(lineText.slice(2));\n }\n if (classification.skip) return [];\n return this.collectTokenObjects(lineText);\n }\n\n private collectTokenObjects(lineText: string): Token[] {\n this.resetExpression(lineText);\n const result: Token[] = [];\n for (const token of this) {\n if (token.type === \"WS\" || token.type === \"NEWLINE\") continue;\n if (token.type.startsWith(\"MD_\")) continue;\n if (token.type === \"INLINE_SOLVE_START\" || token.type === \"BACKTICK_CLOSE\") continue;\n result.push(token);\n }\n return result;\n }\n\n private collectHighlightTokens(lineText: string): {type: string; value: string; offset: number; col: number; length: number; category: TokenCategory | undefined}[] {\n return this.collectTokenObjects(lineText).map(token => ({\n type: token.type,\n value: token.value,\n offset: token.offset,\n col: token.col,\n // `text`, not `value`: this is a span into the source, and the two\n // differ for a string literal, whose value is the payload while its\n // text still carries the quote characters the reader typed.\n length: token.text.length,\n category: getTokenCategory(token.type),\n }));\n }\n}\n\n/**\n * A lexer for operations that do not depend on registered vocabulary.\n *\n * Line classification and inline-solve detection read characters looking for\n * headings, comment markers, fences and backtick spans, and never consult the\n * keyword, unit or operator tables. Every lexer therefore returns the same\n * answer, so the callers that have no engine to ask can use this one. Checked\n * by `__tests__/lexer/LineClassificationIsVocabularyIndependent.spec.ts`.\n *\n * Do not tokenize with this. An engine's own lexer carries the vocabulary its\n * packages registered; this one carries none.\n */\nexport const sharedLexer = new Lexer(\"en\", undefined);","/**\n * TokenClass, Plugin-extensible keyword registration for the Lexer.\n *\n * Providers call `registry.register(tokenClass)` to teach the lexer about\n * their keywords. The registry merges locale keywords, provider keywords,\n * phrase mappings, and unit names into an optimized TokenLookup structure\n * consumed by the Lexer.\n *\n * @example\n * registry.register({\n * tokenType: 'CARET',\n * keywords: {},\n * phrases: { 'to the power of': true, 'power of': true },\n * priority: 10,\n * description: 'Exponentiation operators (x^y)',\n * });\n */\nexport interface TokenClass {\n /** The token type string produced by the lexer (e.g., \"FUNC\", \"PI\", \"CARET\").\n * Must match a token type that a ParseletRegistry has a parselet for. */\n tokenType: string;\n\n /** Single-word keywords (case-insensitive). The lexer lowercases input\n * before lookup, so these should be lowercase. Example:\n * { sqrt: true, abs: true, sin: true, cos: true } for tokenType \"FUNC\" */\n keywords: Record<string, boolean>;\n\n /** Multi-word phrases (case-insensitive). Matched by the built-in PhraseMatcher\n * via the phrase trie. Example:\n * { \"to the power of\": true, \"power of\": true } for tokenType \"CARET\" */\n phrases?: Record<string, boolean>;\n\n /** Priority for conflict resolution. When two TokenClasses register\n * the same keyword, the higher-priority class wins. Locale keywords\n * have priority 0 (set via setLocale). Providers should use\n * priority >= 10 to override locale defaults. Default: 0 */\n priority?: number;\n\n /** Human-readable description for debugging and introspection */\n description?: string;\n}\n\n// ── Phrase Trie ──────────────────────────────────────────────────────────────\n\n/** Trie node for multi-word phrase matching. */\nexport interface PhraseNode {\n /** Complete phrase token type (null = intermediate node) */\n type?: string;\n children: Map<string, PhraseNode>;\n}\n\n// ── TokenLookup, Optimized lookup structure for the Lexer ──────────────────\n\n/**\n * The optimized lookup structure built by TokenClassRegistry.build().\n * Consumed by the Lexer for O(1) keyword → token type lookups and\n * O(word-count) phrase matching.\n */\nexport interface TokenLookup {\n /** Lowercase keyword → token type. O(1) Map lookup. */\n keywordToType: Map<string, string>;\n\n /** Phrase trie for multi-word matching. Root node with children maps.\n * Null if no phrases registered. */\n phraseTrie: PhraseNode | null;\n\n /** Set of lowercase first-words of all registered phrases.\n * Used by the lexer to emit IDENT (not a phrase keyword) for words\n * that start multi-word phrases, deferring to the PhraseMatcher.\n *\n * Example: \"to\" is in phraseStartWords because \"to the power of\" is a phrase.\n * When the lexer sees \"to\", it emits IDENT and lets the phrase matcher\n * combine \"to the power of\" into a single CARET token.\n *\n * This prevents plugins from accidentally overriding phrase-start words.\n */\n phraseStartWords: Set<string>;\n\n /** Case-sensitive unit names for UNIT fallback after keyword lookup fails. */\n unitNames: ReadonlySet<string>;\n}\n\n// ── TokenClassRegistry ───────────────────────────────────────────────────────\n\n/**\n * Central registry for keyword→token-type mappings.\n *\n * Providers register TokenClasses; locales provide keyword maps;\n * units provide a name set. `build()` merges all sources into an\n * optimized TokenLookup consumed by the Lexer.\n *\n * Merge order (later overrides earlier):\n * 1. Locale keywords (priority 0)\n * 2. Provider keywords (sorted by priority ascending, higher priority wins)\n *\n * Unit names are stored separately (checked AFTER keyword lookup fails).\n * Phrases are stored in a trie for O(phrase-length) matching.\n */\nexport class TokenClassRegistry {\n private classes: TokenClass[] = [];\n private localeKeywordMap: Record<string, string> | null = null;\n private localePhraseMap: Record<string, string> | null = null;\n private unitNames: ReadonlySet<string> | null = null;\n\n /**\n * Register a provider's TokenClass. Must be called BEFORE build().\n * Can be called multiple times to add more entries.\n *\n * Built-in token types CANNOT be overridden, throws a EngineError\n * if the TokenClass attempts to register a keyword that conflicts\n * with an already-registered token type.\n */\n register(tokenClass: TokenClass): void {\n this.classes.push(tokenClass);\n }\n\n /**\n * Unregister all TokenClasses for a given token type.\n * Useful for plugin unload. Requires rebuild() to take effect.\n */\n unregister(tokenType: string): void {\n this.classes = this.classes.filter(c => c.tokenType !== tokenType);\n }\n\n /**\n * Set the locale's keyword→type map and optional phrase map.\n * Called on locale change. Priority 0 (cannot override providers with higher priority).\n */\n setLocale(keywordMap: Record<string, string>, phraseMap?: Record<string, string>): void {\n this.localeKeywordMap = keywordMap;\n this.localePhraseMap = phraseMap ?? null;\n }\n\n /**\n * Set the unit name set. Called when unit list changes.\n * Units are stored separately (checked AFTER keyword lookup fails).\n *\n * Takes a ReadonlySet because the caller's set is derived from the\n * conversion tables and must not be mutated; this class only ever reads it.\n */\n setUnits(unitNames: ReadonlySet<string>): void {\n this.unitNames = unitNames;\n }\n\n /**\n * Build the optimized TokenLookup from all registered sources.\n *\n * Merge order (later overrides earlier):\n * 1. Locale keywords (priority 0)\n * 2. Provider classes (sorted by priority ascending)\n *\n * Returns a frozen TokenLookup that the Lexer consumes.\n * Call build() again after register()/setLocale()/setUnits() changes.\n */\n build(): TokenLookup {\n const keywordToType = new Map<string, string>();\n\n // Layer 1: Locale keywords (priority 0, lowest)\n if (this.localeKeywordMap) {\n for (const [keyword, tokenType] of Object.entries(this.localeKeywordMap)) {\n keywordToType.set(keyword.toLowerCase(), tokenType);\n }\n }\n\n // Layer 2: Provider keywords (sorted by priority ascending, higher wins)\n const sorted = [...this.classes].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));\n for (const tc of sorted) {\n for (const keyword of Object.keys(tc.keywords)) {\n keywordToType.set(keyword.toLowerCase(), tc.tokenType);\n }\n }\n\n // Build phrase trie from locale + provider phrases\n const phraseTrie = this.buildPhraseTrie();\n\n // Build phraseStartWords set (first word of every phrase)\n const phraseStartWords = this.buildPhraseStartWords();\n\n return {\n keywordToType,\n phraseTrie,\n phraseStartWords,\n unitNames: this.unitNames ?? new Set(),\n };\n }\n\n // ── Private helpers ─────────────────────────────────────────────────────\n\n private buildPhraseTrie(): PhraseNode | null {\n const root: PhraseNode = { children: new Map() };\n\n // Layer 1: Locale phrases\n if (this.localePhraseMap) {\n for (const [phrase, tokenType] of Object.entries(this.localePhraseMap)) {\n this.insertPhrase(root, phrase.toLowerCase(), tokenType);\n }\n }\n\n // Layer 2: Provider phrases\n for (const tc of this.classes) {\n if (!tc.phrases) continue;\n for (const phrase of Object.keys(tc.phrases)) {\n this.insertPhrase(root, phrase.toLowerCase(), tc.tokenType);\n }\n }\n\n return root.children.size > 0 ? root : null;\n }\n\n private insertPhrase(root: PhraseNode, phrase: string, tokenType: string): void {\n const words = phrase.split(' ');\n let node = root;\n for (const word of words) {\n if (!node.children.has(word)) {\n node.children.set(word, { children: new Map() });\n }\n node = node.children.get(word)!;\n }\n // Only set type if not already set, first-registered (locale) wins\n if (!node.type) {\n node.type = tokenType;\n }\n }\n\n private buildPhraseStartWords(): Set<string> {\n const startWords = new Set<string>();\n\n // Locale phrase first words\n if (this.localePhraseMap) {\n for (const phrase of Object.keys(this.localePhraseMap)) {\n const first = phrase.split(' ')[0].toLowerCase();\n startWords.add(first);\n }\n }\n\n // Provider phrase first words\n for (const tc of this.classes) {\n if (!tc.phrases) continue;\n for (const phrase of Object.keys(tc.phrases)) {\n const first = phrase.split(' ')[0].toLowerCase();\n startWords.add(first);\n }\n }\n\n return startWords;\n }\n}","/**\n * tokenRegistration.ts, Bootstrap for building TokenLookup from locale, units, and phrases.\n *\n * This module centralizes the assembly of the TokenLookup consumed by ExpressionLexer.\n * It merges:\n * 1. Locale keywords (from ILocale.keywordMap)\n * 2. Built-in phrase patterns (to the power of, increase by, etc.)\n * 3. Known unit names (from units.ts)\n *\n * The resulting TokenLookup is frozen and passed to ExpressionLexer.configuredLookup\n * at construction time, enabling data-driven keyword/unit/phrase resolution.\n */\nimport { TokenClassRegistry } from '@solve-js/lexer/TokenClassRegistry';\nimport type { TokenLookup } from '@solve-js/lexer/TokenClassRegistry';\nimport { getLocale, type ILocale } from '@solve-js/constants/locales';\nimport { knownUnits } from '@solve-js/lexer/units';\n\n// ── Built-in phrase map ───────────────────────────────────────────────────\n// These are the multi-word expressions handled as compound tokens.\n// Matched by the PhraseMatcher (trie-based) in ExpressionLexer.tryMatchPhrase().\nconst BUILTIN_PHRASES: Record<string, string> = {\n 'to the power of': 'CARET',\n 'power of': 'CARET',\n 'increase by': 'INCREASE_BY',\n 'decrease by': 'DECREASE_BY',\n 'times by': 'TIMES_BY',\n 'multiply by': 'MULTIPLY_BY',\n 'multiplied by': 'MULTIPLY_BY',\n 'divide by': 'DIVIDE_BY',\n};\n\n/**\n * Build a TokenLookup from locale keywords, known units, and built-in phrases.\n *\n * Merge order (later overrides earlier):\n * 1. Locale keywords (priority 0, lowest, can be overridden by providers)\n * 2. Built-in phrases (via locale phraseMap)\n * 3. Known units (checked AFTER keyword lookup fails, via unitNames set)\n *\n * The resulting TokenLookup replaces the internal keyword map, unit set,\n * phrase trie, and phraseStartWords in ExpressionLexer when set via\n * ExpressionLexer.configuredLookup.\n *\n * @param localeCode - The locale code (e.g., \"en\", \"de\"). Defaults to \"en\".\n * @returns A frozen TokenLookup ready for consumption by the lexer.\n */\nexport function buildTokenLookup(localeCode = 'en'): TokenLookup {\n const locale: ILocale = getLocale(localeCode);\n const registry = new TokenClassRegistry();\n\n // Layer 1: Locale keywords (priority 0, lowest)\n registry.setLocale(locale.keywordMap, BUILTIN_PHRASES);\n\n // Layer 2: Known units (checked after keyword lookup)\n registry.setUnits(knownUnits);\n\n // Build and return the lookup\n return registry.build();\n}\n"]}