solve-engine 1.0.0-beta.6 → 1.0.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 (206) hide show
  1. package/README.md +10 -3
  2. package/dist/{BytecodeBuilder-3egMyuDi.d.cts → BytecodeBuilder-B0xskcv5.d.cts} +2 -1
  3. package/dist/{BytecodeBuilder-3egMyuDi.d.ts → BytecodeBuilder-B0xskcv5.d.ts} +2 -1
  4. package/dist/{Configuration-fVpd-HC-.d.cts → Configuration-B-G5gTRn.d.cts} +107 -29
  5. package/dist/{Configuration-fVpd-HC-.d.ts → Configuration-B-G5gTRn.d.ts} +107 -29
  6. package/dist/{EngineError-DvPSnhZi.d.cts → EngineError-LU7W7AgI.d.cts} +96 -16
  7. package/dist/{EngineError-DvPSnhZi.d.ts → EngineError-LU7W7AgI.d.ts} +96 -16
  8. package/dist/{Lexer-W9MBOP0V.d.ts → Lexer-BN5mt30n.d.ts} +16 -0
  9. package/dist/{Lexer-Cfm79Dak.d.cts → Lexer-D78E2yDW.d.cts} +16 -0
  10. package/dist/{PackageRegistry-CjDt-Jy_.d.ts → PackageRegistry-DFeINv2O.d.ts} +54 -13
  11. package/dist/{PackageRegistry-pHtKythi.d.cts → PackageRegistry-u2zdfFaj.d.cts} +54 -13
  12. package/dist/{Parselet-DEdF9I7n.d.ts → Parselet-BaySkMV3.d.ts} +37 -5
  13. package/dist/{Parselet-Cu0bLSis.d.cts → Parselet-DuI1Pjiq.d.cts} +37 -5
  14. package/dist/{ScopeManager-CKfQtl7l.d.cts → ScopeManager-B6GzdhVG.d.cts} +75 -6
  15. package/dist/{ScopeManager-B5k0nk05.d.ts → ScopeManager-udv4Twwq.d.ts} +75 -6
  16. package/dist/{VMCheckpoints-BmDwIXgK.d.ts → VMCheckpoints-BiaIlOOY.d.ts} +4 -4
  17. package/dist/{VMCheckpoints-CqFuLwrT.d.cts → VMCheckpoints-DwLjivM7.d.cts} +4 -4
  18. package/dist/{Value-KtAQNHur.d.cts → Value-CXJqDH9J.d.cts} +5 -2
  19. package/dist/{Value-KtAQNHur.d.ts → Value-CXJqDH9J.d.ts} +5 -2
  20. package/dist/{chunk-CSG5XVNJ.cjs → chunk-3AFRJYP4.cjs} +556 -414
  21. package/dist/chunk-3AFRJYP4.cjs.map +1 -0
  22. package/dist/chunk-3BOK2LDK.js +17 -0
  23. package/dist/chunk-3BOK2LDK.js.map +1 -0
  24. package/dist/{chunk-6RDSQURE.js → chunk-3D7V24DG.js} +57 -6
  25. package/dist/chunk-3D7V24DG.js.map +1 -0
  26. package/dist/{chunk-MEOHSQEH.js → chunk-3LAEG75D.js} +47 -15
  27. package/dist/chunk-3LAEG75D.js.map +1 -0
  28. package/dist/{chunk-NUR3K7EW.js → chunk-3VNGREMU.js} +118 -41
  29. package/dist/chunk-3VNGREMU.js.map +1 -0
  30. package/dist/{chunk-4AVD7NZW.cjs → chunk-4B2CNWQU.cjs} +13 -7
  31. package/dist/chunk-4B2CNWQU.cjs.map +1 -0
  32. package/dist/{chunk-6GCKCWLB.js → chunk-526PMQOA.js} +126 -69
  33. package/dist/chunk-526PMQOA.js.map +1 -0
  34. package/dist/{chunk-2CS6OMZK.js → chunk-5F4C26RU.js} +8 -5
  35. package/dist/chunk-5F4C26RU.js.map +1 -0
  36. package/dist/{chunk-M4N5GA5Z.cjs → chunk-5KMIY374.cjs} +57 -6
  37. package/dist/chunk-5KMIY374.cjs.map +1 -0
  38. package/dist/{chunk-R24DI24X.cjs → chunk-5LI5EPGJ.cjs} +6 -5
  39. package/dist/chunk-5LI5EPGJ.cjs.map +1 -0
  40. package/dist/{chunk-BAMZT3GL.js → chunk-5WVP4YHP.js} +939 -134
  41. package/dist/chunk-5WVP4YHP.js.map +1 -0
  42. package/dist/{chunk-MZOVP3WI.cjs → chunk-6KFYJ6TD.cjs} +3 -2
  43. package/dist/chunk-6KFYJ6TD.cjs.map +1 -0
  44. package/dist/{chunk-BXKJLM5R.cjs → chunk-6WFMPTGB.cjs} +972 -636
  45. package/dist/chunk-6WFMPTGB.cjs.map +1 -0
  46. package/dist/{chunk-2MV4HBKC.cjs → chunk-A2N2GFCG.cjs} +10 -10
  47. package/dist/{chunk-2MV4HBKC.cjs.map → chunk-A2N2GFCG.cjs.map} +1 -1
  48. package/dist/chunk-ADBA3XBE.cjs +20 -0
  49. package/dist/chunk-ADBA3XBE.cjs.map +1 -0
  50. package/dist/{chunk-MBNQVDVC.cjs → chunk-AMOJYLG2.cjs} +16 -10
  51. package/dist/chunk-AMOJYLG2.cjs.map +1 -0
  52. package/dist/{chunk-CLVQBF5C.cjs → chunk-AQNHHJMJ.cjs} +5 -5
  53. package/dist/{chunk-CLVQBF5C.cjs.map → chunk-AQNHHJMJ.cjs.map} +1 -1
  54. package/dist/{chunk-AHCLWAM5.cjs → chunk-BHTNFEGZ.cjs} +13 -13
  55. package/dist/chunk-BHTNFEGZ.cjs.map +1 -0
  56. package/dist/{chunk-62W2DYYA.cjs → chunk-E4NUZXVK.cjs} +58 -27
  57. package/dist/chunk-E4NUZXVK.cjs.map +1 -0
  58. package/dist/{chunk-LVLUHTRD.js → chunk-GLG5ZMX7.js} +54 -23
  59. package/dist/chunk-GLG5ZMX7.js.map +1 -0
  60. package/dist/{chunk-BVAR5J2F.js → chunk-GQCOSXMG.js} +117 -6
  61. package/dist/chunk-GQCOSXMG.js.map +1 -0
  62. package/dist/{chunk-QDMPOAI7.cjs → chunk-HDP7VK3C.cjs} +1118 -313
  63. package/dist/chunk-HDP7VK3C.cjs.map +1 -0
  64. package/dist/{chunk-GVWHCL2N.js → chunk-HMOISHXR.js} +217 -75
  65. package/dist/chunk-HMOISHXR.js.map +1 -0
  66. package/dist/{chunk-MTX2KVU7.cjs → chunk-HVQFNJKE.cjs} +122 -90
  67. package/dist/chunk-HVQFNJKE.cjs.map +1 -0
  68. package/dist/{chunk-OC6LTXYS.cjs → chunk-JMXUNXQS.cjs} +126 -7
  69. package/dist/chunk-JMXUNXQS.cjs.map +1 -0
  70. package/dist/{chunk-WWOLFXTX.cjs → chunk-KBSXGXPM.cjs} +10 -7
  71. package/dist/chunk-KBSXGXPM.cjs.map +1 -0
  72. package/dist/{chunk-YU2CUNFO.js → chunk-KV7UW6T6.js} +11 -5
  73. package/dist/chunk-KV7UW6T6.js.map +1 -0
  74. package/dist/{chunk-CCJPSHGI.cjs → chunk-N7FNVFXW.cjs} +4 -12
  75. package/dist/chunk-N7FNVFXW.cjs.map +1 -0
  76. package/dist/{chunk-CYFK5SY2.js → chunk-O3ANBHSA.js} +169 -39
  77. package/dist/chunk-O3ANBHSA.js.map +1 -0
  78. package/dist/{chunk-NZFKROS7.cjs → chunk-PA4VC73I.cjs} +130 -72
  79. package/dist/chunk-PA4VC73I.cjs.map +1 -0
  80. package/dist/{chunk-NJTXJ5AG.cjs → chunk-PFUESQTW.cjs} +18 -18
  81. package/dist/{chunk-NJTXJ5AG.cjs.map → chunk-PFUESQTW.cjs.map} +1 -1
  82. package/dist/{chunk-SFQWJMKT.js → chunk-QY25VWBF.js} +51 -12
  83. package/dist/chunk-QY25VWBF.js.map +1 -0
  84. package/dist/{chunk-WC5FFSHB.js → chunk-R3PY4G7J.js} +3 -3
  85. package/dist/{chunk-WC5FFSHB.js.map → chunk-R3PY4G7J.js.map} +1 -1
  86. package/dist/{chunk-M5E34VG5.js → chunk-SBUFNJVE.js} +3 -3
  87. package/dist/{chunk-M5E34VG5.js.map → chunk-SBUFNJVE.js.map} +1 -1
  88. package/dist/{chunk-UKPGSAZW.js → chunk-TMA4RCEN.js} +3 -3
  89. package/dist/{chunk-UKPGSAZW.js.map → chunk-TMA4RCEN.js.map} +1 -1
  90. package/dist/{chunk-FN2WMF2W.cjs → chunk-U5VAY32K.cjs} +215 -138
  91. package/dist/chunk-U5VAY32K.cjs.map +1 -0
  92. package/dist/{chunk-DUEZFTK2.js → chunk-UKQHXPGW.js} +4 -12
  93. package/dist/chunk-UKQHXPGW.js.map +1 -0
  94. package/dist/{chunk-4CVLFLOB.cjs → chunk-UM6BVY2S.cjs} +201 -69
  95. package/dist/chunk-UM6BVY2S.cjs.map +1 -0
  96. package/dist/{chunk-75JP4BZX.js → chunk-UQ3UIZJC.js} +3 -2
  97. package/dist/chunk-UQ3UIZJC.js.map +1 -0
  98. package/dist/{chunk-PCPX42KL.js → chunk-V4XG5QF6.js} +16 -10
  99. package/dist/chunk-V4XG5QF6.js.map +1 -0
  100. package/dist/{chunk-GPPLSM2Z.js → chunk-VB37OC6I.js} +6 -5
  101. package/dist/chunk-VB37OC6I.js.map +1 -0
  102. package/dist/{chunk-MVBEL57Q.js → chunk-Y7FT4IQT.js} +500 -170
  103. package/dist/chunk-Y7FT4IQT.js.map +1 -0
  104. package/dist/{chunk-OFXOTECC.js → chunk-YPPPYLSR.js} +7 -7
  105. package/dist/chunk-YPPPYLSR.js.map +1 -0
  106. package/dist/{chunk-M4F66R4O.cjs → chunk-YWQ6V4ZN.cjs} +121 -82
  107. package/dist/chunk-YWQ6V4ZN.cjs.map +1 -0
  108. package/dist/constants.cjs +5 -5
  109. package/dist/constants.d.cts +1 -1
  110. package/dist/constants.d.ts +1 -1
  111. package/dist/constants.js +2 -2
  112. package/dist/engine.cjs +31 -31
  113. package/dist/engine.d.cts +11 -11
  114. package/dist/engine.d.ts +11 -11
  115. package/dist/engine.js +21 -21
  116. package/dist/errors.cjs +19 -19
  117. package/dist/errors.d.cts +2 -2
  118. package/dist/errors.d.ts +2 -2
  119. package/dist/errors.js +1 -1
  120. package/dist/format.cjs +29 -22
  121. package/dist/format.cjs.map +1 -1
  122. package/dist/format.d.cts +1 -2
  123. package/dist/format.d.ts +1 -2
  124. package/dist/format.js +23 -16
  125. package/dist/format.js.map +1 -1
  126. package/dist/index.cjs +31 -31
  127. package/dist/index.d.cts +10 -10
  128. package/dist/index.d.ts +10 -10
  129. package/dist/index.js +22 -22
  130. package/dist/language.cjs +8 -8
  131. package/dist/language.cjs.map +1 -1
  132. package/dist/language.d.cts +10 -10
  133. package/dist/language.d.ts +10 -10
  134. package/dist/language.js +6 -6
  135. package/dist/language.js.map +1 -1
  136. package/dist/lexer.cjs +18 -18
  137. package/dist/lexer.d.cts +2 -2
  138. package/dist/lexer.d.ts +2 -2
  139. package/dist/lexer.js +6 -6
  140. package/dist/normalizer.cjs +12 -12
  141. package/dist/normalizer.js +6 -6
  142. package/dist/packages.cjs +39 -39
  143. package/dist/packages.d.cts +9 -9
  144. package/dist/packages.d.ts +9 -9
  145. package/dist/packages.js +16 -16
  146. package/dist/parser.cjs +15 -15
  147. package/dist/parser.d.cts +23 -9
  148. package/dist/parser.d.ts +23 -9
  149. package/dist/parser.js +5 -5
  150. package/dist/{pipeline-CrsRPmsv.d.ts → pipeline-B6k5lCB7.d.ts} +1 -1
  151. package/dist/{pipeline-DPUQt7yL.d.cts → pipeline-BEb3hujr.d.cts} +1 -1
  152. package/dist/resolvers.d.cts +2 -2
  153. package/dist/resolvers.d.ts +2 -2
  154. package/dist/uom.cjs +17 -17
  155. package/dist/uom.d.cts +2 -2
  156. package/dist/uom.d.ts +2 -2
  157. package/dist/uom.js +7 -7
  158. package/dist/utilities.cjs +8 -4
  159. package/dist/utilities.d.cts +19 -3
  160. package/dist/utilities.d.ts +19 -3
  161. package/dist/utilities.js +2 -2
  162. package/dist/vm.cjs +43 -31
  163. package/dist/vm.d.cts +105 -9
  164. package/dist/vm.d.ts +105 -9
  165. package/dist/vm.js +9 -9
  166. package/package.json +3 -3
  167. package/dist/chunk-2CS6OMZK.js.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-62W2DYYA.cjs.map +0 -1
  171. package/dist/chunk-6GCKCWLB.js.map +0 -1
  172. package/dist/chunk-6RDSQURE.js.map +0 -1
  173. package/dist/chunk-75JP4BZX.js.map +0 -1
  174. package/dist/chunk-AHCLWAM5.cjs.map +0 -1
  175. package/dist/chunk-BAMZT3GL.js.map +0 -1
  176. package/dist/chunk-BVAR5J2F.js.map +0 -1
  177. package/dist/chunk-BXKJLM5R.cjs.map +0 -1
  178. package/dist/chunk-CCJPSHGI.cjs.map +0 -1
  179. package/dist/chunk-CSG5XVNJ.cjs.map +0 -1
  180. package/dist/chunk-CYFK5SY2.js.map +0 -1
  181. package/dist/chunk-DUEZFTK2.js.map +0 -1
  182. package/dist/chunk-FN2WMF2W.cjs.map +0 -1
  183. package/dist/chunk-GPPLSM2Z.js.map +0 -1
  184. package/dist/chunk-GVWHCL2N.js.map +0 -1
  185. package/dist/chunk-LVLUHTRD.js.map +0 -1
  186. package/dist/chunk-M4F66R4O.cjs.map +0 -1
  187. package/dist/chunk-M4N5GA5Z.cjs.map +0 -1
  188. package/dist/chunk-MBNQVDVC.cjs.map +0 -1
  189. package/dist/chunk-MEOHSQEH.js.map +0 -1
  190. package/dist/chunk-MTX2KVU7.cjs.map +0 -1
  191. package/dist/chunk-MVBEL57Q.js.map +0 -1
  192. package/dist/chunk-MZOVP3WI.cjs.map +0 -1
  193. package/dist/chunk-N5YFR4UP.cjs +0 -10
  194. package/dist/chunk-N5YFR4UP.cjs.map +0 -1
  195. package/dist/chunk-NUR3K7EW.js.map +0 -1
  196. package/dist/chunk-NZFKROS7.cjs.map +0 -1
  197. package/dist/chunk-OC6LTXYS.cjs.map +0 -1
  198. package/dist/chunk-OFXOTECC.js.map +0 -1
  199. package/dist/chunk-PCPX42KL.js.map +0 -1
  200. package/dist/chunk-PFSDGGYL.js +0 -8
  201. package/dist/chunk-PFSDGGYL.js.map +0 -1
  202. package/dist/chunk-QDMPOAI7.cjs.map +0 -1
  203. package/dist/chunk-R24DI24X.cjs.map +0 -1
  204. package/dist/chunk-SFQWJMKT.js.map +0 -1
  205. package/dist/chunk-WWOLFXTX.cjs.map +0 -1
  206. package/dist/chunk-YU2CUNFO.js.map +0 -1
@@ -1,21 +1,21 @@
1
1
  'use strict';
2
2
 
3
- var chunkNZFKROS7_cjs = require('./chunk-NZFKROS7.cjs');
4
- var chunkAHCLWAM5_cjs = require('./chunk-AHCLWAM5.cjs');
5
- var chunkN5YFR4UP_cjs = require('./chunk-N5YFR4UP.cjs');
6
- var chunk4AVD7NZW_cjs = require('./chunk-4AVD7NZW.cjs');
3
+ var chunkPA4VC73I_cjs = require('./chunk-PA4VC73I.cjs');
4
+ var chunkBHTNFEGZ_cjs = require('./chunk-BHTNFEGZ.cjs');
5
+ var chunkADBA3XBE_cjs = require('./chunk-ADBA3XBE.cjs');
6
+ var chunk4B2CNWQU_cjs = require('./chunk-4B2CNWQU.cjs');
7
7
  var chunkZ2XP767T_cjs = require('./chunk-Z2XP767T.cjs');
8
- var chunkBXKJLM5R_cjs = require('./chunk-BXKJLM5R.cjs');
8
+ var chunk6WFMPTGB_cjs = require('./chunk-6WFMPTGB.cjs');
9
9
  var chunkVEKIWQ3F_cjs = require('./chunk-VEKIWQ3F.cjs');
10
- var chunk4CVLFLOB_cjs = require('./chunk-4CVLFLOB.cjs');
11
- var chunkOC6LTXYS_cjs = require('./chunk-OC6LTXYS.cjs');
12
- var chunkNJTXJ5AG_cjs = require('./chunk-NJTXJ5AG.cjs');
13
- var chunkM4F66R4O_cjs = require('./chunk-M4F66R4O.cjs');
14
- var chunkR24DI24X_cjs = require('./chunk-R24DI24X.cjs');
10
+ var chunkUM6BVY2S_cjs = require('./chunk-UM6BVY2S.cjs');
11
+ var chunkJMXUNXQS_cjs = require('./chunk-JMXUNXQS.cjs');
12
+ var chunkPFUESQTW_cjs = require('./chunk-PFUESQTW.cjs');
13
+ var chunkYWQ6V4ZN_cjs = require('./chunk-YWQ6V4ZN.cjs');
14
+ var chunk5LI5EPGJ_cjs = require('./chunk-5LI5EPGJ.cjs');
15
15
  var chunkOUHT5Z36_cjs = require('./chunk-OUHT5Z36.cjs');
16
- var chunkCLVQBF5C_cjs = require('./chunk-CLVQBF5C.cjs');
17
- var chunkMBNQVDVC_cjs = require('./chunk-MBNQVDVC.cjs');
18
- var chunkM4N5GA5Z_cjs = require('./chunk-M4N5GA5Z.cjs');
16
+ var chunkAQNHHJMJ_cjs = require('./chunk-AQNHHJMJ.cjs');
17
+ var chunkAMOJYLG2_cjs = require('./chunk-AMOJYLG2.cjs');
18
+ var chunk5KMIY374_cjs = require('./chunk-5KMIY374.cjs');
19
19
 
20
20
  // src/packages/arithmetic/parselets/NumberParselet.ts
21
21
  var CHAINED_DOT_THOUSANDS_GROUPS = /^\d{1,3}(\.\d{3}){2,}$/;
