solve-engine 2.32.0 → 2.33.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 (226) hide show
  1. package/dist/{EngineError-CqGtaT_v.d.cts → EngineError-Bm4OYmw8.d.cts} +6 -0
  2. package/dist/{EngineError-CqGtaT_v.d.ts → EngineError-Bm4OYmw8.d.ts} +6 -0
  3. package/dist/{Lexer-CqFjYoRA.d.ts → Lexer-DPn5dfCH.d.ts} +1 -13
  4. package/dist/{Lexer-sCI05tqO.d.cts → Lexer-DaWkCu84.d.cts} +1 -13
  5. package/dist/{PackageCompatibility-phvSFP4f.d.ts → PackageCompatibility-CkzZfoJ3.d.ts} +1 -1
  6. package/dist/{PackageCompatibility-Bn-T_xKW.d.cts → PackageCompatibility-E_5GtcQW.d.cts} +1 -1
  7. package/dist/{PackageRegistry-C78jVkI9.d.ts → PackageRegistry-DSqic8kz.d.ts} +132 -23
  8. package/dist/{PackageRegistry-B-C1duZw.d.cts → PackageRegistry-js47hr28.d.cts} +132 -23
  9. package/dist/{Parselet-Dgymjxzd.d.ts → Parselet-CQjcHOKw.d.ts} +13 -6
  10. package/dist/{Parselet-DF3864la.d.cts → Parselet-s1sRRn8H.d.cts} +13 -6
  11. package/dist/{TokenNormalizer-Pe3_390t.d.cts → TokenNormalizer-D382VSYh.d.cts} +4 -1
  12. package/dist/{TokenNormalizer-IF7nPRMp.d.ts → TokenNormalizer-DAzPp-j1.d.ts} +4 -1
  13. package/dist/{VMBuiltins-BkKzhj6C.d.cts → VMBuiltins-JCavlQUj.d.cts} +53 -18
  14. package/dist/{VMBuiltins-Du9y8sEo.d.ts → VMBuiltins-qgzA6qGi.d.ts} +53 -18
  15. package/dist/{VMCheckpoints-WdUQrdc9.d.cts → VMCheckpoints-BxPzmdu0.d.cts} +2 -2
  16. package/dist/{VMCheckpoints-gvy_yxYh.d.ts → VMCheckpoints-DjjE92mf.d.ts} +2 -2
  17. package/dist/{Value-BYHw-x7q.d.cts → Value-2TIKi-YL.d.cts} +19 -0
  18. package/dist/{Value-BYHw-x7q.d.ts → Value-2TIKi-YL.d.ts} +19 -0
  19. package/dist/{WorkerError-DTrl3Jag.d.ts → WorkerError-BaN8_eok.d.ts} +1 -1
  20. package/dist/{WorkerError-CRoM8Ju1.d.cts → WorkerError-CexHHmbb.d.cts} +1 -1
  21. package/dist/{chunk-AGCNMEP2.cjs → chunk-3MG7VIPL.cjs} +2 -2
  22. package/dist/{chunk-AGCNMEP2.cjs.map → chunk-3MG7VIPL.cjs.map} +1 -1
  23. package/dist/chunk-4ASM522I.js +2 -0
  24. package/dist/chunk-4ASM522I.js.map +1 -0
  25. package/dist/chunk-4M3FZRGL.cjs +5 -0
  26. package/dist/chunk-4M3FZRGL.cjs.map +1 -0
  27. package/dist/{chunk-KH4QXKLT.js → chunk-4MD5L23F.js} +2 -2
  28. package/dist/{chunk-KH4QXKLT.js.map → chunk-4MD5L23F.js.map} +1 -1
  29. package/dist/{chunk-IQVSCL2R.js → chunk-4XWZXP6I.js} +3 -3
  30. package/dist/{chunk-IQVSCL2R.js.map → chunk-4XWZXP6I.js.map} +1 -1
  31. package/dist/{chunk-AXTYQFIV.cjs → chunk-6DCSGINN.cjs} +3 -3
  32. package/dist/{chunk-AXTYQFIV.cjs.map → chunk-6DCSGINN.cjs.map} +1 -1
  33. package/dist/{chunk-RELMEWY6.js → chunk-6G2NES2I.js} +2 -2
  34. package/dist/chunk-6G2NES2I.js.map +1 -0
  35. package/dist/{chunk-CDE2ZUGG.js → chunk-6NL7RBAG.js} +2 -2
  36. package/dist/{chunk-CDE2ZUGG.js.map → chunk-6NL7RBAG.js.map} +1 -1
  37. package/dist/{chunk-SUAGBRQ7.cjs → chunk-6SYU4MH7.cjs} +2 -2
  38. package/dist/chunk-6SYU4MH7.cjs.map +1 -0
  39. package/dist/chunk-72J5V7SN.cjs +2 -0
  40. package/dist/chunk-72J5V7SN.cjs.map +1 -0
  41. package/dist/chunk-7CRVRPV7.cjs +3 -0
  42. package/dist/chunk-7CRVRPV7.cjs.map +1 -0
  43. package/dist/chunk-ADK7LGYN.js +5 -0
  44. package/dist/chunk-ADK7LGYN.js.map +1 -0
  45. package/dist/chunk-APYRNAU2.js +2 -0
  46. package/dist/chunk-APYRNAU2.js.map +1 -0
  47. package/dist/{chunk-IJE4AEDX.js → chunk-D55NMAGM.js} +3 -3
  48. package/dist/{chunk-IJE4AEDX.js.map → chunk-D55NMAGM.js.map} +1 -1
  49. package/dist/chunk-DB5ISONG.js +2 -0
  50. package/dist/chunk-DB5ISONG.js.map +1 -0
  51. package/dist/chunk-EOKHRS2T.js +2 -0
  52. package/dist/chunk-EOKHRS2T.js.map +1 -0
  53. package/dist/{chunk-NQFCXLEF.js → chunk-EOO6M65F.js} +2 -2
  54. package/dist/{chunk-NQFCXLEF.js.map → chunk-EOO6M65F.js.map} +1 -1
  55. package/dist/{chunk-A764BY7L.cjs → chunk-EQNKDTMX.cjs} +2 -2
  56. package/dist/{chunk-A764BY7L.cjs.map → chunk-EQNKDTMX.cjs.map} +1 -1
  57. package/dist/chunk-FESR6PZI.cjs +2 -0
  58. package/dist/chunk-FESR6PZI.cjs.map +1 -0
  59. package/dist/chunk-G5TZ6TDA.js +2 -0
  60. package/dist/chunk-G5TZ6TDA.js.map +1 -0
  61. package/dist/chunk-GDLYXRMA.cjs +2 -0
  62. package/dist/chunk-GDLYXRMA.cjs.map +1 -0
  63. package/dist/chunk-HOU7QTE7.js +3 -0
  64. package/dist/chunk-HOU7QTE7.js.map +1 -0
  65. package/dist/{chunk-CAJTDZ5B.cjs → chunk-HPV4CKCC.cjs} +2 -2
  66. package/dist/{chunk-CAJTDZ5B.cjs.map → chunk-HPV4CKCC.cjs.map} +1 -1
  67. package/dist/{chunk-7DJYS5PO.cjs → chunk-HSTGWWU2.cjs} +2 -2
  68. package/dist/{chunk-7DJYS5PO.cjs.map → chunk-HSTGWWU2.cjs.map} +1 -1
  69. package/dist/{chunk-OE2DBN4K.js → chunk-INMJ7ZXL.js} +2 -2
  70. package/dist/chunk-INMJ7ZXL.js.map +1 -0
  71. package/dist/{chunk-TSJ4RQLZ.js → chunk-J3YC3IQD.js} +2 -2
  72. package/dist/{chunk-TSJ4RQLZ.js.map → chunk-J3YC3IQD.js.map} +1 -1
  73. package/dist/{chunk-5AKT36UK.cjs → chunk-K3PZ66XR.cjs} +2 -2
  74. package/dist/{chunk-5AKT36UK.cjs.map → chunk-K3PZ66XR.cjs.map} +1 -1
  75. package/dist/chunk-LI6LYJDA.cjs +2 -0
  76. package/dist/chunk-LI6LYJDA.cjs.map +1 -0
  77. package/dist/{chunk-WQGHJAW2.cjs → chunk-M4UC2PB6.cjs} +2 -2
  78. package/dist/{chunk-WQGHJAW2.cjs.map → chunk-M4UC2PB6.cjs.map} +1 -1
  79. package/dist/chunk-O7HF345B.js +2 -0
  80. package/dist/chunk-O7HF345B.js.map +1 -0
  81. package/dist/{chunk-CM2WM5CM.cjs → chunk-OBZJKZ2F.cjs} +2 -2
  82. package/dist/{chunk-CM2WM5CM.cjs.map → chunk-OBZJKZ2F.cjs.map} +1 -1
  83. package/dist/{chunk-Q7TBBV62.cjs → chunk-P5YWBIIU.cjs} +2 -2
  84. package/dist/chunk-P5YWBIIU.cjs.map +1 -0
  85. package/dist/chunk-PICFFFJV.js +3 -0
  86. package/dist/chunk-PICFFFJV.js.map +1 -0
  87. package/dist/{chunk-P43SV4NJ.cjs → chunk-QOOTRUY7.cjs} +3 -3
  88. package/dist/{chunk-P43SV4NJ.cjs.map → chunk-QOOTRUY7.cjs.map} +1 -1
  89. package/dist/chunk-R3W53ZMP.cjs +2 -0
  90. package/dist/chunk-R3W53ZMP.cjs.map +1 -0
  91. package/dist/chunk-RMDCGYZM.js +2 -0
  92. package/dist/chunk-RMDCGYZM.js.map +1 -0
  93. package/dist/{chunk-CB3EXUM2.js → chunk-RU3KGJRA.js} +2 -2
  94. package/dist/chunk-RU3KGJRA.js.map +1 -0
  95. package/dist/chunk-S3SPDK6N.cjs +2 -0
  96. package/dist/chunk-S3SPDK6N.cjs.map +1 -0
  97. package/dist/chunk-SF5QVUEI.cjs +3 -0
  98. package/dist/chunk-SF5QVUEI.cjs.map +1 -0
  99. package/dist/{chunk-FXB5GCBT.js → chunk-TJKN466F.js} +2 -2
  100. package/dist/{chunk-FXB5GCBT.js.map → chunk-TJKN466F.js.map} +1 -1
  101. package/dist/{chunk-VLX7ZVK4.js → chunk-U5MESNRT.js} +2 -2
  102. package/dist/{chunk-VLX7ZVK4.js.map → chunk-U5MESNRT.js.map} +1 -1
  103. package/dist/{chunk-YWF6C2IO.cjs → chunk-WFT3XUSH.cjs} +2 -2
  104. package/dist/{chunk-YWF6C2IO.cjs.map → chunk-WFT3XUSH.cjs.map} +1 -1
  105. package/dist/{chunk-3ZGFAE3Q.js → chunk-X2GQAKL2.js} +2 -2
  106. package/dist/{chunk-3ZGFAE3Q.js.map → chunk-X2GQAKL2.js.map} +1 -1
  107. package/dist/{chunk-G3POUURF.js → chunk-YID47OPR.js} +2 -2
  108. package/dist/{chunk-G3POUURF.js.map → chunk-YID47OPR.js.map} +1 -1
  109. package/dist/chunk-YV4GDW5A.cjs +2 -0
  110. package/dist/chunk-YV4GDW5A.cjs.map +1 -0
  111. package/dist/chunk-ZSXQP7PD.cjs +2 -0
  112. package/dist/chunk-ZSXQP7PD.cjs.map +1 -0
  113. package/dist/constants.cjs +1 -1
  114. package/dist/constants.js +1 -1
  115. package/dist/engine.cjs +1 -1
  116. package/dist/engine.d.cts +10 -10
  117. package/dist/engine.d.ts +10 -10
  118. package/dist/engine.js +1 -1
  119. package/dist/engine.worker.cjs +1 -1
  120. package/dist/engine.worker.cjs.map +1 -1
  121. package/dist/engine.worker.js +1 -1
  122. package/dist/engine.worker.js.map +1 -1
  123. package/dist/errors.cjs +1 -1
  124. package/dist/errors.d.cts +3 -3
  125. package/dist/errors.d.ts +3 -3
  126. package/dist/errors.js +1 -1
  127. package/dist/format.cjs +1 -1
  128. package/dist/format.d.cts +1 -1
  129. package/dist/format.d.ts +1 -1
  130. package/dist/format.js +1 -1
  131. package/dist/index.cjs +1 -1
  132. package/dist/index.cjs.map +1 -1
  133. package/dist/index.d.cts +10 -10
  134. package/dist/index.d.ts +10 -10
  135. package/dist/index.js +1 -1
  136. package/dist/index.js.map +1 -1
  137. package/dist/language.d.cts +9 -9
  138. package/dist/language.d.ts +9 -9
  139. package/dist/lexer.cjs +1 -1
  140. package/dist/lexer.d.cts +3 -3
  141. package/dist/lexer.d.ts +3 -3
  142. package/dist/lexer.js +1 -1
  143. package/dist/normalizer.cjs +1 -1
  144. package/dist/normalizer.d.cts +2 -2
  145. package/dist/normalizer.d.ts +2 -2
  146. package/dist/normalizer.js +1 -1
  147. package/dist/packages.cjs +1 -1
  148. package/dist/packages.d.cts +8 -8
  149. package/dist/packages.d.ts +8 -8
  150. package/dist/packages.js +1 -1
  151. package/dist/parser.cjs +1 -1
  152. package/dist/parser.d.cts +3 -3
  153. package/dist/parser.d.ts +3 -3
  154. package/dist/parser.js +1 -1
  155. package/dist/{pipeline-BYkKNpql.d.cts → pipeline-Bum6y1B9.d.cts} +1 -1
  156. package/dist/{pipeline-Cl7KW8CB.d.ts → pipeline-DOo3KHaq.d.ts} +1 -1
  157. package/dist/resolvers.cjs +1 -1
  158. package/dist/resolvers.d.cts +69 -3
  159. package/dist/resolvers.d.ts +69 -3
  160. package/dist/resolvers.js +1 -1
  161. package/dist/temporal.cjs +1 -1
  162. package/dist/temporal.js +1 -1
  163. package/dist/testing.cjs +2 -2
  164. package/dist/testing.cjs.map +1 -1
  165. package/dist/testing.d.cts +9 -9
  166. package/dist/testing.d.ts +9 -9
  167. package/dist/testing.js +1 -1
  168. package/dist/testing.js.map +1 -1
  169. package/dist/uom.cjs +1 -1
  170. package/dist/uom.d.cts +35 -2
  171. package/dist/uom.d.ts +35 -2
  172. package/dist/uom.js +1 -1
  173. package/dist/vm.cjs +1 -1
  174. package/dist/vm.d.cts +6 -6
  175. package/dist/vm.d.ts +6 -6
  176. package/dist/vm.js +1 -1
  177. package/dist/worker.cjs +2 -2
  178. package/dist/worker.cjs.map +1 -1
  179. package/dist/worker.d.cts +9 -9
  180. package/dist/worker.d.ts +9 -9
  181. package/dist/worker.js +1 -1
  182. package/dist/worker.js.map +1 -1
  183. package/package.json +1 -1
  184. package/dist/chunk-4DR5RBHQ.cjs +0 -2
  185. package/dist/chunk-4DR5RBHQ.cjs.map +0 -1
  186. package/dist/chunk-4IC5OARK.js +0 -3
  187. package/dist/chunk-4IC5OARK.js.map +0 -1
  188. package/dist/chunk-7ODHPWQC.js +0 -5
  189. package/dist/chunk-7ODHPWQC.js.map +0 -1
  190. package/dist/chunk-A755LVPT.cjs +0 -2
  191. package/dist/chunk-A755LVPT.cjs.map +0 -1
  192. package/dist/chunk-AF6NDOIE.js +0 -2
  193. package/dist/chunk-AF6NDOIE.js.map +0 -1
  194. package/dist/chunk-B2NL65FI.js +0 -2
  195. package/dist/chunk-B2NL65FI.js.map +0 -1
  196. package/dist/chunk-CB3EXUM2.js.map +0 -1
  197. package/dist/chunk-DUFEONVN.cjs +0 -3
  198. package/dist/chunk-DUFEONVN.cjs.map +0 -1
  199. package/dist/chunk-IJHL3LMH.js +0 -2
  200. package/dist/chunk-IJHL3LMH.js.map +0 -1
  201. package/dist/chunk-LCYQQFUH.cjs +0 -2
  202. package/dist/chunk-LCYQQFUH.cjs.map +0 -1
  203. package/dist/chunk-LP3JYC3A.js +0 -2
  204. package/dist/chunk-LP3JYC3A.js.map +0 -1
  205. package/dist/chunk-OE2DBN4K.js.map +0 -1
  206. package/dist/chunk-OKKGPINQ.cjs +0 -5
  207. package/dist/chunk-OKKGPINQ.cjs.map +0 -1
  208. package/dist/chunk-OM7NOHJF.cjs +0 -2
  209. package/dist/chunk-OM7NOHJF.cjs.map +0 -1
  210. package/dist/chunk-PTXUWGRR.js +0 -3
  211. package/dist/chunk-PTXUWGRR.js.map +0 -1
  212. package/dist/chunk-Q7TBBV62.cjs.map +0 -1
  213. package/dist/chunk-RELMEWY6.js.map +0 -1
  214. package/dist/chunk-SFM4XFGJ.js +0 -2
  215. package/dist/chunk-SFM4XFGJ.js.map +0 -1
  216. package/dist/chunk-SRAU3BLV.cjs +0 -3
  217. package/dist/chunk-SRAU3BLV.cjs.map +0 -1
  218. package/dist/chunk-SUAGBRQ7.cjs.map +0 -1
  219. package/dist/chunk-UNKZ5XRC.cjs +0 -2
  220. package/dist/chunk-UNKZ5XRC.cjs.map +0 -1
  221. package/dist/chunk-WU7SBKVU.cjs +0 -2
  222. package/dist/chunk-WU7SBKVU.cjs.map +0 -1
  223. package/dist/chunk-X5K72MBV.js +0 -2
  224. package/dist/chunk-X5K72MBV.js.map +0 -1
  225. package/dist/chunk-ZVPZQ66D.cjs +0 -2
  226. package/dist/chunk-ZVPZQ66D.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { B as BytecodeBuilder } from './BytecodeBuilder-DSWKZi4f.js';
