solve-engine 1.1.0 → 1.2.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 (188) hide show
  1. package/dist/{EngineError-B61GS1jp.d.cts → EngineError-CNA_rHY-.d.cts} +6 -0
  2. package/dist/{EngineError-B61GS1jp.d.ts → EngineError-CNA_rHY-.d.ts} +6 -0
  3. package/dist/{Lexer-BOs7euZe.d.cts → Lexer-B4C1qHXu.d.cts} +1 -1
  4. package/dist/{Lexer-CSI_lwbW.d.ts → Lexer-DKMlj7Sy.d.ts} +1 -1
  5. package/dist/{PackageCompatibility-B-7rK1TD.d.cts → PackageCompatibility-B6NX9IaN.d.cts} +1 -1
  6. package/dist/{PackageCompatibility-Dh59eF-X.d.ts → PackageCompatibility-Ceg5XdAp.d.ts} +1 -1
  7. package/dist/{PackageRegistry-BHWJP83F.d.cts → PackageRegistry-DnJYVw9G.d.cts} +55 -8
  8. package/dist/{PackageRegistry-_8rDlvxI.d.ts → PackageRegistry-DrCPQNyy.d.ts} +55 -8
  9. package/dist/{Parselet-BBT8riYh.d.ts → Parselet-Bhf7d0_W.d.ts} +2 -2
  10. package/dist/{Parselet-BHcgK9S7.d.cts → Parselet-Cv7S7KRt.d.cts} +2 -2
  11. package/dist/{ScopeManager-CxA24W5n.d.ts → ScopeManager-Bzq87GfA.d.ts} +10 -3
  12. package/dist/{ScopeManager-8vf02dwj.d.cts → ScopeManager-DRDBVfan.d.cts} +10 -3
  13. package/dist/{Token-B1hdkedD.d.cts → Token-CbP_OutD.d.cts} +9 -0
  14. package/dist/{Token-B1hdkedD.d.ts → Token-CbP_OutD.d.ts} +9 -0
  15. package/dist/{TokenNormalizer-C6VzZgHa.d.ts → TokenNormalizer-DCWdZjGz.d.ts} +1 -1
  16. package/dist/{TokenNormalizer-DRc1Js1V.d.cts → TokenNormalizer-DnlL7_8c.d.cts} +1 -1
  17. package/dist/{VMCheckpoints-MK--EBH2.d.ts → VMCheckpoints-C6c17Hbo.d.ts} +2 -2
  18. package/dist/{VMCheckpoints-ELYqITdF.d.cts → VMCheckpoints-dZxSMGHG.d.cts} +2 -2
  19. package/dist/{Value-BUi1RA3S.d.cts → Value-DZNQ_PU7.d.cts} +32 -5
  20. package/dist/{Value-BUi1RA3S.d.ts → Value-DZNQ_PU7.d.ts} +32 -5
  21. package/dist/{WorkerError-_-RkoQ5P.d.ts → WorkerError-B7t7R2-m.d.ts} +1 -1
  22. package/dist/{WorkerError-gzmaopj2.d.cts → WorkerError-Djd7GGGa.d.cts} +1 -1
  23. package/dist/{chunk-SSV46KFA.cjs → chunk-4K5W7EH2.cjs} +6 -6
  24. package/dist/{chunk-SSV46KFA.cjs.map → chunk-4K5W7EH2.cjs.map} +1 -1
  25. package/dist/{chunk-267JPOTF.js → chunk-5EFKSKMA.js} +11 -4
  26. package/dist/chunk-5EFKSKMA.js.map +1 -0
  27. package/dist/{chunk-536WPM2V.cjs → chunk-7AXJNQMF.cjs} +17 -3
  28. package/dist/chunk-7AXJNQMF.cjs.map +1 -0
  29. package/dist/{chunk-GUG7SNSV.js → chunk-7JM3F4KL.js} +39 -8
  30. package/dist/chunk-7JM3F4KL.js.map +1 -0
  31. package/dist/{chunk-XJGJCF2R.cjs → chunk-7USV76HV.cjs} +6 -6
  32. package/dist/{chunk-XJGJCF2R.cjs.map → chunk-7USV76HV.cjs.map} +1 -1
  33. package/dist/{chunk-HIQ5HSZL.cjs → chunk-A2DZ5BEJ.cjs} +53 -46
  34. package/dist/{chunk-HIQ5HSZL.cjs.map → chunk-A2DZ5BEJ.cjs.map} +1 -1
  35. package/dist/{chunk-CKQMXMHR.cjs → chunk-AKNGX4TZ.cjs} +28 -11
  36. package/dist/chunk-AKNGX4TZ.cjs.map +1 -0
  37. package/dist/{chunk-I4GAWIPW.js → chunk-AOH6UR2L.js} +6 -6
  38. package/dist/{chunk-I4GAWIPW.js.map → chunk-AOH6UR2L.js.map} +1 -1
  39. package/dist/{chunk-MG6Q3DUO.cjs → chunk-BESTLPRK.cjs} +326 -214
  40. package/dist/chunk-BESTLPRK.cjs.map +1 -0
  41. package/dist/{chunk-Z7XGGLI2.js → chunk-BSPXMGIS.js} +3 -3
  42. package/dist/{chunk-Z7XGGLI2.js.map → chunk-BSPXMGIS.js.map} +1 -1
  43. package/dist/{chunk-SRGQ72IR.cjs → chunk-C2OMO3WN.cjs} +376 -370
  44. package/dist/chunk-C2OMO3WN.cjs.map +1 -0
  45. package/dist/{chunk-G7Z4HJQA.js → chunk-CSDQMDU2.js} +4 -4
  46. package/dist/{chunk-G7Z4HJQA.js.map → chunk-CSDQMDU2.js.map} +1 -1
  47. package/dist/{chunk-7KYSUDQO.js → chunk-F4UB4XIL.js} +4 -4
  48. package/dist/{chunk-7KYSUDQO.js.map → chunk-F4UB4XIL.js.map} +1 -1
  49. package/dist/{chunk-WXEHD6TT.js → chunk-FE4RC37D.js} +15 -9
  50. package/dist/chunk-FE4RC37D.js.map +1 -0
  51. package/dist/{chunk-7ZX6B7SY.cjs → chunk-FR7RNOPT.cjs} +637 -556
  52. package/dist/chunk-FR7RNOPT.cjs.map +1 -0
  53. package/dist/{chunk-QFTDTX6K.cjs → chunk-G2YPPLGX.cjs} +29 -2
  54. package/dist/chunk-G2YPPLGX.cjs.map +1 -0
  55. package/dist/{chunk-HVRVSI2Z.cjs → chunk-GDEU72RG.cjs} +86 -86
  56. package/dist/{chunk-HVRVSI2Z.cjs.map → chunk-GDEU72RG.cjs.map} +1 -1
  57. package/dist/{chunk-OTN6SZOD.cjs → chunk-HKTQCQ4Z.cjs} +860 -489
  58. package/dist/chunk-HKTQCQ4Z.cjs.map +1 -0
  59. package/dist/{chunk-XA4CKRML.cjs → chunk-HWHU642X.cjs} +2 -2
  60. package/dist/{chunk-XA4CKRML.cjs.map → chunk-HWHU642X.cjs.map} +1 -1
  61. package/dist/{chunk-C75AFGVD.cjs → chunk-ICEKS6YC.cjs} +11 -11
  62. package/dist/{chunk-C75AFGVD.cjs.map → chunk-ICEKS6YC.cjs.map} +1 -1
  63. package/dist/{chunk-JIPATHVY.js → chunk-IJGOFP2J.js} +138 -26
  64. package/dist/chunk-IJGOFP2J.js.map +1 -0
  65. package/dist/{chunk-ENKKJYD3.js → chunk-IQJGDZOP.js} +4 -4
  66. package/dist/{chunk-ENKKJYD3.js.map → chunk-IQJGDZOP.js.map} +1 -1
  67. package/dist/{chunk-2TZKENDH.cjs → chunk-IT74O4BE.cjs} +15 -7
  68. package/dist/chunk-IT74O4BE.cjs.map +1 -0
  69. package/dist/{chunk-ZVTWQLK4.cjs → chunk-KXDQKVNX.cjs} +10 -10
  70. package/dist/{chunk-ZVTWQLK4.cjs.map → chunk-KXDQKVNX.cjs.map} +1 -1
  71. package/dist/{chunk-JJIXHXFQ.js → chunk-L5YHV6BQ.js} +5 -5
  72. package/dist/{chunk-JJIXHXFQ.js.map → chunk-L5YHV6BQ.js.map} +1 -1
  73. package/dist/{chunk-ZXCESUJS.cjs → chunk-LO7HU5WB.cjs} +8 -8
  74. package/dist/{chunk-ZXCESUJS.cjs.map → chunk-LO7HU5WB.cjs.map} +1 -1
  75. package/dist/{chunk-UO6BUV6K.js → chunk-LSALB3IN.js} +17 -3
  76. package/dist/chunk-LSALB3IN.js.map +1 -0
  77. package/dist/{chunk-J45BCEZ4.cjs → chunk-MI7OTUHL.cjs} +27 -27
  78. package/dist/{chunk-J45BCEZ4.cjs.map → chunk-MI7OTUHL.cjs.map} +1 -1
  79. package/dist/{chunk-B4HBEFTB.cjs → chunk-MIGXCBXT.cjs} +8 -2
  80. package/dist/chunk-MIGXCBXT.cjs.map +1 -0
  81. package/dist/{chunk-ERCOHGXD.js → chunk-N7OA4WPJ.js} +8 -2
  82. package/dist/chunk-N7OA4WPJ.js.map +1 -0
  83. package/dist/{chunk-4D6NIHE2.js → chunk-NAWZATKT.js} +29 -2
  84. package/dist/chunk-NAWZATKT.js.map +1 -0
  85. package/dist/{chunk-GQMUHVE3.js → chunk-ORM7CHYZ.js} +36 -5
  86. package/dist/chunk-ORM7CHYZ.js.map +1 -0
  87. package/dist/{chunk-B7NLZMQ3.cjs → chunk-PCZVMMWU.cjs} +8 -8
  88. package/dist/{chunk-B7NLZMQ3.cjs.map → chunk-PCZVMMWU.cjs.map} +1 -1
  89. package/dist/{chunk-OADDUPT3.js → chunk-RNKDIXDV.js} +4 -4
  90. package/dist/{chunk-OADDUPT3.js.map → chunk-RNKDIXDV.js.map} +1 -1
  91. package/dist/{chunk-SNHVVOJK.cjs → chunk-TC6BTUSU.cjs} +55 -24
  92. package/dist/chunk-TC6BTUSU.cjs.map +1 -0
  93. package/dist/{chunk-RRLHC37V.js → chunk-TPOK3UNI.js} +387 -17
  94. package/dist/chunk-TPOK3UNI.js.map +1 -0
  95. package/dist/{chunk-CCBZZQAE.js → chunk-UF6JG5SG.js} +2 -2
  96. package/dist/{chunk-CCBZZQAE.js.map → chunk-UF6JG5SG.js.map} +1 -1
  97. package/dist/{chunk-NKW7LKYU.js → chunk-WMQRJTAO.js} +88 -7
  98. package/dist/chunk-WMQRJTAO.js.map +1 -0
  99. package/dist/{chunk-YTIYVHL7.cjs → chunk-YJHY7CMN.cjs} +108 -77
  100. package/dist/chunk-YJHY7CMN.cjs.map +1 -0
  101. package/dist/{chunk-3OWCDIPN.js → chunk-YNIWOYW6.js} +21 -4
  102. package/dist/chunk-YNIWOYW6.js.map +1 -0
  103. package/dist/{chunk-WWQEY7BV.js → chunk-ZN6YYPIW.js} +3 -3
  104. package/dist/{chunk-WWQEY7BV.js.map → chunk-ZN6YYPIW.js.map} +1 -1
  105. package/dist/{chunk-NNQ2TYDF.js → chunk-ZNFFTYWH.js} +11 -5
  106. package/dist/chunk-ZNFFTYWH.js.map +1 -0
  107. package/dist/constants.cjs +5 -5
  108. package/dist/constants.js +2 -2
  109. package/dist/engine.cjs +33 -33
  110. package/dist/engine.d.cts +27 -11
  111. package/dist/engine.d.ts +27 -11
  112. package/dist/engine.js +20 -20
  113. package/dist/errors.cjs +26 -26
  114. package/dist/errors.d.cts +3 -3
  115. package/dist/errors.d.ts +3 -3
  116. package/dist/errors.js +2 -2
  117. package/dist/format.cjs +7 -7
  118. package/dist/format.d.cts +1 -1
  119. package/dist/format.d.ts +1 -1
  120. package/dist/format.js +4 -4
  121. package/dist/index.cjs +48 -48
  122. package/dist/index.d.cts +11 -11
  123. package/dist/index.d.ts +11 -11
  124. package/dist/index.js +21 -21
  125. package/dist/language.cjs +7 -7
  126. package/dist/language.d.cts +10 -10
  127. package/dist/language.d.ts +10 -10
  128. package/dist/language.js +2 -2
  129. package/dist/lexer.cjs +16 -16
  130. package/dist/lexer.d.cts +3 -3
  131. package/dist/lexer.d.ts +3 -3
  132. package/dist/lexer.js +5 -5
  133. package/dist/normalizer.cjs +10 -10
  134. package/dist/normalizer.d.cts +3 -3
  135. package/dist/normalizer.d.ts +3 -3
  136. package/dist/normalizer.js +4 -4
  137. package/dist/packages.cjs +40 -36
  138. package/dist/packages.d.cts +37 -11
  139. package/dist/packages.d.ts +37 -11
  140. package/dist/packages.js +11 -11
  141. package/dist/parser.cjs +13 -13
  142. package/dist/parser.d.cts +4 -4
  143. package/dist/parser.d.ts +4 -4
  144. package/dist/parser.js +5 -5
  145. package/dist/{pipeline-CtfJtPQc.d.cts → pipeline-D-PS9gVw.d.ts} +3 -3
  146. package/dist/{pipeline-DCd5M6Gk.d.ts → pipeline-DtSBJ8TS.d.cts} +3 -3
  147. package/dist/resolvers.d.cts +2 -2
  148. package/dist/resolvers.d.ts +2 -2
  149. package/dist/testing.cjs +26 -26
  150. package/dist/testing.d.cts +10 -10
  151. package/dist/testing.d.ts +10 -10
  152. package/dist/testing.js +19 -19
  153. package/dist/uom.cjs +8 -8
  154. package/dist/uom.d.cts +2 -2
  155. package/dist/uom.d.ts +2 -2
  156. package/dist/uom.js +4 -4
  157. package/dist/vm.cjs +32 -32
  158. package/dist/vm.d.cts +7 -7
  159. package/dist/vm.d.ts +7 -7
  160. package/dist/vm.js +7 -7
  161. package/dist/worker.cjs +38 -38
  162. package/dist/worker.d.cts +10 -10
  163. package/dist/worker.d.ts +10 -10
  164. package/dist/worker.js +20 -20
  165. package/package.json +1 -1
  166. package/dist/chunk-267JPOTF.js.map +0 -1
  167. package/dist/chunk-2TZKENDH.cjs.map +0 -1
  168. package/dist/chunk-3OWCDIPN.js.map +0 -1
  169. package/dist/chunk-4D6NIHE2.js.map +0 -1
  170. package/dist/chunk-536WPM2V.cjs.map +0 -1
  171. package/dist/chunk-7ZX6B7SY.cjs.map +0 -1
  172. package/dist/chunk-B4HBEFTB.cjs.map +0 -1
  173. package/dist/chunk-CKQMXMHR.cjs.map +0 -1
  174. package/dist/chunk-ERCOHGXD.js.map +0 -1
  175. package/dist/chunk-GQMUHVE3.js.map +0 -1
  176. package/dist/chunk-GUG7SNSV.js.map +0 -1
  177. package/dist/chunk-JIPATHVY.js.map +0 -1
  178. package/dist/chunk-MG6Q3DUO.cjs.map +0 -1
  179. package/dist/chunk-NKW7LKYU.js.map +0 -1
  180. package/dist/chunk-NNQ2TYDF.js.map +0 -1
  181. package/dist/chunk-OTN6SZOD.cjs.map +0 -1
  182. package/dist/chunk-QFTDTX6K.cjs.map +0 -1
  183. package/dist/chunk-RRLHC37V.js.map +0 -1
  184. package/dist/chunk-SNHVVOJK.cjs.map +0 -1
  185. package/dist/chunk-SRGQ72IR.cjs.map +0 -1
  186. package/dist/chunk-UO6BUV6K.js.map +0 -1
  187. package/dist/chunk-WXEHD6TT.js.map +0 -1
  188. package/dist/chunk-YTIYVHL7.cjs.map +0 -1
