solve-engine 1.0.0-beta.7 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/dist/{BytecodeBuilder-3egMyuDi.d.cts → BytecodeBuilder-B0xskcv5.d.cts} +2 -1
  2. package/dist/{BytecodeBuilder-3egMyuDi.d.ts → BytecodeBuilder-B0xskcv5.d.ts} +2 -1
  3. package/dist/{Configuration-fVpd-HC-.d.cts → Configuration-B-G5gTRn.d.cts} +107 -29
  4. package/dist/{Configuration-fVpd-HC-.d.ts → Configuration-B-G5gTRn.d.ts} +107 -29
  5. package/dist/{EngineError-DvPSnhZi.d.cts → EngineError-LU7W7AgI.d.cts} +96 -16
  6. package/dist/{EngineError-DvPSnhZi.d.ts → EngineError-LU7W7AgI.d.ts} +96 -16
  7. package/dist/{Lexer-W9MBOP0V.d.ts → Lexer-BN5mt30n.d.ts} +16 -0
  8. package/dist/{Lexer-Cfm79Dak.d.cts → Lexer-D78E2yDW.d.cts} +16 -0
  9. package/dist/{PackageRegistry-pHtKythi.d.cts → PackageRegistry-B37mRvvz.d.cts} +69 -13
  10. package/dist/{PackageRegistry-CjDt-Jy_.d.ts → PackageRegistry-DCUEzbQt.d.ts} +69 -13
  11. package/dist/{Parselet-DEdF9I7n.d.ts → Parselet-BaySkMV3.d.ts} +37 -5
  12. package/dist/{Parselet-Cu0bLSis.d.cts → Parselet-DuI1Pjiq.d.cts} +37 -5
  13. package/dist/{ScopeManager-CKfQtl7l.d.cts → ScopeManager-B6GzdhVG.d.cts} +75 -6
  14. package/dist/{ScopeManager-B5k0nk05.d.ts → ScopeManager-udv4Twwq.d.ts} +75 -6
  15. package/dist/{VMCheckpoints-BmDwIXgK.d.ts → VMCheckpoints-BiaIlOOY.d.ts} +4 -4
  16. package/dist/{VMCheckpoints-CqFuLwrT.d.cts → VMCheckpoints-DwLjivM7.d.cts} +4 -4
  17. package/dist/{Value-KtAQNHur.d.cts → Value-CXJqDH9J.d.cts} +5 -2
  18. package/dist/{Value-KtAQNHur.d.ts → Value-CXJqDH9J.d.ts} +5 -2
  19. package/dist/{chunk-35IWNZPJ.cjs → chunk-2XLQPQKI.cjs} +58 -27
  20. package/dist/chunk-2XLQPQKI.cjs.map +1 -0
  21. package/dist/{chunk-CSG5XVNJ.cjs → chunk-3AFRJYP4.cjs} +556 -414
  22. package/dist/chunk-3AFRJYP4.cjs.map +1 -0
  23. package/dist/chunk-3BOK2LDK.js +17 -0
  24. package/dist/chunk-3BOK2LDK.js.map +1 -0
  25. package/dist/{chunk-6RDSQURE.js → chunk-3D7V24DG.js} +57 -6
  26. package/dist/chunk-3D7V24DG.js.map +1 -0
  27. package/dist/{chunk-MEOHSQEH.js → chunk-3LAEG75D.js} +47 -15
  28. package/dist/chunk-3LAEG75D.js.map +1 -0
  29. package/dist/{chunk-4AVD7NZW.cjs → chunk-4B2CNWQU.cjs} +13 -7
  30. package/dist/chunk-4B2CNWQU.cjs.map +1 -0
  31. package/dist/{chunk-6GCKCWLB.js → chunk-526PMQOA.js} +126 -69
  32. package/dist/chunk-526PMQOA.js.map +1 -0
  33. package/dist/{chunk-2CS6OMZK.js → chunk-5F4C26RU.js} +8 -5
  34. package/dist/chunk-5F4C26RU.js.map +1 -0
  35. package/dist/{chunk-M4N5GA5Z.cjs → chunk-5KMIY374.cjs} +57 -6
  36. package/dist/chunk-5KMIY374.cjs.map +1 -0
  37. package/dist/{chunk-R24DI24X.cjs → chunk-5LI5EPGJ.cjs} +6 -5
  38. package/dist/chunk-5LI5EPGJ.cjs.map +1 -0
  39. package/dist/{chunk-BAMZT3GL.js → chunk-5WVP4YHP.js} +939 -134
  40. package/dist/chunk-5WVP4YHP.js.map +1 -0
  41. package/dist/{chunk-MZOVP3WI.cjs → chunk-6KFYJ6TD.cjs} +3 -2
  42. package/dist/chunk-6KFYJ6TD.cjs.map +1 -0
  43. package/dist/{chunk-BXKJLM5R.cjs → chunk-6WFMPTGB.cjs} +972 -636
  44. package/dist/chunk-6WFMPTGB.cjs.map +1 -0
  45. package/dist/{chunk-2MV4HBKC.cjs → chunk-A2N2GFCG.cjs} +10 -10
  46. package/dist/{chunk-2MV4HBKC.cjs.map → chunk-A2N2GFCG.cjs.map} +1 -1
  47. package/dist/chunk-ADBA3XBE.cjs +20 -0
  48. package/dist/chunk-ADBA3XBE.cjs.map +1 -0
  49. package/dist/{chunk-MBNQVDVC.cjs → chunk-AMOJYLG2.cjs} +16 -10
  50. package/dist/chunk-AMOJYLG2.cjs.map +1 -0
  51. package/dist/{chunk-CLVQBF5C.cjs → chunk-AQNHHJMJ.cjs} +5 -5
  52. package/dist/{chunk-CLVQBF5C.cjs.map → chunk-AQNHHJMJ.cjs.map} +1 -1
  53. package/dist/{chunk-V6HA6JJZ.cjs → chunk-B7TLZABL.cjs} +242 -138
  54. package/dist/chunk-B7TLZABL.cjs.map +1 -0
  55. package/dist/{chunk-AHCLWAM5.cjs → chunk-BHTNFEGZ.cjs} +13 -13
  56. package/dist/chunk-BHTNFEGZ.cjs.map +1 -0
  57. package/dist/{chunk-BVAR5J2F.js → chunk-GQCOSXMG.js} +117 -6
  58. package/dist/chunk-GQCOSXMG.js.map +1 -0
  59. package/dist/{chunk-QDMPOAI7.cjs → chunk-HDP7VK3C.cjs} +1118 -313
  60. package/dist/chunk-HDP7VK3C.cjs.map +1 -0
  61. package/dist/{chunk-GVWHCL2N.js → chunk-HMOISHXR.js} +217 -75
  62. package/dist/chunk-HMOISHXR.js.map +1 -0
  63. package/dist/{chunk-MTX2KVU7.cjs → chunk-HVQFNJKE.cjs} +122 -90
  64. package/dist/chunk-HVQFNJKE.cjs.map +1 -0
  65. package/dist/{chunk-OC6LTXYS.cjs → chunk-JMXUNXQS.cjs} +126 -7
  66. package/dist/chunk-JMXUNXQS.cjs.map +1 -0
  67. package/dist/{chunk-WWOLFXTX.cjs → chunk-KBSXGXPM.cjs} +10 -7
  68. package/dist/chunk-KBSXGXPM.cjs.map +1 -0
  69. package/dist/{chunk-YU2CUNFO.js → chunk-KV7UW6T6.js} +11 -5
  70. package/dist/chunk-KV7UW6T6.js.map +1 -0
  71. package/dist/{chunk-CCJPSHGI.cjs → chunk-N7FNVFXW.cjs} +4 -12
  72. package/dist/chunk-N7FNVFXW.cjs.map +1 -0
  73. package/dist/{chunk-CYFK5SY2.js → chunk-O3ANBHSA.js} +169 -39
  74. package/dist/chunk-O3ANBHSA.js.map +1 -0
  75. package/dist/{chunk-NZFKROS7.cjs → chunk-PA4VC73I.cjs} +130 -72
  76. package/dist/chunk-PA4VC73I.cjs.map +1 -0
  77. package/dist/{chunk-NJTXJ5AG.cjs → chunk-PFUESQTW.cjs} +18 -18
  78. package/dist/{chunk-NJTXJ5AG.cjs.map → chunk-PFUESQTW.cjs.map} +1 -1
  79. package/dist/{chunk-SFQWJMKT.js → chunk-QY25VWBF.js} +51 -12
  80. package/dist/chunk-QY25VWBF.js.map +1 -0
  81. package/dist/{chunk-WC5FFSHB.js → chunk-R3PY4G7J.js} +3 -3
  82. package/dist/{chunk-WC5FFSHB.js.map → chunk-R3PY4G7J.js.map} +1 -1
  83. package/dist/{chunk-M5E34VG5.js → chunk-SBUFNJVE.js} +3 -3
  84. package/dist/{chunk-M5E34VG5.js.map → chunk-SBUFNJVE.js.map} +1 -1
  85. package/dist/{chunk-P33SBYGG.js → chunk-TBN7DEHO.js} +54 -23
  86. package/dist/chunk-TBN7DEHO.js.map +1 -0
  87. package/dist/{chunk-UKPGSAZW.js → chunk-TMA4RCEN.js} +3 -3
  88. package/dist/{chunk-UKPGSAZW.js.map → chunk-TMA4RCEN.js.map} +1 -1
  89. package/dist/{chunk-DUEZFTK2.js → chunk-UKQHXPGW.js} +4 -12
  90. package/dist/chunk-UKQHXPGW.js.map +1 -0
  91. package/dist/{chunk-4CVLFLOB.cjs → chunk-UM6BVY2S.cjs} +201 -69
  92. package/dist/chunk-UM6BVY2S.cjs.map +1 -0
  93. package/dist/{chunk-75JP4BZX.js → chunk-UQ3UIZJC.js} +3 -2
  94. package/dist/chunk-UQ3UIZJC.js.map +1 -0
  95. package/dist/{chunk-PCPX42KL.js → chunk-V4XG5QF6.js} +16 -10
  96. package/dist/chunk-V4XG5QF6.js.map +1 -0
  97. package/dist/{chunk-P75775WC.js → chunk-V5PYO44Y.js} +145 -41
  98. package/dist/chunk-V5PYO44Y.js.map +1 -0
  99. package/dist/{chunk-GPPLSM2Z.js → chunk-VB37OC6I.js} +6 -5
  100. package/dist/chunk-VB37OC6I.js.map +1 -0
  101. package/dist/{chunk-MVBEL57Q.js → chunk-Y7FT4IQT.js} +500 -170
  102. package/dist/chunk-Y7FT4IQT.js.map +1 -0
  103. package/dist/{chunk-OFXOTECC.js → chunk-YPPPYLSR.js} +7 -7
  104. package/dist/chunk-YPPPYLSR.js.map +1 -0
  105. package/dist/{chunk-M4F66R4O.cjs → chunk-YWQ6V4ZN.cjs} +121 -82
  106. package/dist/chunk-YWQ6V4ZN.cjs.map +1 -0
  107. package/dist/constants.cjs +5 -5
  108. package/dist/constants.d.cts +1 -1
  109. package/dist/constants.d.ts +1 -1
  110. package/dist/constants.js +2 -2
  111. package/dist/engine.cjs +31 -31
  112. package/dist/engine.d.cts +11 -11
  113. package/dist/engine.d.ts +11 -11
  114. package/dist/engine.js +21 -21
  115. package/dist/errors.cjs +19 -19
  116. package/dist/errors.d.cts +2 -2
  117. package/dist/errors.d.ts +2 -2
  118. package/dist/errors.js +1 -1
  119. package/dist/format.cjs +29 -22
  120. package/dist/format.cjs.map +1 -1
  121. package/dist/format.d.cts +1 -2
  122. package/dist/format.d.ts +1 -2
  123. package/dist/format.js +23 -16
  124. package/dist/format.js.map +1 -1
  125. package/dist/index.cjs +31 -31
  126. package/dist/index.d.cts +10 -10
  127. package/dist/index.d.ts +10 -10
  128. package/dist/index.js +22 -22
  129. package/dist/language.cjs +8 -8
  130. package/dist/language.cjs.map +1 -1
  131. package/dist/language.d.cts +10 -10
  132. package/dist/language.d.ts +10 -10
  133. package/dist/language.js +6 -6
  134. package/dist/language.js.map +1 -1
  135. package/dist/lexer.cjs +18 -18
  136. package/dist/lexer.d.cts +2 -2
  137. package/dist/lexer.d.ts +2 -2
  138. package/dist/lexer.js +6 -6
  139. package/dist/normalizer.cjs +12 -12
  140. package/dist/normalizer.js +6 -6
  141. package/dist/packages.cjs +39 -39
  142. package/dist/packages.d.cts +9 -9
  143. package/dist/packages.d.ts +9 -9
  144. package/dist/packages.js +16 -16
  145. package/dist/parser.cjs +15 -15
  146. package/dist/parser.d.cts +23 -9
  147. package/dist/parser.d.ts +23 -9
  148. package/dist/parser.js +5 -5
  149. package/dist/{pipeline-CrsRPmsv.d.ts → pipeline-B6k5lCB7.d.ts} +1 -1
  150. package/dist/{pipeline-DPUQt7yL.d.cts → pipeline-BEb3hujr.d.cts} +1 -1
  151. package/dist/resolvers.d.cts +2 -2
  152. package/dist/resolvers.d.ts +2 -2
  153. package/dist/uom.cjs +17 -17
  154. package/dist/uom.d.cts +2 -2
  155. package/dist/uom.d.ts +2 -2
  156. package/dist/uom.js +7 -7
  157. package/dist/utilities.cjs +8 -4
  158. package/dist/utilities.d.cts +19 -3
  159. package/dist/utilities.d.ts +19 -3
  160. package/dist/utilities.js +2 -2
  161. package/dist/vm.cjs +43 -31
  162. package/dist/vm.d.cts +105 -9
  163. package/dist/vm.d.ts +105 -9
  164. package/dist/vm.js +9 -9
  165. package/package.json +1 -1
  166. package/dist/chunk-2CS6OMZK.js.map +0 -1
  167. package/dist/chunk-35IWNZPJ.cjs.map +0 -1
  168. package/dist/chunk-4AVD7NZW.cjs.map +0 -1
  169. package/dist/chunk-4CVLFLOB.cjs.map +0 -1
  170. package/dist/chunk-6GCKCWLB.js.map +0 -1
  171. package/dist/chunk-6RDSQURE.js.map +0 -1
  172. package/dist/chunk-75JP4BZX.js.map +0 -1
  173. package/dist/chunk-AHCLWAM5.cjs.map +0 -1
  174. package/dist/chunk-BAMZT3GL.js.map +0 -1
  175. package/dist/chunk-BVAR5J2F.js.map +0 -1
  176. package/dist/chunk-BXKJLM5R.cjs.map +0 -1
  177. package/dist/chunk-CCJPSHGI.cjs.map +0 -1
  178. package/dist/chunk-CSG5XVNJ.cjs.map +0 -1
  179. package/dist/chunk-CYFK5SY2.js.map +0 -1
  180. package/dist/chunk-DUEZFTK2.js.map +0 -1
  181. package/dist/chunk-GPPLSM2Z.js.map +0 -1
  182. package/dist/chunk-GVWHCL2N.js.map +0 -1
  183. package/dist/chunk-M4F66R4O.cjs.map +0 -1
  184. package/dist/chunk-M4N5GA5Z.cjs.map +0 -1
  185. package/dist/chunk-MBNQVDVC.cjs.map +0 -1
  186. package/dist/chunk-MEOHSQEH.js.map +0 -1
  187. package/dist/chunk-MTX2KVU7.cjs.map +0 -1
  188. package/dist/chunk-MVBEL57Q.js.map +0 -1
  189. package/dist/chunk-MZOVP3WI.cjs.map +0 -1
  190. package/dist/chunk-N5YFR4UP.cjs +0 -10
  191. package/dist/chunk-N5YFR4UP.cjs.map +0 -1
  192. package/dist/chunk-NZFKROS7.cjs.map +0 -1
  193. package/dist/chunk-OC6LTXYS.cjs.map +0 -1
  194. package/dist/chunk-OFXOTECC.js.map +0 -1
  195. package/dist/chunk-P33SBYGG.js.map +0 -1
  196. package/dist/chunk-P75775WC.js.map +0 -1
  197. package/dist/chunk-PCPX42KL.js.map +0 -1
  198. package/dist/chunk-PFSDGGYL.js +0 -8
  199. package/dist/chunk-PFSDGGYL.js.map +0 -1
  200. package/dist/chunk-QDMPOAI7.cjs.map +0 -1
  201. package/dist/chunk-R24DI24X.cjs.map +0 -1
  202. package/dist/chunk-SFQWJMKT.js.map +0 -1
  203. package/dist/chunk-V6HA6JJZ.cjs.map +0 -1
  204. package/dist/chunk-WWOLFXTX.cjs.map +0 -1
  205. package/dist/chunk-YU2CUNFO.js.map +0 -1