2
2
  import { T as Token } from './Token-D8f7yaz1.js';
3
- import { D as DiagnosticPipeline } from './pipeline-Cl7KW8CB.js';
3
+ import { D as DiagnosticPipeline } from './pipeline-DOo3KHaq.js';
4
4
  import { C as CalendarBackend } from './CalendarBackend-MdS3Bb4P.js';
5
5
 
6
6
  /**
@@ -77,16 +77,15 @@ declare class ParseletRegistry {
77
77
  * one higher. That is the standard encoding for a left-associative
78
78
  * operator, and it is what the parser itself does, see
79
79
  * `PrecedenceParser.parseExpression()`'s `bp + 1` for the right operand.
80
- * Every operator is reported that way, `^` included. Associativity is not
81
- * something a parselet declares, it is a property of how each one calls
82
- * `parseExpression`, so this API cannot report it without a new field on
83
- * the interface. See {@link ParseletBindingPowers} for why scraping a
84
- * plausible-looking one off the parselet is worse than not reporting it.
80
+ * An operator that declares `rightAssociative` (`^`) is reported with the
81
+ * right power one BELOW the left, which is how it parses its right operand
82
+ * (see `parseRightOperand`), and `associativity` says which in words.
85
83
  */
86
84
  getAllInfix(): Array<{
87
85
  tokenType: string;
88
86
  leftBindingPower: number;
89
87
  rightBindingPower: number;
88
+ associativity: "left" | "right";
90
89
  category?: string;
91
90
  }>;