@@ -308,5 +308,5 @@ var DiagnosticEventType = {
308
308
  };
309
309
 
310
310
  export { DiagnosticEventType, DiagnosticPipeline, TimelineDiagnosticCollector };
311
- //# sourceMappingURL=chunk-CCBZZQAE.js.map
312
- //# sourceMappingURL=chunk-CCBZZQAE.js.map
311
+ //# sourceMappingURL=chunk-UF6JG5SG.js.map
312
+ //# sourceMappingURL=chunk-UF6JG5SG.js.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-CCBZZQAE.js","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}"]}
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-UF6JG5SG.js","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, SplitData } 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 | SplitData | 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 | SplitData | 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,10 +1,10 @@
1
1
  import { VariableResolver } from './chunk-GCM5JHMX.js';
2
- import { sharedCurrencyExchange } from './chunk-Z7XGGLI2.js';
3
- import { decimalFromInteger, toPolynomial, polyDegree, polyCoefficients, fromPolynomial, constNode, rationalDiv, rationalNeg, powNode, callNode, decimalCompare, isRationalZero, rationalMul, rationalSub, rationalAdd, rationalToNumber, rationalCompare, simplifySymbolic, sameShape, decimalFromNumberIfExact, decimalMultiply, decimalToNumber, decimalAdd, decimalNegate, cancelSymbolic, complexNode, complex, RATIONAL_ZERO, rationalFromNumber, freeVariables, symbolicToEntry, rowMajorToColumnMajor, expandSymbolic, matrixMultiply, inverse, determinant, transpose, matrixPower, exactIntegerSqrt, surdNode, rational, decimalIsZero, decimalDivide, decimalSubtract, decimalFromLiteral, decimalRound, substitute, varNode, isRationalOne, RATIONAL_ONE, polyUnivariateVar, COMPLEX_I, squareFreePart, coefficientGcd, polynomialDivide, isZeroPolynomial, exactRationalSqrt, symbolicKey, compareMonomials, signedSurdNode, monomialFromKey, monomialToKey, exactIntegerCbrt } from './chunk-NNQ2TYDF.js';
4
- import { faultedOperand, errorValue, numberValueRational, numberValueUncertain, symbolicValue, numberValue, bigIntValue, uomValue, matrixValue, uomValueExact, percentageValue, stringValue, hexValue } from './chunk-267JPOTF.js';
2
+ import { sharedCurrencyExchange } from './chunk-BSPXMGIS.js';
3
+ import { decimalFromInteger, toPolynomial, polyDegree, polyCoefficients, fromPolynomial, constNode, rationalDiv, rationalNeg, powNode, callNode, decimalCompare, isRationalZero, rationalMul, rationalSub, rationalAdd, rationalToNumber, rationalCompare, simplifySymbolic, sameShape, decimalFromNumberIfExact, decimalMultiply, decimalToNumber, decimalAdd, decimalNegate, cancelSymbolic, complexNode, complex, RATIONAL_ZERO, rationalFromNumber, freeVariables, symbolicToEntry, rowMajorToColumnMajor, expandSymbolic, matrixMultiply, inverse, determinant, transpose, matrixPower, exactIntegerSqrt, surdNode, rational, decimalIsZero, decimalDivide, decimalSubtract, decimalFromLiteral, decimalRound, substitute, varNode, isRationalOne, RATIONAL_ONE, polyUnivariateVar, COMPLEX_I, squareFreePart, makeDecimal, coefficientGcd, polynomialDivide, isZeroPolynomial, exactRationalSqrt, symbolicKey, compareMonomials, signedSurdNode, monomialFromKey, monomialToKey, exactIntegerCbrt } from './chunk-ZNFFTYWH.js';
4
+ import { faultedOperand, errorValue, numberValueRational, numberValueUncertain, symbolicValue, numberValue, bigIntValue, uomValue, matrixValue, uomValueExact, splitValue, percentageValue, stringValue, hexValue } from './chunk-5EFKSKMA.js';
5
5
  import { getMeasure, convertUnit } from './chunk-MVTOCRV2.js';