@@ -29,17 +29,17 @@ var NumberParselet = class {
29
29
  if (raw.startsWith("0x") || raw.startsWith("0X")) {
30
30
  v = parseInt(raw, 16);
31
31
  if (Number.isNaN(v)) {
32
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing("INVALID_NUMBER_LITERAL", `Invalid hex literal: "${raw}"`, { raw });
32
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing("INVALID_NUMBER_LITERAL", `Invalid hex literal: "${raw}"`, { raw });
33
33
  }
34
34
  } else if (raw.startsWith("0b") || raw.startsWith("0B")) {
35
35
  v = parseInt(raw.slice(2), 2);
36
36
  if (Number.isNaN(v)) {
37
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing("INVALID_NUMBER_LITERAL", `Invalid binary literal: "${raw}"`, { raw });
37
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing("INVALID_NUMBER_LITERAL", `Invalid binary literal: "${raw}"`, { raw });
38
38
  }
39
39
  } else if (raw.startsWith("0o") || raw.startsWith("0O")) {
40
40
  v = parseInt(raw.slice(2), 8);
41
41
  if (Number.isNaN(v)) {
42
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing("INVALID_NUMBER_LITERAL", `Invalid octal literal: "${raw}"`, { raw });
42
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing("INVALID_NUMBER_LITERAL", `Invalid octal literal: "${raw}"`, { raw });
43
43
  }
44
44
  } else if (CHAINED_DOT_THOUSANDS_GROUPS.test(raw)) {
45
45
  v = parseFloat(raw.split(".").join(""));
@@ -75,13 +75,14 @@ var PrefixOpParselet = class {
75
75
 
76
76
  // src/packages/arithmetic/parselets/BinaryOpParselet.ts
77
77
  var BinaryOpParselet = class {
78
- constructor(bp, opcode) {
78
+ constructor(bp, opcode, rightAssociative = false) {
79
79
  this.opcode = opcode;
80
80
  this.category = "Arithmetic";
81
81
  this.bindingPower = bp;
82
+ this.rightBindingPower = rightAssociative ? bp - 1 : bp;
82
83
  }
83
84
  parse(parser, left, token, builder) {
84
- parser.parseExpression(this.bindingPower, builder);
85
+ parser.parseExpression(this.rightBindingPower, builder);
85
86
  builder.emitOpcode(this.opcode);
86
87
  }
87
88
  };
@@ -164,12 +165,13 @@ function largeNumberSuffixNormalizerRule(priority = 65) {
164
165
  if (!suffixToken) return null;
165
166
  if (suffixToken.type !== "IDENT" && suffixToken.type !== "UNIT") return null;
166
167
  const adjacent = numberToken.offset + numberToken.text.length === suffixToken.offset;
167
- const magnitude = adjacent ? SUFFIX_MAGNITUDE[suffixToken.value] ?? WORD_MAGNITUDE[suffixToken.value.toLowerCase()] : WORD_MAGNITUDE[suffixToken.value.toLowerCase()];
168
+ const wordMagnitude = suffixToken.type === "UNIT" ? void 0 : WORD_MAGNITUDE[suffixToken.value.toLowerCase()];
169
+ const magnitude = adjacent ? SUFFIX_MAGNITUDE[suffixToken.value] ?? wordMagnitude : wordMagnitude;
168
170
  if (magnitude === void 0) return null;
169
171
  const scaled = scaleDecimalString(numberToken.text, magnitude);
170
172
  return {
171
173
  consumed: 2,
172
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("NUMBER", scaled, tokens.slice(pos, pos + 2))],
174
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("NUMBER", scaled, tokens.slice(pos, pos + 2))],
173
175
  ruleName: "arithmetic:large-number-suffix"
174
176
  };
175
177
  }
@@ -192,25 +194,35 @@ var ARITHMETIC_PACKAGE = {
192
194
  { tokenType: "BIT_NOT", parselet: new PrefixOpParselet(36 /* BIT_NOT */) }
193
195
  ],
194
196
  infixParselets: [
195
- { tokenType: "PLUS", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Sum, 20 /* ADD */) },
197
+ { tokenType: "PLUS", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Sum, 20 /* ADD */) },
196
198
  // The word "and", which adds exactly like "+" but at a looser binding
197
199
  // power so a phrase parselet can use it as a list separator. See
198
200
  // Token.ts's AND_CONJ comment for why it is not simply mapped to PLUS.
199
- { tokenType: "AND_CONJ", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Conjunction, 20 /* ADD */) },
200
- { tokenType: "MINUS", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Sum, 21 /* SUB */) },
201
- { tokenType: "STAR", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 22 /* MUL */) },
202
- { tokenType: "SLASH", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 23 /* DIV */) },
203
- { tokenType: "MOD", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 24 /* MOD */) },
204
- { tokenType: "CARET", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Exponent, 25 /* EXP */) },
205
- { tokenType: "TIMES_BY", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 22 /* MUL */) },
206
- { tokenType: "MULTIPLY_BY", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 22 /* MUL */) },
207
- { tokenType: "DIVIDE_BY", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 23 /* DIV */) },
208
- { tokenType: "LSHIFT", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Sum, 30 /* LSHIFT */) },
209
- { tokenType: "RSHIFT", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Sum, 31 /* RSHIFT */) },
210
- { tokenType: "URSHIFT", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Sum, 32 /* URSHIFT */) },
211
- { tokenType: "BIT_AND", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Product, 33 /* BIT_AND */) },
212
- { tokenType: "BIT_OR", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.Sum, 34 /* BIT_OR */) },
213
- { tokenType: "BIT_XOR", parselet: new BinaryOpParselet(chunkNZFKROS7_cjs.BindingPower.BitwiseXor, 35 /* BIT_XOR */) }
201
+ { tokenType: "AND_CONJ", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Conjunction, 20 /* ADD */) },
202
+ { tokenType: "MINUS", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Sum, 21 /* SUB */) },
203
+ { tokenType: "STAR", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Product, 22 /* MUL */) },
204
+ { tokenType: "SLASH", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Product, 23 /* DIV */) },
205
+ { tokenType: "MOD", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Product, 24 /* MOD */) },
206
+ // `^` is right-associative, so "2 ^ 3 ^ 2" is 2^(3^2) = 512. The Tier 1
207
+ // fast path in PrecedenceParser is what actually runs for `^`; this
208
+ // registration has to agree with it or the two tiers describe different
209
+ // languages.
210
+ { tokenType: "CARET", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Exponent, 25 /* EXP */, true) },
211
+ { tokenType: "TIMES_BY", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Product, 22 /* MUL */) },
212
+ { tokenType: "MULTIPLY_BY", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Product, 22 /* MUL */) },
213
+ { tokenType: "DIVIDE_BY", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Product, 23 /* DIV */) },
214
+ // The shifts and the bitwise trio, at the levels BindingPower gives them
215
+ // and therefore at C and JavaScript precedence. These six are declared
216
+ // twice, here and in BUILTIN_INFIX_BP, and only the Tier 1 numbers are
217
+ // ever read, so the levels must be the SAME names in both places. When
218
+ // they were not, the four that had a fast-path entry ran at one level
219
+ // while `>>>`, which had none, ran at another.
220
+ { tokenType: "LSHIFT", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Shift, 30 /* LSHIFT */) },
221
+ { tokenType: "RSHIFT", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Shift, 31 /* RSHIFT */) },
222
+ { tokenType: "URSHIFT", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.Shift, 32 /* URSHIFT */) },
223
+ { tokenType: "BIT_AND", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.BitwiseAnd, 33 /* BIT_AND */) },
224
+ { tokenType: "BIT_OR", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.BitwiseOr, 34 /* BIT_OR */) },
225
+ { tokenType: "BIT_XOR", parselet: new BinaryOpParselet(chunkPA4VC73I_cjs.BindingPower.BitwiseXor, 35 /* BIT_XOR */) }
214
226
  ],
215
227
  normalizerRules: [largeNumberSuffixNormalizerRule()]
216
228
  };