92
91
  /** Number of registered prefix parselets. */
@@ -363,6 +362,14 @@ interface InfixParselet {
363
362
  readonly category: string;
364
363
  /** Binding power (precedence), property access avoids vtable dispatch in hot loop */
365
364
  readonly bindingPower: number;
365
+ /**
366
+ * Whether the operator groups from the right (`2 ^ 3 ^ 2` is `2 ^ (3 ^ 2)`).
367
+ * Absent means left, which is what every operator but exponentiation
368
+ * wants. Read by {@link parseRightOperand}, and reported by
369
+ * `ParseletRegistry.getAllInfix` so a precedence table built from the
370
+ * registry says what the parser does.
371
+ */
372
+ readonly rightAssociative?: boolean;
366
373
  parse(parser: PrecedenceParser, left: Token, token: Token, builder: BytecodeBuilder): void;
367
374
  }
368
375
 
@@ -1,6 +1,6 @@
1
1
  import { B as BytecodeBuilder } from './BytecodeBuilder-DSWKZi4f.cjs';
2
2
  import { T as Token } from './Token-D8f7yaz1.cjs';
3
- import { D as DiagnosticPipeline } from './pipeline-BYkKNpql.cjs';
3
+ import { D as DiagnosticPipeline } from './pipeline-Bum6y1B9.cjs';
4
4
  import { C as CalendarBackend } from './CalendarBackend-MdS3Bb4P.cjs';