6
6
  import { UNIT_TABLE } from './chunk-V4XG5QF6.js';
7
- import { ErrorFactory } from './chunk-ERCOHGXD.js';
7
+ import { ErrorFactory } from './chunk-N7OA4WPJ.js';
8
8
 
9
9
  // src/symbolic/MultivariateFactor.ts
10
10
  function exactRoot(value, degree) {
@@ -1502,6 +1502,29 @@ function taxInExact(money, unit, rate) {
1502
1502
  const tax = decimalSubtract(base, decimalDivide(base, divisor));
1503
1503
  return uomValueExact(decimalToNumber(tax), unit, tax);
1504
1504
  }
1505
+ function splitEachExact(amount, n) {
1506
+ const unit = amount.unit;
1507
+ const cents = unit !== void 0 && sharedCurrencyExchange.isCurrency(unit) ? centsOfMoney(amount, unit) : null;
1508
+ if (cents === null) {
1509
+ return { unit, shares: [{ value: amount.toNumber() / n, count: n }] };
1510
+ }
1511
+ const divisor = BigInt(n);
1512
+ const baseCents = cents / divisor;
1513
+ const remainder = cents - baseCents * divisor;
1514
+ const extraShares = Number(remainder < 0n ? -remainder : remainder);
1515
+ const step = cents < 0n ? -1n : 1n;
1516
+ const base = centShare(baseCents, n - extraShares);
1517
+ if (extraShares === 0) return { unit, shares: [base] };
1518
+ return { unit, shares: [base, centShare(baseCents + step, extraShares)] };
1519
+ }
1520
+ function centShare(cents, count) {
1521
+ const exact = makeDecimal(cents, 2);
1522
+ return { value: decimalToNumber(exact), exact, count };
1523
+ }
1524
+ function centsOfMoney(amount, unit) {
1525
+ const base = moneyExactMagnitude(amount, unit);
1526
+ return base === null ? null : decimalRound(base, 2).coef;
1527
+ }
1505
1528
 
1506
1529
  // src/symbolic/PartialFractions.ts
1507
1530
  var APART_MAX_DEGREE = 12;
@@ -3030,8 +3053,66 @@ var builtinFunctions = {
3030
3053
  // fractional part to round at all, and the round trip through 1e23 was
3031
3054
  // pure loss. Asking for fewer decimal places than a number has cannot
3032
3055
  // change it, so a value that is already whole is returned untouched.
3033
- 97: (args) => roundToPlaces(args[0], args[1].toNumber())
3056
+ 97: (args) => roundToPlaces(args[0], args[1].toNumber()),
3057
+ // splitEach(amount, n): a per-person bill split, `split $180 between 4` and
3058
+ // `$120 + 18% split 3 ways`. Backs both split spellings (see
3059
+ // BillSplitParselets.ts). Money stays exact and the shares add back to the
3060
+ // total to the cent (see splitEachExact in MoneyExact.ts). A bare number
3061
+ // splits to a bare number; the odd penny is named, not rounded away.
3062
+ 98: (args) => {
3063
+ const n = args[1].toNumber();
3064
+ if (!Number.isInteger(n) || n < 1) {
3065
+ return errorValue("INVALID_RANGE", `split: the number of shares must be a whole number of at least 1, not ${args[1].toNumber()}.`);
3066
+ }
3067
+ return splitValue(splitEachExact(args[0], n));
3068
+ },
3069
+ // ── Savings goals ──────────────────────────────────────────────
3070
+ // savingsGoalPayment(target, duration, annualRate): the level contribution
3071
+ // per month that reaches `target` over `duration` (months or years), at an
3072
+ // optional annual rate compounded monthly. Backs "how much per month to
3073
+ // save/reach <target> in <duration> [at <rate>]".
3074
+ 99: (args) => {
3075
+ const target = args[0].toNumber();
3076
+ const months = monthsOfDuration(args[1]);
3077
+ const annualRate = args[2].toNumber();
3078
+ if (months === null) return errorValue("INVALID_RANGE", `savings goal: the duration must be in months or years, e.g. "in 2 years".`);
3079
+ if (target <= 0) return errorValue("INVALID_RANGE", `savings goal: the target must be positive.`);
3080
+ if (months <= 0) return errorValue("INVALID_RANGE", `savings goal: the duration must be positive.`);
3081
+ if (annualRate < 0) return errorValue("INVALID_RATE", `savings goal: the rate must not be negative.`);
3082
+ const payment = annuityPayment(target, annualRate / 12, months);
3083
+ return args[0].type === 6 /* Uom */ ? uomValue(payment, args[0].unit) : numberValue(payment);
3084
+ },
3085
+ // savingsGoalPeriods(target, contribution, periodsPerYear, annualRate,
3086
+ // periodUnit): how many whole periods of `contribution` reach `target`,
3087
+ // rounded UP, since a part period has not yet reached the goal. Backs
3088
+ // "how long to save <target> at <amount> <period> [at <rate>]".
3089
+ 100: (args) => {
3090
+ const target = args[0].toNumber();
3091
+ const contribution = args[1].toNumber();
3092
+ const periodsPerYear = args[2].toNumber();
3093
+ const annualRate = args[3].toNumber();
3094
+ const unit = typeof args[4]?.value === "string" ? args[4].value : "periods";
3095
+ if (target <= 0) return errorValue("INVALID_RANGE", `savings goal: the target must be positive.`);
3096
+ if (contribution <= 0) return errorValue("INVALID_RANGE", `savings goal: the contribution must be positive.`);
3097
+ if (annualRate < 0) return errorValue("INVALID_RATE", `savings goal: the rate must not be negative.`);
3098
+ const periods = annuityPeriods(target, contribution, annualRate / periodsPerYear);
3099
+ return uomValue(periods, unit);
3100
+ }
3034
3101
  };
3102
+ function monthsOfDuration(duration) {
3103
+ if (duration.type !== 6 /* Uom */) return null;
3104
+ const unit = duration.unit;
3105
+ if (unit === "months" || unit === "month") return duration.toNumber();
3106
+ if (unit === "years" || unit === "year") return duration.toNumber() * 12;
3107
+ return null;
3108
+ }
3109
+ function annuityPayment(target, i, months) {
3110
+ return i === 0 ? target / months : target * i / (Math.pow(1 + i, months) - 1);
3111
+ }
3112
+ function annuityPeriods(target, contribution, i) {
3113
+ const raw = i === 0 ? target / contribution : Math.log(1 + target * i / contribution) / Math.log(1 + i);
3114
+ return Math.ceil(raw - 1e-9);
3115
+ }
3035
3116
  function applyComplexAccessor(name, value) {
3036
3117
  const node = valueToSymbolic(value);
3037
3118
  if (node === null) return errorValue("SYMBOLIC_NONFINITE_OPERAND", name + " needs a value with an exact number.");
@@ -3181,5 +3262,5 @@ function globalDagKey(name) {
3181
3262
  }
3182
3263
 
3183
3264
  export { CPI_MAX_YEAR, CPI_MIN_YEAR, OpRegistry, SYMBOLIC_NATIVE_BUILTINS, adjustForInflation, allocatePluginFunctionIndex, asConverterRegistry, bigIntDivisionByZero, binaryOp, builtinFunctions, compareBigIntOperands, compareRationalOperands, compareUom, createEngineContext, defaultEngineContext, describeConversionMismatch, exactRationalOp, globalDagKey, incomparableUnitsError, moneyExactMagnitude, pluginFunctionRegistry, power, registerAsConverter, scaleMoneyByPercent, scaleMoneyExact, sharedGlobalVariableStore, sharedOpRegistry, solveEquationValues, solveForVariable, symbolicBuiltin, symbolicNeg, symbolicPow, toBigIntOperand, uncertainOp, unifyUom, unregisterAsConverter };
3184
- //# sourceMappingURL=chunk-NKW7LKYU.js.map
3185
- //# sourceMappingURL=chunk-NKW7LKYU.js.map
3265
+ //# sourceMappingURL=chunk-WMQRJTAO.js.map
3266
+ //# sourceMappingURL=chunk-WMQRJTAO.js.map