@@ -219,7 +231,7 @@ var ARITHMETIC_PACKAGE = {
219
231
  var PercentParselet = class {
220
232
  constructor() {
221
233
  this.category = "Percentage";
222
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Prefix;
234
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Prefix;
223
235
  }
224
236
  parse(parser, left, token, builder) {
225
237
  builder.emitOpcode(10 /* PUSH_NUMBER */);
@@ -235,7 +247,7 @@ var IsWhatParselet = class {
235
247
  this.category = "Percentage";
236
248
  // Below arithmetic, so the whole expression to the left is the value being
237
249
  // asked about: `10 + 10 is what % of 200` asks about 20.
238
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
250
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
239
251
  }
240
252
  parse(parser, _left, _token, builder) {
241
253
  if (nextWordIs(parser, "what")) {
@@ -250,7 +262,7 @@ var IsWhatParselet = class {
250
262
  */
251
263
  parseWhatRate(parser, builder) {
252
264
  if (!parser.match("PERCENT")) {
253
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
265
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
254
266
  "IS_WHAT_EXPECTED_PERCENT",
255
267
  'Expected "%" after "is what", as in "20 is what % of 200"'
256
268
  );
@@ -260,7 +272,7 @@ var IsWhatParselet = class {
260
272
  builder.emitOpcode(74 /* TO_PERCENTAGE */);
261
273
  return;
262
274
  }
263
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
275
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
264
276
  builder.emitOpcode(23 /* DIV */);
265
277
  if (preposition === "off") {
266
278
  builder.emitOpcode(10 /* PUSH_NUMBER */);
@@ -278,7 +290,7 @@ var IsWhatParselet = class {
278
290
  * `<part> is <rate> of|off|on what`, solving for the base.
279
291
  */
280
292
  parseWhatBase(parser, builder) {
281
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
293
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
282
294
  if (parser.match("TO")) {
283
295
  expectWord(parser, "what", '"81 is 9 to what power"');
284
296
  expectWord(parser, "power", '"81 is 9 to what power"');
@@ -295,7 +307,7 @@ var IsWhatParselet = class {
295
307
  }
296
308
  const preposition = parser.match("OF_WHAT") ? "of" : parser.match("OFF_WHAT") ? "off" : parser.match("ON_WHAT") ? "on" : null;
297
309
  if (preposition === null) {
298
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
310
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
299
311
  "IS_WHAT_EXPECTED_PREPOSITION",
300
312
  'Expected "of what", "off what" or "on what", as in "20 is 10% of what"'
301
313
  );
@@ -321,7 +333,7 @@ function nextWordIs(parser, word) {
321
333
  }
322
334
  function expectWord(parser, word, example) {
323
335
  if (!nextWordIs(parser, word)) {
324
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
336
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
325
337
  "IS_WHAT_EXPECTED_WORD",
326
338
  `Expected "${word}" here, as in ${example}`
327
339
  );
@@ -344,10 +356,10 @@ var OnOffBaseParselet = class {
344
356
  constructor(sign) {
345
357
  this.sign = sign;
346
358
  this.category = "Percentage";
347
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
359
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
348
360
  }
349
361
  parse(parser, _left, _token, builder) {
350
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
362
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
351
363
  builder.emitOpcode(2 /* SWAP */);
352
364
  builder.emitOpcode(10 /* PUSH_NUMBER */);
353
365
  builder.emitNumber(1);
@@ -378,7 +390,7 @@ function percentOnOffNormalizerRule(priority = 68) {
378
390
  consumed: 2,
379
391
  replacement: [
380
392
  tokens[pos],
381
- chunkAHCLWAM5_cjs.createFusedToken(text === "on" ? "PCT_ON" : "PCT_OFF", text, [word])
393
+ chunkBHTNFEGZ_cjs.createFusedToken(text === "on" ? "PCT_ON" : "PCT_OFF", text, [word])
382
394
  ],
383
395
  ruleName: "percentage:on-off"
384
396
  };
@@ -390,7 +402,7 @@ function percentOnOffNormalizerRule(priority = 68) {
390
402
  var OfParselet = class {
391
403
  constructor() {
392
404
  this.category = "Percentage";
393
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Product;
405
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Product;
394
406
  }
395
407
  parse(parser, left, token, builder) {
396
408
  parser.parseExpression(this.bindingPower, builder);
@@ -402,7 +414,7 @@ var OfParselet = class {
402
414
  var OfWhatIsParselet = class {
403
415
  constructor() {
404
416
  this.category = "Percentage";
405
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Product;
417
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Product;
406
418
  }
407
419
  parse(parser, left, token, builder) {
408
420
  parser.parseExpression(this.bindingPower, builder);
@@ -416,7 +428,7 @@ var OnOffWhatIsParselet = class {
416
428
  constructor(sign) {
417
429
  this.sign = sign;
418
430
  this.category = "Percentage";
419
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Product;
431
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Product;
420
432
  }
421
433
  parse(parser, left, token, builder) {
422
434
  builder.emitOpcode(10 /* PUSH_NUMBER */);
@@ -459,7 +471,7 @@ var IncreaseByParselet = class {
459
471
  constructor(multiplier) {
460
472
  this.multiplier = multiplier;
461
473
  this.category = "Percentage";
462
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
474
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
463
475
  }
464
476
  parse(parser, left, token, builder) {
465
477
  parser.parseExpression(this.bindingPower, builder);
@@ -475,14 +487,14 @@ var IncreaseByParselet = class {
475
487
  var PercentageChangeParselet = class {
476
488
  constructor() {
477
489
  this.category = "Percentage";
478
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
490
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
479
491
  }
480
492
  parse(parser, left, token, builder) {
481
493
  if (left.type === "UNIT") {
482
494
  return;
483
495
  }
484
496
  const nextToken = parser.peek();
485
- if (nextToken && ((nextToken.type === "UNIT" || nextToken.type === "IDENT") && chunkCLVQBF5C_cjs.isKnownUnit(nextToken.value) || nextToken.type === "IN")) {
497
+ if (nextToken && ((nextToken.type === "UNIT" || nextToken.type === "IDENT") && chunkAQNHHJMJ_cjs.isKnownUnit(nextToken.value) || nextToken.type === "IN")) {
486
498
  parser.consume();
487
499
  builder.emitOpcode(13 /* PUSH_STRING */);
488
500
  builder.emitString(nextToken.value);
@@ -644,7 +656,7 @@ var FunctionCallParselet = class {
644
656
  const fnName = token.value.toLowerCase();
645
657
  const fnIdx = builtinNameToIndex[fnName];
646
658
  if (fnIdx === void 0) {
647
- throw chunkM4N5GA5Z_cjs.ErrorFactory.execution(
659
+ throw chunk5KMIY374_cjs.ErrorFactory.execution(
648
660
  "UNKNOWN_FUNCTION",
649
661
  `Unknown function: ${fnName}`,
650
662
  { functionName: fnName }
@@ -653,10 +665,10 @@ var FunctionCallParselet = class {
653
665
  parser.consume("LPAREN");
654
666
  let argCount = 0;
655
667
  if (parser.peek()?.type !== "RPAREN") {
656
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
668
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
657
669
  argCount++;
658
670
  while (parser.match("COMMA")) {
659
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
671
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
660
672
  argCount++;
661
673
  }
662
674
  }
@@ -679,13 +691,16 @@ var FUNCTION_PACKAGE = {
679
691
  var NowParselet = class {
680
692
  constructor(dayOffset = 0) {
681
693
  this.category = "Date/Time";
682
- this.msOffset = dayOffset * 24 * 60 * 60 * 1e3;
694
+ this.dayOffset = dayOffset;
683
695
  }
684
696
  parse(parser, token, builder) {
685
697
  builder.emitOpcode(90 /* DATE_NOW */);
686
- if (this.msOffset !== 0) {
698
+ if (this.dayOffset !== 0) {
687
699
  builder.emitOpcode(10 /* PUSH_NUMBER */);
688
- builder.emitNumber(this.msOffset);
700
+ builder.emitNumber(this.dayOffset);
701
+ builder.emitOpcode(13 /* PUSH_STRING */);
702
+ builder.emitString("days");
703
+ builder.emitOpcode(80 /* UOM_CONVERT */);
689
704
  builder.emitOpcode(20 /* ADD */);
690
705
  }
691
706
  }
@@ -710,7 +725,7 @@ var NextLastParselet = class {
710
725
  const dayToken = parser.peek();
711
726
  const targetDay = dayToken ? WEEKDAY_TOKEN_INDEX[dayToken.type] : void 0;
712
727
  if (targetDay === void 0) {
713
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
728
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
714
729
  "MISSING_WEEKDAY",
715
730
  `"${token.value}" must be followed by a day of the week (e.g. "${token.value} Saturday")`,
716
731
  { keyword: token.value, actualType: dayToken?.type, actualValue: dayToken?.value }
@@ -779,34 +794,36 @@ function unixTimestampToEpochMs(n) {
779
794
  }
780
795
 
781
796
  // src/packages/datetime/parselets/DatetimeTimestampPluginFunctions.ts
782
- var WORKDAYS_IN_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
783
- var WEEKDAY_ON_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
784
- var TO_DATE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
785
- var TO_TIMESTAMP_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
786
- var MONTH_ON_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
787
- var WEEK_ON_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
788
- var IS_WEEKEND_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
789
- var IS_WORKDAY_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
790
- var SPAN_BETWEEN_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
797
+ var WORKDAYS_IN_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
798
+ var WEEKDAY_ON_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
799
+ var TO_DATE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
800
+ var TO_TIMESTAMP_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
801
+ var MONTH_ON_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
802
+ var WEEK_ON_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
803
+ var IS_WEEKEND_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
804
+ var IS_WORKDAY_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
805
+ var SPAN_BETWEEN_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
791
806
  function workdaysInDurationHandler(args) {
792
807
  const v = args[0];
793
808
  let totalDays;
794
809
  if (v.type === 6 /* Uom */ && v.unit) {
795
- const measure = chunkNJTXJ5AG_cjs.getMeasure(v.unit);
810
+ const measure = chunkPFUESQTW_cjs.getMeasure(v.unit);
796
811
  if (measure !== "time") {
797
- return chunkOC6LTXYS_cjs.errorValue(
812
+ return chunkJMXUNXQS_cjs.errorValue(
798
813
  "WORKDAYS_IN_EXPECTED_DURATION",
799
814
  `"workdays in" expects a time duration, got unit "${v.unit}"`
800
815
  );
801
816
  }
802
- totalDays = chunkNJTXJ5AG_cjs.convertUnit(v.toNumber(), v.unit, "day");
817
+ totalDays = chunkPFUESQTW_cjs.convertUnit(v.toNumber(), v.unit, "day");
803
818
  } else {
804
819
  totalDays = v.toNumber();
805
820
  }
806
- const fullWeeks = Math.floor(totalDays / 7);
807
- const remainderDays = totalDays - fullWeeks * 7;
808
- const workdays = fullWeeks * 5 + Math.min(remainderDays, 5);
809
- return chunkOC6LTXYS_cjs.numberValue(workdays);
821
+ const sign = totalDays < 0 ? -1 : 1;
822
+ const magnitudeDays = Math.abs(totalDays);
823
+ const fullWeeks = Math.floor(magnitudeDays / 7);
824
+ const remainderDays = magnitudeDays - fullWeeks * 7;
825
+ const workdays = sign * (fullWeeks * 5 + Math.min(remainderDays, 5));
826
+ return chunkJMXUNXQS_cjs.numberValue(workdays);
810
827
  }
811
828
  var WEEKDAY_NAMES = [
812
829
  "Sunday",
@@ -819,15 +836,15 @@ var WEEKDAY_NAMES = [
819
836
  ];
820
837
  function asEpochMs(value, fieldName) {
821
838
  if (value.type === 4 /* Datetime */) return value.toNumber();
822
- return chunkOC6LTXYS_cjs.errorValue(
839
+ return chunkJMXUNXQS_cjs.errorValue(
823
840
  "DATE_FIELD_EXPECTED_DATE",
824
- `"${fieldName}" expects a date, got ${chunkOC6LTXYS_cjs.ValueType[value.type] ?? "an unsupported value"}`
841
+ `"${fieldName}" expects a date, got ${chunkJMXUNXQS_cjs.ValueType[value.type] ?? "an unsupported value"}`
825
842
  );
826
843
  }
827
844
  function weekdayOnDateHandler(args) {
828
845
  const epochMs = asEpochMs(args[0], "weekday");
829
846
  if (typeof epochMs !== "number") return epochMs;
830
- return chunkOC6LTXYS_cjs.stringValue(WEEKDAY_NAMES[new Date(epochMs).getDay()]);
847
+ return chunkJMXUNXQS_cjs.stringValue(WEEKDAY_NAMES[new Date(epochMs).getDay()]);
831
848
  }
832
849
  var MONTH_NAMES = [
833
850
  "January",
@@ -846,7 +863,7 @@ var MONTH_NAMES = [
846
863
  function monthOnDateHandler(args) {
847
864
  const epochMs = asEpochMs(args[0], "month");
848
865
  if (typeof epochMs !== "number") return epochMs;
849
- return chunkOC6LTXYS_cjs.stringValue(MONTH_NAMES[new Date(epochMs).getMonth()]);
866
+ return chunkJMXUNXQS_cjs.stringValue(MONTH_NAMES[new Date(epochMs).getMonth()]);
850
867
  }
851
868
  function weekOnDateHandler(args) {
852
869
  const epochMs = asEpochMs(args[0], "week");
@@ -857,7 +874,7 @@ function weekOnDateHandler(args) {
857
874
  target.setUTCDate(target.getUTCDate() + 4 - isoDay);
858
875
  const yearStart = Date.UTC(target.getUTCFullYear(), 0, 1);
859
876
  const days = Math.floor((target.getTime() - yearStart) / 864e5);
860
- return chunkOC6LTXYS_cjs.numberValue(Math.floor(days / 7) + 1);
877
+ return chunkJMXUNXQS_cjs.numberValue(Math.floor(days / 7) + 1);
861
878
  }
862
879
  function isWeekendDate(epochMs) {
863
880
  const day = new Date(epochMs).getDay();
@@ -866,15 +883,15 @@ function isWeekendDate(epochMs) {
866
883
  function isWeekendOnDateHandler(args) {
867
884
  const epochMs = asEpochMs(args[0], "is a weekend");
868
885
  if (typeof epochMs !== "number") return epochMs;
869
- return chunkOC6LTXYS_cjs.boolValue(isWeekendDate(epochMs));
886
+ return chunkJMXUNXQS_cjs.boolValue(isWeekendDate(epochMs));
870
887
  }
871
888
  function isWorkdayOnDateHandler(args) {
872
889
  const epochMs = asEpochMs(args[0], "is a workday");
873
890
  if (typeof epochMs !== "number") return epochMs;
874
- return chunkOC6LTXYS_cjs.boolValue(!isWeekendDate(epochMs));
891
+ return chunkJMXUNXQS_cjs.boolValue(!isWeekendDate(epochMs));
875
892
  }
876
893
  function spanBetweenDatesHandler(args) {
877
- return chunkOC6LTXYS_cjs.uomValue(Math.abs(args[0].toNumber() - args[1].toNumber()), "ms");
894
+ return chunkJMXUNXQS_cjs.uomValue(Math.abs(args[0].toNumber() - args[1].toNumber()), "ms");
878
895
  }
879
896
  function toDateFromAnyHandler(args) {
880
897
  const v = args[0];
@@ -884,28 +901,28 @@ function toDateFromAnyHandler(args) {
884
901
  if (v.type === 3 /* String */) {
885
902
  const ms = parseIso8601(v.value);
886
903
  if (ms === null) {
887
- return chunkOC6LTXYS_cjs.errorValue(
904
+ return chunkJMXUNXQS_cjs.errorValue(
888
905
  "INVALID_ISO8601_STRING",
889
906
  `"${v.value}" is not a recognizable ISO8601 date/time string`
890
907
  );
891
908
  }
892
- return chunkOC6LTXYS_cjs.datetimeValue(ms);
909
+ return chunkJMXUNXQS_cjs.datetimeValue(ms);
893
910
  }
894
- return chunkOC6LTXYS_cjs.datetimeValue(unixTimestampToEpochMs(v.toNumber()));
911
+ return chunkJMXUNXQS_cjs.datetimeValue(unixTimestampToEpochMs(v.toNumber()));
895
912
  }
896
913
  function toTimestampFromAnyHandler(args) {
897
914
  const v = args[0];
898
915
  if (v.type === 3 /* String */) {
899
916
  const ms = parseIso8601(v.value);
900
917
  if (ms === null) {
901
- return chunkOC6LTXYS_cjs.errorValue(
918
+ return chunkJMXUNXQS_cjs.errorValue(
902
919
  "INVALID_ISO8601_STRING",
903
920
  `"${v.value}" is not a recognizable ISO8601 date/time string`
904
921
  );
905
922
  }
906
- return chunkOC6LTXYS_cjs.numberValue(Math.floor(ms / 1e3));
923
+ return chunkJMXUNXQS_cjs.numberValue(Math.floor(ms / 1e3));
907
924
  }
908
- return chunkOC6LTXYS_cjs.numberValue(Math.floor(v.toNumber() / 1e3));
925
+ return chunkJMXUNXQS_cjs.numberValue(Math.floor(v.toNumber() / 1e3));
909
926
  }
910
927
  var workdaysInDuration = workdaysInDurationHandler;
911
928
  var weekdayOnDate = weekdayOnDateHandler;
@@ -960,9 +977,9 @@ var DurationBetweenParselet = class {
960
977
  }
961
978
  parse(parser, token, builder) {
962
979
  const unit = token.value;
963
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
980
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
964
981
  parser.consume("AND_CONJ");
965
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
982
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
966
983
  builder.emitOpcode(50 /* CALL_PLUGIN */);
967
984
  builder.emitIndex(SPAN_BETWEEN_FN_IDX);
968
985
  builder.emitIndex(2);
@@ -977,7 +994,7 @@ var DayTypePredicateParselet = class {
977
994
  constructor(functionIndex) {
978
995
  this.functionIndex = functionIndex;
979
996
  this.category = "Date/Time";
980
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
997
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
981
998
  }
982
999
  parse(parser, left, token, builder) {
983
1000
  builder.emitOpcode(50 /* CALL_PLUGIN */);
@@ -1003,7 +1020,7 @@ var CurrentTimestampParselet = class {
1003
1020
  var ToDateParselet = class {
1004
1021
  constructor() {
1005
1022
  this.category = "Date/Time";
1006
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
1023
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
1007
1024
  }
1008
1025
  parse(parser, left, token, builder) {
1009
1026
  builder.emitOpcode(50 /* CALL_PLUGIN */);
@@ -1016,7 +1033,7 @@ var ToDateParselet = class {
1016
1033
  var ToTimestampParselet = class {
1017
1034
  constructor() {
1018
1035
  this.category = "Date/Time";
1019
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
1036
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
1020
1037
  }
1021
1038
  parse(parser, left, token, builder) {
1022
1039
  builder.emitOpcode(50 /* CALL_PLUGIN */);
@@ -1050,7 +1067,7 @@ function untilSinceNormalizerRule(priority = 60) {
1050
1067
  const fusedType = keywordToken.type === "UNTIL" ? "UNTIL_UNIT" : "SINCE_UNIT";
1051
1068
  return {
1052
1069
  consumed: 2,
1053
- replacement: [chunkAHCLWAM5_cjs.createFusedToken(fusedType, unitToken.value, [unitToken, keywordToken])],
1070
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken(fusedType, unitToken.value, [unitToken, keywordToken])],
1054
1071
  ruleName: `datetime:${keywordToken.type.toLowerCase()}`
1055
1072
  };
1056
1073
  }
@@ -1087,7 +1104,7 @@ function betweenUnitNormalizerRule(priority = 60) {
1087
1104
  }
1088
1105
  return {
1089
1106
  consumed: howManyLength + 2,
1090
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("BETWEEN_UNIT", unitToken.value, sources)],
1107
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("BETWEEN_UNIT", unitToken.value, sources)],
1091
1108
  ruleName: "datetime:between"
1092
1109
  };
1093
1110
  }
@@ -1108,7 +1125,7 @@ function workdayRateDenominatorNormalizerRule(priority = 70) {
1108
1125
  const syntheticOne = {
1109
1126
  ...unit,
1110
1127
  type: "NUMBER",
1111
- typeId: chunkR24DI24X_cjs.tokenTypeId("NUMBER"),
1128
+ typeId: chunk5LI5EPGJ_cjs.tokenTypeId("NUMBER"),
1112
1129
  value: "1",
1113
1130
  text: "1"
1114
1131
  };
@@ -1123,10 +1140,19 @@ function workdayRateDenominatorNormalizerRule(priority = 70) {
1123
1140
 
1124
1141
  // src/packages/datetime/normalizer/DateLiteralNormalizerRule.ts
1125
1142
  var DATETIME_LITERAL_TYPE = "DATETIME_LITERAL";
1126
- var DATETIME_LITERAL_TYPE_ID = chunkR24DI24X_cjs.tokenTypeId(DATETIME_LITERAL_TYPE);
1143
+ var DATETIME_LITERAL_TYPE_ID = chunk5LI5EPGJ_cjs.tokenTypeId(DATETIME_LITERAL_TYPE);
1127
1144
  var PLAIN_INTEGER = /^\d+$/;
1128
1145
  var DOT_DAY_MONTH = /^\d{1,2}\.\d{1,2}$/;
1129
1146
  var DOT_LEADING_YEAR = /^\.(\d{2}|\d{4})$/;
1147
+ var DAY_OR_MONTH = /^\d{1,2}$/;
1148
+ function writtenAsOneRun(tokens) {
1149
+ for (let i = 0; i < tokens.length - 1; i++) {
1150
+ const token = tokens[i];
1151
+ const end = token.sourceEnd ?? token.offset + token.text.length;
1152
+ if (end !== tokens[i + 1].offset) return false;
1153
+ }
1154
+ return true;
1155
+ }
1130
1156
  function resolveYear(digits) {
1131
1157
  if (digits.length === 4) return Number(digits);
1132
1158
  if (digits.length === 2) {
@@ -1143,7 +1169,7 @@ function buildDateToken(day, month, year, sourceTokens, ruleName) {
1143
1169
  }
1144
1170
  const first = sourceTokens[0];
1145
1171
  const text = sourceTokens.map((t) => t.value).join("");
1146
- const fusedToken = new chunkM4F66R4O_cjs.LexerToken(
1172
+ const fusedToken = new chunkYWQ6V4ZN_cjs.LexerToken(
1147
1173
  DATETIME_LITERAL_TYPE,
1148
1174
  DATETIME_LITERAL_TYPE_ID,
1149
1175
  String(date.getTime()),
@@ -1155,6 +1181,48 @@ function buildDateToken(day, month, year, sourceTokens, ruleName) {
1155
1181
  );
1156
1182
  return { consumed: sourceTokens.length, replacement: [fusedToken], ruleName };
1157
1183
  }
1184
+ var ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?/;
1185
+ var ISO_TOKEN_TYPES = /* @__PURE__ */ new Set(["NUMBER", "MINUS", "PLUS", "COLON", "IDENT"]);
1186
+ var ISO_MAX_TOKENS = 16;
1187
+ function fuseIsoTimestamp(tokens, pos, ruleName) {
1188
+ const first = tokens[pos];
1189
+ if (first.sourceEnd !== void 0) return null;
1190
+ let text = first.text;
1191
+ let runEnd = first.offset + first.text.length;
1192
+ const window = [first];
1193
+ for (let i = pos + 1; i < tokens.length && window.length < ISO_MAX_TOKENS; i++) {
1194
+ const next = tokens[i];
1195
+ if (next.sourceEnd !== void 0) break;
1196
+ if (next.offset !== runEnd || !ISO_TOKEN_TYPES.has(next.type)) break;
1197
+ text += next.text;
1198
+ runEnd = next.offset + next.text.length;
1199
+ window.push(next);
1200
+ }
1201
+ const matched = ISO_TIMESTAMP.exec(text);
1202
+ if (matched === null) return null;
1203
+ let consumed = 0;
1204
+ let covered = 0;
1205
+ for (const token of window) {
1206
+ covered += token.text.length;
1207
+ consumed++;
1208
+ if (covered >= matched[0].length) break;
1209
+ }
1210
+ if (covered !== matched[0].length) return null;
1211
+ const epochMs = parseIso8601(matched[0]);
1212
+ if (epochMs === null) return null;
1213
+ const fusedToken = new chunkYWQ6V4ZN_cjs.LexerToken(
1214
+ DATETIME_LITERAL_TYPE,
1215
+ DATETIME_LITERAL_TYPE_ID,
1216
+ String(epochMs),
1217
+ matched[0],
1218
+ first.offset,
1219
+ 0,
1220
+ first.line,
1221
+ first.col,
1222
+ first.offset + matched[0].length
1223
+ );
1224
+ return { consumed, replacement: [fusedToken], ruleName };
1225
+ }
1158
1226
  function dateLiteralNormalizerRule() {
1159
1227
  return {
1160
1228
  name: "datetime:date-literal",
@@ -1180,6 +1248,10 @@ function dateLiteralNormalizerRule() {
1180
1248
  }
1181
1249
  return null;
1182
1250
  }
1251
+ if (t0.value.length === 4 && PLAIN_INTEGER.test(t0.value)) {
1252
+ const timestamp = fuseIsoTimestamp(tokens, pos, "datetime:date-literal:iso-timestamp");
1253
+ if (timestamp) return timestamp;
1254
+ }
1183
1255
  if (!PLAIN_INTEGER.test(t0.value)) return null;
1184
1256
  const sep1 = tokens[pos + 1];
1185
1257
  if (!sep1 || sep1.type !== "SLASH" && sep1.type !== "MINUS") return null;
@@ -1190,14 +1262,18 @@ function dateLiteralNormalizerRule() {
1190
1262
  if (!sep2 || sep2.type !== sep1.type) return null;
1191
1263
  if (!t2 || t2.type !== "NUMBER" || !PLAIN_INTEGER.test(t2.value)) return null;
1192
1264
  const sourceTokens = [t0, sep1, t1, sep2, t2];
1265
+ if (!writtenAsOneRun(sourceTokens)) return null;
1193
1266
  if (sep1.type === "SLASH") {
1267
+ if (!DAY_OR_MONTH.test(t0.value) || !DAY_OR_MONTH.test(t1.value)) return null;
1194
1268
  const year2 = resolveYear(t2.value);
1195
1269
  if (year2 === null) return null;
1196
1270
  return buildDateToken(Number(t0.value), Number(t1.value), year2, sourceTokens, "datetime:date-literal:european");
1197
1271
  }
1198
1272
  if (t0.value.length === 4) {
1273
+ if (!DAY_OR_MONTH.test(t1.value) || !DAY_OR_MONTH.test(t2.value)) return null;
1199
1274
  return buildDateToken(Number(t2.value), Number(t1.value), Number(t0.value), sourceTokens, "datetime:date-literal:iso");
1200
1275
  }
1276
+ if (!DAY_OR_MONTH.test(t0.value) || !DAY_OR_MONTH.test(t1.value)) return null;
1201
1277
  const year = resolveYear(t2.value);
1202
1278
  if (year === null) return null;
1203
1279
  return buildDateToken(Number(t1.value), Number(t0.value), year, sourceTokens, "datetime:date-literal:us");
@@ -1327,7 +1403,7 @@ var DaysInPeriodParselet = class {
1327
1403
  }
1328
1404
  const year = this.readOptionalYear(parser);
1329
1405
  if (year !== null) return daysInYear(year);
1330
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
1406
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
1331
1407
  "DAYS_IN_EXPECTED_PERIOD",
1332
1408
  'Expected a month, quarter or year, as in "days in February 2020" or "days in Q3"'
1333
1409
  );
@@ -1393,7 +1469,7 @@ function daysInPeriodNormalizerRule(priority = 60) {
1393
1469
  if (!startsPeriod(tokens[pos + 2])) return null;
1394
1470
  return {
1395
1471
  consumed: 2,
1396
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("DAYS_IN_PERIOD", "days in", [days, tokens[pos + 1]])],
1472
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("DAYS_IN_PERIOD", "days in", [days, tokens[pos + 1]])],
1397
1473
  ruleName: "datetime:days-in-period"
1398
1474
  };
1399
1475
  }
@@ -1512,7 +1588,7 @@ var DATETIME_PACKAGE = {
1512
1588
  { index: SPAN_BETWEEN_FN_IDX, handler: spanBetweenDates }
1513
1589
  ],
1514
1590
  asConverters: {
1515
- iso8601: (value) => chunkOC6LTXYS_cjs.stringValue(formatIso8601Local(value.toNumber())),
1591
+ iso8601: (value) => chunkJMXUNXQS_cjs.stringValue(formatIso8601Local(value.toNumber())),
1516
1592
  // The same three fields the "what X is it" questions answer, in the
1517
1593
  // composable form: `next friday + 2 weeks as weekday`. Question phrases
1518
1594
  // only ever take a bare date expression, whereas `as` binds after a
@@ -1836,10 +1912,10 @@ function tryConsumeZoneReference(parser) {
1836
1912
  }
1837
1913
 
1838
1914
  // src/packages/time/parselets/TimezonePluginFunctions.ts
1839
- var ZONE_CONVERT_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
1840
- var TIME_IN_ZONE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
1841
- var DATE_IN_ZONE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
1842
- var TIME_DIFFERENCE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
1915
+ var ZONE_CONVERT_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
1916
+ var TIME_IN_ZONE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
1917
+ var DATE_IN_ZONE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
1918
+ var TIME_DIFFERENCE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
1843
1919
  function zoneConvertHandler(args) {
1844
1920
  const totalMinutes = args[0].toNumber();
1845
1921
  const sourceZoneRef = args[1].value;
@@ -1855,17 +1931,17 @@ function zoneConvertHandler(args) {
1855
1931
  );
1856
1932
  const time = formatTimeInZone(utcMs, targetZoneRef);
1857
1933
  const dayShift = dayShiftBetweenZones(utcMs, targetZoneRef, sourceZoneRef);
1858
- if (dayShift === 0) return chunkOC6LTXYS_cjs.stringValue(time);
1934
+ if (dayShift === 0) return chunkJMXUNXQS_cjs.stringValue(time);
1859
1935
  const sign = dayShift > 0 ? "+" : "";
1860
- return chunkOC6LTXYS_cjs.stringValue(`${time} (${sign}${dayShift} day${Math.abs(dayShift) === 1 ? "" : "s"})`);
1936
+ return chunkJMXUNXQS_cjs.stringValue(`${time} (${sign}${dayShift} day${Math.abs(dayShift) === 1 ? "" : "s"})`);
1861
1937
  }
1862
1938
  function timeInZoneHandler(args) {
1863
1939
  const zoneRef = args[0].value;
1864
- return chunkOC6LTXYS_cjs.stringValue(formatTimeInZone(Date.now(), zoneRef));
1940
+ return chunkJMXUNXQS_cjs.stringValue(formatTimeInZone(Date.now(), zoneRef));
1865
1941
  }
1866
1942
  function dateInZoneHandler(args) {
1867
1943
  const zoneRef = args[0].value;
1868
- return chunkOC6LTXYS_cjs.stringValue(formatDateInZone(Date.now(), zoneRef));
1944
+ return chunkJMXUNXQS_cjs.stringValue(formatDateInZone(Date.now(), zoneRef));
1869
1945
  }
1870
1946
  function timeDifferenceHandler(args) {
1871
1947
  const zoneRef1 = args[0].value;
@@ -1877,7 +1953,7 @@ function timeDifferenceHandler(args) {
1877
1953
  const offset2 = resolveOffsetMinutes(zoneRef2, now);
1878
1954
  const diff = offset2 - offset1;
1879
1955
  if (diff === 0) {
1880
- return chunkOC6LTXYS_cjs.stringValue(`${label2} and ${label1} currently share the same UTC offset`);
1956
+ return chunkJMXUNXQS_cjs.stringValue(`${label2} and ${label1} currently share the same UTC offset`);
1881
1957
  }
1882
1958
  const ahead = diff > 0 ? label2 : label1;
1883
1959
  const behind = diff > 0 ? label1 : label2;
@@ -1887,7 +1963,7 @@ function timeDifferenceHandler(args) {
1887
1963
  const parts = [];
1888
1964
  if (hours > 0) parts.push(`${hours} hour${hours === 1 ? "" : "s"}`);
1889
1965
  if (minutes > 0) parts.push(`${minutes} minute${minutes === 1 ? "" : "s"}`);
1890
- return chunkOC6LTXYS_cjs.stringValue(`${ahead} is ${parts.join(" ")} ahead of ${behind}`);
1966
+ return chunkJMXUNXQS_cjs.stringValue(`${ahead} is ${parts.join(" ")} ahead of ${behind}`);
1891
1967
  }
1892
1968
 
1893
1969
  // src/packages/time/parselets/ClockTimeParselet.ts
@@ -1900,7 +1976,7 @@ var ClockTimeParselet = class {
1900
1976
  const sourceZoneRef = tryConsumeZoneReference(parser);
1901
1977
  if (sourceZoneRef !== null) {
1902
1978
  if (parser.peek()?.type !== "IN") {
1903
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
1979
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
1904
1980
  "TIME_ZONE_EXPECTED_IN",
1905
1981
  `Expected "in <city>" after the zone name (e.g. "6pm Sydney in Chicago") but got ${parser.peek() ? `"${parser.peek().value}"` : "end of input"}`
1906
1982
  );
@@ -1908,7 +1984,7 @@ var ClockTimeParselet = class {
1908
1984
  parser.consume();
1909
1985
  const target = tryConsumeZoneReference(parser);
1910
1986
  if (target === null) {
1911
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
1987
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
1912
1988
  "TIME_ZONE_EXPECTED_TARGET",
1913
1989
  `Expected a city or zone name after "in" (e.g. "6pm Sydney in Chicago")`
1914
1990
  );
@@ -1983,7 +2059,7 @@ function timeOrDateInZoneParselet(pluginFnIdx) {
1983
2059
  parse(parser, token, builder) {
1984
2060
  const zone = tryConsumeZoneReference(parser);
1985
2061
  if (zone === null) {
1986
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2062
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
1987
2063
  "TIME_ZONE_EXPECTED_CITY",
1988
2064
  `Expected a city or zone name after "${token.value}" (e.g. "time in Paris")`
1989
2065
  );
@@ -2005,7 +2081,7 @@ var TimeDifferenceParselet = class {
2005
2081
  parse(parser, token, builder) {
2006
2082
  const zone1 = tryConsumeZoneReference(parser);
2007
2083
  if (zone1 === null) {
2008
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2084
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2009
2085
  "TIME_DIFFERENCE_EXPECTED_CITY",
2010
2086
  `Expected a city or zone name after "time difference between" (e.g. "time difference between Seattle and Moscow")`
2011
2087
  );
@@ -2013,7 +2089,7 @@ var TimeDifferenceParselet = class {
2013
2089
  parser.consume("AND_CONJ");
2014
2090
  const zone2 = tryConsumeZoneReference(parser);
2015
2091
  if (zone2 === null) {
2016
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2092
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2017
2093
  "TIME_DIFFERENCE_EXPECTED_SECOND_CITY",
2018
2094
  `Expected a second city or zone name after "and" (e.g. "time difference between Seattle and Moscow")`
2019
2095
  );
@@ -2041,7 +2117,7 @@ var VideoTimecodeParselet = class {
2041
2117
  const [hours, minutes, seconds, frames] = token.value.split(",").map(Number);
2042
2118
  const separator = parser.peek();
2043
2119
  if (!separator || separator.type !== "RATE_AT" && separator.type !== "AT") {
2044
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2120
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2045
2121
  "TIMECODE_EXPECTED_FPS",
2046
2122
  `A video timecode must specify a frame rate, e.g. "${token.value.split(",").join(":")} at 30 fps" or "... @ 30 fps"`
2047
2123
  );
@@ -2049,27 +2125,27 @@ var VideoTimecodeParselet = class {
2049
2125
  parser.consume();
2050
2126
  const fpsToken = parser.peek();
2051
2127
  if (!fpsToken || fpsToken.type !== "FPS_RATE") {
2052
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2128
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2053
2129
  "TIMECODE_EXPECTED_FPS",
2054
2130
  `Expected "<number> fps" after "${separator.value}" (e.g. "at 30 fps")`
2055
2131
  );
2056
2132
  }
2057
2133
  parser.consume();
2058
2134
  const fps = parseFloat(fpsToken.value);
2059
- const fpsWhole = Math.floor(fps);
2135
+ const fpsWhole = Math.round(fps);
2060
2136
  if (frames >= fpsWhole) {
2061
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2137
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2062
2138
  "TIMECODE_FRAME_OUT_OF_RANGE",
2063
2139
  `Frame number ${frames} is out of range for ${fps} fps (must be 0-${fpsWhole - 1})`
2064
2140
  );
2065
2141
  }
2066
- const totalFrames = Math.round((hours * 3600 + minutes * 60 + seconds) * fps) + frames;
2067
- let unit = chunkOC6LTXYS_cjs.timecodeUnit(fps);
2142
+ const totalFrames = (hours * 3600 + minutes * 60 + seconds) * fpsWhole + frames;
2143
+ let unit = chunkJMXUNXQS_cjs.timecodeUnit(fps);
2068
2144
  if (parser.peek()?.type === "IN") {
2069
2145
  parser.consume();
2070
2146
  const framesWord = parser.peek();
2071
2147
  if (!framesWord || framesWord.type !== "IDENT" || framesWord.value.toLowerCase() !== "frames") {
2072
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2148
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2073
2149
  "TIMECODE_EXPECTED_FRAMES",
2074
2150
  `Expected "frames" after "in" (e.g. "... in frames") but got ${framesWord ? `"${framesWord.value}"` : "end of input"}`
2075
2151
  );
@@ -2110,7 +2186,7 @@ var FrameCountParselet = class {
2110
2186
  parser.consume();
2111
2187
  const fpsToken = parser.peek();
2112
2188
  if (!fpsToken || fpsToken.type !== "FPS_RATE") {
2113
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2189
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2114
2190
  "TIMECODE_EXPECTED_FPS",
2115
2191
  `Expected "<number> fps" after "${separator.value}" (e.g. "@ 30 fps")`
2116
2192
  );
@@ -2149,7 +2225,7 @@ function clockTimeNormalizerRule(priority = 65) {
2149
2225
  name: "time:clock-time",
2150
2226
  priority,
2151
2227
  match(tokens, pos) {
2152
- if (chunkAHCLWAM5_cjs.isInsideRangeContext(tokens, pos)) return null;
2228
+ if (chunkBHTNFEGZ_cjs.isInsideRangeContext(tokens, pos)) return null;
2153
2229
  const hourToken = tokens[pos];
2154
2230
  if (hourToken.type !== "NUMBER") return null;
2155
2231
  const hour = parseInt(hourToken.value, 10);
@@ -2165,7 +2241,7 @@ function clockTimeNormalizerRule(priority = 65) {
2165
2241
  const consumed = hasAmPm ? 4 : 3;
2166
2242
  return {
2167
2243
  consumed,
2168
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("CLOCK_TIME", String(totalMinutes), tokens.slice(pos, pos + consumed))],
2244
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("CLOCK_TIME", String(totalMinutes), tokens.slice(pos, pos + consumed))],
2169
2245
  ruleName: "time:clock-time"
2170
2246
  };
2171
2247
  }
@@ -2175,7 +2251,7 @@ function clockTimeNormalizerRule(priority = 65) {
2175
2251
  if (totalMinutes === null) return null;
2176
2252
  return {
2177
2253
  consumed: 2,
2178
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("CLOCK_TIME", String(totalMinutes), tokens.slice(pos, pos + 2))],
2254
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("CLOCK_TIME", String(totalMinutes), tokens.slice(pos, pos + 2))],
2179
2255
  ruleName: "time:clock-time"
2180
2256
  };
2181
2257
  }
@@ -2198,7 +2274,7 @@ function clockTimeIntervalNormalizerRule(priority = 66) {
2198
2274
  if (end?.type !== "CLOCK_TIME") return null;
2199
2275
  return {
2200
2276
  consumed: 3,
2201
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("CLOCK_TIME_INTERVAL", `${start.value}:${end.value}`, tokens.slice(pos, pos + 3))],
2277
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("CLOCK_TIME_INTERVAL", `${start.value}:${end.value}`, tokens.slice(pos, pos + 3))],
2202
2278
  ruleName: "time:clock-time-interval"
2203
2279
  };
2204
2280
  }
@@ -2217,7 +2293,7 @@ function fpsRateNormalizerRule(priority = 65) {
2217
2293
  if (fpsToken?.type !== "IDENT" || fpsToken.value.toLowerCase() !== "fps") return null;
2218
2294
  return {
2219
2295
  consumed: 2,
2220
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("FPS_RATE", numberToken.value, tokens.slice(pos, pos + 2))],
2296
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("FPS_RATE", numberToken.value, tokens.slice(pos, pos + 2))],
2221
2297
  ruleName: "time:fps-rate"
2222
2298
  };
2223
2299
  }
@@ -2230,7 +2306,7 @@ function laptimeNormalizerRule(priority = 70) {
2230
2306
  name: "time:laptime",
2231
2307
  priority,
2232
2308
  match(tokens, pos) {
2233
- if (chunkAHCLWAM5_cjs.isInsideRangeContext(tokens, pos)) return null;
2309
+ if (chunkBHTNFEGZ_cjs.isInsideRangeContext(tokens, pos)) return null;
2234
2310
  const h = tokens[pos];
2235
2311
  const c1 = tokens[pos + 1];
2236
2312
  const m = tokens[pos + 2];
@@ -2249,7 +2325,7 @@ function laptimeNormalizerRule(priority = 70) {
2249
2325
  const totalSeconds = hours * 3600 + minutes * 60 + seconds;
2250
2326
  return {
2251
2327
  consumed: 5,
2252
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("LAPTIME", String(totalSeconds), tokens.slice(pos, pos + 5))],
2328
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("LAPTIME", String(totalSeconds), tokens.slice(pos, pos + 5))],
2253
2329
  ruleName: "time:laptime"
2254
2330
  };
2255
2331
  }
@@ -2262,7 +2338,7 @@ function videoTimecodeNormalizerRule(priority = 75) {
2262
2338
  name: "time:video-timecode",
2263
2339
  priority,
2264
2340
  match(tokens, pos) {
2265
- if (chunkAHCLWAM5_cjs.isInsideRangeContext(tokens, pos)) return null;
2341
+ if (chunkBHTNFEGZ_cjs.isInsideRangeContext(tokens, pos)) return null;
2266
2342
  const h = tokens[pos];
2267
2343
  const c1 = tokens[pos + 1];
2268
2344
  const m = tokens[pos + 2];
@@ -2288,7 +2364,7 @@ function videoTimecodeNormalizerRule(priority = 75) {
2288
2364
  return {
2289
2365
  consumed: 7,
2290
2366
  replacement: [
2291
- chunkAHCLWAM5_cjs.createFusedToken("VIDEO_TIMECODE", `${hours},${minutes},${seconds},${frames}`, tokens.slice(pos, pos + 7))
2367
+ chunkBHTNFEGZ_cjs.createFusedToken("VIDEO_TIMECODE", `${hours},${minutes},${seconds},${frames}`, tokens.slice(pos, pos + 7))
2292
2368
  ],
2293
2369
  ruleName: "time:video-timecode"
2294
2370
  };
@@ -2308,7 +2384,7 @@ function frameCountNormalizerRule(priority = 65) {
2308
2384
  if (framesToken?.type !== "IDENT" || framesToken.value.toLowerCase() !== "frames") return null;
2309
2385
  return {
2310
2386
  consumed: 2,
2311
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("FRAME_COUNT", numberToken.value, tokens.slice(pos, pos + 2))],
2387
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("FRAME_COUNT", numberToken.value, tokens.slice(pos, pos + 2))],
2312
2388
  ruleName: "time:frame-count"
2313
2389
  };
2314
2390
  }
@@ -2327,14 +2403,14 @@ var TIMESPAN_PARTS = [
2327
2403
  function durationSeconds(value) {
2328
2404
  if (value.type === 0 /* Number */) return value.toNumber();
2329
2405
  if (value.type !== 6 /* Uom */ || value.unit === void 0) return null;
2330
- const entry = chunkMBNQVDVC_cjs.UNIT_TABLE[value.unit.toLowerCase()];
2406
+ const entry = chunkAMOJYLG2_cjs.UNIT_TABLE[value.unit.toLowerCase()];
2331
2407
  if (entry === void 0 || entry[0] !== TIME_KIND) return null;
2332
2408
  return value.toNumber() * entry[1];
2333
2409
  }
2334
2410
  function toTimespanString(value) {
2335
2411
  const total = durationSeconds(value);
2336
2412
  if (total === null) {
2337
- return chunkOC6LTXYS_cjs.stringValue(`"as timespan" needs a duration, got ${value.unit ?? "a non-duration"}`);
2413
+ return chunkJMXUNXQS_cjs.stringValue(`"as timespan" needs a duration, got ${value.unit ?? "a non-duration"}`);
2338
2414
  }
2339
2415
  const negative = total < 0;
2340
2416
  let remaining = Math.abs(total);
@@ -2351,12 +2427,12 @@ function toTimespanString(value) {
2351
2427
  if (secondsLeft > 0 || parts.length === 0) {
2352
2428
  parts.push(`${secondsLeft} ${secondsLeft === 1 ? "second" : "seconds"}`);
2353
2429
  }
2354
- return chunkOC6LTXYS_cjs.stringValue((negative ? "-" : "") + parts.join(" "));
2430
+ return chunkJMXUNXQS_cjs.stringValue((negative ? "-" : "") + parts.join(" "));
2355
2431
  }
2356
2432
  function toLaptimeString(value) {
2357
2433
  const total = durationSeconds(value);
2358
2434
  if (total === null) {
2359
- return chunkOC6LTXYS_cjs.stringValue(`"as laptime" needs a duration, got ${value.unit ?? "a non-duration"}`);
2435
+ return chunkJMXUNXQS_cjs.stringValue(`"as laptime" needs a duration, got ${value.unit ?? "a non-duration"}`);
2360
2436
  }
2361
2437
  const negative = total < 0;
2362
2438
  const rounded = Math.round(Math.abs(total) * 1e3) / 1e3;
@@ -2366,7 +2442,7 @@ function toLaptimeString(value) {
2366
2442
  const whole = Math.floor(seconds);
2367
2443
  const fraction = Math.round((seconds - whole) * 1e3);
2368
2444
  const base = `${pad(hours)}:${pad(minutes)}:${pad(whole)}`;
2369
- return chunkOC6LTXYS_cjs.stringValue((negative ? "-" : "") + (fraction > 0 ? `${base}.${String(fraction).padStart(3, "0")}` : base));
2445
+ return chunkJMXUNXQS_cjs.stringValue((negative ? "-" : "") + (fraction > 0 ? `${base}.${String(fraction).padStart(3, "0")}` : base));
2370
2446
  }
2371
2447
  function pad(n) {
2372
2448
  return n < 10 ? `0${n}` : String(n);
@@ -2419,7 +2495,7 @@ function definePhrasePattern(opts) {
2419
2495
  for (const alt of opts.alternatives) {
2420
2496
  const first = alt.slots[0];
2421
2497
  if (!first || first.kind !== "keyword") {
2422
- throw chunkM4N5GA5Z_cjs.ErrorFactory.config(
2498
+ throw chunk5KMIY374_cjs.ErrorFactory.config(
2423
2499
  "INVALID_PHRASE_PATTERN",
2424
2500
  "Every PhraseAlternative's first slot must be a `keyword` slot \u2014 alternatives are chosen by peeking the next token, which only works if the choice is decidable from one leading keyword.",
2425
2501
  { category: opts.category }
@@ -2436,7 +2512,7 @@ function definePhrasePattern(opts) {
2436
2512
  });
2437
2513
  if (!alternative) {
2438
2514
  const expected = opts.alternatives.map((alt) => alt.slots[0].tokenTypes.join("|")).join(", ");
2439
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2515
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2440
2516
  "NO_MATCHING_PHRASE_ALTERNATIVE",
2441
2517
  `Expected one of [${expected}] but got "${next?.type ?? "end of input"}" ("${next?.value ?? ""}")`,
2442
2518
  { category: opts.category, expected, actualType: next?.type, actualValue: next?.value }
@@ -2447,7 +2523,7 @@ function definePhrasePattern(opts) {
2447
2523
  if (slot.kind === "keyword") {
2448
2524
  const token = parser.peek();
2449
2525
  if (!token || !slot.tokenTypes.includes(token.type)) {
2450
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2526
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2451
2527
  "PHRASE_KEYWORD_MISMATCH",
2452
2528
  `Expected one of [${slot.tokenTypes.join("|")}] but got "${token?.type ?? "end of input"}" ("${token?.value ?? ""}")`,
2453
2529
  { category: opts.category, expected: slot.tokenTypes, actualType: token?.type, actualValue: token?.value }
@@ -2477,7 +2553,7 @@ var keywordLedRollPattern = definePhrasePattern({
2477
2553
  {
2478
2554
  slots: [
2479
2555
  { kind: "keyword", tokenTypes: ["BETWEEN"] },
2480
- { kind: "expr", bindingPower: chunkNZFKROS7_cjs.BindingPower.Product },
2556
+ { kind: "expr", bindingPower: chunkPA4VC73I_cjs.BindingPower.Product },
2481
2557
  // The word "and" lexes as PLUS, not a dedicated AND token, en.ts's
2482
2558
  // keywordMap maps `and: "PLUS"` (a synonym for arithmetic "+").
2483
2559
  // The original hand-written parselet never actually checked the
@@ -2492,7 +2568,7 @@ var keywordLedRollPattern = definePhrasePattern({
2492
2568
  {
2493
2569
  slots: [
2494
2570
  { kind: "keyword", tokenTypes: ["FROM"] },
2495
- { kind: "expr", bindingPower: chunkNZFKROS7_cjs.BindingPower.Product },
2571
+ { kind: "expr", bindingPower: chunkPA4VC73I_cjs.BindingPower.Product },
2496
2572
  { kind: "keyword", tokenTypes: ["TO"] },
2497
2573
  { kind: "expr" }
2498
2574
  ],
@@ -2547,7 +2623,7 @@ var VariableParselet = class {
2547
2623
  parse(parser, _token, builder) {
2548
2624
  const nameToken = parser.consume();
2549
2625
  if (nameToken.type !== "IDENT" && nameToken.type !== "UNIT") {
2550
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2626
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2551
2627
  "EXPECTED_IDENTIFIER",
2552
2628
  `Expected identifier or unit after colon, got ${nameToken.type}`,
2553
2629
  { tokenType: nameToken.type }
@@ -2586,7 +2662,7 @@ var GlobalVariableParselet = class {
2586
2662
  parser.consume("COLON");
2587
2663
  const nameToken = parser.consume();
2588
2664
  if (nameToken.type !== "IDENT" && nameToken.type !== "UNIT") {
2589
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
2665
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
2590
2666
  "EXPECTED_IDENTIFIER",
2591
2667
  `Expected identifier after 'global :', got ${nameToken.type}`,
2592
2668
  { tokenType: nameToken.type }
@@ -2636,11 +2712,11 @@ var GlobalVariableAsyncResolver = class {
2636
2712
  const op = opcodes[i];
2637
2713
  if (op === 62 /* LOAD_GLOBAL_VAR */) {
2638
2714
  const varName = strings[opcodes[i + 1]];
2639
- if (!chunkBXKJLM5R_cjs.sharedGlobalVariableStore.has(varName)) {
2715
+ if (!chunk6WFMPTGB_cjs.sharedGlobalVariableStore.has(varName)) {
2640
2716
  return this.pendingResultFor(varName, packageId, signal);
2641
2717
  }
2642
2718
  }
2643
- i = chunk4AVD7NZW_cjs.nextInstruction(opcodes, i);
2719
+ i = chunk4B2CNWQU_cjs.nextInstruction(opcodes, i);
2644
2720
  }
2645
2721
  return null;
2646
2722
  }
@@ -2648,7 +2724,7 @@ var GlobalVariableAsyncResolver = class {
2648
2724
  let resolver = this.pending.get(varName);
2649
2725
  if (!resolver) {
2650
2726
  resolver = new Promise((resolve) => {
2651
- const unsubscribe = chunkBXKJLM5R_cjs.sharedGlobalVariableStore.subscribe((name, value) => {
2727
+ const unsubscribe = chunk6WFMPTGB_cjs.sharedGlobalVariableStore.subscribe((name, value) => {
2652
2728
  if (name !== varName) return;
2653
2729
  unsubscribe();
2654
2730
  this.pending.delete(varName);
@@ -2695,12 +2771,12 @@ var VARIABLES_PACKAGE = {
2695
2771
 
2696
2772
  // src/packages/uom/parselets/UomLiteralParselet.ts
2697
2773
  function resolveUnitAlias(rawUnit) {
2698
- return chunk4CVLFLOB_cjs.resolveCurrencyAlias(rawUnit) ?? rawUnit;
2774
+ return chunkUM6BVY2S_cjs.resolveCurrencyAlias(rawUnit) ?? rawUnit;
2699
2775
  }
2700
2776
  var UomLiteralParselet = class {
2701
2777
  constructor() {
2702
2778
  this.category = "UoM";
2703
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Postfix;
2779
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Postfix;
2704
2780
  }
2705
2781
  parse(parser, left, token, builder) {
2706
2782
  const unit = resolveUnitAlias(token.value);
@@ -2733,14 +2809,14 @@ var UomLiteralParselet = class {
2733
2809
 
2734
2810
  // src/packages/uom/parselets/ConvertParselet.ts
2735
2811
  function resolveUnitAlias2(rawUnit) {
2736
- return chunk4CVLFLOB_cjs.resolveCurrencyAlias(rawUnit) ?? rawUnit;
2812
+ return chunkUM6BVY2S_cjs.resolveCurrencyAlias(rawUnit) ?? rawUnit;
2737
2813
  }
2738
2814
  var ConvertParselet = class {
2739
2815
  constructor() {
2740
2816
  this.category = "UoM";
2741
2817
  }
2742
2818
  parse(parser, token, builder) {
2743
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Postfix, builder);
2819
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Postfix, builder);
2744
2820
  const nextToken = parser.peek();
2745
2821
  if (nextToken && nextToken.type === "UNIT") {
2746
2822
  parser.consume();
@@ -2805,7 +2881,7 @@ function uomPossibilitiesNormalizerRule(priority = 60) {
2805
2881
  if (questionToken.type !== "QUESTION") return null;
2806
2882
  return {
2807
2883
  consumed: 3,
2808
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("UOM_POSSIBILITIES_QUERY", unitToken.value, [unitToken, toToken, questionToken])],
2884
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("UOM_POSSIBILITIES_QUERY", unitToken.value, [unitToken, toToken, questionToken])],
2809
2885
  ruleName: "uom:possibilities"
2810
2886
  };
2811
2887
  }
@@ -2820,7 +2896,7 @@ function unitEntry(token, previousKind) {
2820
2896
  if (spelling === "m" && previousKind === TIME_KIND2) {
2821
2897
  return { kind: TIME_KIND2, ratio: 60, spelling: "minutes" };
2822
2898
  }
2823
- const entry = chunkMBNQVDVC_cjs.UNIT_TABLE[spelling];
2899
+ const entry = chunkAMOJYLG2_cjs.UNIT_TABLE[spelling];
2824
2900
  return entry === void 0 ? void 0 : { kind: entry[0], ratio: entry[1], spelling };
2825
2901
  }
2826
2902
  var PLAIN_NUMBER = /^\d+(\.\d+)?$/;
@@ -2857,8 +2933,8 @@ function compoundQuantityNormalizerRule(priority = 63) {
2857
2933
  return {
2858
2934
  consumed,
2859
2935
  replacement: [
2860
- chunkAHCLWAM5_cjs.createFusedToken("NUMBER", String(scaled), source),
2861
- chunkAHCLWAM5_cjs.createFusedToken("UNIT", smallestUnit, [smallestUnitToken])
2936
+ chunkBHTNFEGZ_cjs.createFusedToken("NUMBER", String(scaled), source),
2937
+ chunkBHTNFEGZ_cjs.createFusedToken("UNIT", smallestUnit, [smallestUnitToken])
2862
2938
  ],
2863
2939
  ruleName: "uom:compound-quantity"
2864
2940
  };
@@ -2869,7 +2945,7 @@ function compoundQuantityNormalizerRule(priority = 63) {
2869
2945
  // src/packages/uom/normalizer/TwoUnitConversionNormalizerRule.ts
2870
2946
  function isUnit(token) {
2871
2947
  if (token === void 0 || token.type !== "UNIT") return false;
2872
- return chunkMBNQVDVC_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
2948
+ return chunkAMOJYLG2_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
2873
2949
  }
2874
2950
  function twoUnitConversionNormalizerRule(priority = 59) {
2875
2951
  return {
@@ -2886,7 +2962,7 @@ function twoUnitConversionNormalizerRule(priority = 59) {
2886
2962
  return {
2887
2963
  consumed: 4,
2888
2964
  replacement: [
2889
- chunkAHCLWAM5_cjs.createFusedToken("IN_TWO_UNITS", `${major} ${minor}`, tokens.slice(pos, pos + 4))
2965
+ chunkBHTNFEGZ_cjs.createFusedToken("IN_TWO_UNITS", `${major} ${minor}`, tokens.slice(pos, pos + 4))
2890
2966
  ],
2891
2967
  ruleName: "uom:two-unit-conversion"
2892
2968
  };
@@ -2907,7 +2983,7 @@ function degreeSymbolNormalizerRule(priority = 74) {
2907
2983
  if ((symbol.text ?? symbol.value ?? "") !== "\xB0") return null;
2908
2984
  return {
2909
2985
  consumed: 2,
2910
- replacement: [number, chunkAHCLWAM5_cjs.createFusedToken("UNIT", "degrees", [symbol])],
2986
+ replacement: [number, chunkBHTNFEGZ_cjs.createFusedToken("UNIT", "degrees", [symbol])],
2911
2987
  ruleName: "uom:degree-symbol"
2912
2988
  };
2913
2989
  }
@@ -2919,7 +2995,7 @@ var TwoUnitConversionParselet = class {
2919
2995
  constructor(builtinIndex) {
2920
2996
  this.builtinIndex = builtinIndex;
2921
2997
  this.category = "Uom";
2922
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
2998
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
2923
2999
  }
2924
3000
  parse(_parser, _left, token, builder) {
2925
3001
  const [major, minor] = String(token.value).split(" ");
@@ -2936,14 +3012,14 @@ var TwoUnitConversionParselet = class {
2936
3012
  // src/packages/uom/normalizer/BareRateDenominatorNormalizerRule.ts
2937
3013
  function isUnit2(token) {
2938
3014
  if (token === void 0 || token.type !== "UNIT") return false;
2939
- return chunkMBNQVDVC_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3015
+ return chunkAMOJYLG2_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
2940
3016
  }
2941
3017
  var PER_WORDS = /* @__PURE__ */ new Set(["per", "a", "an", "each", "every"]);
2942
3018
  function isCountLabel(token) {
2943
3019
  if (token === void 0 || token.type !== "IDENT") return false;
2944
3020
  const word = (token.text ?? token.value ?? "").toLowerCase();
2945
3021
  if (PER_WORDS.has(word)) return false;
2946
- return /^[a-z][a-z_]{2,}$/.test(word) && chunkMBNQVDVC_cjs.UNIT_TABLE[word] === void 0;
3022
+ return /^[a-z][a-z_]{2,}$/.test(word) && chunkAMOJYLG2_cjs.UNIT_TABLE[word] === void 0;
2947
3023
  }
2948
3024
  function bareRateDenominatorNormalizerRule(priority = 75) {
2949
3025
  return {
@@ -2959,7 +3035,7 @@ function bareRateDenominatorNormalizerRule(priority = 75) {
2959
3035
  if (introduces && isUnit2(tokens[pos + 3])) {
2960
3036
  return {
2961
3037
  consumed: 2,
2962
- replacement: [head, chunkAHCLWAM5_cjs.createFusedToken("UNIT", label.value, [label])],
3038
+ replacement: [head, chunkBHTNFEGZ_cjs.createFusedToken("UNIT", label.value, [label])],
2963
3039
  ruleName: "uom:bare-rate-denominator"
2964
3040
  };
2965
3041
  }
@@ -2973,7 +3049,7 @@ function bareRateDenominatorNormalizerRule(priority = 75) {
2973
3049
  return {
2974
3050
  consumed: 2,
2975
3051
  replacement: [
2976
- chunkAHCLWAM5_cjs.createFusedToken("PER_UNIT", unitToken.value, [head, unitToken])
3052
+ chunkBHTNFEGZ_cjs.createFusedToken("PER_UNIT", unitToken.value, [head, unitToken])
2977
3053
  ],
2978
3054
  ruleName: "uom:bare-rate-denominator"
2979
3055
  };
@@ -2986,7 +3062,7 @@ var PerUnitParselet = class {
2986
3062
  constructor(builtinIndex) {
2987
3063
  this.builtinIndex = builtinIndex;
2988
3064
  this.category = "Uom";
2989
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Product;
3065
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Product;
2990
3066
  }
2991
3067
  parse(_parser, _left, token, builder) {
2992
3068
  builder.emitOpcode(13 /* PUSH_STRING */);
@@ -3002,10 +3078,10 @@ var AtRateParselet = class {
3002
3078
  constructor(builtinIndex) {
3003
3079
  this.builtinIndex = builtinIndex;
3004
3080
  this.category = "Uom";
3005
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Product;
3081
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Product;
3006
3082
  }
3007
3083
  parse(parser, _left, _token, builder) {
3008
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
3084
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
3009
3085
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3010
3086
  builder.emitIndex(this.builtinIndex);
3011
3087
  builder.emitIndex(2);
@@ -3015,7 +3091,7 @@ var AtRateParselet = class {
3015
3091
  // src/packages/uom/normalizer/AtRateNormalizerRule.ts
3016
3092
  function isUnit3(token) {
3017
3093
  if (token === void 0 || token.type !== "UNIT") return false;
3018
- return chunkMBNQVDVC_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3094
+ return chunkAMOJYLG2_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3019
3095
  }
3020
3096
  var PER_WORDS2 = /* @__PURE__ */ new Set(["per", "a", "an", "each", "every"]);
3021
3097
  function hasRateAhead(tokens, from) {
@@ -3038,7 +3114,7 @@ function atRateNormalizerRule(priority = 73) {
3038
3114
  if (!hasRateAhead(tokens, pos + 1)) return null;
3039
3115
  return {
3040
3116
  consumed: 1,
3041
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("AT_RATE", "at", [tokens[pos]])],
3117
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("AT_RATE", "at", [tokens[pos]])],
3042
3118
  ruleName: "uom:at-rate"
3043
3119
  };
3044
3120
  }
@@ -3048,7 +3124,7 @@ function atRateNormalizerRule(priority = 73) {
3048
3124
  // src/packages/uom/normalizer/ForDurationNormalizerRule.ts
3049
3125
  function isUnit4(token) {
3050
3126
  if (token === void 0 || token.type !== "UNIT") return false;
3051
- return chunkMBNQVDVC_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3127
+ return chunkAMOJYLG2_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3052
3128
  }
3053
3129
  var ARTICLES = /* @__PURE__ */ new Set(["a", "an"]);
3054
3130
  function forDurationNormalizerRule(priority = 76) {
@@ -3065,8 +3141,8 @@ function forDurationNormalizerRule(priority = 76) {
3065
3141
  return {
3066
3142
  consumed: 3,
3067
3143
  replacement: [
3068
- chunkAHCLWAM5_cjs.createFusedToken("STAR", "*", [head]),
3069
- chunkAHCLWAM5_cjs.createFusedToken("NUMBER", "1", [article]),
3144
+ chunkBHTNFEGZ_cjs.createFusedToken("STAR", "*", [head]),
3145
+ chunkBHTNFEGZ_cjs.createFusedToken("NUMBER", "1", [article]),
3070
3146
  tokens[pos + 2]
3071
3147
  ],
3072
3148
  ruleName: "uom:for-duration"
@@ -3078,7 +3154,7 @@ function forDurationNormalizerRule(priority = 76) {
3078
3154
  // src/packages/uom/normalizer/ReversedConversionNormalizerRule.ts
3079
3155
  function isUnit5(token) {
3080
3156
  if (token === void 0 || token.type !== "UNIT") return false;
3081
- return chunkMBNQVDVC_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3157
+ return chunkAMOJYLG2_cjs.UNIT_TABLE[(token.value ?? "").toLowerCase()] !== void 0;
3082
3158
  }
3083
3159
  var ARTICLES2 = /* @__PURE__ */ new Set(["a", "an"]);
3084
3160
  function reversedConversionNormalizerRule(priority = 61) {
@@ -3103,7 +3179,7 @@ function reversedConversionNormalizerRule(priority = 61) {
3103
3179
  return {
3104
3180
  consumed: 4,
3105
3181
  replacement: [
3106
- chunkAHCLWAM5_cjs.createFusedToken("NUMBER", "1", [third]),
3182
+ chunkBHTNFEGZ_cjs.createFusedToken("NUMBER", "1", [third]),
3107
3183
  tokens[pos + 3],
3108
3184
  tokens[pos + 1],
3109
3185
  target
@@ -3212,54 +3288,54 @@ function getIngredientDensity(name) {
3212
3288
  }
3213
3289
 
3214
3290
  // src/packages/uom/parselets/CookingPluginFunctions.ts
3215
- var COOKING_CONVERT_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
3291
+ var COOKING_CONVERT_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
3216
3292
  function cookingConvertHandler(args) {
3217
3293
  const amountValue = args[0];
3218
3294
  const ingredientName = args[1].value;
3219
3295
  const targetUnitText = args[2].value;
3220
3296
  if (amountValue.type !== 6 /* Uom */ || !amountValue.unit) {
3221
- return chunkOC6LTXYS_cjs.errorValue(
3297
+ return chunkJMXUNXQS_cjs.errorValue(
3222
3298
  "COOKING_CONVERSION_REQUIRES_UNIT",
3223
3299
  `Expected a value with a mass or volume unit (e.g. "300g", "10 cups"), got a plain number`
3224
3300
  );
3225
3301
  }
3226
3302
  const sourceUnit = amountValue.unit;
3227
3303
  const amount = amountValue.toNumber();
3228
- const sourceMeasure = chunkNJTXJ5AG_cjs.getMeasure(sourceUnit);
3229
- const targetMeasure = chunkNJTXJ5AG_cjs.getMeasure(targetUnitText);
3304
+ const sourceMeasure = chunkPFUESQTW_cjs.getMeasure(sourceUnit);
3305
+ const targetMeasure = chunkPFUESQTW_cjs.getMeasure(targetUnitText);
3230
3306
  const isMassOrVolume = (m) => m === "mass" || m === "volume";
3231
3307
  if (!isMassOrVolume(sourceMeasure)) {
3232
- return chunkOC6LTXYS_cjs.errorValue(
3308
+ return chunkJMXUNXQS_cjs.errorValue(
3233
3309
  "COOKING_CONVERSION_UNSUPPORTED_UNIT",
3234
3310
  `"${sourceUnit}" is not a recognized mass or volume unit`
3235
3311
  );
3236
3312
  }
3237
3313
  if (!isMassOrVolume(targetMeasure)) {
3238
- return chunkOC6LTXYS_cjs.errorValue(
3314
+ return chunkJMXUNXQS_cjs.errorValue(
3239
3315
  "COOKING_CONVERSION_UNSUPPORTED_UNIT",
3240
3316
  `"${targetUnitText}" is not a recognized mass or volume unit`
3241
3317
  );
3242
3318
  }
3243
3319
  if (sourceMeasure === targetMeasure) {
3244
- return chunkOC6LTXYS_cjs.uomValue(chunkNJTXJ5AG_cjs.convertUnit(amount, sourceUnit, targetUnitText), targetUnitText);
3320
+ return chunkJMXUNXQS_cjs.uomValue(chunkPFUESQTW_cjs.convertUnit(amount, sourceUnit, targetUnitText), targetUnitText);
3245
3321
  }
3246
3322
  const density = getIngredientDensity(ingredientName);
3247
3323
  if (density === void 0) {
3248
- return chunkOC6LTXYS_cjs.errorValue(
3324
+ return chunkJMXUNXQS_cjs.errorValue(
3249
3325
  "COOKING_UNKNOWN_INGREDIENT",
3250
3326
  `No density data for "${ingredientName}" \u2014 cannot convert between mass and volume for this ingredient`
3251
3327
  );
3252
3328
  }
3253
3329
  if (sourceMeasure === "mass") {
3254
- const grams2 = chunkNJTXJ5AG_cjs.convertUnit(amount, sourceUnit, "g");
3330
+ const grams2 = chunkPFUESQTW_cjs.convertUnit(amount, sourceUnit, "g");
3255
3331
  const mL2 = grams2 / density;
3256
- const result2 = chunkNJTXJ5AG_cjs.convertUnit(mL2, "ml", targetUnitText);
3257
- return chunkOC6LTXYS_cjs.uomValue(result2, targetUnitText);
3332
+ const result2 = chunkPFUESQTW_cjs.convertUnit(mL2, "ml", targetUnitText);
3333
+ return chunkJMXUNXQS_cjs.uomValue(result2, targetUnitText);
3258
3334
  }
3259
- const mL = chunkNJTXJ5AG_cjs.convertUnit(amount, sourceUnit, "ml");
3335
+ const mL = chunkPFUESQTW_cjs.convertUnit(amount, sourceUnit, "ml");
3260
3336
  const grams = mL * density;
3261
- const result = chunkNJTXJ5AG_cjs.convertUnit(grams, "g", targetUnitText);
3262
- return chunkOC6LTXYS_cjs.uomValue(result, targetUnitText);
3337
+ const result = chunkPFUESQTW_cjs.convertUnit(grams, "g", targetUnitText);
3338
+ return chunkJMXUNXQS_cjs.uomValue(result, targetUnitText);
3263
3339
  }
3264
3340
 
3265
3341
  // src/packages/uom/parselets/CookingConversionParselet.ts
@@ -3302,7 +3378,7 @@ function ingredientNameNormalizerRule(priority = 68) {
3302
3378
  const candidate = candidateTokens.map((t) => t.value.toLowerCase()).join(" ");
3303
3379
  return {
3304
3380
  consumed: wordCount,
3305
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("INGREDIENT_NAME", candidate, candidateTokens)],
3381
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("INGREDIENT_NAME", candidate, candidateTokens)],
3306
3382
  ruleName: "uom-cooking:ingredient-name"
3307
3383
  };
3308
3384
  }
@@ -3311,6 +3387,27 @@ function ingredientNameNormalizerRule(priority = 68) {
3311
3387
  };
3312
3388
  }
3313
3389
 
3390
+ // src/packages/uom/normalizer/MultiWordUnitNormalizerRule.ts
3391
+ function multiWordUnitNormalizerRule(priority = 78) {
3392
+ return {
3393
+ name: "uom:multi-word-unit",
3394
+ priority,
3395
+ match(tokens, pos) {
3396
+ const first = tokens[pos];
3397
+ const second = tokens[pos + 1];
3398
+ if (first?.type !== "UNIT" || second?.type !== "UNIT") return null;
3399
+ if (first.offset + first.text.length + 1 !== second.offset) return null;
3400
+ const spelling = `${first.value} ${second.value}`;
3401
+ if (chunkAMOJYLG2_cjs.UNIT_TABLE[spelling] === void 0) return null;
3402
+ return {
3403
+ consumed: 2,
3404
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("UNIT", spelling, tokens.slice(pos, pos + 2))],
3405
+ ruleName: "uom:multi-word-unit"
3406
+ };
3407
+ }
3408
+ };
3409
+ }
3410
+
3314
3411
  // src/packages/uom/UomPackage.ts
3315
3412
  var UOM_PACKAGE = {
3316
3413
  name: "solve-uom",
@@ -3326,6 +3423,9 @@ var UOM_PACKAGE = {
3326
3423
  { tokenType: "INGREDIENT_NAME", parselet: new CookingConversionParselet() }
3327
3424
  ],
3328
3425
  normalizerRules: [
3426
+ // Highest priority of the unit rules: a two-word spelling has to become one
3427
+ // token before anything else reads the first word as a unit on its own.
3428
+ multiWordUnitNormalizerRule(),
3329
3429
  uomPossibilitiesNormalizerRule(),
3330
3430
  compoundQuantityNormalizerRule(),
3331
3431
  twoUnitConversionNormalizerRule(),
@@ -3347,8 +3447,8 @@ var CurrencySymbolParselet = class {
3347
3447
  this.category = "UoM";
3348
3448
  }
3349
3449
  parse(parser, token, builder) {
3350
- const currency = chunk4CVLFLOB_cjs.resolveCurrencyAlias(token.value) ?? token.value.toUpperCase();
3351
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Prefix, builder);
3450
+ const currency = chunkUM6BVY2S_cjs.resolveCurrencyAlias(token.value) ?? token.value.toUpperCase();
3451
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Prefix, builder);
3352
3452
  if (parser.peek()?.type === "UNIT") {
3353
3453
  parser.consume();
3354
3454
  }
@@ -3369,7 +3469,7 @@ var InParselet = class {
3369
3469
  if (targetToken && (targetToken.type === "UNIT" || targetToken.type === "DOLLAR" || targetToken.type === "POUND" || targetToken.type === "EURO" || targetToken.type === "YEN" || targetToken.type === "RUBLE" || targetToken.type === "WON" || targetToken.type === "CURRENCY_SYMBOL" || targetToken.type === "IDENT" || targetToken.type === "IN")) {
3370
3470
  parser.consume();
3371
3471
  builder.emitOpcode(13 /* PUSH_STRING */);
3372
- builder.emitString(chunk4CVLFLOB_cjs.resolveCurrencyAlias(targetToken.value) ?? targetToken.value);
3472
+ builder.emitString(chunkUM6BVY2S_cjs.resolveCurrencyAlias(targetToken.value) ?? targetToken.value);
3373
3473
  builder.emitOpcode(84 /* UOM_CONVERT_IN */);
3374
3474
  }
3375
3475
  }
@@ -3378,7 +3478,7 @@ var InParselet = class {
3378
3478
  // src/packages/currency/CurrencyPackage.ts
3379
3479
  var CURRENCY_PACKAGE = {
3380
3480
  name: "solve-currency",
3381
- asyncResolvers: [new chunk4AVD7NZW_cjs.CurrencyAsyncResolver()],
3481
+ asyncResolvers: [new chunk4B2CNWQU_cjs.CurrencyAsyncResolver()],
3382
3482
  prefixParselets: [
3383
3483
  { tokenType: "DOLLAR", parselet: new CurrencySymbolParselet() },
3384
3484
  { tokenType: "POUND", parselet: new CurrencySymbolParselet() },
@@ -3454,7 +3554,7 @@ var MatrixLiteralParselet = class {
3454
3554
  let rows = 0;
3455
3555
  let cols = -1;
3456
3556
  if (parser.peek()?.type === "RBRACKET") {
3457
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3557
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3458
3558
  "EMPTY_MATRIX_LITERAL",
3459
3559
  "A matrix literal cannot be empty \u2014 `[]` has no valid shape.",
3460
3560
  {}
@@ -3471,7 +3571,7 @@ var MatrixLiteralParselet = class {
3471
3571
  if (cols === -1) {
3472
3572
  cols = rowCols;
3473
3573
  } else if (rowCols !== cols) {
3474
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3574
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3475
3575
  "RAGGED_MATRIX_LITERAL",
3476
3576
  `Matrix literal rows must all have the same number of columns \u2014 row ${rows + 1} has ${rowCols}, but a previous row has ${cols}.`,
3477
3577
  { expectedCols: cols, actualCols: rowCols, row: rows + 1 }
@@ -3491,7 +3591,7 @@ var MatrixLiteralParselet = class {
3491
3591
  var MatrixIndexParselet = class {
3492
3592
  constructor() {
3493
3593
  this.category = "Matrix";
3494
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Postfix;
3594
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Postfix;
3495
3595
  }
3496
3596
  parse(parser, _left, _token, builder) {
3497
3597
  const isSlice = this.hasTopLevelColon(parser);
@@ -3511,7 +3611,7 @@ var MatrixIndexParselet = class {
3511
3611
  return;
3512
3612
  }
3513
3613
  if (argCount !== 2) {
3514
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3614
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3515
3615
  "INVALID_MATRIX_SLICE_ARITY",
3516
3616
  `Range-based matrix slicing needs exactly 2 arguments ("a[rowRange, colRange]"), got ${argCount}.`,
3517
3617
  { argCount }
@@ -3594,12 +3694,12 @@ function parseTransform(parser, builder) {
3594
3694
  }
3595
3695
  return { kind: 2, name };
3596
3696
  }
3597
- const transformBuilder = new chunkNZFKROS7_cjs.BytecodeBuilder();
3598
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, transformBuilder);
3697
+ const transformBuilder = new chunkPA4VC73I_cjs.BytecodeBuilder();
3698
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, transformBuilder);
3599
3699
  parser.setBuilder(builder);
3600
3700
  const program = transformBuilder.build();
3601
3701
  if (program.hasAsync) {
3602
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3702
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3603
3703
  "MAP_REDUCE_TRANSFORM_MUST_BE_SYNCHRONOUS",
3604
3704
  `map/reduce transform expressions must be synchronous (no weather/stocks/currency calls).`
3605
3705
  );
@@ -3617,7 +3717,7 @@ function consumeCollectionName(parser) {
3617
3717
  parser.consume();
3618
3718
  return token.value;
3619
3719
  }
3620
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3720
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3621
3721
  "MAP_REDUCE_EXPECTED_COLLECTION_NAME",
3622
3722
  `Expected a collection name (e.g. "x" in "x=[1,2,3]") but got ${token ? `"${token.value}"` : "end of input"}.`
3623
3723
  );
@@ -3681,7 +3781,7 @@ var ReduceParselet = class {
3681
3781
  parseCollectionExpr(parser, builder);
3682
3782
  let hasInitial = 0;
3683
3783
  if (parser.match("COMMA")) {
3684
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
3784
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3685
3785
  hasInitial = 1;
3686
3786
  }
3687
3787
  parser.consume("RPAREN");
@@ -3696,15 +3796,15 @@ var SumParselet = class {
3696
3796
  }
3697
3797
  parse(parser, _token, builder) {
3698
3798
  parser.consume("LPAREN");
3699
- const bodyBuilder = new chunkNZFKROS7_cjs.BytecodeBuilder();
3799
+ const bodyBuilder = new chunkPA4VC73I_cjs.BytecodeBuilder();
3700
3800
  bodyBuilder.emitOpcode(60 /* LOAD_VAR */);
3701
3801
  bodyBuilder.emitString("acc");
3702
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, bodyBuilder);
3802
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, bodyBuilder);
3703
3803
  parser.setBuilder(builder);
3704
3804
  bodyBuilder.emitOpcode(20 /* ADD */);
3705
3805
  const bodyProgram = bodyBuilder.build();
3706
3806
  if (bodyProgram.hasAsync) {
3707
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3807
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3708
3808
  "MAP_REDUCE_TRANSFORM_MUST_BE_SYNCHRONOUS",
3709
3809
  `sum's element expression must be synchronous (no weather/stocks/currency calls).`
3710
3810
  );
@@ -3712,7 +3812,9 @@ var SumParselet = class {
3712
3812
  parser.consume("COMMA");
3713
3813
  parseCollectionExpr(parser, builder);
3714
3814
  parser.consume("RPAREN");
3715
- emitInvoke(builder, 158 /* REDUCE_INVOKE */, { kind: 0, program: bodyProgram }, ["acc", "x"], 0);
3815
+ builder.emitOpcode(10 /* PUSH_NUMBER */);
3816
+ builder.emitNumber(0);
3817
+ emitInvoke(builder, 158 /* REDUCE_INVOKE */, { kind: 0, program: bodyProgram }, ["acc", "x"], 1);
3716
3818
  }
3717
3819
  };
3718
3820
 
@@ -3723,15 +3825,15 @@ var ProdParselet = class {
3723
3825
  }
3724
3826
  parse(parser, _token, builder) {
3725
3827
  parser.consume("LPAREN");
3726
- const bodyBuilder = new chunkNZFKROS7_cjs.BytecodeBuilder();
3828
+ const bodyBuilder = new chunkPA4VC73I_cjs.BytecodeBuilder();
3727
3829
  bodyBuilder.emitOpcode(60 /* LOAD_VAR */);
3728
3830
  bodyBuilder.emitString("acc");
3729
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, bodyBuilder);
3831
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, bodyBuilder);
3730
3832
  parser.setBuilder(builder);
3731
3833
  bodyBuilder.emitOpcode(22 /* MUL */);
3732
3834
  const bodyProgram = bodyBuilder.build();
3733
3835
  if (bodyProgram.hasAsync) {
3734
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3836
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3735
3837
  "MAP_REDUCE_TRANSFORM_MUST_BE_SYNCHRONOUS",
3736
3838
  `prod's element expression must be synchronous (no weather/stocks/currency calls).`
3737
3839
  );
@@ -3739,7 +3841,9 @@ var ProdParselet = class {
3739
3841
  parser.consume("COMMA");
3740
3842
  parseCollectionExpr(parser, builder);
3741
3843
  parser.consume("RPAREN");
3742
- emitInvoke(builder, 158 /* REDUCE_INVOKE */, { kind: 0, program: bodyProgram }, ["acc", "x"], 0);
3844
+ builder.emitOpcode(10 /* PUSH_NUMBER */);
3845
+ builder.emitNumber(1);
3846
+ emitInvoke(builder, 158 /* REDUCE_INVOKE */, { kind: 0, program: bodyProgram }, ["acc", "x"], 1);
3743
3847
  }
3744
3848
  };
3745
3849
 
@@ -3774,7 +3878,7 @@ function mapReduceCallNormalizerRule(priority = 80) {
3774
3878
  return {
3775
3879
  consumed: 1,
3776
3880
  replacement: [
3777
- new chunkM4F66R4O_cjs.LexerToken(tokenType, chunkR24DI24X_cjs.tokenTypeId(tokenType), token.value, token.value, token.offset, 0, token.line, token.col)
3881
+ new chunkYWQ6V4ZN_cjs.LexerToken(tokenType, chunk5LI5EPGJ_cjs.tokenTypeId(tokenType), token.value, token.value, token.offset, 0, token.line, token.col)
3778
3882
  ],
3779
3883
  ruleName: "mapreduce:call"
3780
3884
  };
@@ -3816,7 +3920,7 @@ var ExpandParselet = class {
3816
3920
  }
3817
3921
  parse(parser, _token, builder) {
3818
3922
  parser.consume("LPAREN");
3819
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
3923
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3820
3924
  parser.consume("RPAREN");
3821
3925
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3822
3926
  builder.emitIndex(SYMBOLIC_BUILTIN_EXPAND);
@@ -3831,7 +3935,7 @@ var FactorParselet = class {
3831
3935
  }
3832
3936
  parse(parser, _token, builder) {
3833
3937
  parser.consume("LPAREN");
3834
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
3938
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3835
3939
  parser.consume("RPAREN");
3836
3940
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3837
3941
  builder.emitIndex(SYMBOLIC_BUILTIN_FACTOR);
@@ -3839,6 +3943,42 @@ var FactorParselet = class {
3839
3943
  }
3840
3944
  };
3841
3945
 
3946
+ // src/packages/symbolic/parselets/VariableArgument.ts
3947
+ function readVariableName(parser, verb) {
3948
+ const token = parser.peek();
3949
+ if (!token || token.type !== "IDENT" && token.type !== "UNIT") {
3950
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3951
+ "SYMBOLIC_REQUIRES_VARIABLE_NAME",
3952
+ `${verb} needs the name of an unknown here, as in ${verb}(x^2, x).`,
3953
+ { found: token?.type ?? "end of input" }
3954
+ );
3955
+ }
3956
+ parser.consume();
3957
+ return token.value;
3958
+ }
3959
+ function emitVariableName(builder, name) {
3960
+ builder.emitOpcode(13 /* PUSH_STRING */);
3961
+ builder.emitString(name);
3962
+ }
3963
+ function parseBoundExpression(parser, builder, verb) {
3964
+ const inner = new chunkPA4VC73I_cjs.BytecodeBuilder();
3965
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, inner);
3966
+ parser.setBuilder(builder);
3967
+ const program = inner.build();
3968
+ if (program.hasAsync) {
3969
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3970
+ "SYMBOLIC_ARGUMENT_MUST_BE_SYNCHRONOUS",
3971
+ `${verb}'s expression must be synchronous (no weather/stocks/currency calls).`
3972
+ );
3973
+ }
3974
+ return program;
3975
+ }
3976
+ function emitBoundExpression(builder, program, name) {
3977
+ const index = builder.emitAnonymousBody([name], program);
3978
+ builder.emitOpcode(159 /* BIND_UNKNOWN */);
3979
+ builder.emitIndex(index);
3980
+ }
3981
+
3842
3982
  // src/packages/symbolic/parselets/SolveParselet.ts
3843
3983
  var SolveParselet = class {
3844
3984
  constructor() {
@@ -3846,25 +3986,26 @@ var SolveParselet = class {
3846
3986
  }
3847
3987
  parse(parser, _token, builder) {
3848
3988
  parser.consume("LPAREN");
3849
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
3850
- if (parser.match("EQUALS")) {
3851
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
3852
- } else {
3853
- builder.emitOpcode(10 /* PUSH_NUMBER */);
3854
- builder.emitNumber(0);
3855
- }
3989
+ const left = parseBoundExpression(parser, builder, "solve");
3990
+ const right = parser.match("EQUALS") ? parseBoundExpression(parser, builder, "solve") : null;
3856
3991
  parser.consume("COMMA");
3857
3992
  const variable = parser.peek();
3858
3993
  if (!variable || variable.type !== "IDENT" && variable.type !== "UNIT") {
3859
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3994
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
3860
3995
  "SOLVE_REQUIRES_VARIABLE_NAME",
3861
3996
  `solve's second argument must be the name of the unknown to solve for, as in solve(x^2-4=0, x).`,
3862
3997
  { found: variable?.type ?? "end of input" }
3863
3998
  );
3864
3999
  }
3865
4000
  parser.consume();
3866
- builder.emitOpcode(13 /* PUSH_STRING */);
3867
- builder.emitString(variable.value);
4001
+ emitBoundExpression(builder, left, variable.value);
4002
+ if (right) {
4003
+ emitBoundExpression(builder, right, variable.value);
4004
+ } else {
4005
+ builder.emitOpcode(10 /* PUSH_NUMBER */);
4006
+ builder.emitNumber(0);
4007
+ }
4008
+ emitVariableName(builder, variable.value);
3868
4009
  parser.consume("RPAREN");
3869
4010
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3870
4011
  builder.emitIndex(SYMBOLIC_BUILTIN_SOLVE);
@@ -3872,21 +4013,6 @@ var SolveParselet = class {
3872
4013
  }
3873
4014
  };
3874
4015
 
3875
- // src/packages/symbolic/parselets/VariableArgument.ts
3876
- function consumeVariableName(parser, builder, verb) {
3877
- const token = parser.peek();
3878
- if (!token || token.type !== "IDENT" && token.type !== "UNIT") {
3879
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
3880
- "SYMBOLIC_REQUIRES_VARIABLE_NAME",
3881
- `${verb} needs the name of an unknown here, as in ${verb}(x^2, x).`,
3882
- { found: token?.type ?? "end of input" }
3883
- );
3884
- }
3885
- parser.consume();
3886
- builder.emitOpcode(13 /* PUSH_STRING */);
3887
- builder.emitString(token.value);
3888
- }
3889
-
3890
4016
  // src/packages/symbolic/parselets/DerParselet.ts
3891
4017
  var DerParselet = class {
3892
4018
  constructor() {
@@ -3894,11 +4020,13 @@ var DerParselet = class {
3894
4020
  }
3895
4021
  parse(parser, _token, builder) {
3896
4022
  parser.consume("LPAREN");
3897
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4023
+ const expression = parseBoundExpression(parser, builder, "der");
3898
4024
  parser.consume("COMMA");
3899
- consumeVariableName(parser, builder, "der");
4025
+ const variable = readVariableName(parser, "der");
4026
+ emitBoundExpression(builder, expression, variable);
4027
+ emitVariableName(builder, variable);
3900
4028
  if (parser.match("COMMA")) {
3901
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4029
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3902
4030
  } else {
3903
4031
  builder.emitOpcode(10 /* PUSH_NUMBER */);
3904
4032
  builder.emitNumber(1);
@@ -3917,9 +4045,11 @@ var IntegralParselet = class {
3917
4045
  }
3918
4046
  parse(parser, _token, builder) {
3919
4047
  parser.consume("LPAREN");
3920
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4048
+ const expression = parseBoundExpression(parser, builder, "integral");
3921
4049
  parser.consume("COMMA");
3922
- consumeVariableName(parser, builder, "integral");
4050
+ const variable = readVariableName(parser, "integral");
4051
+ emitBoundExpression(builder, expression, variable);
4052
+ emitVariableName(builder, variable);
3923
4053
  parser.consume("RPAREN");
3924
4054
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3925
4055
  builder.emitIndex(SYMBOLIC_BUILTIN_INTEGRAL);
@@ -3934,13 +4064,15 @@ var TaylorParselet = class {
3934
4064
  }
3935
4065
  parse(parser, _token, builder) {
3936
4066
  parser.consume("LPAREN");
3937
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4067
+ const expression = parseBoundExpression(parser, builder, "taylor");
3938
4068
  parser.consume("COMMA");
3939
- consumeVariableName(parser, builder, "taylor");
4069
+ const variable = readVariableName(parser, "taylor");
4070
+ emitBoundExpression(builder, expression, variable);
4071
+ emitVariableName(builder, variable);
3940
4072
  parser.consume("EQUALS");
3941
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4073
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3942
4074
  parser.consume("COMMA");
3943
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4075
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3944
4076
  parser.consume("RPAREN");
3945
4077
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3946
4078
  builder.emitIndex(SYMBOLIC_BUILTIN_TAYLOR);
@@ -3957,7 +4089,7 @@ var JacobianParselet = class {
3957
4089
  parser.consume("LPAREN");
3958
4090
  let count = 0;
3959
4091
  do {
3960
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4092
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3961
4093
  count++;
3962
4094
  } while (parser.match("COMMA"));
3963
4095
  parser.consume("RPAREN");
@@ -3988,7 +4120,7 @@ var ConjParselet = class {
3988
4120
  }
3989
4121
  parse(parser, _token, builder) {
3990
4122
  parser.consume("LPAREN");
3991
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4123
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
3992
4124
  parser.consume("RPAREN");
3993
4125
  builder.emitOpcode(51 /* CALL_BUILTIN */);
3994
4126
  builder.emitIndex(SYMBOLIC_BUILTIN_CONJ);
@@ -4003,7 +4135,7 @@ var ReParselet = class {
4003
4135
  }
4004
4136
  parse(parser, _token, builder) {
4005
4137
  parser.consume("LPAREN");
4006
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4138
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4007
4139
  parser.consume("RPAREN");
4008
4140
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4009
4141
  builder.emitIndex(SYMBOLIC_BUILTIN_RE);
@@ -4018,7 +4150,7 @@ var ImParselet = class {
4018
4150
  }
4019
4151
  parse(parser, _token, builder) {
4020
4152
  parser.consume("LPAREN");
4021
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4153
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4022
4154
  parser.consume("RPAREN");
4023
4155
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4024
4156
  builder.emitIndex(SYMBOLIC_BUILTIN_IM);
@@ -4033,7 +4165,7 @@ var CancelParselet = class {
4033
4165
  }
4034
4166
  parse(parser, _token, builder) {
4035
4167
  parser.consume("LPAREN");
4036
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4168
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4037
4169
  parser.consume("RPAREN");
4038
4170
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4039
4171
  builder.emitIndex(SYMBOLIC_BUILTIN_CANCEL);
@@ -4048,7 +4180,7 @@ var ApartParselet = class {
4048
4180
  }
4049
4181
  parse(parser, _token, builder) {
4050
4182
  parser.consume("LPAREN");
4051
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4183
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4052
4184
  parser.consume("RPAREN");
4053
4185
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4054
4186
  builder.emitIndex(SYMBOLIC_BUILTIN_APART);
@@ -4071,9 +4203,9 @@ function imaginaryLiteralNormalizerRule(priority = 75) {
4071
4203
  return {
4072
4204
  consumed: 2,
4073
4205
  replacement: [
4074
- new chunkM4F66R4O_cjs.LexerToken(
4206
+ new chunkYWQ6V4ZN_cjs.LexerToken(
4075
4207
  "IMAGINARY",
4076
- chunkR24DI24X_cjs.tokenTypeId("IMAGINARY"),
4208
+ chunk5LI5EPGJ_cjs.tokenTypeId("IMAGINARY"),
4077
4209
  number.value,
4078
4210
  number.value,
4079
4211
  number.offset,
@@ -4117,7 +4249,7 @@ function symbolicCallNormalizerRule(priority = 80) {
4117
4249
  return {
4118
4250
  consumed: 1,
4119
4251
  replacement: [
4120
- new chunkM4F66R4O_cjs.LexerToken(tokenType, chunkR24DI24X_cjs.tokenTypeId(tokenType), token.value, token.value, token.offset, 0, token.line, token.col)
4252
+ new chunkYWQ6V4ZN_cjs.LexerToken(tokenType, chunk5LI5EPGJ_cjs.tokenTypeId(tokenType), token.value, token.value, token.offset, 0, token.line, token.col)
4121
4253
  ],
4122
4254
  ruleName: "symbolic:call"
4123
4255
  };
@@ -4269,10 +4401,8 @@ var BigIntNumberParselet = class {
4269
4401
  this.category = "BigInt";
4270
4402
  }
4271
4403
  parse(parser, token, builder) {
4272
- let raw = token.value;
4273
- if (raw.endsWith("n")) raw = raw.slice(0, -1);
4274
4404
  builder.emitOpcode(11 /* PUSH_BIGINT */);
4275
- builder.emitString(raw);
4405
+ builder.emitString(chunkPA4VC73I_cjs.bigIntLiteralDigits(token.value, parser.getLocaleCode()));
4276
4406
  }
4277
4407
  };
4278
4408
 
@@ -4289,7 +4419,7 @@ var ComparisonParselet = class {
4289
4419
  constructor(opcode) {
4290
4420
  this.opcode = opcode;
4291
4421
  this.category = "Conditionals";
4292
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
4422
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4293
4423
  }
4294
4424
  parse(parser, left, token, builder) {
4295
4425
  parser.parseExpression(this.bindingPower, builder);
@@ -4352,9 +4482,9 @@ var CONDITIONALS_PACKAGE = {
4352
4482
  { tokenType: "GT", parselet: new ComparisonParselet(44 /* GT */) },
4353
4483
  { tokenType: "LTE", parselet: new ComparisonParselet(43 /* LTE */) },
4354
4484
  { tokenType: "GTE", parselet: new ComparisonParselet(45 /* GTE */) },
4355
- { tokenType: "OR", parselet: new LogicalParselet(131 /* LOGICAL_OR */, chunkNZFKROS7_cjs.BindingPower.LogicalOr) },
4356
- { tokenType: "LOGICAL_AND", parselet: new LogicalParselet(130 /* LOGICAL_AND */, chunkNZFKROS7_cjs.BindingPower.LogicalAnd) },
4357
- { tokenType: "LOGICAL_OR", parselet: new LogicalParselet(131 /* LOGICAL_OR */, chunkNZFKROS7_cjs.BindingPower.LogicalOr) }
4485
+ { tokenType: "OR", parselet: new LogicalParselet(131 /* LOGICAL_OR */, chunkPA4VC73I_cjs.BindingPower.LogicalOr) },
4486
+ { tokenType: "LOGICAL_AND", parselet: new LogicalParselet(130 /* LOGICAL_AND */, chunkPA4VC73I_cjs.BindingPower.LogicalAnd) },
4487
+ { tokenType: "LOGICAL_OR", parselet: new LogicalParselet(131 /* LOGICAL_OR */, chunkPA4VC73I_cjs.BindingPower.LogicalOr) }
4358
4488
  ]
4359
4489
  };
4360
4490
 
@@ -4386,7 +4516,7 @@ var BASE_CONVERTERS = {
4386
4516
  var AsConverterParselet = class {
4387
4517
  constructor() {
4388
4518
  this.category = "Converters";
4389
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
4519
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4390
4520
  }
4391
4521
  parse(parser, left, token, builder) {
4392
4522
  const nextToken = parser.peek();
@@ -4396,7 +4526,7 @@ var AsConverterParselet = class {
4396
4526
  return;
4397
4527
  }
4398
4528
  if (!nextToken || nextToken.type !== "CONVERTER_NAME" && nextToken.type !== "IDENT" && nextToken.type !== "FUNC" && nextToken.type !== "UNIT") {
4399
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4529
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4400
4530
  "AS_CONVERTER_EXPECTED_NAME",
4401
4531
  `Expected a converter name after "as" (e.g. "as hex", "as decimal") but got ${nextToken ? `"${nextToken.value}"` : "end of input"}`
4402
4532
  );
@@ -4408,7 +4538,7 @@ var AsConverterParselet = class {
4408
4538
  const radix = radixToken?.type === "NUMBER" ? Number(radixToken.value) : NaN;
4409
4539
  const opcode = BASE_CONVERTERS[radix];
4410
4540
  if (opcode === void 0) {
4411
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4541
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4412
4542
  "AS_CONVERTER_UNSUPPORTED_BASE",
4413
4543
  `"as base ${radixToken?.value ?? "?"}": only bases ${Object.keys(BASE_CONVERTERS).join(", ")} can be written out`
4414
4544
  );
@@ -4420,7 +4550,7 @@ var AsConverterParselet = class {
4420
4550
  const builtinOp = BUILTIN_CONVERTERS[name];
4421
4551
  if (builtinOp !== void 0) {
4422
4552
  if (builtinOp === 141 /* TO_MULTIPLIER */ && parser.match("OF")) {
4423
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
4553
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4424
4554
  builder.emitOpcode(23 /* DIV */);
4425
4555
  }
4426
4556
  builder.emitOpcode(builtinOp);
@@ -4458,6 +4588,7 @@ function emitRoundDirection(builder, direction) {
4458
4588
  var ROUND_BUILTIN = 8;
4459
4589
  var CEIL_BUILTIN = 6;
4460
4590
  var FLOOR_BUILTIN = 7;
4591
+ var ROUND_TO_PLACES_BUILTIN = 97;
4461
4592
  function readDirection(parser) {
4462
4593
  const next = parser.peek();
4463
4594
  const word = (next?.text ?? "").toLowerCase();
@@ -4474,7 +4605,7 @@ function readDirection(parser) {
4474
4605
  var RoundedParselet = class {
4475
4606
  constructor() {
4476
4607
  this.category = "Converters";
4477
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
4608
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4478
4609
  }
4479
4610
  parse(parser, _left, _token, builder) {
4480
4611
  const direction = readDirection(parser);
@@ -4488,7 +4619,7 @@ var RoundedParselet = class {
4488
4619
  var ToNearestParselet = class {
4489
4620
  constructor() {
4490
4621
  this.category = "Converters";
4491
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
4622
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4492
4623
  }
4493
4624
  parse(parser, _left, _token, builder) {
4494
4625
  emitRoundToIncrement(builder, readIncrement(parser), "nearest");
@@ -4507,7 +4638,7 @@ function readIncrement(parser) {
4507
4638
  const value = Number(next.value);
4508
4639
  if (Number.isFinite(value) && value > 0) return value;
4509
4640
  }
4510
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4641
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4511
4642
  "INVALID_ROUNDING_INCREMENT",
4512
4643
  `"to nearest ${next?.value ?? "?"}": expected a positive number or one of ${Object.keys(INCREMENT_WORDS).join(", ")}`
4513
4644
  );
@@ -4515,24 +4646,21 @@ function readIncrement(parser) {
4515
4646
  var DecimalPlacesParselet = class {
4516
4647
  constructor() {
4517
4648
  this.category = "Converters";
4518
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
4649
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4519
4650
  }
4520
4651
  parse(_parser, _left, token, builder) {
4521
4652
  const places = Number(token.value);
4522
4653
  if (!Number.isFinite(places) || places < 0 || places > 100) {
4523
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4654
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4524
4655
  "INVALID_DECIMAL_PLACES",
4525
4656
  `"to ${token.value} dp": expected a place count between 0 and 100`
4526
4657
  );
4527
4658
  }
4528
- const scale = Math.pow(10, places);
4529
4659
  builder.emitOpcode(10 /* PUSH_NUMBER */);
4530
- builder.emitNumber(scale);
4531
- builder.emitOpcode(22 /* MUL */);
4532
- emitRoundDirection(builder, "nearest");
4533
- builder.emitOpcode(10 /* PUSH_NUMBER */);
4534
- builder.emitNumber(scale);
4535
- builder.emitOpcode(23 /* DIV */);
4660
+ builder.emitNumber(places);
4661
+ builder.emitOpcode(51 /* CALL_BUILTIN */);
4662
+ builder.emitIndex(ROUND_TO_PLACES_BUILTIN);
4663
+ builder.emitIndex(2);
4536
4664
  }
4537
4665
  };
4538
4666
 
@@ -4562,7 +4690,7 @@ function decimalPlacesNormalizerRule(priority = 66) {
4562
4690
  return {
4563
4691
  consumed,
4564
4692
  replacement: [
4565
- chunkAHCLWAM5_cjs.createFusedToken("DECIMAL_PLACES", count.value, tokens.slice(pos, pos + consumed))
4693
+ chunkBHTNFEGZ_cjs.createFusedToken("DECIMAL_PLACES", count.value, tokens.slice(pos, pos + consumed))
4566
4694
  ],
4567
4695
  ruleName: "converters:decimal-places"
4568
4696
  };
@@ -4571,6 +4699,7 @@ function decimalPlacesNormalizerRule(priority = 66) {
4571
4699
  }
4572
4700
 
4573
4701
  // src/packages/converters/normalizer/ConverterPrepositionNormalizerRule.ts
4702
+ var FUNC_TYPED_CONVERTERS = /* @__PURE__ */ new Set(["hex", "bin"]);
4574
4703
  function converterPrepositionNormalizerRule(priority = 67) {
4575
4704
  return {
4576
4705
  name: "converters:preposition",
@@ -4578,10 +4707,12 @@ function converterPrepositionNormalizerRule(priority = 67) {
4578
4707
  match(tokens, pos) {
4579
4708
  const preposition = tokens[pos];
4580
4709
  if (preposition?.type !== "IN" && preposition?.type !== "TO") return null;
4581
- if (tokens[pos + 1]?.type !== "CONVERTER_NAME") return null;
4710
+ const target = tokens[pos + 1];
4711
+ const isConverterTarget = target?.type === "CONVERTER_NAME" || target?.type === "FUNC" && FUNC_TYPED_CONVERTERS.has(target.value.toLowerCase());
4712
+ if (!isConverterTarget) return null;
4582
4713
  return {
4583
4714
  consumed: 1,
4584
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("AS", "as", [preposition])],
4715
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("AS", "as", [preposition])],
4585
4716
  ruleName: "converters:preposition"
4586
4717
  };
4587
4718
  }
@@ -4618,10 +4749,10 @@ var VariadicAggregateParselet = class {
4618
4749
  }
4619
4750
  parse(parser, token, builder) {
4620
4751
  let argCount = 0;
4621
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conjunction, builder);
4752
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conjunction, builder);
4622
4753
  argCount++;
4623
4754
  while (parser.match("COMMA") || parser.match("AND_CONJ")) {
4624
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conjunction, builder);
4755
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conjunction, builder);
4625
4756
  argCount++;
4626
4757
  }
4627
4758
  builder.emitOpcode(51 /* CALL_BUILTIN */);
@@ -4635,7 +4766,7 @@ function unaryPhraseParselet(builtinIndex) {
4635
4766
  return {
4636
4767
  category: "MathPhrases",
4637
4768
  parse(parser, _token, builder) {
4638
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4769
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4639
4770
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4640
4771
  builder.emitIndex(builtinIndex);
4641
4772
  builder.emitIndex(1);
@@ -4647,28 +4778,28 @@ function unaryPhraseParselet(builtinIndex) {
4647
4778
  var remainderOfParselet = {
4648
4779
  category: "MathPhrases",
4649
4780
  parse(parser, _token, builder) {
4650
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
4781
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
4651
4782
  if (!parser.match("DIVIDE_BY") && !parser.match("SLASH")) {
4652
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4783
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4653
4784
  "REMAINDER_EXPECTED_DIVIDED_BY",
4654
4785
  'Expected "divided by" or "/", as in "remainder of 21 divided by 5"'
4655
4786
  );
4656
4787
  }
4657
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
4788
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
4658
4789
  builder.emitOpcode(24 /* MOD */);
4659
4790
  }
4660
4791
  };
4661
4792
  var nthRootParselet = {
4662
4793
  category: "MathPhrases",
4663
4794
  parse(parser, _token, builder) {
4664
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
4795
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
4665
4796
  if (!parser.match("OF")) {
4666
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4797
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4667
4798
  "ROOT_EXPECTED_OF",
4668
4799
  'Expected "of", as in "root 5 of 100"'
4669
4800
  );
4670
4801
  }
4671
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
4802
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4672
4803
  builder.emitOpcode(2 /* SWAP */);
4673
4804
  builder.emitOpcode(10 /* PUSH_NUMBER */);
4674
4805
  builder.emitNumber(1);
@@ -4680,15 +4811,15 @@ var nthRootParselet = {
4680
4811
  var logBaseParselet = {
4681
4812
  category: "MathPhrases",
4682
4813
  parse(parser, _token, builder) {
4683
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
4814
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4684
4815
  emitNaturalLog(builder);
4685
4816
  if (!parser.match("LOG_BASE")) {
4686
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4817
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4687
4818
  "LOG_EXPECTED_BASE",
4688
4819
  'Expected "base", as in "log 20 base 4"'
4689
4820
  );
4690
4821
  }
4691
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
4822
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4692
4823
  emitNaturalLog(builder);
4693
4824
  builder.emitOpcode(23 /* DIV */);
4694
4825
  }
@@ -4714,15 +4845,15 @@ function functionPhraseNormalizerRule(priority = 69) {
4714
4845
  if (word === "root") {
4715
4846
  return {
4716
4847
  consumed: 1,
4717
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("NTH_ROOT", "root", [head])],
4848
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("NTH_ROOT", "root", [head])],
4718
4849
  ruleName: "mathphrases:function-phrase"
4719
4850
  };
4720
4851
  }
4721
4852
  const baseAt = findBase(tokens, pos + 1);
4722
4853
  if (baseAt === -1) return null;
4723
4854
  const replacement = tokens.slice(pos, baseAt + 1).map((token, index) => {
4724
- if (index === 0) return chunkAHCLWAM5_cjs.createFusedToken("LOG_PHRASE", "log", [token]);
4725
- if (index === baseAt - pos) return chunkAHCLWAM5_cjs.createFusedToken("LOG_BASE", "base", [token]);
4855
+ if (index === 0) return chunkBHTNFEGZ_cjs.createFusedToken("LOG_PHRASE", "log", [token]);
4856
+ if (index === baseAt - pos) return chunkBHTNFEGZ_cjs.createFusedToken("LOG_BASE", "base", [token]);
4726
4857
  return token;
4727
4858
  });
4728
4859
  return {
@@ -4747,9 +4878,9 @@ function largerSmallerParselet(builtinIndex) {
4747
4878
  return {
4748
4879
  category: "MathPhrases",
4749
4880
  parse(parser, token, builder) {
4750
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conjunction, builder);
4881
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conjunction, builder);
4751
4882
  parser.consume("AND_CONJ");
4752
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4883
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4753
4884
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4754
4885
  builder.emitIndex(builtinIndex);
4755
4886
  builder.emitIndex(2);
@@ -4761,7 +4892,7 @@ function largerSmallerParselet(builtinIndex) {
4761
4892
  var halfParselet = {
4762
4893
  category: "MathPhrases",
4763
4894
  parse(parser, token, builder) {
4764
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4895
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4765
4896
  builder.emitOpcode(10 /* PUSH_NUMBER */);
4766
4897
  builder.emitNumber(2);
4767
4898
  builder.emitOpcode(23 /* DIV */);
@@ -4772,9 +4903,9 @@ var halfParselet = {
4772
4903
  var midpointParselet = {
4773
4904
  category: "MathPhrases",
4774
4905
  parse(parser, token, builder) {
4775
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conjunction, builder);
4906
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conjunction, builder);
4776
4907
  parser.consume("AND_CONJ");
4777
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4908
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4778
4909
  builder.emitOpcode(20 /* ADD */);
4779
4910
  builder.emitOpcode(10 /* PUSH_NUMBER */);
4780
4911
  builder.emitNumber(2);
@@ -4789,7 +4920,7 @@ var randomNumberParselet = definePhrasePattern({
4789
4920
  {
4790
4921
  slots: [
4791
4922
  { kind: "keyword", tokenTypes: ["BETWEEN"] },
4792
- { kind: "expr", bindingPower: chunkNZFKROS7_cjs.BindingPower.Product },
4923
+ { kind: "expr", bindingPower: chunkPA4VC73I_cjs.BindingPower.Product },
4793
4924
  { kind: "keyword", tokenTypes: ["AND_CONJ"] },
4794
4925
  { kind: "expr" }
4795
4926
  ],
@@ -4809,20 +4940,20 @@ var ClampParselet = class {
4809
4940
  this.category = "MathPhrases";
4810
4941
  }
4811
4942
  parse(parser, token, builder) {
4812
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4943
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4813
4944
  const mid = parser.peek();
4814
4945
  if (mid?.type === "BETWEEN") {
4815
4946
  parser.consume();
4816
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
4947
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
4817
4948
  parser.consume("AND_CONJ");
4818
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4949
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4819
4950
  } else if (mid?.type === "FROM") {
4820
4951
  parser.consume();
4821
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4952
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4822
4953
  parser.consume("TO");
4823
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
4954
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
4824
4955
  } else {
4825
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4956
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4826
4957
  "CLAMP_EXPECTED_BETWEEN_OR_FROM",
4827
4958
  `Expected "between" or "from" after "clamp <value>" but got ${mid ? `"${mid.value}"` : "end of input"}`
4828
4959
  );
@@ -4838,7 +4969,7 @@ var PROPORTION_BUILTIN_INDEX = 46;
4838
4969
  var ProportionParselet = class {
4839
4970
  constructor() {
4840
4971
  this.category = "MathPhrases";
4841
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
4972
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4842
4973
  }
4843
4974
  parse(parser, left, token, builder) {
4844
4975
  parser.parseExpression(this.bindingPower, builder);
@@ -4847,7 +4978,7 @@ var ProportionParselet = class {
4847
4978
  parser.consume("IS_TO");
4848
4979
  const whatToken = parser.consume();
4849
4980
  if (!whatToken || whatToken.value.toLowerCase() !== "what") {
4850
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
4981
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4851
4982
  "PROPORTION_EXPECTED_WHAT",
4852
4983
  `Expected "what" but got ${whatToken ? `"${whatToken.value}"` : "end of input"}`
4853
4984
  );
@@ -4939,7 +5070,7 @@ function readCompoundingInterval(parser) {
4939
5070
  const name = (token?.text ?? token?.value ?? "").toLowerCase();
4940
5071
  const periods = PERIODS_PER_YEAR[name];
4941
5072
  if (periods === void 0) {
4942
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5073
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
4943
5074
  "UNKNOWN_COMPOUNDING_INTERVAL",
4944
5075
  `compounding ${name || "?"}: expected one of ${Object.keys(PERIODS_PER_YEAR).join(", ")}`
4945
5076
  );
@@ -4957,12 +5088,12 @@ var InvestmentGrowthParselet = class {
4957
5088
  this.annualIndex = annualIndex;
4958
5089
  this.intervalIndex = intervalIndex;
4959
5090
  this.category = "Finance";
4960
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
5091
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
4961
5092
  }
4962
5093
  parse(parser, _left, _token, builder) {
4963
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5094
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4964
5095
  if (!parser.match("RATE_AT")) parser.consume("AT");
4965
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5096
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4966
5097
  const periods = readCompoundingInterval(parser);
4967
5098
  builder.emitOpcode(2 /* SWAP */);
4968
5099
  if (periods === 1) {
@@ -4984,13 +5115,13 @@ var PresentValueParselet = class {
4984
5115
  this.category = "Finance";
4985
5116
  }
4986
5117
  parse(parser, _token, builder) {
4987
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5118
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4988
5119
  if (!parser.match("AFTER") && !parser.match("OVER") && !parser.match("IN")) {
4989
5120
  parser.consume("AFTER");
4990
5121
  }
4991
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5122
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4992
5123
  if (!parser.match("RATE_AT")) parser.consume("AT");
4993
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5124
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
4994
5125
  builder.emitOpcode(2 /* SWAP */);
4995
5126
  builder.emitOpcode(51 /* CALL_BUILTIN */);
4996
5127
  builder.emitIndex(this.builtinIndex);
@@ -5001,10 +5132,10 @@ var ReturnOnInvestmentParselet = class {
5001
5132
  constructor(builtinIndex) {
5002
5133
  this.builtinIndex = builtinIndex;
5003
5134
  this.category = "Finance";
5004
- this.bindingPower = chunkNZFKROS7_cjs.BindingPower.Conditional;
5135
+ this.bindingPower = chunkPA4VC73I_cjs.BindingPower.Conditional;
5005
5136
  }
5006
5137
  parse(parser, _left, _token, builder) {
5007
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5138
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
5008
5139
  parser.consume("RETURNED");
5009
5140
  builder.emitOpcode(51 /* CALL_BUILTIN */);
5010
5141
  builder.emitIndex(this.builtinIndex);
@@ -5017,14 +5148,14 @@ var AnnualReturnParselet = class {
5017
5148
  this.category = "Finance";
5018
5149
  }
5019
5150
  parse(parser, _token, builder) {
5020
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5151
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
5021
5152
  parser.consume("INVESTED");
5022
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5153
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
5023
5154
  parser.consume("RETURNED");
5024
5155
  if (!parser.match("AFTER") && !parser.match("OVER") && !parser.match("IN")) {
5025
5156
  parser.consume("AFTER");
5026
5157
  }
5027
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5158
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
5028
5159
  builder.emitOpcode(51 /* CALL_BUILTIN */);
5029
5160
  builder.emitIndex(this.builtinIndex);
5030
5161
  builder.emitIndex(3);
@@ -5044,13 +5175,13 @@ var CompoundInterestParselet = class {
5044
5175
  this.category = "Finance";
5045
5176
  }
5046
5177
  parse(parser, _token, builder) {
5047
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Conditional, builder);
5178
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Conditional, builder);
5048
5179
  if (!parser.match("AFTER") && !parser.match("FOR_DURATION")) {
5049
5180
  parser.consume("OVER");
5050
5181
  }
5051
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5182
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5052
5183
  if (!parser.match("RATE_AT")) parser.consume("AT");
5053
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5184
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5054
5185
  const periods = readCompoundingInterval(parser);
5055
5186
  builder.emitOpcode(2 /* SWAP */);
5056
5187
  if (periods === 1) {
@@ -5075,11 +5206,11 @@ var LoanRepaymentParselet = class {
5075
5206
  this.category = "Finance";
5076
5207
  }
5077
5208
  parse(parser, _token, builder) {
5078
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5209
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5079
5210
  parser.consume("OVER");
5080
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5211
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5081
5212
  if (!parser.match("RATE_AT")) parser.consume("AT");
5082
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5213
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5083
5214
  builder.emitOpcode(2 /* SWAP */);
5084
5215
  builder.emitOpcode(10 /* PUSH_NUMBER */);
5085
5216
  builder.emitNumber(this.periodsPerYear);
@@ -5096,9 +5227,9 @@ var SalesTaxParselet = class {
5096
5227
  this.category = "Finance";
5097
5228
  }
5098
5229
  parse(parser, _token, builder) {
5099
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5230
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5100
5231
  parser.consume("RATE_AT");
5101
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5232
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5102
5233
  builder.emitOpcode(51 /* CALL_BUILTIN */);
5103
5234
  builder.emitIndex(this.builtinIndex);
5104
5235
  builder.emitIndex(2);
@@ -5106,30 +5237,30 @@ var SalesTaxParselet = class {
5106
5237
  };
5107
5238
 
5108
5239
  // src/packages/finance/parselets/InflationPluginFunctions.ts
5109
- var INFLATION_FROM_YEAR_TO_PRESENT_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
5110
- var INFLATION_TO_YEAR_FROM_PRESENT_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
5111
- var INFLATION_FUTURE_VALUE_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
5240
+ var INFLATION_FROM_YEAR_TO_PRESENT_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
5241
+ var INFLATION_TO_YEAR_FROM_PRESENT_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
5242
+ var INFLATION_FUTURE_VALUE_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
5112
5243
  function yearRangeError(code, badYear) {
5113
- return chunkOC6LTXYS_cjs.errorValue(
5244
+ return chunkJMXUNXQS_cjs.errorValue(
5114
5245
  code,
5115
- `Year ${badYear} is outside the bundled CPI table's range (${chunkBXKJLM5R_cjs.CPI_MIN_YEAR}-${chunkBXKJLM5R_cjs.CPI_MAX_YEAR})`
5246
+ `Year ${badYear} is outside the bundled CPI table's range (${chunk6WFMPTGB_cjs.CPI_MIN_YEAR}-${chunk6WFMPTGB_cjs.CPI_MAX_YEAR})`
5116
5247
  );
5117
5248
  }
5118
5249
  function inflationFromYearToPresentHandler(args) {
5119
5250
  const amountValue = args[0];
5120
5251
  const fromYear = args[1].toNumber();
5121
5252
  const toYear = (/* @__PURE__ */ new Date()).getFullYear();
5122
- const result = chunkBXKJLM5R_cjs.adjustForInflation(amountValue.toNumber(), fromYear, toYear);
5253
+ const result = chunk6WFMPTGB_cjs.adjustForInflation(amountValue.toNumber(), fromYear, toYear);
5123
5254
  if (result === void 0) return yearRangeError("INFLATION_YEAR_OUT_OF_RANGE", fromYear);
5124
- return amountValue.type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(result, amountValue.unit) : chunkOC6LTXYS_cjs.numberValue(result);
5255
+ return amountValue.type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, amountValue.unit) : chunkJMXUNXQS_cjs.numberValue(result);
5125
5256
  }
5126
5257
  function inflationToYearFromPresentHandler(args) {
5127
5258
  const amountValue = args[0];
5128
5259
  const fromYear = (/* @__PURE__ */ new Date()).getFullYear();
5129
5260
  const toYear = args[1].toNumber();
5130
- const result = chunkBXKJLM5R_cjs.adjustForInflation(amountValue.toNumber(), fromYear, toYear);
5261
+ const result = chunk6WFMPTGB_cjs.adjustForInflation(amountValue.toNumber(), fromYear, toYear);
5131
5262
  if (result === void 0) return yearRangeError("INFLATION_YEAR_OUT_OF_RANGE", toYear);
5132
- return amountValue.type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(result, amountValue.unit) : chunkOC6LTXYS_cjs.numberValue(result);
5263
+ return amountValue.type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(result, amountValue.unit) : chunkJMXUNXQS_cjs.numberValue(result);
5133
5264
  }
5134
5265
  function inflationFutureValueHandler(args) {
5135
5266
  const amountValue = args[0];
@@ -5137,25 +5268,36 @@ function inflationFutureValueHandler(args) {
5137
5268
  const rate = args[2].toNumber();
5138
5269
  const years = futureYear - (/* @__PURE__ */ new Date()).getFullYear();
5139
5270
  if (1 + rate <= 0) {
5140
- return chunkOC6LTXYS_cjs.errorValue("INVALID_RATE", `inflationFutureValue: rate ${rate} makes (1 + rate) non-positive`);
5271
+ return chunkJMXUNXQS_cjs.errorValue("INVALID_RATE", `inflationFutureValue: rate ${rate} makes (1 + rate) non-positive`);
5141
5272
  }
5142
5273
  const amount = amountValue.toNumber();
5143
5274
  const worth = amount / Math.pow(1 + rate, years);
5144
- return amountValue.type === 6 /* Uom */ ? chunkOC6LTXYS_cjs.uomValue(worth, amountValue.unit) : chunkOC6LTXYS_cjs.numberValue(worth);
5275
+ return amountValue.type === 6 /* Uom */ ? chunkJMXUNXQS_cjs.uomValue(worth, amountValue.unit) : chunkJMXUNXQS_cjs.numberValue(worth);
5145
5276
  }
5146
5277
 
5147
5278
  // src/packages/finance/parselets/InflationQueryParselet.ts
5148
5279
  var INFLATION_ADJUST_BUILTIN_IDX = 60;
5280
+ function hasInflationKeyword(parser) {
5281
+ for (let offset = 0; ; offset++) {
5282
+ const token = parser.peekAt(offset);
5283
+ if (!token) return false;
5284
+ if (token.type === "FROM" || token.type === "WORTH_IN") return true;
5285
+ }
5286
+ }
5149
5287
  var InflationQueryParselet = class {
5150
5288
  constructor(variant) {
5151
5289
  this.variant = variant;
5152
5290
  this.category = "Finance";
5153
5291
  }
5154
5292
  parse(parser, _token, builder) {
5155
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
5293
+ if (!hasInflationKeyword(parser)) {
5294
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5295
+ return;
5296
+ }
5297
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
5156
5298
  if (this.variant === "what-was") {
5157
5299
  parser.consume("WORTH_IN");
5158
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5300
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5159
5301
  builder.emitOpcode(50 /* CALL_PLUGIN */);
5160
5302
  builder.emitIndex(INFLATION_TO_YEAR_FROM_PRESENT_IDX);
5161
5303
  builder.emitIndex(2);
@@ -5164,7 +5306,7 @@ var InflationQueryParselet = class {
5164
5306
  const next = parser.peek();
5165
5307
  if (next?.type === "FROM") {
5166
5308
  parser.consume();
5167
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5309
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5168
5310
  builder.emitOpcode(50 /* CALL_PLUGIN */);
5169
5311
  builder.emitIndex(INFLATION_FROM_YEAR_TO_PRESENT_IDX);
5170
5312
  builder.emitIndex(2);
@@ -5172,16 +5314,16 @@ var InflationQueryParselet = class {
5172
5314
  }
5173
5315
  if (next?.type === "IN") {
5174
5316
  parser.consume();
5175
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5317
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5176
5318
  parser.consume("WORTH_IN");
5177
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5319
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5178
5320
  builder.emitOpcode(51 /* CALL_BUILTIN */);
5179
5321
  builder.emitIndex(INFLATION_ADJUST_BUILTIN_IDX);
5180
5322
  builder.emitIndex(3);
5181
5323
  return;
5182
5324
  }
5183
5325
  const gotType = next ? next.type : "end of input";
5184
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5326
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5185
5327
  "INFLATION_EXPECTED_FROM_OR_IN",
5186
5328
  `Expected "from <year>" or "in <year> worth in <year>" after "what is <amount>", got ${gotType}`
5187
5329
  );
@@ -5194,16 +5336,16 @@ var InflationFutureValueParselet = class {
5194
5336
  this.category = "Finance";
5195
5337
  }
5196
5338
  parse(parser, _token, builder) {
5197
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
5339
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
5198
5340
  parser.consume("IN");
5199
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5341
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5200
5342
  parser.consume("ASSUMING");
5201
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Lowest, builder);
5343
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Lowest, builder);
5202
5344
  const inflationToken = parser.peek();
5203
5345
  const inflationWord = inflationToken && inflationToken.type === "IDENT" ? inflationToken.value.toLowerCase() : void 0;
5204
5346
  if (inflationWord !== "inflation") {
5205
5347
  const got = inflationToken ? inflationToken.value : "end of input";
5206
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5348
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5207
5349
  "INFLATION_EXPECTED_INFLATION_WORD",
5208
5350
  `Expected the word "inflation" after "assuming <rate>%", got "${got}"`
5209
5351
  );
@@ -5247,7 +5389,7 @@ function inYearDollarsNormalizerRule(priority = 70) {
5247
5389
  if (word !== "dollars" && word !== "dollar") return null;
5248
5390
  return {
5249
5391
  consumed: 3,
5250
- replacement: [chunkAHCLWAM5_cjs.createFusedToken("IN_YEAR_DOLLARS", yearToken.value, tokens.slice(pos, pos + 3))],
5392
+ replacement: [chunkBHTNFEGZ_cjs.createFusedToken("IN_YEAR_DOLLARS", yearToken.value, tokens.slice(pos, pos + 3))],
5251
5393
  ruleName: "finance:in-year-dollars"
5252
5394
  };
5253
5395
  }
@@ -5341,7 +5483,7 @@ var FINANCE_PACKAGE = {
5341
5483
 
5342
5484
  // src/resolvers/QueryResolver.ts
5343
5485
  function defaultOnError(namespace) {
5344
- return (query, error) => chunkOC6LTXYS_cjs.errorValue(
5486
+ return (query, error) => chunkJMXUNXQS_cjs.errorValue(
5345
5487
  `${namespace.toUpperCase()}_QUERY_FAILED`,
5346
5488
  `Failed to resolve "${query}": ${error instanceof Error ? error.message : String(error)}`
5347
5489
  );
@@ -5396,7 +5538,7 @@ function createQueryResolver(opts) {
5396
5538
  i += 3;
5397
5539
  continue;
5398
5540
  }
5399
- i = chunk4AVD7NZW_cjs.nextInstruction(opcodes, i);
5541
+ i = chunk4B2CNWQU_cjs.nextInstruction(opcodes, i);
5400
5542
  }
5401
5543
  return null;
5402
5544
  },
@@ -5407,7 +5549,7 @@ function createQueryResolver(opts) {
5407
5549
  const query = args[0]?.value;
5408
5550
  const cached = chunkZ2XP767T_cjs.getActiveQueryClient()?.getQueryData(queryKeyFor(query));
5409
5551
  if (cached !== void 0) return cached;
5410
- return chunkOC6LTXYS_cjs.errorValue(`${opts.namespace.toUpperCase()}_NOT_PREFLIGHTED`, `No cached result for "${query}"`);
5552
+ return chunkJMXUNXQS_cjs.errorValue(`${opts.namespace.toUpperCase()}_NOT_PREFLIGHTED`, `No cached result for "${query}"`);
5411
5553
  };
5412
5554
  return { resolver, pluginFunction };
5413
5555
  }
@@ -5419,7 +5561,7 @@ function consumeCityName(parser, triggerText) {
5419
5561
  words.push(parser.consume().value);
5420
5562
  }
5421
5563
  if (words.length === 0) {
5422
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5564
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5423
5565
  "WEATHER_EXPECTED_CITY",
5424
5566
  `Expected a city name after "${triggerText}" (e.g. "${triggerText} London")`
5425
5567
  );
@@ -5495,7 +5637,7 @@ async function geocodeCity(city, signal) {
5495
5637
  const url = `${GEOCODING_API_URL}?name=${encodeURIComponent(city)}&count=1&language=en&format=json`;
5496
5638
  const response = await fetch(url, { signal });
5497
5639
  if (!response.ok) {
5498
- throw chunkM4N5GA5Z_cjs.ErrorFactory.external(
5640
+ throw chunk5KMIY374_cjs.ErrorFactory.external(
5499
5641
  WeatherErrorCodes.GEOCODING_API_ERROR,
5500
5642
  `Open-Meteo geocoding API returned ${response.status} for "${city}"`,
5501
5643
  { city, status: response.status }
@@ -5504,7 +5646,7 @@ async function geocodeCity(city, signal) {
5504
5646
  const json = await response.json();
5505
5647
  const first = json?.results?.[0];
5506
5648
  if (!first) {
5507
- throw chunkM4N5GA5Z_cjs.ErrorFactory.validation(
5649
+ throw chunk5KMIY374_cjs.ErrorFactory.validation(
5508
5650
  WeatherErrorCodes.CITY_NOT_FOUND,
5509
5651
  `No location found for "${city}"`,
5510
5652
  { city }
@@ -5523,7 +5665,7 @@ async function fetchForecast(lat, lon, signal) {
5523
5665
  });
5524
5666
  const response = await fetch(`${FORECAST_API_URL}?${params.toString()}`, { signal });
5525
5667
  if (!response.ok) {
5526
- throw chunkM4N5GA5Z_cjs.ErrorFactory.external(
5668
+ throw chunk5KMIY374_cjs.ErrorFactory.external(
5527
5669
  WeatherErrorCodes.FORECAST_API_ERROR,
5528
5670
  `Open-Meteo forecast API returned ${response.status}`,
5529
5671
  { status: response.status }
@@ -5533,7 +5675,7 @@ async function fetchForecast(lat, lon, signal) {
5533
5675
  const current = json?.current;
5534
5676
  const daily = json?.daily;
5535
5677
  if (!current || !daily) {
5536
- throw chunkM4N5GA5Z_cjs.ErrorFactory.external(
5678
+ throw chunk5KMIY374_cjs.ErrorFactory.external(
5537
5679
  WeatherErrorCodes.FORECAST_RESPONSE_MALFORMED,
5538
5680
  "Open-Meteo forecast response missing current/daily blocks"
5539
5681
  );
@@ -5584,7 +5726,7 @@ function fetchCityWeather(city, signal) {
5584
5726
  }
5585
5727
 
5586
5728
  // src/packages/weather/WeatherPackage.ts
5587
- var WEATHER_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
5729
+ var WEATHER_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
5588
5730
  var { resolver: weatherResolver, pluginFunction: weatherPluginFunction } = createQueryResolver({
5589
5731
  namespace: "weather",
5590
5732
  pluginFunctionIndex: WEATHER_FN_IDX,
@@ -5597,17 +5739,17 @@ var { resolver: weatherResolver, pluginFunction: weatherPluginFunction } = creat
5597
5739
  const data = await fetchCityWeather(city, signal);
5598
5740
  switch (kind) {
5599
5741
  case "current":
5600
- return chunkOC6LTXYS_cjs.stringValue(`${Math.round(data.temperature)}\xB0C, ${data.description}`);
5742
+ return chunkJMXUNXQS_cjs.stringValue(`${Math.round(data.temperature)}\xB0C, ${data.description}`);
5601
5743
  case "temperature":
5602
- return chunkOC6LTXYS_cjs.uomValue(data.temperature, "C");
5744
+ return chunkJMXUNXQS_cjs.uomValue(data.temperature, "C");
5603
5745
  case "feelslike":
5604
- return chunkOC6LTXYS_cjs.uomValue(data.apparentTemperature, "C");
5746
+ return chunkJMXUNXQS_cjs.uomValue(data.apparentTemperature, "C");
5605
5747
  case "high":
5606
- return chunkOC6LTXYS_cjs.uomValue(data.high, "C");
5748
+ return chunkJMXUNXQS_cjs.uomValue(data.high, "C");
5607
5749
  case "low":
5608
- return chunkOC6LTXYS_cjs.uomValue(data.low, "C");
5750
+ return chunkJMXUNXQS_cjs.uomValue(data.low, "C");
5609
5751
  default:
5610
- throw chunkM4N5GA5Z_cjs.ErrorFactory.internal(
5752
+ throw chunk5KMIY374_cjs.ErrorFactory.internal(
5611
5753
  WeatherErrorCodes.UNKNOWN_QUERY_KIND,
5612
5754
  `Unknown weather query kind "${kind}"`,
5613
5755
  { kind }
@@ -5670,7 +5812,7 @@ function pad2(n) {
5670
5812
  function validateAndFormat(year, monthIndex, day, raw) {
5671
5813
  const d = new Date(year, monthIndex, day);
5672
5814
  if (d.getFullYear() !== year || d.getMonth() !== monthIndex || d.getDate() !== day) {
5673
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5815
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5674
5816
  "STOCKS_INVALID_DATE",
5675
5817
  `"${raw}" is not a valid calendar date`
5676
5818
  );
@@ -5679,7 +5821,7 @@ function validateAndFormat(year, monthIndex, day, raw) {
5679
5821
  }
5680
5822
  function requireYear(text, raw) {
5681
5823
  if (!/^\d{4}$/.test(text)) {
5682
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5824
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5683
5825
  "STOCKS_INVALID_DATE",
5684
5826
  `Expected a 4-digit year in "${raw}", got "${text}"`
5685
5827
  );
@@ -5736,7 +5878,7 @@ function tryParseDatePhrase(parser) {
5736
5878
  const year = requireYear(yearTok.value, raw);
5737
5879
  return validateAndFormat(year, monthIndex, parseInt(g1.value, 10), raw);
5738
5880
  }
5739
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
5881
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5740
5882
  "STOCKS_INVALID_DATE",
5741
5883
  `Expected a date after "on" (e.g. "April 12, 2005" or "4/12/2005"), got "${g1.value}"`
5742
5884
  );
@@ -5823,7 +5965,7 @@ var MAJOR_TICKERS = /* @__PURE__ */ new Set([
5823
5965
 
5824
5966
  // src/packages/stocks/normalizer/StockTickerNormalizerRule.ts
5825
5967
  var STOCK_TICKER_TYPE = "STOCK_TICKER";
5826
- var STOCK_TICKER_TYPE_ID = chunkR24DI24X_cjs.tokenTypeId(STOCK_TICKER_TYPE);
5968
+ var STOCK_TICKER_TYPE_ID = chunk5LI5EPGJ_cjs.tokenTypeId(STOCK_TICKER_TYPE);
5827
5969
  function stockTickerNormalizerRule() {
5828
5970
  return {
5829
5971
  name: "stocks:bare-ticker",
@@ -5833,7 +5975,7 @@ function stockTickerNormalizerRule() {
5833
5975
  if (!token || token.type !== "IDENT") return null;
5834
5976
  if (!MAJOR_TICKERS.has(token.value)) return null;
5835
5977
  if (pos > 0 && tokens[pos - 1].type === "COLON") return null;
5836
- const fusedToken = new chunkM4F66R4O_cjs.LexerToken(
5978
+ const fusedToken = new chunkYWQ6V4ZN_cjs.LexerToken(
5837
5979
  STOCK_TICKER_TYPE,
5838
5980
  STOCK_TICKER_TYPE_ID,
5839
5981
  token.value,
@@ -5859,7 +6001,7 @@ function tryParseDateSuffix(parser) {
5859
6001
  parser.consume();
5860
6002
  const onTok = parser.peek();
5861
6003
  if (!onTok || onTok.type !== "IDENT" || onTok.value.toLowerCase() !== "on") {
5862
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
6004
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5863
6005
  "STOCKS_EXPECTED_ON",
5864
6006
  `Expected "on <date>" after "${lower}" (e.g. "AAPL ${lower} on April 12, 2005")`
5865
6007
  );
@@ -5872,7 +6014,7 @@ function tryParseDateSuffix(parser) {
5872
6014
  }
5873
6015
  const date = tryParseDatePhrase(parser);
5874
6016
  if (!date) {
5875
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
6017
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5876
6018
  "STOCKS_EXPECTED_DATE",
5877
6019
  `Expected a date after "on" (e.g. "April 12, 2005" or "4/12/2005")`
5878
6020
  );
@@ -5902,7 +6044,7 @@ function finishStockExpression(parser, builder, ticker, currentFnIdx, historical
5902
6044
  const suffix = tryParseDateSuffix(parser);
5903
6045
  if (sawStar && !suffix) {
5904
6046
  emitStockQuery(builder, ticker, null, currentFnIdx, historicalFnIdx);
5905
- parser.parseExpression(chunkNZFKROS7_cjs.BindingPower.Product, builder);
6047
+ parser.parseExpression(chunkPA4VC73I_cjs.BindingPower.Product, builder);
5906
6048
  builder.emitOpcode(22 /* MUL */);
5907
6049
  return;
5908
6050
  }
@@ -5916,11 +6058,11 @@ function stockFnParselet(currentFnIdx, historicalFnIdx) {
5916
6058
  const tickerToken = parser.consume();
5917
6059
  let ticker;
5918
6060
  if (tickerToken.type === "STRING") {
5919
- ticker = chunkN5YFR4UP_cjs.stripQuotes(tickerToken.value).toUpperCase();
6061
+ ticker = chunkADBA3XBE_cjs.stripQuotes(tickerToken.value).toUpperCase();
5920
6062
  } else if (tickerToken.type === "IDENT" || tickerToken.type === STOCK_TICKER_TYPE) {
5921
6063
  ticker = tickerToken.value.toUpperCase();
5922
6064
  } else {
5923
- throw chunkM4N5GA5Z_cjs.ErrorFactory.parsing(
6065
+ throw chunk5KMIY374_cjs.ErrorFactory.parsing(
5924
6066
  "STOCKS_INVALID_TICKER",
5925
6067
  `Expected a ticker symbol inside stock(...), got "${tickerToken.value}" (${tickerToken.type})`
5926
6068
  );
@@ -5942,10 +6084,10 @@ function bareStockTickerParselet(currentFnIdx, historicalFnIdx) {
5942
6084
 
5943
6085
  // src/packages/stocks/StocksPackage.ts
5944
6086
  function createStocksPackage(config = {}) {
5945
- const currentFnIdx = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
5946
- const historicalFnIdx = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6087
+ const currentFnIdx = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6088
+ const historicalFnIdx = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
5947
6089
  function notConfigured(what) {
5948
- return chunkOC6LTXYS_cjs.errorValue(
6090
+ return chunkJMXUNXQS_cjs.errorValue(
5949
6091
  "STOCKS_NOT_CONFIGURED",
5950
6092
  `Stock data provider not configured. Supply ${what} via createStocksPackage({ ... }); see the StocksPackage doc comment.`
5951
6093
  );
@@ -5958,7 +6100,7 @@ function createStocksPackage(config = {}) {
5958
6100
  fetchQuery: async (ticker, signal) => {
5959
6101
  if (!config.fetchQuote) return notConfigured("fetchQuote");
5960
6102
  const quote = await config.fetchQuote(ticker, signal);
5961
- return chunkOC6LTXYS_cjs.uomValue(quote.price, quote.currency ?? "USD");
6103
+ return chunkJMXUNXQS_cjs.uomValue(quote.price, quote.currency ?? "USD");
5962
6104
  }
5963
6105
  });
5964
6106
  const { resolver: historicalResolver, pluginFunction: historicalPluginFunction } = createQueryResolver({
@@ -5970,8 +6112,8 @@ function createStocksPackage(config = {}) {
5970
6112
  const [field, ticker, isoDate] = query.split(":");
5971
6113
  if (!config.fetchHistoricalQuote) return notConfigured("fetchHistoricalQuote");
5972
6114
  const quote = await config.fetchHistoricalQuote(ticker, isoDate, signal);
5973
- if (field === "volume") return chunkOC6LTXYS_cjs.numberValue(quote.volume ?? 0);
5974
- return chunkOC6LTXYS_cjs.uomValue(quote.close, quote.currency ?? "USD");
6115
+ if (field === "volume") return chunkJMXUNXQS_cjs.numberValue(quote.volume ?? 0);
6116
+ return chunkJMXUNXQS_cjs.uomValue(quote.close, quote.currency ?? "USD");
5975
6117
  }
5976
6118
  });
5977
6119
  const pkg = {
@@ -6018,20 +6160,20 @@ function knowledgeQueryParselet(pluginFnIdx) {
6018
6160
 
6019
6161
  // src/packages/knowledge/KnowledgePackage.ts
6020
6162
  function createKnowledgePackage(config = {}) {
6021
- const fnIdx = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6163
+ const fnIdx = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6022
6164
  const { resolver, pluginFunction } = createQueryResolver({
6023
6165
  namespace: "knowledge",
6024
6166
  pluginFunctionIndex: fnIdx,
6025
6167
  staleTimeMs: config.staleTimeMs ?? 5 * 60 * 1e3,
6026
6168
  fetchQuery: async (query, signal) => {
6027
6169
  if (!config.answerQuery) {
6028
- return chunkOC6LTXYS_cjs.errorValue(
6170
+ return chunkJMXUNXQS_cjs.errorValue(
6029
6171
  "KNOWLEDGE_NOT_CONFIGURED",
6030
6172
  `Knowledge answer provider not configured. Supply answerQuery via createKnowledgePackage({ ... }); see the KnowledgePackage doc comment.`
6031
6173
  );
6032
6174
  }
6033
6175
  const answer = await config.answerQuery(query, signal);
6034
- return chunkOC6LTXYS_cjs.stringValue(answer);
6176
+ return chunkJMXUNXQS_cjs.stringValue(answer);
6035
6177
  }
6036
6178
  });
6037
6179
  return {
@@ -6058,23 +6200,23 @@ function createKnowledgePackage(config = {}) {
6058
6200
  // src/packages/lines/LinesPluginFunctions.ts
6059
6201
  function checkLineValue(v, lineNumber) {
6060
6202
  if (v === void 0) {
6061
- return chunkOC6LTXYS_cjs.errorValue("LINE_NOT_YET_EVALUATED", `Line ${lineNumber} has not been evaluated yet (forward reference, or out of range)`);
6203
+ return chunkJMXUNXQS_cjs.errorValue("LINE_NOT_YET_EVALUATED", `Line ${lineNumber} has not been evaluated yet (forward reference, or out of range)`);
6062
6204
  }
6063
6205
  if (v.type === 12 /* Pending */) {
6064
- return chunkOC6LTXYS_cjs.errorValue("LINE_RESULT_PENDING", `Line ${lineNumber}'s result is still resolving`);
6206
+ return chunkJMXUNXQS_cjs.errorValue("LINE_RESULT_PENDING", `Line ${lineNumber}'s result is still resolving`);
6065
6207
  }
6066
6208
  if (v.type === 13 /* Error */) {
6067
- return chunkOC6LTXYS_cjs.errorValue("LINE_RESULT_ERROR", `Line ${lineNumber} has an error`);
6209
+ return chunkJMXUNXQS_cjs.errorValue("LINE_RESULT_ERROR", `Line ${lineNumber} has an error`);
6068
6210
  }
6069
6211
  return null;
6070
6212
  }
6071
6213
  function requireContext(context) {
6072
6214
  if (!context?.getLineResult) {
6073
- return chunkOC6LTXYS_cjs.errorValue("LINE_REF_NO_DOCUMENT", "Cross-line references require a real document \u2014 not available outside one (e.g. evaluateExpression()'s single-expression path)");
6215
+ return chunkJMXUNXQS_cjs.errorValue("LINE_REF_NO_DOCUMENT", "Cross-line references require a real document \u2014 not available outside one (e.g. evaluateExpression()'s single-expression path)");
6074
6216
  }
6075
6217
  return null;
6076
6218
  }
6077
- var PREV_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6219
+ var PREV_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6078
6220
  function prevHandler(_args, context) {
6079
6221
  const ctxError = requireContext(context);
6080
6222
  if (ctxError) return ctxError;
@@ -6083,7 +6225,7 @@ function prevHandler(_args, context) {
6083
6225
  const err = checkLineValue(v, targetLine);
6084
6226
  return err ?? v;
6085
6227
  }
6086
- var LINE_REF_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6228
+ var LINE_REF_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6087
6229
  function lineRefHandler(args, context) {
6088
6230
  const ctxError = requireContext(context);
6089
6231
  if (ctxError) return ctxError;
@@ -6103,28 +6245,28 @@ function aggregateRange(from, to, context, isAverage) {
6103
6245
  const err = checkLineValue(v, n);
6104
6246
  if (err) return err;
6105
6247
  if (v.type !== 0 /* Number */ && v.type !== 6 /* Uom */) {
6106
- return chunkOC6LTXYS_cjs.errorValue("LINE_RANGE_NON_NUMERIC", `Line ${n} is not a plain number or unit value \u2014 cannot include it in a sum/total/average range`);
6248
+ return chunkJMXUNXQS_cjs.errorValue("LINE_RANGE_NON_NUMERIC", `Line ${n} is not a plain number or unit value \u2014 cannot include it in a sum/total/average range`);
6107
6249
  }
6108
6250
  if (v.type === 6 /* Uom */) {
6109
6251
  sawUom = true;
6110
6252
  if (commonUnit === void 0) commonUnit = v.unit;
6111
6253
  else if (v.unit !== commonUnit) {
6112
- return chunkOC6LTXYS_cjs.errorValue("LINE_RANGE_MIXED_UNITS", `Line ${n}'s unit (${v.unit}) doesn't match the range's first unit (${commonUnit}) \u2014 aggregating mixed units would silently misrepresent the result`);
6254
+ return chunkJMXUNXQS_cjs.errorValue("LINE_RANGE_MIXED_UNITS", `Line ${n}'s unit (${v.unit}) doesn't match the range's first unit (${commonUnit}) \u2014 aggregating mixed units would silently misrepresent the result`);
6113
6255
  }
6114
6256
  }
6115
6257
  total += v.toNumber();
6116
6258
  count++;
6117
6259
  }
6118
6260
  const result = isAverage ? total / count : total;
6119
- return sawUom ? chunkOC6LTXYS_cjs.uomValue(result, commonUnit) : chunkOC6LTXYS_cjs.numberValue(result);
6261
+ return sawUom ? chunkJMXUNXQS_cjs.uomValue(result, commonUnit) : chunkJMXUNXQS_cjs.numberValue(result);
6120
6262
  }
6121
- var SUM_RANGE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6263
+ var SUM_RANGE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6122
6264
  function sumRangeHandler(args, context) {
6123
6265
  const ctxError = requireContext(context);
6124
6266
  if (ctxError) return ctxError;
6125
6267
  return aggregateRange(args[0].toNumber(), args[1].toNumber(), context, false);
6126
6268
  }
6127
- var AVERAGE_RANGE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6269
+ var AVERAGE_RANGE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6128
6270
  function averageRangeHandler(args, context) {
6129
6271
  const ctxError = requireContext(context);
6130
6272
  if (ctxError) return ctxError;
@@ -6133,7 +6275,7 @@ function averageRangeHandler(args, context) {
6133
6275
  function aggregateAbove(context, isAverage) {
6134
6276
  const boundaryCheck = context.isLineBoundary;
6135
6277
  if (!boundaryCheck) {
6136
- return chunkOC6LTXYS_cjs.errorValue("LINE_REF_NO_DOCUMENT", '"above" aggregation requires a real document');
6278
+ return chunkJMXUNXQS_cjs.errorValue("LINE_REF_NO_DOCUMENT", '"above" aggregation requires a real document');
6137
6279
  }
6138
6280
  let total = 0;
6139
6281
  let count = 0;
@@ -6145,29 +6287,29 @@ function aggregateAbove(context, isAverage) {
6145
6287
  const err = checkLineValue(v, n);
6146
6288
  if (err) return err;
6147
6289
  if (v.type !== 0 /* Number */ && v.type !== 6 /* Uom */) {
6148
- return chunkOC6LTXYS_cjs.errorValue("LINE_RANGE_NON_NUMERIC", `Line ${n} is not a plain number or unit value \u2014 cannot include it in "above" aggregation`);
6290
+ return chunkJMXUNXQS_cjs.errorValue("LINE_RANGE_NON_NUMERIC", `Line ${n} is not a plain number or unit value \u2014 cannot include it in "above" aggregation`);
6149
6291
  }
6150
6292
  if (v.type === 6 /* Uom */) {
6151
6293
  sawUom = true;
6152
6294
  if (commonUnit === void 0) commonUnit = v.unit;
6153
6295
  else if (v.unit !== commonUnit) {
6154
- return chunkOC6LTXYS_cjs.errorValue("LINE_RANGE_MIXED_UNITS", `Line ${n}'s unit (${v.unit}) doesn't match the range's unit (${commonUnit})`);
6296
+ return chunkJMXUNXQS_cjs.errorValue("LINE_RANGE_MIXED_UNITS", `Line ${n}'s unit (${v.unit}) doesn't match the range's unit (${commonUnit})`);
6155
6297
  }
6156
6298
  }
6157
6299
  total += v.toNumber();
6158
6300
  count++;
6159
6301
  }
6160
- if (count === 0) return chunkOC6LTXYS_cjs.errorValue("LINE_RANGE_EMPTY", "No lines above to aggregate (hit the top of the document, a blank line, or a heading immediately)");
6302
+ if (count === 0) return chunkJMXUNXQS_cjs.errorValue("LINE_RANGE_EMPTY", "No lines above to aggregate (hit the top of the document, a blank line, or a heading immediately)");
6161
6303
  const result = isAverage ? total / count : total;
6162
- return sawUom ? chunkOC6LTXYS_cjs.uomValue(result, commonUnit) : chunkOC6LTXYS_cjs.numberValue(result);
6304
+ return sawUom ? chunkJMXUNXQS_cjs.uomValue(result, commonUnit) : chunkJMXUNXQS_cjs.numberValue(result);
6163
6305
  }
6164
- var TOTAL_ABOVE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6306
+ var TOTAL_ABOVE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6165
6307
  function totalAboveHandler(_args, context) {
6166
6308
  const ctxError = requireContext(context);
6167
6309
  if (ctxError) return ctxError;
6168
6310
  return aggregateAbove(context, false);
6169
6311
  }
6170
- var AVERAGE_ABOVE_FN_IDX = chunkBXKJLM5R_cjs.allocatePluginFunctionIndex();
6312
+ var AVERAGE_ABOVE_FN_IDX = chunk6WFMPTGB_cjs.allocatePluginFunctionIndex();
6171
6313
  function averageAboveHandler(_args, context) {
6172
6314
  const ctxError = requireContext(context);
6173
6315
  if (ctxError) return ctxError;
@@ -6239,9 +6381,9 @@ var AboveAggregateParselet = class {
6239
6381
  };
6240
6382
 
6241
6383
  // src/packages/lines/normalizer/LineRefNormalizerRule.ts
6242
- var LINE_REF_TYPE_ID = chunkR24DI24X_cjs.tokenTypeId("LINE_REF");
6243
- var SUM_RANGE_CALL_TYPE_ID = chunkR24DI24X_cjs.tokenTypeId("SUM_RANGE_CALL");
6244
- var AVERAGE_RANGE_CALL_TYPE_ID = chunkR24DI24X_cjs.tokenTypeId("AVERAGE_RANGE_CALL");
6384
+ var LINE_REF_TYPE_ID = chunk5LI5EPGJ_cjs.tokenTypeId("LINE_REF");
6385
+ var SUM_RANGE_CALL_TYPE_ID = chunk5LI5EPGJ_cjs.tokenTypeId("SUM_RANGE_CALL");
6386
+ var AVERAGE_RANGE_CALL_TYPE_ID = chunk5LI5EPGJ_cjs.tokenTypeId("AVERAGE_RANGE_CALL");
6245
6387
  function lineRefNormalizerRule() {
6246
6388
  return {
6247
6389
  name: "lines:line-ref",
@@ -6278,7 +6420,7 @@ function lineRefNormalizerRule() {
6278
6420
  };
6279
6421
  }
6280
6422
  function makeLineRefToken(lineNumberText, sourceToken) {
6281
- return new chunkM4F66R4O_cjs.LexerToken(
6423
+ return new chunkYWQ6V4ZN_cjs.LexerToken(
6282
6424
  "LINE_REF",
6283
6425
  LINE_REF_TYPE_ID,
6284
6426
  lineNumberText,
@@ -6304,7 +6446,7 @@ function rangeCallNormalizerRule() {
6304
6446
  return {
6305
6447
  consumed: 1,
6306
6448
  replacement: [
6307
- new chunkM4F66R4O_cjs.LexerToken(tokenType, typeId, token.value, token.value, token.offset, 0, token.line, token.col)
6449
+ new chunkYWQ6V4ZN_cjs.LexerToken(tokenType, typeId, token.value, token.value, token.offset, 0, token.line, token.col)
6308
6450
  ],
6309
6451
  ruleName: "lines:range-call"
6310
6452
  };
@@ -6391,5 +6533,5 @@ exports.WEATHER_PACKAGE = WEATHER_PACKAGE;
6391
6533
  exports.containsSymbolicCall = containsSymbolicCall;
6392
6534
  exports.createKnowledgePackage = createKnowledgePackage;
6393
6535
  exports.createStocksPackage = createStocksPackage;
6394
- //# sourceMappingURL=chunk-CSG5XVNJ.cjs.map
6395
- //# sourceMappingURL=chunk-CSG5XVNJ.cjs.map
6536
+ //# sourceMappingURL=chunk-3AFRJYP4.cjs.map
6537
+ //# sourceMappingURL=chunk-3AFRJYP4.cjs.map