5
5
 
6
6
  /**
@@ -77,16 +77,15 @@ declare class ParseletRegistry {
77
77
  * one higher. That is the standard encoding for a left-associative
78
78
  * operator, and it is what the parser itself does, see
79
79
  * `PrecedenceParser.parseExpression()`'s `bp + 1` for the right operand.
80
- * Every operator is reported that way, `^` included. Associativity is not
81
- * something a parselet declares, it is a property of how each one calls
82
- * `parseExpression`, so this API cannot report it without a new field on
83
- * the interface. See {@link ParseletBindingPowers} for why scraping a
84
- * plausible-looking one off the parselet is worse than not reporting it.
80
+ * An operator that declares `rightAssociative` (`^`) is reported with the
81
+ * right power one BELOW the left, which is how it parses its right operand
82
+ * (see `parseRightOperand`), and `associativity` says which in words.
85
83
  */
86
84
  getAllInfix(): Array<{
87
85
  tokenType: string;
88
86
  leftBindingPower: number;
89
87
  rightBindingPower: number;
88
+ associativity: "left" | "right";
90
89
  category?: string;
91
90
  }>;
92
91
  /** Number of registered prefix parselets. */
@@ -363,6 +362,14 @@ interface InfixParselet {
363
362
  readonly category: string;
364
363
  /** Binding power (precedence), property access avoids vtable dispatch in hot loop */
365
364
  readonly bindingPower: number;
365
+ /**
366
+ * Whether the operator groups from the right (`2 ^ 3 ^ 2` is `2 ^ (3 ^ 2)`).
367
+ * Absent means left, which is what every operator but exponentiation
368
+ * wants. Read by {@link parseRightOperand}, and reported by
369
+ * `ParseletRegistry.getAllInfix` so a precedence table built from the
370
+ * registry says what the parser does.
371
+ */
372
+ readonly rightAssociative?: boolean;
366
373
  parse(parser: PrecedenceParser, left: Token, token: Token, builder: BytecodeBuilder): void;
367
374
  }
368
375
 
@@ -605,7 +605,10 @@ declare class TokenNormalizer {
605
605
  * @param tokens - Raw tokens from the lexer
606
606
  * @param onFusion - Optional fusion callback (overrides {@link NormalizerOptions.onFusion})
607
607
  * @returns Normalized tokens ready for parsing
608
- * @throws {Error} If the normalized token count exceeds maxTokens
608
+ * @throws {Error} If the normalized token count exceeds maxTokens, or the
609
+ * stream is still changing after maxPasses passes (a rule chain that never
610
+ * settles): NORMALIZER_PASS_LIMIT_EXCEEDED, rather than a stream that is
611
+ * quietly whatever the last pass left.
609
612
  */
610
613
  normalize(tokens: Token[], onFusion?: (fusion: TokenFusion) => void): Token[];
611
614
  }
@@ -605,7 +605,10 @@ declare class TokenNormalizer {
605
605
  * @param tokens - Raw tokens from the lexer
606
606
  * @param onFusion - Optional fusion callback (overrides {@link NormalizerOptions.onFusion})
607
607
  * @returns Normalized tokens ready for parsing
608
- * @throws {Error} If the normalized token count exceeds maxTokens
608
+ * @throws {Error} If the normalized token count exceeds maxTokens, or the
609
+ * stream is still changing after maxPasses passes (a rule chain that never
610
+ * settles): NORMALIZER_PASS_LIMIT_EXCEEDED, rather than a stream that is
611
+ * quietly whatever the last pass left.
609
612
  */
610
613
  normalize(tokens: Token[], onFusion?: (fusion: TokenFusion) => void): Token[];
611
614
  }