@@ -28,6 +28,8 @@
28
28
  */
29
29
  declare const CoreErrorCodes: {
30
30
  readonly INVALID_NUMBER_LITERAL: "INVALID_NUMBER_LITERAL";
31
+ /** A `"` that never meets its closing partner (`lexer/ExpressionLexer.ts`'s `tokenizeString()`). Previously the tokenizer ran off the end of the input and returned what it had, so `"abc` lexed to an ordinary String and an unterminated literal was indistinguishable from a terminated one. */
32
+ readonly UNTERMINATED_STRING: "UNTERMINATED_STRING";
31
33
  readonly NO_PREFIX_PARSELET: "NO_PREFIX_PARSELET";
32
34
  readonly UNEXPECTED_END_OF_INPUT: "UNEXPECTED_END_OF_INPUT";
33
35
  readonly UNEXPECTED_TOKEN_TYPE: "UNEXPECTED_TOKEN_TYPE";
@@ -53,7 +55,9 @@ declare const CoreErrorCodes: {
53
55
  readonly EVALUATION_ERROR: "EVALUATION_ERROR";
54
56
  readonly INSTRUCTION_LIMIT_EXCEEDED: "INSTRUCTION_LIMIT_EXCEEDED";
55
57
  readonly STACK_LIMIT_EXCEEDED: "STACK_LIMIT_EXCEEDED";
56
- /** New this phase. See `VM.ts`'s `safePop()`: a stack-underflow (corrupted bytecode, a buggy plugin) is now a controlled EngineError instead of a raw TypeError. Always `recoverable: false` (internal invariant violation). */
58
+ /** One evaluation asking for more elements (collection Values, matrix cells) than `vm.maxAllocatedElements` allows. The counter the two limits above cannot be: both are checked between opcodes, so neither can see what a single opcode allocates inside a loop of its own. See `vm/AllocationBudget.ts`. Recoverable, since it describes this expression rather than the engine. */
59
+ readonly ALLOCATION_LIMIT_EXCEEDED: "ALLOCATION_LIMIT_EXCEEDED";
60
+ /** New this phase. See `VM.ts`'s `safePop()`: a stack-underflow (corrupted bytecode, a buggy plugin) is now a controlled EngineError instead of a raw TypeError. Category INTERNAL, since it is an engine or plugin fault rather than a typed line, but recoverable: it happened on one line and the engine is still usable. */
57
61
  readonly STACK_UNDERFLOW: "STACK_UNDERFLOW";
58
62
  readonly UNDEFINED_VARIABLE: "UNDEFINED_VARIABLE";
59
63
  /** New this phase, the Tier-2/`LOAD_GLOBAL_VAR` hardening: a global variable read before its async preflight resolved, surfaced as a controlled error instead of pushing `undefined`. */
@@ -64,15 +68,43 @@ declare const CoreErrorCodes: {
64
68
  /** User-defined-function call/definition errors (`CALL_USER_FUNCTION`/`DEFINE_USER_FUNCTION` opcodes), calling a name with no matching definition, calling with the wrong argument count, and the deliberate v1 restriction that a function body can't itself contain async work. */
65
69
  readonly UNDEFINED_FUNCTION: "UNDEFINED_FUNCTION";
66
70
  readonly FUNCTION_ARITY_MISMATCH: "FUNCTION_ARITY_MISMATCH";
71
+ /** The same mistake against a BUILT-IN rather than a user-defined function (`sqrt()`, `atan2(1)`, `sqrt(1,2,3)`). Separate from `FUNCTION_ARITY_MISMATCH` above because the two are raised by different opcodes and a host may want to word them differently. Checked at the `CALL_BUILTIN` dispatch against `vm/VMBuiltinArity.ts`; recoverable, since it is a typo in the line, not an engine fault. */
72
+ readonly BUILTIN_ARITY_MISMATCH: "BUILTIN_ARITY_MISMATCH";
67
73
  readonly USER_FUNCTION_ASYNC_UNSUPPORTED: "USER_FUNCTION_ASYNC_UNSUPPORTED";
68
74
  /** A map/reduce transform body (inline expression or user-defined function) calling an async plugin. Same v1 scope restriction as `USER_FUNCTION_ASYNC_UNSUPPORTED` above, enforced both at parse time (`MAP_REDUCE_TRANSFORM_MUST_BE_SYNCHRONOUS`, packages/mapreduce/) and as a defense-in-depth runtime backstop here. */
69
75
  readonly MAP_REDUCE_ASYNC_UNSUPPORTED: "MAP_REDUCE_ASYNC_UNSUPPORTED";
76
+ /** An algebra verb's expression argument (`BIND_UNKNOWN`'s body) calling an async plugin. Same v1 scope restriction as the two above, and likewise refused at parse time first (`SYMBOLIC_ARGUMENT_MUST_BE_SYNCHRONOUS`, packages/symbolic/). */
77
+ readonly SYMBOLIC_ASYNC_UNSUPPORTED: "SYMBOLIC_ASYNC_UNSUPPORTED";
70
78
  /** `pushCallFrame()`'s recursion guard, a nested `CALL_USER_FUNCTION` re-enters `executeBytecode()`, so `maxInstructions` alone can't catch e.g. `f(x) = f(x)`; this is the dedicated backstop. `recoverable: true` (the default for `.execution()`), ordinary user-written infinite recursion, not an engine bug; the guard exists precisely so it surfaces as a clear error instead of overflowing the native call stack uncatchably. */
71
79
  readonly FUNCTION_RECURSION_LIMIT_EXCEEDED: "FUNCTION_RECURSION_LIMIT_EXCEEDED";
80
+ /** The companion to the code above, and the half it could never see: how MANY user-defined-function calls one evaluation makes, rather than how deeply they nest. A twenty-two-line doubling chain nests twenty-two deep (legal) and makes two million calls (a fatal heap abort). Counted in `vm/AllocationBudget.ts`, because the tally has to survive `executeBytecode()` re-entering itself. Recoverable. */
81
+ readonly FUNCTION_CALL_LIMIT_EXCEEDED: "FUNCTION_CALL_LIMIT_EXCEEDED";
82
+ /** A `<date> + N workdays` offset outside `date.maxOffsetYears`/`minOffsetYears`. Workdays are the one date offset that walks the calendar a day at a time, so the one whose cost is the offset; every other one moves a Date field once. Recoverable. */
83
+ readonly DATE_OFFSET_LIMIT_EXCEEDED: "DATE_OFFSET_LIMIT_EXCEEDED";
84
+ /** A `<<`/`>>` with a bigint operand whose exact result would pass `MAX_EXACT_SHIFT_BITS`, whichever operand is the bigint. Both spellings refuse as of 1.0.0: a bigint on the left used to fall through to `x * 2^n` in doubles and report a 19,870-digit integer as Infinity. See `vm/VM.ts`'s `bigIntShift()`. Recoverable. */
85
+ readonly BIGINT_SHIFT_LIMIT_EXCEEDED: "BIGINT_SHIFT_LIMIT_EXCEEDED";
86
+ /** The same ceiling for `^`, the operator it was written for: `2n ^ 100000` asks for the same 100,001-bit integer `1n << 100000` does, so the two spellings answer the same way. Also new in 1.0.0, and for the same reason: this used to fall through to the double path and answer Infinity. A fractional or negative exponent (`4n ^ 0.5`, `2n ^ -1`) has no exact answer to bound and still uses the double path. See `vm/VM.ts`'s `MAX_EXACT_POW_BITS`. Recoverable. */
87
+ readonly BIGINT_POW_LIMIT_EXCEEDED: "BIGINT_POW_LIMIT_EXCEEDED";
88
+ /** An operand with no whole-number form (a fraction, an infinity, a NaN) meeting a bigint: `1n + 0.5`, `1n & 1.5`, `5n/pi`. `BigInt()` answers those with a raw RangeError, which the VM relabelled UNEXPECTED_ERROR, so a typo in the line was reported as an engine fault. Recoverable; see `vm/VMConversion.ts`'s `toBigIntOperand()`. */
89
+ readonly BIGINT_INEXACT_OPERAND: "BIGINT_INEXACT_OPERAND";
90
+ /** `10n / 0n` and `10n mod 0n`. Deliberately NOT what `1 / 0` does, which is Infinity: a bigint division is exact integer division (`7n / 2n` is 3n), and integer division by zero has no answer, exactly as it has none in C, Java, Python or JavaScript's own BigInt. Previously V8's own RangeError, relabelled UNEXPECTED_ERROR. Recoverable; see `vm/VMConversion.ts`'s `bigIntDivisionByZero()`. */
91
+ readonly BIGINT_DIVISION_BY_ZERO: "BIGINT_DIVISION_BY_ZERO";
72
92
  /** `DEFINE_USER_FUNCTION`'s body-index lookup failing, a compiler/VM invariant violation (the opcode stream referenced a `userFunctionBodies` slot that doesn't exist), never a user-input error. */
73
93
  readonly INTERNAL_MISSING_FUNCTION_BODY: "INTERNAL_MISSING_FUNCTION_BODY";
74
94
  /** `MAP_INVOKE`/`REDUCE_INVOKE`'s anonymous-body-index lookup failing. Same class as `INTERNAL_MISSING_FUNCTION_BODY` above, for the `anonymousBodies` side-table instead of `userFunctionBodies`. */
75
95
  readonly INTERNAL_MISSING_ANONYMOUS_BODY: "INTERNAL_MISSING_ANONYMOUS_BODY";
96
+ /** An operand byte read past the end of the stream: the program ends in the middle of an instruction. */
97
+ readonly MALFORMED_BYTECODE_TRUNCATED: "MALFORMED_BYTECODE_TRUNCATED";
98
+ /** A constant-pool operand indexing a `numbers`/`strings` entry that does not exist, or that is not of the pool's type. */
99
+ readonly MALFORMED_BYTECODE_CONSTANT_INDEX: "MALFORMED_BYTECODE_CONSTANT_INDEX";
100
+ /** A unit or converter name read off the value stack that is not a string. Distinct from the pool case above: the operand is a Value another opcode pushed, not a pool entry. */
101
+ readonly MALFORMED_BYTECODE_OPERAND_TYPE: "MALFORMED_BYTECODE_OPERAND_TYPE";
102
+ /** `MAP_INVOKE`/`REDUCE_INVOKE` carrying a body kind other than 0/1/2. Used to fall through every arm with no body and recurse into `executeBytecode(undefined)`. */
103
+ readonly MALFORMED_BYTECODE_BODY_KIND: "MALFORMED_BYTECODE_BODY_KIND";
104
+ /** A `PUSH_BIGINT` pool entry that is not a whole number, e.g. `"1.000"`. `BigInt()` answers that with a raw SyntaxError. */
105
+ readonly MALFORMED_BYTECODE_BIGINT_LITERAL: "MALFORMED_BYTECODE_BIGINT_LITERAL";
106
+ /** `executeBytecode()` called with something that is not a runnable program at all. Checked before the destructure that used to throw outside the function's own try/catch. */
107
+ readonly MALFORMED_BYTECODE_PROGRAM: "MALFORMED_BYTECODE_PROGRAM";
76
108
  /** A coefficient grew past `RATIONAL_MAX_BITS`, e.g. repeated exact elimination multiplying denominators together. */
77
109
  readonly SYMBOLIC_RATIONAL_OVERFLOW: "SYMBOLIC_RATIONAL_OVERFLOW";
78
110
  /** `NaN` or `±Infinity` reaching a symbolic expression, neither of which has an exact rational value. */
@@ -87,6 +119,8 @@ declare const CoreErrorCodes: {
87
119
  readonly SYMBOLIC_FACTOR_LIMIT_EXCEEDED: "SYMBOLIC_FACTOR_LIMIT_EXCEEDED";
88
120
  /** An equation outside what the solver attempts: not a polynomial, above the degree ceiling, or non-linear in the unknown while another unknown is present. */
89
121
  readonly SYMBOLIC_SOLVE_UNSUPPORTED: "SYMBOLIC_SOLVE_UNSUPPORTED";
122
+ /** Some but not all of an equation's roots were found. Reported rather than returned, because a partial list of roots looks exactly like a complete one. */
123
+ readonly SYMBOLIC_SOLVE_INCOMPLETE: "SYMBOLIC_SOLVE_INCOMPLETE";
90
124
  /** `solve`'s second argument not being a bare name. */
91
125
  readonly SOLVE_REQUIRES_VARIABLE_NAME: "SOLVE_REQUIRES_VARIABLE_NAME";
92
126
  /** A derivative order outside 0..`DERIVATIVE_MAX_ORDER`. */
@@ -105,11 +139,15 @@ declare const CoreErrorCodes: {
105
139
  readonly INTERNAL_RATIONAL_PARSE: "INTERNAL_RATIONAL_PARSE";
106
140
  readonly EXPRESSION_TOO_LONG: "EXPRESSION_TOO_LONG";
107
141
  readonly EXPRESSION_TOO_COMPLEX: "EXPRESSION_TOO_COMPLEX";
142
+ /** A document with more lines than `performance.maxDocumentLines`. The per-line limits above bound what one line may ask for and say nothing about how many lines there are; two hundred thousand of `1 + 1` exhausted the heap on the line records alone. Recoverable. */
143
+ readonly DOCUMENT_TOO_LARGE: "DOCUMENT_TOO_LARGE";
108
144
  readonly NORMALIZED_TOKEN_LIMIT_EXCEEDED: "NORMALIZED_TOKEN_LIMIT_EXCEEDED";
109
145
  /** `"=>"` with nothing before it, needs an expression or variable name to solve/simplify. */
110
146
  readonly THEREFORE_REQUIRES_EXPRESSION: "THEREFORE_REQUIRES_EXPRESSION";
111
147
  /** A `"=>"`-triggered expression called an async plugin (weather/stocks/currency). Same v1 scope restriction as user-function/map-reduce bodies. */
112
148
  readonly THEREFORE_ASYNC_UNSUPPORTED: "THEREFORE_ASYNC_UNSUPPORTED";
149
+ /** Colon-separated numbers that are not a time any clock can show ("24:00", "9:60", "100:5"). Raised by the labeled-line fallback, which used to answer them with whatever stood after the colon. */
150
+ readonly INVALID_TIME_LITERAL: "INVALID_TIME_LITERAL";
113
151
  readonly CONFIG_PATH_NOT_FOUND: "CONFIG_PATH_NOT_FOUND";
114
152
  readonly INVALID_CONFIG_PATH: "INVALID_CONFIG_PATH";
115
153
  readonly CONFIG_SECTION_NOT_FOUND: "CONFIG_SECTION_NOT_FOUND";
@@ -192,20 +230,29 @@ interface EngineErrorInit {
192
230
  /** An actionable, worked-example fix, e.g. `e.g. "weather in London"`. Mirrors this codebase's best existing messages (`WEATHER_EXPECTED_CITY`, `AS_CONVERTER_EXPECTED_NAME`). */
193
231
  suggestion?: string;
194
232
  /**
195
- * `true` (the default) for every EXPECTED failure mode of user input or
196
- * environment, bad syntax, an unknown variable/function, a safety limit
197
- * exceeded, an external API being down. `false` is reserved for genuine
198
- * ENGINE-INTERNAL invariant violations (corrupted bytecode, a stack
199
- * underflow from a buggy plugin, an "impossible" state)
200
- * `ErrorFactory.internal()`/`.config()` default to `false`, every other
201
- * factory method defaults to `true`.
233
+ * Whether this engine instance is still usable. `true` for everything that
234
+ * went wrong on ONE line, whether the line's fault (bad syntax, an unknown
235
+ * variable, a safety limit exceeded), the environment's (an external API
236
+ * down), or the engine's own (corrupted bytecode, a stack underflow from a
237
+ * buggy plugin). `false` is for the far rarer case where there is no working
238
+ * engine to go on with: a configuration or package-registration failure,
239
+ * which is what `ErrorFactory.config()` is for and the only factory method
240
+ * that still defaults to it.
202
241
  *
203
- * This does NOT gate "does evaluation of the rest of the document
204
- * continue", with this engine's per-line containment, it always does
205
- * even for a `recoverable: false` error (see `ARCHITECTURE.md`'s
206
- * async-batcher/Tier-2 hardening notes). It gates MESSAGE FRAMING and
207
- * telemetry: "fix your syntax" vs. "this is an engine bug, worth
208
- * reporting". See `EngineError.isFatal()`.
242
+ * The category answers a different question, and the two used to be answered
243
+ * as one. Category INTERNAL says whose fault this is, the engine's, worth
244
+ * reporting as a bug. `recoverable` says whether the host may carry on, and
245
+ * after an internal slip on one line it may:
246
+ * `__tests__/hardening/RobustnessEngineLifecycle.spec.ts` alternates a
247
+ * throwing line with a good one five hundred times and every answer stays
248
+ * correct. Reporting that as `isFatal()` told a host the opposite, and a host
249
+ * that honours the name would tear a document down over one bad line.
250
+ *
251
+ * This has never gated "does evaluation of the rest of the document
252
+ * continue"; with this engine's per-line containment it always does, even for
253
+ * a `recoverable: false` error (see `ARCHITECTURE.md`'s async-batcher/Tier-2
254
+ * hardening notes). It gates what a host is TOLD. See
255
+ * {@link EngineError.isFatal}.
209
256
  */
210
257
  recoverable?: boolean;
211
258
  /** Character-offset span into the source expression, when available. Not yet threaded through every call site, populate opportunistically, don't block on retrofitting every existing throw site. */
@@ -281,10 +328,23 @@ declare class ErrorFactory {
281
328
  static execution(init: EngineErrorInit): EngineError;
282
329
  static external(code: string, message: string, context?: Record<string, unknown>): EngineError;
283
330
  static external(init: EngineErrorInit): EngineError;
284
- /** Defaults `recoverable: false`, reserve for genuine engine-internal invariant violations, not user-input errors. */
331
+ /**
332
+ * Reserve for genuine engine-internal invariant violations (corrupted
333
+ * bytecode, a stack underflow from a buggy plugin, an "impossible" state),
334
+ * not for user-input errors: the category is a bug report.
335
+ *
336
+ * Defaults `recoverable: true` all the same, because every one of these sites
337
+ * is an invariant that failed on ONE line and none of them leaves the engine
338
+ * unusable. This used to default to `false`, which conflated "the engine's
339
+ * fault" with "the engine is finished" and told a host to tear a document
340
+ * down over a line it could simply have shown an error against. A site that
341
+ * has looked at its own case and concluded the instance really is gone can
342
+ * still pass `recoverable: false` explicitly. See {@link
343
+ * EngineErrorInit.recoverable}.
344
+ */
285
345
  static internal(code: string, message: string, context?: Record<string, unknown>): EngineError;
286
346
  static internal(init: EngineErrorInit): EngineError;
287
- /** Defaults `recoverable: false`, a bad config is an environment-setup problem, not a per-line user-input error. */
347
+ /** Defaults `recoverable: false`, and is now the only method that does: a configuration or package-registration failure is the one class that leaves no working engine to carry on with, rather than one bad line in a document. */
288
348
  static config(code: string, message: string, context?: Record<string, unknown>): EngineError;
289
349
  static config(init: EngineErrorInit): EngineError;
290
350
  }
@@ -298,6 +358,26 @@ declare class ErrorFactory {
298
358
  * per-line containment) so a raw `TypeError` from a genuine engine bug
299
359
  * still surfaces as a structured, catalogued error instead of an opaque
300
360
  * uncaught exception.
361
+ *
362
+ * Both branches state RECOVERABLE explicitly, while keeping the INTERNAL
363
+ * category. The two fields answer different questions and were previously
364
+ * answering the same one:
365
+ *
366
+ * category INTERNAL whose fault is this? The engine's. Worth reporting.
367
+ * recoverable is this engine instance still usable? Yes.
368
+ *
369
+ * Everything reaching here is by definition something the engine did not
370
+ * anticipate on ONE line, and per-line containment means the next line
371
+ * evaluates normally, which `__tests__/hardening/RobustnessEngineLifecycle`
372
+ * demonstrates over hundreds of alternating failure/success pairs. Reporting
373
+ * that as `isFatal()` told a host the opposite, and a host that honours the
374
+ * name would tear a document down over a single bad line. The "this is an
375
+ * engine bug rather than your syntax" signal a caller wants for telemetry is
376
+ * the CATEGORY, which is unchanged.
377
+ *
378
+ * The flag is written out here rather than inherited from
379
+ * `ErrorFactory.internal()`, which now defaults the same way, so that this
380
+ * function's contract survives a future change to that default.
301
381
  */
302
382
  declare function normalizeUnknownError(error: unknown): EngineError;
303
383
 
@@ -364,6 +364,22 @@ declare class ExpressionLexer {
364
364
  private tokenizeOperator;
365
365
  /**
366
366
  * Reads a double-quoted string literal. Supports backslash escapes.
367
+ *
368
+ * `text` is the raw source slice, quotes included, because that is what
369
+ * `offset` + `text.length` has to span for a host to underline the literal.
370
+ * `value` is the PAYLOAD, quotes excluded, because that is what
371
+ * `PUSH_STRING` puts into the Value.
372
+ *
373
+ * The two used to be the same string. `"abc"` carried the five characters
374
+ * `"abc"` as its value, which was invisible on screen (the formatter prints
375
+ * the payload raw and the retained quotes landed where a display would have
376
+ * put them back) and not invisible anywhere else: `parseFloat('"5"')` is NaN
377
+ * whatever the digits say, so `"5" + 5` answered 5.
378
+ *
379
+ * An unterminated literal is an error rather than a string that happens to
380
+ * reach the end of the line. It used to return what it had, so `"abc` and
381
+ * `"abc"` were indistinguishable by payload once the quotes were stripped,
382
+ * which is the other half of why they are stripped here rather than later.
367
383
  */
368
384
  private tokenizeString;
369
385
  /**
@@ -364,6 +364,22 @@ declare class ExpressionLexer {
364
364
  private tokenizeOperator;
365
365
  /**
366
366
  * Reads a double-quoted string literal. Supports backslash escapes.
367
+ *
368
+ * `text` is the raw source slice, quotes included, because that is what
369
+ * `offset` + `text.length` has to span for a host to underline the literal.
370
+ * `value` is the PAYLOAD, quotes excluded, because that is what
371
+ * `PUSH_STRING` puts into the Value.
372
+ *
373
+ * The two used to be the same string. `"abc"` carried the five characters
374
+ * `"abc"` as its value, which was invisible on screen (the formatter prints
375
+ * the payload raw and the retained quotes landed where a display would have
376
+ * put them back) and not invisible anywhere else: `parseFloat('"5"')` is NaN
377
+ * whatever the digits say, so `"5" + 5` answered 5.
378
+ *
379
+ * An unterminated literal is an error rather than a string that happens to
380
+ * reach the end of the line. It used to return what it had, so `"abc` and
381
+ * `"abc"` were indistinguishable by payload once the quotes were stripped,
382
+ * which is the other half of why they are stripped here rather than later.
367
383
  */
368
384
  private tokenizeString;
369
385
  /**
@@ -1,16 +1,16 @@
1
- import { a as PrecedenceParser, b as PrefixParselet, I as InfixParselet } from './Parselet-Cu0bLSis.cjs';
2
- import { V as Value } from './Value-KtAQNHur.cjs';
1
+ import { a as PrecedenceParser, b as PrefixParselet, I as InfixParselet } from './Parselet-DuI1Pjiq.cjs';
2
+ import { V as Value } from './Value-CXJqDH9J.cjs';
3
3
  import { IVariableSource } from './variables.cjs';
4
- import { M as MarkdownLineType, L as Lexer, e as TokenCategory, c as LexerVocabulary } from './Lexer-Cfm79Dak.cjs';
4
+ import { M as MarkdownLineType, L as Lexer, e as TokenCategory, c as LexerVocabulary } from './Lexer-D78E2yDW.cjs';
5
5
  import { IAsyncResolver } from './resolvers.cjs';
6
6
  import { T as TokenFusion, c as TokenNormalizer, a as NormalizerRule } from './TokenNormalizer-DGVa24Q-.cjs';
7
- import { D as DependencyGraph, V as VM, a as DagSnapshot, b as EngineContext, S as ScopeManager, L as LineExecutionContext } from './ScopeManager-CKfQtl7l.cjs';
8
- import { a as BytecodeProgram } from './BytecodeBuilder-3egMyuDi.cjs';
7
+ import { a as DependencyGraph, V as VM, D as DagSnapshot, b as EngineContext, S as ScopeManager, L as LineExecutionContext } from './ScopeManager-B6GzdhVG.cjs';
8
+ import { a as BytecodeProgram } from './BytecodeBuilder-B0xskcv5.cjs';
9
9
  import { QueryClient } from '@tanstack/query-core';
10
- import { E as EngineError } from './EngineError-DvPSnhZi.cjs';
11
- import { a as DiagnosticReportJSON, D as DiagnosticPipeline } from './pipeline-DPUQt7yL.cjs';
10
+ import { E as EngineError } from './EngineError-LU7W7AgI.cjs';
11
+ import { a as DiagnosticReportJSON, D as DiagnosticPipeline } from './pipeline-BEb3hujr.cjs';
12
12
  import { T as Token } from './Token-BzG5G4ja.cjs';
13
- import { D as DEFAULT_CONFIG, E as EngineConfig } from './Configuration-fVpd-HC-.cjs';
13
+ import { D as DEFAULT_CONFIG, E as EngineConfig } from './Configuration-B-G5gTRn.cjs';
14
14
 
15
15
  /**
16
16
  * One line's compiled bytecode, plus the variables it reads and writes.
@@ -213,9 +213,28 @@ declare class DocumentModel {
213
213
  * bottom of a 20k-line document before this fix.
214
214
  */
215
215
  private dirtyLineIds;
216
+ /**
217
+ * Most lines this model will hold. See `constants/Configuration.ts`'s
218
+ * `performance.maxDocumentLines`, which is where the default comes from and
219
+ * which a host raises through its engine config; a host that builds a
220
+ * DocumentModel directly passes it here instead.
221
+ */
222
+ private readonly maxLines;
223
+ /**
224
+ * @param maxLines - Ceiling on the line count, defaulting to the engine's
225
+ * configured one. Every line costs a LineState with six arrays in it
226
+ * whatever the line says, so the cost of a document is its line count and
227
+ * nothing else bounds it: two hundred thousand lines of `1 + 1` exhausted
228
+ * the heap here, before a single expression had been looked at.
229
+ */
230
+ constructor(maxLines?: number);
216
231
  /**
217
232
  * Initialize or replace the entire document from a text blob.
218
233
  * Clears all existing state and assigns new persistent line IDs.
234
+ *
235
+ * @throws `DOCUMENT_TOO_LARGE` for a document past {@link maxLines}, before
236
+ * any of it is stored. Recoverable: nothing has been replaced yet, so the
237
+ * model still holds whatever it held.
219
238
  */
220
239
  setDocument(text: string): void;
221
240
  /**
@@ -1407,9 +1426,17 @@ declare class ExpressionEngine {
1407
1426
  * own contract). This engine-instance-local registration is reversed
1408
1427
  * here too, even though it isn't a "shared" registry, so a package's
1409
1428
  * lexer and highlighting contributions clean up together rather than
1410
- * only half-reversing on unregister. Per-engine parselets/phrases are
1411
- * still left in place: they live in this engine's isolated registries
1412
- * and are discarded with the engine instance.
1429
+ * only half-reversing on unregister. Normalizer rules are reversed here
1430
+ * for the same reason: they are per-engine, but they live in an ARRAY the
1431
+ * normalizer walks at every token position, so re-registering a package
1432
+ * appended a second copy of every rule and lexing got slower with every
1433
+ * register/unregister cycle.
1434
+ *
1435
+ * Per-engine parselets and phrases are still left in place: a parselet
1436
+ * lives in this engine's isolated registry and a phrase goes into a
1437
+ * text-keyed trie where registering the same phrase twice is the same as
1438
+ * registering it once, so neither accumulates and both are discarded with
1439
+ * the engine instance.
1413
1440
  *
1414
1441
  * Clears the bytecode cache, removing handlers changes what compiled
1415
1442
  * bytecode is valid.
@@ -1527,6 +1554,12 @@ declare class ExpressionEngine {
1527
1554
  * parseExpression(). Abstracts the API difference between the two parsers:
1528
1555
  * - PrecedenceParser: parser.setBuilder(builder); parser.parseExpression(0)
1529
1556
  * - RD: parser.builder = builder; parser.parseExpression(0)
1557
+ *
1558
+ * @param allowLabelFallback - Whether a line that does not parse whole may
1559
+ * be retried as "&lt;label&gt;: &lt;expression&gt;". True for a real line, false for
1560
+ * the retries that fallback makes itself, which is what stops it costing
1561
+ * exponential time; see the loop below, and the comment on its recursive
1562
+ * call for the measurement.
1530
1563
  */
1531
1564
  private parseExpression;
1532
1565
  /**
@@ -1548,9 +1581,17 @@ declare class ExpressionEngine {
1548
1581
  * (a bare assignment's RHS, and an equation's own RHS at solve time)
1549
1582
  *, every one of these needs forward-tolerant reads of not-yet-defined
1550
1583
  * names, which ordinary evaluation deliberately never allows.
1584
+ *
1585
+ * `lineNumber` is the 1-based document line this program belongs to, so
1586
+ * the RHS still receives a {@link makeLineContext}, a bare assignment's
1587
+ * right-hand side (`total = prev`, `x = line2`) can therefore read
1588
+ * cross-line results exactly as a bare expression line does. Defaults to
1589
+ * `-1` (the "no real document" sentinel) for the expression-level and
1590
+ * `=>`-without-a-document callers, which naturally yields the same
1591
+ * `LINE_REF_NO_DOCUMENT` a single-expression eval already returns.
1551
1592
  */
1552
1593
  private executeSymbolicTolerant;
1553
- /** Compiles and executes `tokens` in symbolic-tolerant mode, the "just simplify this" `=>` fallback when there's no stored equation to solve. */
1594
+ /** Compiles and executes `tokens` in symbolic-tolerant mode, the "just simplify this" `=>` fallback when there's no stored equation to solve. `lineNumber` (1-based, `-1` outside a document) is forwarded so a bare assignment's RHS can resolve cross-line references. */
1554
1595
  private simplifySymbolically;
1555
1596
  /**
1556
1597
  * Parses a bare (colon-less) equation's left-hand side, `factor1 *
@@ -2111,8 +2152,23 @@ declare class ExpressionEngine {
2111
2152
  * goes through the parser's own throw/catch inside prepareExpression()
2112
2153
  * unavoidable without restructuring the parser's failure signaling, which
2113
2154
  * is out of scope here.
2155
+ *
2156
+ * The "non-throwing" in the first line is a contract callers rely on, not
2157
+ * a description of the happy path, so it is enforced here rather than left
2158
+ * to every stage below agreeing to return its errors. It had been left to
2159
+ * them, and they did not all agree: the lexer throws on an unterminated
2160
+ * string (`"`), and the symbolic grammar threw on an assignment whose
2161
+ * right-hand side is still empty (`total =`). LanguageService calls this
2162
+ * per visible line per keystroke, so both reached CodeMirror's transaction
2163
+ * dispatch and broke the editor on input that is merely half-typed.
2164
+ *
2165
+ * A catch costs nothing on the path that does not throw, so the "no" answer
2166
+ * this method exists to make cheap stays cheap. Anything that does throw
2167
+ * was already paying for the Error it constructed.
2114
2168
  */
2115
2169
  tryCompileExpression(expression: string): boolean;
2170
+ /** The body of {@link tryCompileExpression}, which owns the contract. */
2171
+ private tryCompileExpressionUnguarded;
2116
2172
  /**
2117
2173
  * Execute pre-compiled bytecode against the engine's shared VM.
2118
2174
  * Used by Tier 2 (scroll into view) to re-execute cached bytecode
@@ -2270,7 +2326,7 @@ declare class LanguageService {
2270
2326
  * highlighted the obvious way.
2271
2327
  *
2272
2328
  * A token the normalizer left alone still describes its own text, so its
2273
- * span is `offset` to `offset + value.length`, exactly as before.
2329
+ * span is `offset` to `offset + text.length`, exactly as before.
2274
2330
  *
2275
2331
  * A FUSED token does not. `10 frames` becomes a FRAME_COUNT whose value is
2276
2332
  * `10`, and a timecode becomes a token whose value is a comma-separated
@@ -1,16 +1,16 @@
1
- import { a as PrecedenceParser, b as PrefixParselet, I as InfixParselet } from './Parselet-DEdF9I7n.js';
2
- import { V as Value } from './Value-KtAQNHur.js';
1
+ import { a as PrecedenceParser, b as PrefixParselet, I as InfixParselet } from './Parselet-BaySkMV3.js';
2
+ import { V as Value } from './Value-CXJqDH9J.js';
3
3
  import { IVariableSource } from './variables.js';
4
- import { M as MarkdownLineType, L as Lexer, e as TokenCategory, c as LexerVocabulary } from './Lexer-W9MBOP0V.js';
4
+ import { M as MarkdownLineType, L as Lexer, e as TokenCategory, c as LexerVocabulary } from './Lexer-BN5mt30n.js';
5
5
  import { IAsyncResolver } from './resolvers.js';
6
6
  import { T as TokenFusion, c as TokenNormalizer, a as NormalizerRule } from './TokenNormalizer-t_GotBxr.js';
7
- import { D as DependencyGraph, V as VM, a as DagSnapshot, b as EngineContext, S as ScopeManager, L as LineExecutionContext } from './ScopeManager-B5k0nk05.js';
8
- import { a as BytecodeProgram } from './BytecodeBuilder-3egMyuDi.js';
7
+ import { a as DependencyGraph, V as VM, D as DagSnapshot, b as EngineContext, S as ScopeManager, L as LineExecutionContext } from './ScopeManager-udv4Twwq.js';
8
+ import { a as BytecodeProgram } from './BytecodeBuilder-B0xskcv5.js';
9
9
  import { QueryClient } from '@tanstack/query-core';
10
- import { E as EngineError } from './EngineError-DvPSnhZi.js';
11
- import { a as DiagnosticReportJSON, D as DiagnosticPipeline } from './pipeline-CrsRPmsv.js';
10
+ import { E as EngineError } from './EngineError-LU7W7AgI.js';
11
+ import { a as DiagnosticReportJSON, D as DiagnosticPipeline } from './pipeline-B6k5lCB7.js';
12
12
  import { T as Token } from './Token-BzG5G4ja.js';
13
- import { D as DEFAULT_CONFIG, E as EngineConfig } from './Configuration-fVpd-HC-.js';
13
+ import { D as DEFAULT_CONFIG, E as EngineConfig } from './Configuration-B-G5gTRn.js';
14
14
 
15
15
  /**
16
16
  * One line's compiled bytecode, plus the variables it reads and writes.
@@ -213,9 +213,28 @@ declare class DocumentModel {
213
213
  * bottom of a 20k-line document before this fix.
214
214
  */
215
215
  private dirtyLineIds;
216
+ /**
217
+ * Most lines this model will hold. See `constants/Configuration.ts`'s
218
+ * `performance.maxDocumentLines`, which is where the default comes from and
219
+ * which a host raises through its engine config; a host that builds a
220
+ * DocumentModel directly passes it here instead.
221
+ */
222
+ private readonly maxLines;
223
+ /**
224
+ * @param maxLines - Ceiling on the line count, defaulting to the engine's
225
+ * configured one. Every line costs a LineState with six arrays in it
226
+ * whatever the line says, so the cost of a document is its line count and
227
+ * nothing else bounds it: two hundred thousand lines of `1 + 1` exhausted
228
+ * the heap here, before a single expression had been looked at.
229
+ */
230
+ constructor(maxLines?: number);
216
231
  /**
217
232
  * Initialize or replace the entire document from a text blob.
218
233
  * Clears all existing state and assigns new persistent line IDs.
234
+ *
235
+ * @throws `DOCUMENT_TOO_LARGE` for a document past {@link maxLines}, before
236
+ * any of it is stored. Recoverable: nothing has been replaced yet, so the
237
+ * model still holds whatever it held.
219
238
  */
220
239
  setDocument(text: string): void;
221
240
  /**
@@ -1407,9 +1426,17 @@ declare class ExpressionEngine {
1407
1426
  * own contract). This engine-instance-local registration is reversed
1408
1427
  * here too, even though it isn't a "shared" registry, so a package's
1409
1428
  * lexer and highlighting contributions clean up together rather than
1410
- * only half-reversing on unregister. Per-engine parselets/phrases are
1411
- * still left in place: they live in this engine's isolated registries
1412
- * and are discarded with the engine instance.
1429
+ * only half-reversing on unregister. Normalizer rules are reversed here
1430
+ * for the same reason: they are per-engine, but they live in an ARRAY the
1431
+ * normalizer walks at every token position, so re-registering a package
1432
+ * appended a second copy of every rule and lexing got slower with every
1433
+ * register/unregister cycle.
1434
+ *
1435
+ * Per-engine parselets and phrases are still left in place: a parselet
1436
+ * lives in this engine's isolated registry and a phrase goes into a
1437
+ * text-keyed trie where registering the same phrase twice is the same as
1438
+ * registering it once, so neither accumulates and both are discarded with
1439
+ * the engine instance.
1413
1440
  *
1414
1441
  * Clears the bytecode cache, removing handlers changes what compiled
1415
1442
  * bytecode is valid.
@@ -1527,6 +1554,12 @@ declare class ExpressionEngine {
1527
1554
  * parseExpression(). Abstracts the API difference between the two parsers:
1528
1555
  * - PrecedenceParser: parser.setBuilder(builder); parser.parseExpression(0)
1529
1556
  * - RD: parser.builder = builder; parser.parseExpression(0)
1557
+ *
1558
+ * @param allowLabelFallback - Whether a line that does not parse whole may
1559
+ * be retried as "&lt;label&gt;: &lt;expression&gt;". True for a real line, false for
1560
+ * the retries that fallback makes itself, which is what stops it costing
1561
+ * exponential time; see the loop below, and the comment on its recursive
1562
+ * call for the measurement.
1530
1563
  */
1531
1564
  private parseExpression;
1532
1565
  /**
@@ -1548,9 +1581,17 @@ declare class ExpressionEngine {
1548
1581
  * (a bare assignment's RHS, and an equation's own RHS at solve time)
1549
1582
  *, every one of these needs forward-tolerant reads of not-yet-defined
1550
1583
  * names, which ordinary evaluation deliberately never allows.
1584
+ *
1585
+ * `lineNumber` is the 1-based document line this program belongs to, so
1586
+ * the RHS still receives a {@link makeLineContext}, a bare assignment's
1587
+ * right-hand side (`total = prev`, `x = line2`) can therefore read
1588
+ * cross-line results exactly as a bare expression line does. Defaults to
1589
+ * `-1` (the "no real document" sentinel) for the expression-level and
1590
+ * `=>`-without-a-document callers, which naturally yields the same
1591
+ * `LINE_REF_NO_DOCUMENT` a single-expression eval already returns.
1551
1592
  */
1552
1593
  private executeSymbolicTolerant;
1553
- /** Compiles and executes `tokens` in symbolic-tolerant mode, the "just simplify this" `=>` fallback when there's no stored equation to solve. */
1594
+ /** Compiles and executes `tokens` in symbolic-tolerant mode, the "just simplify this" `=>` fallback when there's no stored equation to solve. `lineNumber` (1-based, `-1` outside a document) is forwarded so a bare assignment's RHS can resolve cross-line references. */
1554
1595
  private simplifySymbolically;
1555
1596
  /**
1556
1597
  * Parses a bare (colon-less) equation's left-hand side, `factor1 *
@@ -2111,8 +2152,23 @@ declare class ExpressionEngine {
2111
2152
  * goes through the parser's own throw/catch inside prepareExpression()
2112
2153
  * unavoidable without restructuring the parser's failure signaling, which
2113
2154
  * is out of scope here.
2155
+ *
2156
+ * The "non-throwing" in the first line is a contract callers rely on, not
2157
+ * a description of the happy path, so it is enforced here rather than left
2158
+ * to every stage below agreeing to return its errors. It had been left to
2159
+ * them, and they did not all agree: the lexer throws on an unterminated
2160
+ * string (`"`), and the symbolic grammar threw on an assignment whose
2161
+ * right-hand side is still empty (`total =`). LanguageService calls this
2162
+ * per visible line per keystroke, so both reached CodeMirror's transaction
2163
+ * dispatch and broke the editor on input that is merely half-typed.
2164
+ *
2165
+ * A catch costs nothing on the path that does not throw, so the "no" answer
2166
+ * this method exists to make cheap stays cheap. Anything that does throw
2167
+ * was already paying for the Error it constructed.
2114
2168
  */
2115
2169
  tryCompileExpression(expression: string): boolean;
2170
+ /** The body of {@link tryCompileExpression}, which owns the contract. */
2171
+ private tryCompileExpressionUnguarded;
2116
2172
  /**
2117
2173
  * Execute pre-compiled bytecode against the engine's shared VM.
2118
2174
  * Used by Tier 2 (scroll into view) to re-execute cached bytecode
@@ -2270,7 +2326,7 @@ declare class LanguageService {
2270
2326
  * highlighted the obvious way.
2271
2327
  *
2272
2328
  * A token the normalizer left alone still describes its own text, so its
2273
- * span is `offset` to `offset + value.length`, exactly as before.
2329
+ * span is `offset` to `offset + text.length`, exactly as before.
2274
2330
  *
2275
2331
  * A FUSED token does not. `10 frames` becomes a FRAME_COUNT whose value is
2276
2332
  * `10`, and a timecode becomes a token whose value is a comma-separated
@@ -1,6 +1,6 @@
1
- import { B as BytecodeBuilder } from './BytecodeBuilder-3egMyuDi.js';
1
+ import { B as BytecodeBuilder } from './BytecodeBuilder-B0xskcv5.js';
2
2
  import { T as Token } from './Token-BzG5G4ja.js';
3
- import { D as DiagnosticPipeline } from './pipeline-CrsRPmsv.js';
3
+ import { D as DiagnosticPipeline } from './pipeline-B6k5lCB7.js';
4
4
 
5
5
  /**
6
6
  * Dual-keyed ParseletRegistry, accepts both string token types and
@@ -44,13 +44,44 @@ declare class ParseletRegistry {
44
44
  registerPrefix(tokenType: string, parselet: PrefixParselet): void;
45
45
  /** Register an infix parselet for `tokenType`. See {@link registerPrefix} for the collision-warning behavior this mirrors. */
46
46
  registerInfix(tokenType: string, parselet: InfixParselet): void;
47
- /** Iterate all registered prefix parselets for diagnostic display. */
47
+ /**
48
+ * Iterate all registered prefix parselets for diagnostic display.
49
+ *
50
+ * `PrefixParselet` declares no binding power, and this used to read a field
51
+ * of that name and report 0 for every one of them. 0 is not a neutral
52
+ * wrong answer: it is the value that means "not an operator, stop the
53
+ * expression", so a host drawing a table from this was told none of them
54
+ * bind at all. A prefix parselet in this parser has no per-parselet power
55
+ * to report, they all bind at the prefix level and each chooses for itself
56
+ * at what power to parse its own operand, so that level is what is
57
+ * reported. A parselet that does carry its own `bindingPower` still wins.
58
+ */
48
59
  getAllPrefix(): Array<{
49
60
  tokenType: string;
50
61
  bindingPower: number;
51
62
  category?: string;
52
63
  }>;
53
- /** Iterate all registered infix parselets for diagnostic display. */
64
+ /**
65
+ * Iterate all registered infix parselets for diagnostic display.
66
+ *
67
+ * The field an `InfixParselet` actually declares is `bindingPower`. This
68
+ * used to read `leftBindingPower` and `rightBindingPower`, which no
69
+ * parselet in this codebase declares, so both reads were `undefined`, both
70
+ * fell to the `?? 0` default, and the public `getParseletRegistry()`
71
+ * reported a binding power of 0 for every one of the ~60 infix operators.
72
+ * A host building a precedence table from it was told `*` and `+` bind
73
+ * equally, and that neither binds at all.
74
+ *
75
+ * The left/right split: `bindingPower` is the LEFT power, and the right is
76
+ * one higher. That is the standard encoding for a left-associative
77
+ * operator, and it is what the parser itself does, see
78
+ * `PrecedenceParser.parseExpression()`'s `bp + 1` for the right operand.
79
+ * Every operator is reported that way, `^` included. Associativity is not
80
+ * something a parselet declares, it is a property of how each one calls
81
+ * `parseExpression`, so this API cannot report it without a new field on
82
+ * the interface. See {@link ParseletBindingPowers} for why scraping a
83
+ * plausible-looking one off the parselet is worse than not reporting it.
84
+ */
54
85
  getAllInfix(): Array<{
55
86
  tokenType: string;
56
87
  leftBindingPower: number;
@@ -137,6 +168,7 @@ declare class PrecedenceParser {
137
168
  private static readonly CARET_ID;
138
169
  private static readonly LSHIFT_ID;
139
170
  private static readonly RSHIFT_ID;
171
+ private static readonly URSHIFT_ID;
140
172
  private static readonly BIT_AND_ID;
141
173
  private static readonly BIT_OR_ID;
142
174
  private static readonly BIT_XOR_ID;
@@ -170,7 +202,7 @@ declare class PrecedenceParser {
170
202
  *
171
203
  * @param minBp - minimum binding power (precedence climbing threshold).
172
204
  * For left-associative operators, the recursive call uses `bp + 1`.
173
- * For right-associative operators (^), it uses `bp`.
205
+ * For right-associative operators (^), it uses `bp - 1`.
174
206
  * @param _builder - accepted for parselet API compatibility; always uses `this.builder`.
175
207
  */
176
208
  parseExpression(minBp?: number, _builder?: BytecodeBuilder): void;