@@ -1,8 +1,8 @@
1
- import { V as Value } from './Value-BYHw-x7q.cjs';
1
+ import { V as Value } from './Value-2TIKi-YL.cjs';
2
2
  import { U as UserFunctionDef, A as AnonymousBodyDef, a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.cjs';
3
3
  import { C as CalendarBackend } from './CalendarBackend-MdS3Bb4P.cjs';
4
- import { E as EngineError } from './EngineError-CqGtaT_v.cjs';
5
- import { D as DiagnosticPipeline } from './pipeline-BYkKNpql.cjs';
4
+ import { E as EngineError } from './EngineError-Bm4OYmw8.cjs';
5
+ import { D as DiagnosticPipeline } from './pipeline-Bum6y1B9.cjs';
6
6
 
7
7
  /**
8
8
  * Create a new VM instance with the given opcode registry and configurable limits.
@@ -13,7 +13,11 @@ import { D as DiagnosticPipeline } from './pipeline-BYkKNpql.cjs';
13
13
  * - An instruction counter (bounded by `maxInstructions`)
14
14
  * - An AbortSignal for async cancellation
15
15
  *
16
- * @param registry - Opcode handler registry for plugin-extensible opcodes
16
+ * @param registry - Never consulted, and kept only so the parameter list a
17
+ * host already calls with keeps working. The dispatch loop refuses any
18
+ * opcode it has no arm for, whatever a registry claims about it; a package
19
+ * reaches the VM through `pluginFunctions` and `CALL_PLUGIN`. See
20
+ * `OpRegistry.ts`, and the deprecation there.
17
21
  * @param maxStackDepth - Maximum stack slots (default 200)
18
22
  * @param maxInstructions - Maximum opcodes per expression (default 50000)
19
23
  * @param maxFunctionRecursionDepth - Maximum nested user-defined-function
@@ -176,9 +180,12 @@ type EvalResult = {
176
180
  * switches (OpCode values 0–200) into a jump table with O(1) dispatch.
177
181
  * All handler code is inlined directly in the switch cases, allowing
178
182
  * TurboFan to optimize across opcode boundaries.
179
- * - ADD/SUB/MUL have an inlined numeric fast path that skips the `binaryOp()`
180
- * function call + closure allocation when both operands are plain numbers
181
- * (>90% of arithmetic ops).
183
+ * - ADD/SUB/MUL/DIV and the six comparisons open with an inlined plain-number
184
+ * branch: two Numbers carrying no rational or uncertainty sidecar (>90% of
185
+ * arithmetic ops) are answered before any helper (fault propagation,
186
+ * percentage, rate period, money, unit, `binaryOp()`) is called. The
187
+ * sidecar checks are what keep the branch honest: an exact fraction or a
188
+ * measurement takes the ladder below it, exactly as before.
182
189
  * - Tracing uses a boolean guard (`shouldTrace`) that the JIT eliminates
183
190
  * entirely when diagnostics are disabled. No function call overhead.
184
191
  * - `Value.toNumber()` caches its result, computed once, read thereafter.
@@ -346,26 +353,44 @@ interface ScalarEquationDef {
346
353
  rhsProgram: BytecodeProgram;
347
354
  }
348
355
  /**
349
- * Handler function for plugin-registered opcodes via CALL_PLUGIN (opcode 50).
350
- * No longer dispatched directly from the VM switch, plugins register
351
- * functions in pluginFunctionRegistry instead.
356
+ * Handler function for a custom opcode, in the shape the VM never calls.
352
357
  *
353
- * @deprecated Use CALL_PLUGIN + pluginFunctionRegistry for plugin functionality.
354
- * OpRegistry remains for the VM interface contract only.
358
+ * @deprecated Nothing dispatches to a handler of this type. A package reaches
359
+ * the VM through `IEnginePackage.pluginFunctions`, which `CALL_PLUGIN`
360
+ * resolves per engine. Removed in the next major with {@link OpRegistry}.
355
361
  */
356
362
  type OpcodeHandler = (vm: VM, opcodes: Uint8Array, ip: number, numbers: Float64Array, strings: string[]) => number;
357
- /** Registration payload for an opcode handler. Binds an OpCode to its handler function with plugin attribution. */
363
+ /**
364
+ * Registration payload for an opcode handler.
365
+ *
366
+ * @deprecated See {@link OpcodeHandler}. Removed in the next major.
367
+ */
358
368
  interface IOpcodeHandlerRegistration {
359
369
  opcode: number;
360
370
  handler: OpcodeHandler;
361
371
  pluginName: string;
362
372
  }
363
373
  /**
364
- * Legacy opcode registry, retained for the VM interface contract.
374
+ * A table of custom opcode handlers the virtual machine never reads.
365
375
  *
366
- * Previously dispatched custom opcodes (>= 200) from the VM switch-default
367
- * branch. Now plugins should use CALL_PLUGIN (opcode 50) via
368
- * pluginFunctionRegistry instead.
376
+ * This once described an extension point: a package allocated an opcode from
377
+ * the dynamic range (201 to 254), registered a handler for it, and the VM's
378
+ * dispatch switch was meant to call that handler from its default arm. The
379
+ * switch never consulted the registry, and until recently had no default arm
380
+ * at all, so a registered opcode ran as a no-op and the program failed some
381
+ * instructions later with a misleading STACK_UNDERFLOW. The dispatch loop now
382
+ * refuses any opcode it has no arm for, at that instruction, with
383
+ * `MALFORMED_BYTECODE_UNKNOWN_OPCODE`, whatever a registry claims about it.
384
+ *
385
+ * The class, the {@link sharedOpRegistry} singleton, the `registry` field on
386
+ * {@link VM} and the first parameter of `createVM()` are kept so the calls a
387
+ * host already makes keep compiling and running; every one of them is
388
+ * deprecated and goes in the next major. A package that wants the VM to run
389
+ * its code declares `IEnginePackage.pluginFunctions`, which `CALL_PLUGIN`
390
+ * resolves through the engine's own context, one table per engine.
391
+ *
392
+ * @deprecated Never consulted by the VM. Use `IEnginePackage.pluginFunctions`.
393
+ * Removed in the next major.
369
394
  */
370
395
  declare class OpRegistry {
371
396
  private handlers;
@@ -435,6 +460,11 @@ interface VM {
435
460
  popString(): string;
436
461
  peek(): Value;
437
462
  getStack(): Value[];
463
+ /**
464
+ * The registry this machine was built with, which it never reads.
465
+ *
466
+ * @deprecated See {@link OpRegistry}. Removed in the next major.
467
+ */
438
468
  registry: OpRegistry;
439
469
  /**
440
470
  * Read a variable by name, checks the INNERMOST active user-defined-
@@ -550,7 +580,12 @@ interface VM {
550
580
  */
551
581
  context: EngineContext;
552
582
  }
553
- /** Shared singleton OpRegistry, used when no custom opcodes are needed. */
583
+ /**
584
+ * The registry every `createVM()` call without one of its own is handed.
585
+ *
586
+ * @deprecated See {@link OpRegistry}: the VM never reads it. Removed in the
587
+ * next major, together with `createVM()`'s first parameter.
588
+ */
554
589
  declare const sharedOpRegistry: OpRegistry;
555
590
 
556
591
  /** Serialized snapshot of the dependency graph for diagnostic rendering. */
@@ -1,8 +1,8 @@
1
- import { V as Value } from './Value-BYHw-x7q.js';
1
+ import { V as Value } from './Value-2TIKi-YL.js';
2
2
  import { U as UserFunctionDef, A as AnonymousBodyDef, a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.js';
3
3
  import { C as CalendarBackend } from './CalendarBackend-MdS3Bb4P.js';
4
- import { E as EngineError } from './EngineError-CqGtaT_v.js';
5
- import { D as DiagnosticPipeline } from './pipeline-Cl7KW8CB.js';
4
+ import { E as EngineError } from './EngineError-Bm4OYmw8.js';
5
+ import { D as DiagnosticPipeline } from './pipeline-DOo3KHaq.js';
6
6
 
7
7
  /**
8
8
  * Create a new VM instance with the given opcode registry and configurable limits.
@@ -13,7 +13,11 @@ import { D as DiagnosticPipeline } from './pipeline-Cl7KW8CB.js';
13
13
  * - An instruction counter (bounded by `maxInstructions`)
14
14
  * - An AbortSignal for async cancellation
15
15
  *
16
- * @param registry - Opcode handler registry for plugin-extensible opcodes
16
+ * @param registry - Never consulted, and kept only so the parameter list a
17
+ * host already calls with keeps working. The dispatch loop refuses any
18
+ * opcode it has no arm for, whatever a registry claims about it; a package
19
+ * reaches the VM through `pluginFunctions` and `CALL_PLUGIN`. See
20
+ * `OpRegistry.ts`, and the deprecation there.
17
21
  * @param maxStackDepth - Maximum stack slots (default 200)
18
22
  * @param maxInstructions - Maximum opcodes per expression (default 50000)
19
23
  * @param maxFunctionRecursionDepth - Maximum nested user-defined-function
@@ -176,9 +180,12 @@ type EvalResult = {
176
180
  * switches (OpCode values 0–200) into a jump table with O(1) dispatch.
177
181
  * All handler code is inlined directly in the switch cases, allowing
178
182
  * TurboFan to optimize across opcode boundaries.
179
- * - ADD/SUB/MUL have an inlined numeric fast path that skips the `binaryOp()`
180
- * function call + closure allocation when both operands are plain numbers
181
- * (>90% of arithmetic ops).
183
+ * - ADD/SUB/MUL/DIV and the six comparisons open with an inlined plain-number
184
+ * branch: two Numbers carrying no rational or uncertainty sidecar (>90% of
185
+ * arithmetic ops) are answered before any helper (fault propagation,
186
+ * percentage, rate period, money, unit, `binaryOp()`) is called. The
187
+ * sidecar checks are what keep the branch honest: an exact fraction or a
188
+ * measurement takes the ladder below it, exactly as before.
182
189
  * - Tracing uses a boolean guard (`shouldTrace`) that the JIT eliminates
183
190
  * entirely when diagnostics are disabled. No function call overhead.
184
191
  * - `Value.toNumber()` caches its result, computed once, read thereafter.
@@ -346,26 +353,44 @@ interface ScalarEquationDef {
346
353
  rhsProgram: BytecodeProgram;
347
354
  }
348
355
  /**
349
- * Handler function for plugin-registered opcodes via CALL_PLUGIN (opcode 50).
350
- * No longer dispatched directly from the VM switch, plugins register
351
- * functions in pluginFunctionRegistry instead.
356
+ * Handler function for a custom opcode, in the shape the VM never calls.
352
357
  *
353
- * @deprecated Use CALL_PLUGIN + pluginFunctionRegistry for plugin functionality.
354
- * OpRegistry remains for the VM interface contract only.
358
+ * @deprecated Nothing dispatches to a handler of this type. A package reaches
359
+ * the VM through `IEnginePackage.pluginFunctions`, which `CALL_PLUGIN`
360
+ * resolves per engine. Removed in the next major with {@link OpRegistry}.
355
361
  */
356
362
  type OpcodeHandler = (vm: VM, opcodes: Uint8Array, ip: number, numbers: Float64Array, strings: string[]) => number;
357
- /** Registration payload for an opcode handler. Binds an OpCode to its handler function with plugin attribution. */
363
+ /**
364
+ * Registration payload for an opcode handler.
365
+ *
366
+ * @deprecated See {@link OpcodeHandler}. Removed in the next major.
367
+ */
358
368
  interface IOpcodeHandlerRegistration {
359
369
  opcode: number;
360
370
  handler: OpcodeHandler;
361
371
  pluginName: string;
362
372
  }
363
373
  /**
364
- * Legacy opcode registry, retained for the VM interface contract.
374
+ * A table of custom opcode handlers the virtual machine never reads.
365
375
  *
366
- * Previously dispatched custom opcodes (>= 200) from the VM switch-default
367
- * branch. Now plugins should use CALL_PLUGIN (opcode 50) via
368
- * pluginFunctionRegistry instead.
376
+ * This once described an extension point: a package allocated an opcode from
377
+ * the dynamic range (201 to 254), registered a handler for it, and the VM's
378
+ * dispatch switch was meant to call that handler from its default arm. The
379
+ * switch never consulted the registry, and until recently had no default arm
380
+ * at all, so a registered opcode ran as a no-op and the program failed some
381
+ * instructions later with a misleading STACK_UNDERFLOW. The dispatch loop now
382
+ * refuses any opcode it has no arm for, at that instruction, with
383
+ * `MALFORMED_BYTECODE_UNKNOWN_OPCODE`, whatever a registry claims about it.
384
+ *
385
+ * The class, the {@link sharedOpRegistry} singleton, the `registry` field on
386
+ * {@link VM} and the first parameter of `createVM()` are kept so the calls a
387
+ * host already makes keep compiling and running; every one of them is
388
+ * deprecated and goes in the next major. A package that wants the VM to run
389
+ * its code declares `IEnginePackage.pluginFunctions`, which `CALL_PLUGIN`
390
+ * resolves through the engine's own context, one table per engine.
391
+ *
392
+ * @deprecated Never consulted by the VM. Use `IEnginePackage.pluginFunctions`.
393
+ * Removed in the next major.
369
394
  */
370
395
  declare class OpRegistry {
371
396
  private handlers;
@@ -435,6 +460,11 @@ interface VM {
435
460
  popString(): string;
436
461
  peek(): Value;
437
462
  getStack(): Value[];
463
+ /**
464
+ * The registry this machine was built with, which it never reads.
465
+ *
466
+ * @deprecated See {@link OpRegistry}. Removed in the next major.
467
+ */
438
468
  registry: OpRegistry;
439
469
  /**
440
470
  * Read a variable by name, checks the INNERMOST active user-defined-
@@ -550,7 +580,12 @@ interface VM {
550
580
  */
551
581
  context: EngineContext;
552
582
  }
553
- /** Shared singleton OpRegistry, used when no custom opcodes are needed. */
583
+ /**
584
+ * The registry every `createVM()` call without one of its own is handed.
585
+ *
586
+ * @deprecated See {@link OpRegistry}: the VM never reads it. Removed in the
587
+ * next major, together with `createVM()`'s first parameter.
588
+ */
554
589
  declare const sharedOpRegistry: OpRegistry;
555
590
 
556
591
  /** Serialized snapshot of the dependency graph for diagnostic rendering. */
@@ -1,5 +1,5 @@
1
- import { V as Value } from './Value-BYHw-x7q.cjs';
2
- import { V as VM } from './VMBuiltins-BkKzhj6C.cjs';
1
+ import { V as Value } from './Value-2TIKi-YL.cjs';
2
+ import { V as VM } from './VMBuiltins-JCavlQUj.cjs';
3
3
  import { U as UserFunctionDef } from './BytecodeBuilder-DSWKZi4f.cjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { V as Value } from './Value-BYHw-x7q.js';
2
- import { V as VM } from './VMBuiltins-Du9y8sEo.js';
1
+ import { V as Value } from './Value-2TIKi-YL.js';
2
+ import { V as VM } from './VMBuiltins-qgzA6qGi.js';
3
3
  import { U as UserFunctionDef } from './BytecodeBuilder-DSWKZi4f.js';
4
4
 
5
5
  /**
@@ -469,6 +469,25 @@ declare class Value {
469
469
  * Called by ValueArena.acquire(), zero allocation, just field assignment.
470
470
  */
471
471
  recycle(type: ValueType, value: number | bigint | string | boolean | MatrixData | RangeData | ColourData | SplitData | ChartData | IpCidrData | SymbolicNode, unit?: string): void;
472
+ /**
473
+ * A fresh Value carrying everything this one does: the payload, the unit,
474
+ * the cached number and every sidecar, present or future.
475
+ *
476
+ * The inverse of {@link recycle}, and written as a whole-object copy rather
477
+ * than a list of fields on purpose. `persistentValue()` used to name the
478
+ * sidecars it copied, and the two it did not name (`decimalPlaces`,
479
+ * `timedOut`) were silently dropped by every viewport evaluation, so
480
+ * `3.14159 to 4 dp` displayed as 3.14 there and as 3.1416 on a single line.
481
+ * A sidecar added later is carried here without this method knowing its
482
+ * name, which closes that class of bug rather than the one instance.
483
+ *
484
+ * Shallow, as the old copy was: a matrix, a chart or a symbolic tree is
485
+ * shared with the original, which is fine because a Value's payload is
486
+ * treated as immutable everywhere outside the arena's own `recycle()`.
487
+ *
488
+ * @returns A new Value equal to this one in every field.
489
+ */
490
+ clone(): Value;
472
491
  isNumber(): this is Value & {
473
492
  value: number;
474
493
  };
@@ -469,6 +469,25 @@ declare class Value {
469
469
  * Called by ValueArena.acquire(), zero allocation, just field assignment.
470
470
  */
471
471
  recycle(type: ValueType, value: number | bigint | string | boolean | MatrixData | RangeData | ColourData | SplitData | ChartData | IpCidrData | SymbolicNode, unit?: string): void;
472
+ /**
473
+ * A fresh Value carrying everything this one does: the payload, the unit,
474
+ * the cached number and every sidecar, present or future.
475
+ *
476
+ * The inverse of {@link recycle}, and written as a whole-object copy rather
477
+ * than a list of fields on purpose. `persistentValue()` used to name the
478
+ * sidecars it copied, and the two it did not name (`decimalPlaces`,
479
+ * `timedOut`) were silently dropped by every viewport evaluation, so
480
+ * `3.14159 to 4 dp` displayed as 3.14 there and as 3.1416 on a single line.
481
+ * A sidecar added later is carried here without this method knowing its
482
+ * name, which closes that class of bug rather than the one instance.
483
+ *
484
+ * Shallow, as the old copy was: a matrix, a chart or a symbolic tree is
485
+ * shared with the original, which is fine because a Value's payload is
486
+ * treated as immutable everywhere outside the arena's own `recycle()`.
487
+ *
488
+ * @returns A new Value equal to this one in every field.
489
+ */
490
+ clone(): Value;
472
491
  isNumber(): this is Value & {
473
492
  value: number;
474
493
  };
@@ -1,4 +1,4 @@
1
- import { c as ErrorCategory, S as SourceSpan, E as EngineError } from './EngineError-CqGtaT_v.js';
1
+ import { c as ErrorCategory, S as SourceSpan, E as EngineError } from './EngineError-Bm4OYmw8.js';
2
2
 
3
3
  /**
4
4
  * Structured errors for the off-main-thread worker harness, and the pair of
@@ -1,4 +1,4 @@
1
- import { c as ErrorCategory, S as SourceSpan, E as EngineError } from './EngineError-CqGtaT_v.cjs';
1
+ import { c as ErrorCategory, S as SourceSpan, E as EngineError } from './EngineError-Bm4OYmw8.cjs';
2
2
 
3
3
  /**
4
4
  * Structured errors for the off-main-thread worker harness, and the pair of
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkY7O4D3BJ_cjs=require('./chunk-Y7O4D3BJ.cjs'),chunkWU7SBKVU_cjs=require('./chunk-WU7SBKVU.cjs'),chunkSUAGBRQ7_cjs=require('./chunk-SUAGBRQ7.cjs');var h=(s=>(s.Main="main",s.Inline="inline",s.String="string",s))(h||{});var n=class{constructor(e="en",t){this.currentState="main";this.hasPeeked=false;this.tokens=[];this.tokenIdx=0;this.expressionLexer=new chunkWU7SBKVU_cjs.b(e);}reset(e,t){let s=t??"main";if(this.currentState=s,this.hasPeeked=false,this.peekedToken=void 0,s==="main"){if(this.expressionLexer.classifyLine(e).skip){this.tokens=[],this.tokenIdx=0;return}this.expressionLexer.reset(e),this.tokens=this.expressionLexer.tokenizeAll(),this.tokenIdx=0;}else this.expressionLexer.reset(e),this.tokens=this.expressionLexer.tokenizeAll(),this.tokenIdx=0;}classifyLine(e){return this.expressionLexer.classifyLine(e)}findInlineSolves(e){return this.expressionLexer.findInlineSolves(e)}getKeywords(){return this.expressionLexer.getKeywords()}next(){if(this.hasPeeked)return this.hasPeeked=false,this.peekedToken;if(this.tokenIdx<this.tokens.length)return this.tokens[this.tokenIdx++]}peek(){return this.hasPeeked?this.peekedToken:(this.peekedToken=this.next(),this.hasPeeked=true,this.peekedToken)}[Symbol.iterator](){return this.tokens[Symbol.iterator]()}registerVocabulary(e){this.expressionLexer.registerVocabulary(e);}unregisterVocabulary(e){this.expressionLexer.unregisterVocabulary(e);}resetExpression(e){this.currentState="main",this.hasPeeked=false,this.peekedToken=void 0,this.expressionLexer.reset(e),this.tokens=this.expressionLexer.tokenizeAll(),this.tokenIdx=0;}scanDocument(e){return this.expressionLexer.scanDocument(e)}getState(){return this.currentState}setState(e){this.currentState=e;}getHighlightTokens(e){let t=this.expressionLexer.classifyLine(e);return t.skip&&e.startsWith("> ")?this.collectHighlightTokens(e.slice(2)):t.skip?[]:this.collectHighlightTokens(e)}getHighlightTokenObjects(e){let t=this.expressionLexer.classifyLine(e);return t.skip&&e.startsWith("> ")?this.collectTokenObjects(e.slice(2)):t.skip?[]:this.collectTokenObjects(e)}collectTokenObjects(e){this.currentState="main",this.hasPeeked=false,this.peekedToken=void 0,this.expressionLexer.reset(e);let t=[];try{this.expressionLexer.tokenizeInto(t);}catch(i){if(!(i instanceof chunkSUAGBRQ7_cjs.b))throw i}let s=[];for(let i of t)i.type==="WS"||i.type==="NEWLINE"||i.type.startsWith("MD_")||i.type==="INLINE_SOLVE_START"||i.type==="BACKTICK_CLOSE"||s.push(i);return this.tokens=s,this.tokenIdx=0,s}collectHighlightTokens(e){return this.collectTokenObjects(e).map(t=>({type:t.type,value:t.value,offset:t.offset,col:t.col,length:t.text.length,category:chunkY7O4D3BJ_cjs.d(t.type)}))}},d=new n("en",void 0);exports.a=h;exports.b=n;exports.c=d;//# sourceMappingURL=chunk-AGCNMEP2.cjs.map
2
- //# sourceMappingURL=chunk-AGCNMEP2.cjs.map
1
+ 'use strict';var chunkY7O4D3BJ_cjs=require('./chunk-Y7O4D3BJ.cjs'),chunk72J5V7SN_cjs=require('./chunk-72J5V7SN.cjs'),chunk6SYU4MH7_cjs=require('./chunk-6SYU4MH7.cjs');var h=(s=>(s.Main="main",s.Inline="inline",s.String="string",s))(h||{});var n=class{constructor(e="en",t){this.currentState="main";this.hasPeeked=false;this.tokens=[];this.tokenIdx=0;this.expressionLexer=new chunk72J5V7SN_cjs.b(e);}reset(e,t){let s=t??"main";if(this.currentState=s,this.hasPeeked=false,this.peekedToken=void 0,s==="main"){if(this.expressionLexer.classifyLine(e).skip){this.tokens=[],this.tokenIdx=0;return}this.expressionLexer.reset(e),this.tokens=this.expressionLexer.tokenizeAll(),this.tokenIdx=0;}else this.expressionLexer.reset(e),this.tokens=this.expressionLexer.tokenizeAll(),this.tokenIdx=0;}classifyLine(e){return this.expressionLexer.classifyLine(e)}findInlineSolves(e){return this.expressionLexer.findInlineSolves(e)}getKeywords(){return this.expressionLexer.getKeywords()}next(){if(this.hasPeeked)return this.hasPeeked=false,this.peekedToken;if(this.tokenIdx<this.tokens.length)return this.tokens[this.tokenIdx++]}peek(){return this.hasPeeked?this.peekedToken:(this.peekedToken=this.next(),this.hasPeeked=true,this.peekedToken)}[Symbol.iterator](){return this.tokens[Symbol.iterator]()}registerVocabulary(e){this.expressionLexer.registerVocabulary(e);}unregisterVocabulary(e){this.expressionLexer.unregisterVocabulary(e);}resetExpression(e){this.currentState="main",this.hasPeeked=false,this.peekedToken=void 0,this.expressionLexer.reset(e),this.tokens=this.expressionLexer.tokenizeAll(),this.tokenIdx=0;}scanDocument(e){return this.expressionLexer.scanDocument(e)}getState(){return this.currentState}setState(e){this.currentState=e;}getHighlightTokens(e){let t=this.expressionLexer.classifyLine(e);return t.skip&&e.startsWith("> ")?this.collectHighlightTokens(e.slice(2)):t.skip?[]:this.collectHighlightTokens(e)}getHighlightTokenObjects(e){let t=this.expressionLexer.classifyLine(e);return t.skip&&e.startsWith("> ")?this.collectTokenObjects(e.slice(2)):t.skip?[]:this.collectTokenObjects(e)}collectTokenObjects(e){this.currentState="main",this.hasPeeked=false,this.peekedToken=void 0,this.expressionLexer.reset(e);let t=[];try{this.expressionLexer.tokenizeInto(t);}catch(i){if(!(i instanceof chunk6SYU4MH7_cjs.b))throw i}let s=[];for(let i of t)i.type==="WS"||i.type==="NEWLINE"||i.type.startsWith("MD_")||i.type==="INLINE_SOLVE_START"||i.type==="BACKTICK_CLOSE"||s.push(i);return this.tokens=s,this.tokenIdx=0,s}collectHighlightTokens(e){return this.collectTokenObjects(e).map(t=>({type:t.type,value:t.value,offset:t.offset,col:t.col,length:t.text.length,category:chunkY7O4D3BJ_cjs.d(t.type)}))}},d=new n("en",void 0);exports.a=h;exports.b=n;exports.c=d;//# sourceMappingURL=chunk-3MG7VIPL.cjs.map
2
+ //# sourceMappingURL=chunk-3MG7VIPL.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lexer/LexerState.ts","../src/lexer/Lexer.ts"],"names":["LexerState","Lexer","localeCode","_tokenLookup","ExpressionLexer","input","state","newState","lineText","plugin","text","classification","raw","thrown","EngineError","result","token","getTokenCategory","sharedLexer"],"mappings":"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","file":"chunk-AGCNMEP2.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 { EngineError } from \"@solve-js/errors/UnifiedErrorFramework\";\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 - Ignored. The lexer never read the lookup it was\n * handed; the parameter stays so existing callers compile.\n * @deprecated Removed in 3.0.\n */\n constructor(localeCode = \"en\", _tokenLookup?: TokenLookup) {\n this.expressionLexer = new ExpressionLexer(localeCode);\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 // Scanned into an array this method owns rather than through\n // resetExpression(), which has nothing to hand back when the line faults\n // part way. Highlighting is painted while the line is still being typed,\n // and an unterminated string is what a line looks like between the\n // opening quote and the closing one: the tokens read before the fault are\n // the right thing to paint, and letting the throw escape blanked the line.\n this.currentState = LexerState.Main;\n this.hasPeeked = false;\n this.peekedToken = undefined;\n this.expressionLexer.reset(lineText);\n const raw: Token[] = [];\n try {\n this.expressionLexer.tokenizeInto(raw);\n } catch (thrown) {\n if (!(thrown instanceof EngineError)) throw thrown;\n }\n const result: Token[] = [];\n for (const token of raw) {\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 this.tokens = result;\n this.tokenIdx = 0;\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);"]}
1
+ {"version":3,"sources":["../src/lexer/LexerState.ts","../src/lexer/Lexer.ts"],"names":["LexerState","Lexer","localeCode","_tokenLookup","ExpressionLexer","input","state","newState","lineText","plugin","text","classification","raw","thrown","EngineError","result","token","getTokenCategory","sharedLexer"],"mappings":"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","file":"chunk-3MG7VIPL.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 { EngineError } from \"@solve-js/errors/UnifiedErrorFramework\";\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 - Ignored. The lexer never read the lookup it was\n * handed; the parameter stays so existing callers compile.\n * @deprecated Removed in 3.0.\n */\n constructor(localeCode = \"en\", _tokenLookup?: TokenLookup) {\n this.expressionLexer = new ExpressionLexer(localeCode);\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 // Scanned into an array this method owns rather than through\n // resetExpression(), which has nothing to hand back when the line faults\n // part way. Highlighting is painted while the line is still being typed,\n // and an unterminated string is what a line looks like between the\n // opening quote and the closing one: the tokens read before the fault are\n // the right thing to paint, and letting the throw escape blanked the line.\n this.currentState = LexerState.Main;\n this.hasPeeked = false;\n this.peekedToken = undefined;\n this.expressionLexer.reset(lineText);\n const raw: Token[] = [];\n try {\n this.expressionLexer.tokenizeInto(raw);\n } catch (thrown) {\n if (!(thrown instanceof EngineError)) throw thrown;\n }\n const result: Token[] = [];\n for (const token of raw) {\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 this.tokens = result;\n this.tokenIdx = 0;\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);"]}