solve-engine 1.0.0-beta.2 → 1.0.0-beta.4

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 (171) hide show
  1. package/dist/{Lexer-D9l4Yrk2.d.ts → Lexer-Cfm79Dak.d.cts} +18 -2
  2. package/dist/{Lexer-BJdhlnej.d.cts → Lexer-W9MBOP0V.d.ts} +18 -2
  3. package/dist/{PackageRegistry-DaH4aIKP.d.ts → PackageRegistry-CjDt-Jy_.d.ts} +60 -4
  4. package/dist/{PackageRegistry-D-Tv_7ca.d.cts → PackageRegistry-pHtKythi.d.cts} +60 -4
  5. package/dist/{Parselet-CK8cQu2a.d.cts → Parselet-Cu0bLSis.d.cts} +1 -1
  6. package/dist/{Parselet-ConOIdRO.d.ts → Parselet-DEdF9I7n.d.ts} +1 -1
  7. package/dist/{Token-0jpvUdPY.d.cts → Token-BzG5G4ja.d.cts} +44 -0
  8. package/dist/{Token-0jpvUdPY.d.ts → Token-BzG5G4ja.d.ts} +44 -0
  9. package/dist/TokenNormalizer-DGVa24Q-.d.cts +377 -0
  10. package/dist/TokenNormalizer-t_GotBxr.d.ts +377 -0
  11. package/dist/{chunk-HWSZJQCI.js → chunk-2CS6OMZK.js} +37 -15
  12. package/dist/chunk-2CS6OMZK.js.map +1 -0
  13. package/dist/{chunk-XJCMXB2E.cjs → chunk-2MV4HBKC.cjs} +187 -61
  14. package/dist/chunk-2MV4HBKC.cjs.map +1 -0
  15. package/dist/{chunk-J73SJHR3.cjs → chunk-2NPS5DQ3.cjs} +558 -341
  16. package/dist/chunk-2NPS5DQ3.cjs.map +1 -0
  17. package/dist/{chunk-QWY3VEZN.js → chunk-3MNKQZ77.js} +65 -12
  18. package/dist/chunk-3MNKQZ77.js.map +1 -0
  19. package/dist/{chunk-RZCWSXTA.cjs → chunk-43G3JT2E.cjs} +1491 -218
  20. package/dist/chunk-43G3JT2E.cjs.map +1 -0
  21. package/dist/{chunk-WQTTOGXC.cjs → chunk-4AVD7NZW.cjs} +4 -4
  22. package/dist/{chunk-WQTTOGXC.cjs.map → chunk-4AVD7NZW.cjs.map} +1 -1
  23. package/dist/{chunk-HTXVVJRA.cjs → chunk-4CVLFLOB.cjs} +112 -2
  24. package/dist/chunk-4CVLFLOB.cjs.map +1 -0
  25. package/dist/{chunk-5YEMOYSE.js → chunk-6GCKCWLB.js} +9 -3
  26. package/dist/chunk-6GCKCWLB.js.map +1 -0
  27. package/dist/{chunk-EBSPLUW4.cjs → chunk-AHCLWAM5.cjs} +28 -10
  28. package/dist/chunk-AHCLWAM5.cjs.map +1 -0
  29. package/dist/{chunk-KVILKGMS.js → chunk-AJA6LUI7.js} +36 -2
  30. package/dist/chunk-AJA6LUI7.js.map +1 -0
  31. package/dist/{chunk-EHAHVROS.cjs → chunk-CLVQBF5C.cjs} +5 -5
  32. package/dist/{chunk-EHAHVROS.cjs.map → chunk-CLVQBF5C.cjs.map} +1 -1
  33. package/dist/{chunk-34RRD7PC.js → chunk-CYFK5SY2.js} +111 -3
  34. package/dist/chunk-CYFK5SY2.js.map +1 -0
  35. package/dist/{chunk-M5LX5AOO.js → chunk-DDQVZGLO.js} +25 -12
  36. package/dist/chunk-DDQVZGLO.js.map +1 -0
  37. package/dist/{chunk-LR7YASZF.cjs → chunk-EAAHVJ4P.cjs} +3 -3
  38. package/dist/chunk-EAAHVJ4P.cjs.map +1 -0
  39. package/dist/{chunk-3PPFLFH4.js → chunk-FIFQPKBA.js} +1417 -144
  40. package/dist/chunk-FIFQPKBA.js.map +1 -0
  41. package/dist/{chunk-RIN643A3.js → chunk-GPPLSM2Z.js} +61 -2
  42. package/dist/chunk-GPPLSM2Z.js.map +1 -0
  43. package/dist/{chunk-4QADQTWS.js → chunk-KHJUSHFU.js} +231 -14
  44. package/dist/chunk-KHJUSHFU.js.map +1 -0
  45. package/dist/{chunk-NMD5VRN4.cjs → chunk-M4F66R4O.cjs} +74 -73
  46. package/dist/chunk-M4F66R4O.cjs.map +1 -0
  47. package/dist/{chunk-6NTVRDQV.cjs → chunk-M4Q47KHF.cjs} +126 -73
  48. package/dist/chunk-M4Q47KHF.cjs.map +1 -0
  49. package/dist/{chunk-LIPPNDBE.js → chunk-M5E34VG5.js} +3 -3
  50. package/dist/{chunk-LIPPNDBE.js.map → chunk-M5E34VG5.js.map} +1 -1
  51. package/dist/{chunk-53B6KDDJ.cjs → chunk-MBNQVDVC.cjs} +38 -3
  52. package/dist/{chunk-53B6KDDJ.cjs.map → chunk-MBNQVDVC.cjs.map} +1 -1
  53. package/dist/{chunk-SDGRK7EP.js → chunk-MEOHSQEH.js} +6 -5
  54. package/dist/chunk-MEOHSQEH.js.map +1 -0
  55. package/dist/{chunk-NMCRQP3Z.cjs → chunk-MTX2KVU7.cjs} +71 -70
  56. package/dist/chunk-MTX2KVU7.cjs.map +1 -0
  57. package/dist/{chunk-QNJ4ACRT.cjs → chunk-NJTXJ5AG.cjs} +37 -15
  58. package/dist/chunk-NJTXJ5AG.cjs.map +1 -0
  59. package/dist/{chunk-C4XZV6E7.cjs → chunk-NZFKROS7.cjs} +26 -20
  60. package/dist/chunk-NZFKROS7.cjs.map +1 -0
  61. package/dist/{chunk-64W6GLLZ.js → chunk-OFXOTECC.js} +24 -6
  62. package/dist/chunk-OFXOTECC.js.map +1 -0
  63. package/dist/{chunk-3YNVWKR2.cjs → chunk-OUHT5Z36.cjs} +28 -5
  64. package/dist/chunk-OUHT5Z36.cjs.map +1 -0
  65. package/dist/{chunk-EIGTWK5N.js → chunk-OWRHDUJD.js} +3 -3
  66. package/dist/chunk-OWRHDUJD.js.map +1 -0
  67. package/dist/{chunk-4MG4XKO2.js → chunk-PCPX42KL.js} +38 -3
  68. package/dist/{chunk-4MG4XKO2.js.map → chunk-PCPX42KL.js.map} +1 -1
  69. package/dist/{chunk-GW32KPCU.cjs → chunk-R24DI24X.cjs} +61 -2
  70. package/dist/chunk-R24DI24X.cjs.map +1 -0
  71. package/dist/{chunk-XVWCOTR6.js → chunk-SFQWJMKT.js} +7 -6
  72. package/dist/chunk-SFQWJMKT.js.map +1 -0
  73. package/dist/{chunk-6BKTCEUP.cjs → chunk-TY3TLZAW.cjs} +36 -2
  74. package/dist/chunk-TY3TLZAW.cjs.map +1 -0
  75. package/dist/{chunk-DM3LMRBC.js → chunk-UKPGSAZW.js} +187 -61
  76. package/dist/chunk-UKPGSAZW.js.map +1 -0
  77. package/dist/{chunk-NH2O2AUR.js → chunk-WC5FFSHB.js} +26 -4
  78. package/dist/chunk-WC5FFSHB.js.map +1 -0
  79. package/dist/{chunk-CLL7RUQV.cjs → chunk-WWOLFXTX.cjs} +40 -18
  80. package/dist/chunk-WWOLFXTX.cjs.map +1 -0
  81. package/dist/{chunk-JBSYC7BB.cjs → chunk-X2BWAZAU.cjs} +66 -53
  82. package/dist/chunk-X2BWAZAU.cjs.map +1 -0
  83. package/dist/{chunk-GOLDJNMZ.js → chunk-XBTEO4OB.js} +28 -5
  84. package/dist/chunk-XBTEO4OB.js.map +1 -0
  85. package/dist/{chunk-EPOXXJBK.js → chunk-YU2CUNFO.js} +3 -3
  86. package/dist/{chunk-EPOXXJBK.js.map → chunk-YU2CUNFO.js.map} +1 -1
  87. package/dist/constants.cjs +4 -4
  88. package/dist/constants.js +1 -1
  89. package/dist/engine.cjs +29 -30
  90. package/dist/engine.d.cts +6 -6
  91. package/dist/engine.d.ts +6 -6
  92. package/dist/engine.js +19 -20
  93. package/dist/format.cjs +7 -8
  94. package/dist/format.cjs.map +1 -1
  95. package/dist/format.js +2 -3
  96. package/dist/format.js.map +1 -1
  97. package/dist/index.cjs +28 -29
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.d.cts +6 -6
  100. package/dist/index.d.ts +6 -6
  101. package/dist/index.js +20 -21
  102. package/dist/index.js.map +1 -1
  103. package/dist/language.cjs +74 -12
  104. package/dist/language.cjs.map +1 -1
  105. package/dist/language.d.cts +6 -6
  106. package/dist/language.d.ts +6 -6
  107. package/dist/language.js +68 -6
  108. package/dist/language.js.map +1 -1
  109. package/dist/lexer.cjs +19 -19
  110. package/dist/lexer.d.cts +3 -3
  111. package/dist/lexer.d.ts +3 -3
  112. package/dist/lexer.js +7 -7
  113. package/dist/normalizer.cjs +12 -12
  114. package/dist/normalizer.d.cts +4 -210
  115. package/dist/normalizer.d.ts +4 -210
  116. package/dist/normalizer.js +6 -6
  117. package/dist/packages.cjs +36 -37
  118. package/dist/packages.d.cts +5 -47
  119. package/dist/packages.d.ts +5 -47
  120. package/dist/packages.js +13 -14
  121. package/dist/parser.cjs +12 -12
  122. package/dist/parser.d.cts +3 -2
  123. package/dist/parser.d.ts +3 -2
  124. package/dist/parser.js +4 -4
  125. package/dist/resolvers.d.cts +1 -1
  126. package/dist/resolvers.d.ts +1 -1
  127. package/dist/uom.cjs +14 -14
  128. package/dist/uom.d.cts +12 -4
  129. package/dist/uom.d.ts +12 -4
  130. package/dist/uom.js +4 -4
  131. package/dist/vm.cjs +17 -17
  132. package/dist/vm.js +6 -6
  133. package/package.json +2 -1
  134. package/dist/NormalizerRule-BrVoVjmP.d.cts +0 -163
  135. package/dist/NormalizerRule-CEjf1FyD.d.ts +0 -163
  136. package/dist/chunk-34RRD7PC.js.map +0 -1
  137. package/dist/chunk-3PPFLFH4.js.map +0 -1
  138. package/dist/chunk-3YNVWKR2.cjs.map +0 -1
  139. package/dist/chunk-4QADQTWS.js.map +0 -1
  140. package/dist/chunk-5YEMOYSE.js.map +0 -1
  141. package/dist/chunk-64W6GLLZ.js.map +0 -1
  142. package/dist/chunk-6BKTCEUP.cjs.map +0 -1
  143. package/dist/chunk-6NTVRDQV.cjs.map +0 -1
  144. package/dist/chunk-C4XZV6E7.cjs.map +0 -1
  145. package/dist/chunk-CLL7RUQV.cjs.map +0 -1
  146. package/dist/chunk-DM3LMRBC.js.map +0 -1
  147. package/dist/chunk-EBSPLUW4.cjs.map +0 -1
  148. package/dist/chunk-EIGTWK5N.js.map +0 -1
  149. package/dist/chunk-GOLDJNMZ.js.map +0 -1
  150. package/dist/chunk-GW32KPCU.cjs.map +0 -1
  151. package/dist/chunk-HTXVVJRA.cjs.map +0 -1
  152. package/dist/chunk-HWSZJQCI.js.map +0 -1
  153. package/dist/chunk-J73SJHR3.cjs.map +0 -1
  154. package/dist/chunk-JBSYC7BB.cjs.map +0 -1
  155. package/dist/chunk-KVILKGMS.js.map +0 -1
  156. package/dist/chunk-LR7YASZF.cjs.map +0 -1
  157. package/dist/chunk-M5LX5AOO.js.map +0 -1
  158. package/dist/chunk-NH2O2AUR.js.map +0 -1
  159. package/dist/chunk-NMCRQP3Z.cjs.map +0 -1
  160. package/dist/chunk-NMD5VRN4.cjs.map +0 -1
  161. package/dist/chunk-OT6OJY7C.cjs +0 -114
  162. package/dist/chunk-OT6OJY7C.cjs.map +0 -1
  163. package/dist/chunk-QNJ4ACRT.cjs.map +0 -1
  164. package/dist/chunk-QWY3VEZN.js.map +0 -1
  165. package/dist/chunk-RFYD5TJE.js +0 -111
  166. package/dist/chunk-RFYD5TJE.js.map +0 -1
  167. package/dist/chunk-RIN643A3.js.map +0 -1
  168. package/dist/chunk-RZCWSXTA.cjs.map +0 -1
  169. package/dist/chunk-SDGRK7EP.js.map +0 -1
  170. package/dist/chunk-XJCMXB2E.cjs.map +0 -1
  171. package/dist/chunk-XVWCOTR6.js.map +0 -1
@@ -7,13 +7,16 @@ var enLocale = {
7
7
  e: "E",
8
8
  plus: "PLUS",
9
9
  add: "PLUS",
10
- and: "PLUS",
10
+ and: "AND_CONJ",
11
+ with: "PLUS",
11
12
  minus: "MINUS",
12
13
  subtract: "MINUS",
13
14
  remove: "MINUS",
14
15
  take: "MINUS",
16
+ without: "MINUS",
15
17
  times: "STAR",
16
18
  multiply: "STAR",
19
+ mul: "STAR",
17
20
  divide: "SLASH",
18
21
  modulo: "MOD",
19
22
  mod: "MOD",
@@ -65,6 +68,12 @@ var enLocale = {
65
68
  fround: "FUNC",
66
69
  hypot: "FUNC",
67
70
  imul: "FUNC",
71
+ sind: "FUNC",
72
+ cosd: "FUNC",
73
+ tand: "FUNC",
74
+ asind: "FUNC",
75
+ acosd: "FUNC",
76
+ atand: "FUNC",
68
77
  log10: "FUNC",
69
78
  log1p: "FUNC",
70
79
  log2: "FUNC",
@@ -119,10 +128,15 @@ var enLocale = {
119
128
  // sum(/total(/average( fusion), so `:map = [...]`/`:sum = 100`/etc.
120
129
  // keep working as ordinary variable names.
121
130
  clamp: "CLAMP",
131
+ // `into` is a third spelling of the conversion operator, alongside `to` and
132
+ // `in`. It reads better before a unit than either ("300 cm into m"), and
133
+ // costs nothing: it is not a plausible variable name and has no other
134
+ // meaning in the grammar.
122
135
  convert: "CONVERT",
123
136
  to: "TO",
124
137
  best: "BEST",
125
138
  in: "IN",
139
+ into: "IN",
126
140
  next: "NEXT",
127
141
  last: "LAST",
128
142
  until: "UNTIL",
@@ -143,6 +157,15 @@ var enLocale = {
143
157
  // see Token.ts's OVER/RATE_AT doc comment.
144
158
  over: "OVER",
145
159
  at: "RATE_AT",
160
+ // Only "rounded". Bare "round" is already the round(x) function above.
161
+ rounded: "ROUNDED",
162
+ is: "IS",
163
+ // The investment grammar (packages/finance/). See Token.ts.
164
+ after: "AFTER",
165
+ for: "FOR_DURATION",
166
+ compounding: "COMPOUNDING",
167
+ invested: "INVESTED",
168
+ returned: "RETURNED",
146
169
  by: "BY",
147
170
  vec2: "VEC2",
148
171
  vec3: "VEC3",
@@ -190,7 +213,7 @@ var deLocale = {
190
213
  e: "E",
191
214
  plus: "PLUS",
192
215
  add: "PLUS",
193
- und: "PLUS",
216
+ und: "AND_CONJ",
194
217
  minus: "MINUS",
195
218
  subtract: "MINUS",
196
219
  entfernen: "MINUS",
@@ -286,7 +309,7 @@ var frLocale = {
286
309
  e: "E",
287
310
  plus: "PLUS",
288
311
  ajouter: "PLUS",
289
- et: "PLUS",
312
+ et: "AND_CONJ",
290
313
  moins: "MINUS",
291
314
  soustraire: "MINUS",
292
315
  enlever: "MINUS",
@@ -364,5 +387,5 @@ function getLocale(code) {
364
387
  }
365
388
 
366
389
  export { getLocale };
367
- //# sourceMappingURL=chunk-GOLDJNMZ.js.map
368
- //# sourceMappingURL=chunk-GOLDJNMZ.js.map
390
+ //# sourceMappingURL=chunk-XBTEO4OB.js.map
391
+ //# sourceMappingURL=chunk-XBTEO4OB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants/locales/en.ts","../src/constants/locales/de.ts","../src/constants/locales/fr.ts","../src/constants/locales/index.ts"],"names":[],"mappings":"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","file":"chunk-XBTEO4OB.js","sourcesContent":["/** What a locale supplies: keywords, units, and number formatting conventions. */\nexport interface ILocale {\n code: string;\n label: string;\n keywordMap: Record<string, string>;\n display: {\n resultPrefix: string;\n dateFormat: string;\n decimalSeparator: string;\n thousandsSeparator: string;\n vectorFormat: string;\n percentageSuffix: string;\n };\n}\n\n/** English keywords, units and number formatting. The default and the fallback. */\nexport const enLocale: ILocale = {\n code: \"en\",\n label: \"English\",\n keywordMap: {\n pi: \"PI\", e: \"E\",\n plus: \"PLUS\", add: \"PLUS\", and: \"AND_CONJ\", with: \"PLUS\",\n minus: \"MINUS\", subtract: \"MINUS\", remove: \"MINUS\", take: \"MINUS\",\n without: \"MINUS\",\n times: \"STAR\", multiply: \"STAR\", mul: \"STAR\",\n divide: \"SLASH\",\n modulo: \"MOD\", mod: \"MOD\",\n exponent: \"CARET\", prime: \"CARET\",\n xor: \"BIT_XOR\",\n of: \"OF\",\n now: \"NOW\", today: \"TODAY\", tomorrow: \"TOMORROW\", yesterday: \"YESTERDAY\",\n roll: \"ROLL\",\n sqrt: \"FUNC\", abs: \"FUNC\", sin: \"FUNC\", cos: \"FUNC\", tan: \"FUNC\",\n log: \"FUNC\", ceil: \"FUNC\", floor: \"FUNC\", round: \"FUNC\", min: \"FUNC\", max: \"FUNC\",\n asin: \"FUNC\", acos: \"FUNC\", atan: \"FUNC\", atan2: \"FUNC\",\n // Long-form aliases for asin/acos/atan (Numi/older-calculator naming\n // convention). Same FunctionCallParselet indices, not new behavior.\n arcsin: \"FUNC\", arccos: \"FUNC\", arctan: \"FUNC\",\n sinh: \"FUNC\", cosh: \"FUNC\", tanh: \"FUNC\",\n asinh: \"FUNC\", acosh: \"FUNC\", atanh: \"FUNC\",\n cbrt: \"FUNC\", clz32: \"FUNC\", expm1: \"FUNC\", exp: \"FUNC\",\n // root(n, x) -- n-th root; fact/factorial(n) -- factorial. Bare FUNC\n // keywords, matching gcd/lcm/cbrt's precedent above (technical,\n // call-syntax-only names, not plausible :variableName choices).\n root: \"FUNC\", fact: \"FUNC\", factorial: \"FUNC\",\n fround: \"FUNC\", hypot: \"FUNC\", imul: \"FUNC\",\n sind: \"FUNC\", cosd: \"FUNC\", tand: \"FUNC\",\n asind: \"FUNC\", acosd: \"FUNC\", atand: \"FUNC\",\n log10: \"FUNC\", log1p: \"FUNC\", log2: \"FUNC\",\n pow: \"FUNC\", random: \"FUNC\", sign: \"FUNC\", trunc: \"FUNC\",\n degtorad: \"FUNC\", radtodeg: \"FUNC\",\n gcd: \"FUNC\", lcm: \"FUNC\", permutation: \"FUNC\", combination: \"FUNC\",\n // hex/bin double as CONVERTER_NAME below (\"255 as hex\") AND as FUNC\n // call-syntax (\"hex(255)\"), a word can only have one lexer token\n // type, so these win FUNC (removed from the CONVERTER_NAME list\n // below) and AsConverterParselet.ts's \"as <name>\" check was widened\n // to also accept a FUNC-typed token, preserving \"as hex\"/\"as bin\"\n // unchanged. See AsConverterParselet.ts's class doc for the full\n // reasoning.\n hex: \"FUNC\", bin: \"FUNC\", int: \"FUNC\",\n // Finance (packages/finance/) function-call forms. Bare keywords, not\n // phrase-fused, these are camelCase call-only names (e.g.\n // \"compoundInterest(...)\"), not natural-language words a user would\n // plausibly choose as a variable name, so the bare-keyword collision\n // risk that blocks \"interest\"/\"tax\"/\"principal\" etc. doesn't apply here\n // (matches \"gcd\"/\"lcm\"/... above, not \"clamp\" below).\n compoundinterest: \"FUNC\", interestearned: \"FUNC\",\n compoundinterestrate: \"FUNC\", compoundinterestyears: \"FUNC\",\n loanrepayment: \"FUNC\", loaninterest: \"FUNC\", monthlypayment: \"FUNC\",\n taxadd: \"FUNC\", taxremove: \"FUNC\",\n // Inflation-adjusted value function-call form (packages/finance/).\n inflationadjust: \"FUNC\",\n // Matrix (packages/matrix/) function-call forms -- also reachable via\n // `^T`/`^-1` operator syntax and `|a|` (see FunctionCallParselet.ts's\n // builtinNameToIndex comment for indices 63-66).\n transpose: \"FUNC\", det: \"FUNC\", inv: \"FUNC\", dot: \"FUNC\",\n // map/reduce/sum/prod (packages/mapreduce/) are NOT bare keywordMap\n // entries. See packages/mapreduce/normalizer/MapReduceCallNormalizerRule.ts\n // which fuses them ONLY when immediately followed by \"(\" (same\n // \"conditional-on-LPAREN\" pattern as packages/lines/'s own\n // sum(/total(/average( fusion), so `:map = [...]`/`:sum = 100`/etc.\n // keep working as ordinary variable names.\n clamp: \"CLAMP\",\n // `into` is a third spelling of the conversion operator, alongside `to` and\n // `in`. It reads better before a unit than either (\"300 cm into m\"), and\n // costs nothing: it is not a plausible variable name and has no other\n // meaning in the grammar.\n convert: \"CONVERT\", to: \"TO\", best: \"BEST\", in: \"IN\", into: \"IN\",\n next: \"NEXT\", last: \"LAST\", until: \"UNTIL\", since: \"SINCE\",\n sunday: \"SUNDAY\", monday: \"MONDAY\", tuesday: \"TUESDAY\", wednesday: \"WEDNESDAY\",\n thursday: \"THURSDAY\", friday: \"FRIDAY\", saturday: \"SATURDAY\",\n between: \"BETWEEN\", from: \"FROM\",\n increase: \"INCREASE\", decrease: \"DECREASE\",\n // Finance (packages/finance/) phrase-grammar connectors. Bare\n // prepositions, same accepted-risk category as \"between\"/\"from\" above\n // see Token.ts's OVER/RATE_AT doc comment.\n over: \"OVER\", at: \"RATE_AT\",\n // Only \"rounded\". Bare \"round\" is already the round(x) function above.\n rounded: \"ROUNDED\",\n is: \"IS\",\n // The investment grammar (packages/finance/). See Token.ts.\n after: \"AFTER\", for: \"FOR_DURATION\", compounding: \"COMPOUNDING\",\n invested: \"INVESTED\", returned: \"RETURNED\",\n by: \"BY\",\n vec2: \"VEC2\", vec3: \"VEC3\", vec4: \"VEC4\",\n float: \"FLOAT\",\n global: \"GLOBAL\",\n or: \"OR\",\n true: \"TRUE\", false: \"FALSE\",\n if: \"IF\", then: \"THEN\", else: \"ELSE\",\n as: \"AS\",\n percent: \"CONVERTER_NAME\", percentage: \"CONVERTER_NAME\",\n decimal: \"CONVERTER_NAME\", dec: \"CONVERTER_NAME\", number: \"CONVERTER_NAME\",\n fraction: \"CONVERTER_NAME\",\n multiplier: \"CONVERTER_NAME\",\n sci: \"CONVERTER_NAME\", scientific: \"CONVERTER_NAME\",\n // hex/bin are FUNC (see above), not CONVERTER_NAME, \"as hex\"/\"as bin\"\n // still work via AsConverterParselet.ts's widened token-type check.\n binary: \"CONVERTER_NAME\",\n octal: \"CONVERTER_NAME\", oct: \"CONVERTER_NAME\",\n },\n display: {\n resultPrefix: \"= \",\n dateFormat: \"default\",\n decimalSeparator: \".\",\n thousandsSeparator: \",\",\n vectorFormat: \"[{values}]\",\n percentageSuffix: \"%\",\n },\n};\n","import { ILocale } from \"./en\";\n\n/** German keywords, units and number formatting. */\nexport const deLocale: ILocale = {\n code: \"de\",\n label: \"Deutsch\",\n keywordMap: {\n pi: \"PI\", e: \"E\",\n plus: \"PLUS\", add: \"PLUS\", und: \"AND_CONJ\",\n minus: \"MINUS\", subtract: \"MINUS\", entfernen: \"MINUS\", nehmen: \"MINUS\",\n mal: \"STAR\", multiplizieren: \"STAR\",\n teilen: \"SLASH\",\n modulo: \"MOD\", mod: \"MOD\",\n exponent: \"CARET\", potenz: \"CARET\",\n von: \"OF\",\n jetzt: \"NOW\", heute: \"TODAY\", morgen: \"TOMORROW\", gestern: \"YESTERDAY\",\n rollen: \"ROLL\",\n wurzel: \"FUNC\", abs: \"FUNC\", sin: \"FUNC\", cos: \"FUNC\", tan: \"FUNC\",\n log: \"FUNC\", aufrunden: \"FUNC\", abrunden: \"FUNC\", runden: \"FUNC\", min: \"FUNC\", max: \"FUNC\",\n asin: \"FUNC\", acos: \"FUNC\", atan: \"FUNC\", atan2: \"FUNC\",\n sinh: \"FUNC\", cosh: \"FUNC\", tanh: \"FUNC\",\n asinh: \"FUNC\", acosh: \"FUNC\", atanh: \"FUNC\",\n kubikwurzel: \"FUNC\", clz32: \"FUNC\", expm1: \"FUNC\", exp: \"FUNC\",\n fround: \"FUNC\", hypot: \"FUNC\", imul: \"FUNC\",\n log10: \"FUNC\", log1p: \"FUNC\", log2: \"FUNC\",\n pow: \"FUNC\", zufall: \"FUNC\", zeichen: \"FUNC\", ganzzahl: \"FUNC\",\n degtorad: \"FUNC\", radtodeg: \"FUNC\",\n konvertieren: \"CONVERT\", in: \"TO\", amBesten: \"BEST\",\n naechste: \"NEXT\", letzte: \"LAST\", bis: \"UNTIL\", seit: \"SINCE\",\n sonntag: \"SUNDAY\", montag: \"MONDAY\", dienstag: \"TUESDAY\", mittwoch: \"WEDNESDAY\",\n donnerstag: \"THURSDAY\", freitag: \"FRIDAY\", samstag: \"SATURDAY\",\n zwischen: \"BETWEEN\",\n von_ab: \"FROM\",\n erhoehen: \"INCREASE\", verringern: \"DECREASE\",\n vec2: \"VEC2\", vec3: \"VEC3\", vec4: \"VEC4\",\n },\n display: {\n resultPrefix: \"= \",\n dateFormat: \"default\",\n decimalSeparator: \",\",\n thousandsSeparator: \".\",\n vectorFormat: \"[{values}]\",\n percentageSuffix: \"%\",\n },\n};","import { ILocale } from \"./en\";\n\n/**\n * French locale. See GitHub issue #77 (\"Please allow for localized day\n * of the week\"). Matches `de.ts`'s scope, not `en.ts`'s full coverage: a\n * confident, reviewed core set (arithmetic words, date keywords, weekday\n * names, a handful of common functions), not a guess at every FUNC/phrase\n * keyword across every package. Widening this is a good first issue for\n * a native French speaker, PRs welcome, same as this project's existing\n * convention for locale gaps.\n *\n * \"aujourd'hui\" (today) is deliberately spelled without its apostrophe\n * here (`aujourdhui`), `ExpressionLexer`'s identifier reader only\n * accepts `[a-zA-Z_][a-zA-Z0-9_]*` plus Unicode, so the standard spelling\n * can't lex as a single IDENT token at all. This is a real, disclosed\n * limitation, not a translation choice, anyone typing the standard\n * apostrophed spelling won't get a match today.\n */\nexport const frLocale: ILocale = {\n code: \"fr\",\n label: \"Français\",\n keywordMap: {\n pi: \"PI\", e: \"E\",\n plus: \"PLUS\", ajouter: \"PLUS\", et: \"AND_CONJ\",\n moins: \"MINUS\", soustraire: \"MINUS\", enlever: \"MINUS\",\n fois: \"STAR\", multiplier: \"STAR\",\n diviser: \"SLASH\",\n modulo: \"MOD\", mod: \"MOD\",\n exposant: \"CARET\", puissance: \"CARET\",\n xor: \"BIT_XOR\",\n maintenant: \"NOW\",\n // \"aujourd'hui\". See this file's own doc comment for why the\n // apostrophe is dropped here.\n aujourdhui: \"TODAY\",\n demain: \"TOMORROW\", hier: \"YESTERDAY\",\n lancer: \"ROLL\",\n // Same spellings as English on purpose, not a translation gap: the\n // FUNC token's NAME is looked up in a separate, locale-independent\n // dispatch table (FunctionCallParselet.ts's builtinNameToIndex) that\n // only knows English names, \"racine\" (root) would lex fine as a\n // FUNC token via this keywordMap but then fail at call time with\n // \"Unknown function\", so it's deliberately left out rather than\n // shipped half-working. Widening that dispatch table to be\n // locale-aware is a separate, larger change (it would need the same\n // fix for German too, \"wurzel\" has this identical problem today).\n abs: \"FUNC\", sin: \"FUNC\", cos: \"FUNC\", tan: \"FUNC\",\n log: \"FUNC\", min: \"FUNC\", max: \"FUNC\",\n convertir: \"CONVERT\",\n prochain: \"NEXT\", dernier: \"LAST\",\n dimanche: \"SUNDAY\", lundi: \"MONDAY\", mardi: \"TUESDAY\", mercredi: \"WEDNESDAY\",\n jeudi: \"THURSDAY\", vendredi: \"FRIDAY\", samedi: \"SATURDAY\",\n entre: \"BETWEEN\",\n augmenter: \"INCREASE\", diminuer: \"DECREASE\",\n vec2: \"VEC2\", vec3: \"VEC3\", vec4: \"VEC4\",\n vrai: \"TRUE\", faux: \"FALSE\",\n si: \"IF\", alors: \"THEN\", sinon: \"ELSE\",\n },\n display: {\n resultPrefix: \"= \",\n dateFormat: \"default\",\n decimalSeparator: \",\",\n thousandsSeparator: \" \",\n vectorFormat: \"[{values}]\",\n percentageSuffix: \"%\",\n },\n};\n","import { enLocale, type ILocale } from \"./en\";\nimport { deLocale } from \"./de\";\nimport { frLocale } from \"./fr\";\n\nconst locales: Record<string, ILocale> = {\n en: enLocale,\n de: deLocale,\n fr: frLocale,\n};\n\n/**\n * Look up a locale by code.\n *\n * @param code - Locale code, for example `\"en\"` or `\"de\"`.\n * @returns The locale, or English when the code is unknown. Falling back\n * rather than throwing means an unrecognised code degrades to a working engine\n * instead of a dead one.\n */\nexport function getLocale(code: string): ILocale {\n return locales[code] || enLocale;\n}\n\n/**\n * Add a locale, or replace one already registered under the same code.\n *\n * @param code - Locale code to register under.\n * @param locale - Keywords, units and formatting for that locale.\n */\nexport function registerLocale(code: string, locale: ILocale): void {\n locales[code] = locale;\n}\n\nexport { enLocale, deLocale, frLocale, type ILocale };"]}
@@ -1,4 +1,4 @@
1
- import { currencyExchangeService } from './chunk-DM3LMRBC.js';
1
+ import { currencyExchangeService } from './chunk-UKPGSAZW.js';
2
2
  import { numberValue } from './chunk-BVAR5J2F.js';
3
3
 
4
4
  // src/parser/OperandWidth.ts
@@ -92,5 +92,5 @@ var CurrencyAsyncResolver = class {
92
92
  };
93
93
 
94
94
  export { CurrencyAsyncResolver, nextInstruction };
95
- //# sourceMappingURL=chunk-EPOXXJBK.js.map
96
- //# sourceMappingURL=chunk-EPOXXJBK.js.map
95
+ //# sourceMappingURL=chunk-YU2CUNFO.js.map
96
+ //# sourceMappingURL=chunk-YU2CUNFO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser/OperandWidth.ts","../src/uom/CurrencyResolver.ts"],"names":[],"mappings":"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","file":"chunk-EPOXXJBK.js","sourcesContent":["/**\n * How many operand bytes follow each opcode, and how to step over one.\n *\n * Anything walking a bytecode stream without executing it needs this: the\n * resolver preflight scanners look for specific opcodes and must skip past\n * everything else without mistaking an operand byte for an instruction.\n *\n * It used to be a hand-copied switch in each of those scanners. They had\n * already drifted: two counted `CALL_PLUGIN` as three bytes wide and the third\n * omitted it from that arm, so a stream containing one desynchronised there and\n * every opcode after it was read at the wrong offset. Adding an opcode meant\n * remembering every copy, and nothing checked that you had.\n *\n * `__tests__/parser/OperandWidth.spec.ts` asserts every opcode has a width, so\n * a new one fails a test rather than silently defaulting to zero operands.\n */\n\nimport { OpCode } from \"@solve-js/parser/OpCode\";\n\n/**\n * Opcodes taking one operand byte.\n *\n * A constant-pool index, or a variable-name index.\n */\nconst ONE_OPERAND: readonly OpCode[] = [\n\tOpCode.PUSH_NUMBER,\n\tOpCode.PUSH_BIGINT,\n\tOpCode.PUSH_HEX,\n\tOpCode.PUSH_STRING,\n\tOpCode.PUSH_BOOLEAN,\n\tOpCode.LOAD_VAR,\n\tOpCode.STORE_VAR,\n\tOpCode.LOAD_GLOBAL_VAR,\n\tOpCode.STORE_GLOBAL_VAR,\n\tOpCode.DEFINE_USER_FUNCTION,\n];\n\n/**\n * Opcodes taking two operand bytes.\n *\n * A callable index plus an argument count, or a matrix's row and column counts.\n */\nconst TWO_OPERANDS: readonly OpCode[] = [\n\tOpCode.CALL_PLUGIN,\n\tOpCode.CALL_BUILTIN,\n\tOpCode.CALL_USER_FUNCTION,\n\tOpCode.MAT_NEW,\n];\n\n/**\n * Opcodes taking three operand bytes.\n *\n * The map and reduce invocations, which carry a body index alongside their\n * other operands.\n */\nconst THREE_OPERANDS: readonly OpCode[] = [OpCode.MAP_INVOKE, OpCode.REDUCE_INVOKE];\n\n/**\n * Operand byte count for every opcode, indexed by opcode value.\n *\n * A dense array rather than a map, because the preflight scanners run on every\n * keystroke and this is read once per instruction.\n */\nexport const OPERAND_BYTES: readonly number[] = (() => {\n\tconst widths = new Array<number>(256).fill(0);\n\tfor (const op of ONE_OPERAND) widths[op] = 1;\n\tfor (const op of TWO_OPERANDS) widths[op] = 2;\n\tfor (const op of THREE_OPERANDS) widths[op] = 3;\n\treturn widths;\n})();\n\n/**\n * Every opcode that takes at least one operand.\n *\n * Exported so a test can assert the table stays complete as opcodes are added.\n */\nexport const OPCODES_WITH_OPERANDS: readonly OpCode[] = [\n\t...ONE_OPERAND,\n\t...TWO_OPERANDS,\n\t...THREE_OPERANDS,\n];\n\n/**\n * Offset of the instruction after the one at `index`.\n *\n * @param opcodes - The bytecode stream.\n * @param index - Offset of an opcode, not of an operand byte. Passing an\n * operand offset yields nonsense, which is the failure mode this exists to\n * prevent: a caller stepping by hand and getting one width wrong reads the rest\n * of the stream misaligned.\n * @returns Offset of the next opcode. May be past the end when the instruction\n * at `index` is the last one, so callers loop while it is under `opcodes.length`.\n */\nexport function nextInstruction(opcodes: Uint8Array, index: number): number {\n\treturn index + 1 + (OPERAND_BYTES[opcodes[index]] ?? 0);\n}\n","/**\n * Currency async resolver, bridges CurrencyExchangeService to the\n * IAsyncResolver interface for the Suspense architecture.\n *\n * Uses TanStack Query (injected via queryClient) as the single cache layer.\n */\nimport type { QueryClient } from \"@tanstack/query-core\";\nimport type { Token } from \"@solve-js/lexer\";\nimport type { BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { numberValue } from \"@solve-js/vm/Value\";\nimport {\n\tcurrencyExchangeService,\n\tCurrencyExchangeService,\n} from \"@solve-js/uom/CurrencyExchange\";\nimport type { IAsyncResolver, AsyncCheckResult } from \"@solve-js/resolvers/ResolverRegistry\";\nimport { nextInstruction } from \"@solve-js/parser/OperandWidth\";\n\nconst CURRENCY_NS = \"currency\";\n\n/**\n * Fetches exchange rates before the VM runs, so a conversion has real numbers.\n *\n * Until rates arrive the line evaluates to a pending value rather than a\n * guessed one, and re-evaluates when they land.\n */\nexport class CurrencyAsyncResolver implements IAsyncResolver {\n\treadonly namespace = CURRENCY_NS;\n\n\tprivate exchange: CurrencyExchangeService;\n\n\tconstructor(exchange?: CurrencyExchangeService) {\n\t\tthis.exchange = exchange ?? currencyExchangeService;\n\t}\n\n\tpreflight(_tokens: Token[], bytecode: BytecodeProgram, packageId: string, signal: AbortSignal, queryClient: QueryClient): AsyncCheckResult | null {\n\t\tconst { opcodes, strings } = bytecode;\n\t\tconst len = opcodes.length;\n\t\tlet i = 0;\n\n\t\tlet lastStrIdx = -1;\n\t\tlet prevStrIdx = -1;\n\n\t\twhile (i < len) {\n\t\t\tconst op = opcodes[i] as OpCode;\n\n\t\t\tif (op === OpCode.PUSH_STRING) {\n\t\t\t\tprevStrIdx = lastStrIdx;\n\t\t\t\tlastStrIdx = opcodes[i + 1];\n\t\t\t}\n\n\t\t\t// Explicit \"X to Y\"/\"X in Y\" conversions (UOM_CONVERT_IN/_TO) are\n\t\t\t// the obvious case, but arithmetic directly on two differently-\n\t\t\t// denominated currency literals, \"0.01 BTC + 1 ETH\", needs the\n\t\t\t// exact same preflight fetch and previously never got it: this\n\t\t\t// scanner only looked for the CONVERT opcodes, so ADD/SUB/MUL/DIV\n\t\t\t// between two currency UOMs skipped preflight entirely, ran with\n\t\t\t// no cached rate, and fell through to the VM's silent-wrong-math\n\t\t\t// fallback instead of ever reaching a network fetch.\n\t\t\tconst isCurrencyCombiningOp =\n\t\t\t\top === OpCode.UOM_CONVERT_IN || op === OpCode.UOM_CONVERT_TO ||\n\t\t\t\top === OpCode.ADD || op === OpCode.SUB || op === OpCode.MUL || op === OpCode.DIV;\n\t\t\tif (isCurrencyCombiningOp) {\n\t\t\t\tif (prevStrIdx >= 0 && lastStrIdx >= 0) {\n\t\t\t\t\tconst fromUnit = strings[prevStrIdx];\n\t\t\t\t\tconst toUnit = strings[lastStrIdx];\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.exchange.isCurrency(fromUnit) &&\n\t\t\t\t\t\tthis.exchange.isCurrency(toUnit) &&\n\t\t\t\t\t\tfromUnit.toUpperCase() !== toUnit.toUpperCase()\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst syncRate = this.exchange.getRateSync(fromUnit, toUnit);\n\t\t\t\t\t\tif (syncRate === null) {\n\t\t\t\t\t\t\tconst fromUpper = fromUnit.toUpperCase();\n\t\t\t\t\t\t\tconst toUpper = toUnit.toUpperCase();\n\n\t\t\t\t\t\t\t// Check TanStack Query cache\n\t\t\t\t\t\t\tconst cacheKey = [CURRENCY_NS, fromUpper, toUpper];\n\t\t\t\t\t\t\tif (queryClient.getQueryData(cacheKey) !== undefined) {\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Fetch via TanStack Query (dedup + retry automatic)\n\t\t\t\t\t\t\tconst resolver = queryClient.fetchQuery({\n\t\t\t\t\t\t\t\tqueryKey: cacheKey,\n\t\t\t\t\t\t\t\tqueryFn: ({ signal: qSignal }) => {\n\t\t\t\t\t\t\t\t\treturn this.exchange.getRate(fromUnit, toUnit, qSignal).then((rate) => numberValue(rate));\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tstaleTime: 5 * 60 * 1000,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn { queryKey: cacheKey.join(\":\"), resolver, packageId, signal, metadata: { fromUnit, toUnit } };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Step over this instruction and its operands. Shared table, because\n\t\t\t// three hand-copied versions of this had already drifted.\n\t\t\ti = nextInstruction(opcodes, i);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tdestroy(): void {\n\t\t// Cache cleared by ResolverRegistry.unregister() via removeQueries({ queryKey: [\"currency\"] })\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../src/parser/OperandWidth.ts","../src/uom/CurrencyResolver.ts"],"names":[],"mappings":"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","file":"chunk-YU2CUNFO.js","sourcesContent":["/**\n * How many operand bytes follow each opcode, and how to step over one.\n *\n * Anything walking a bytecode stream without executing it needs this: the\n * resolver preflight scanners look for specific opcodes and must skip past\n * everything else without mistaking an operand byte for an instruction.\n *\n * It used to be a hand-copied switch in each of those scanners. They had\n * already drifted: two counted `CALL_PLUGIN` as three bytes wide and the third\n * omitted it from that arm, so a stream containing one desynchronised there and\n * every opcode after it was read at the wrong offset. Adding an opcode meant\n * remembering every copy, and nothing checked that you had.\n *\n * `__tests__/parser/OperandWidth.spec.ts` asserts every opcode has a width, so\n * a new one fails a test rather than silently defaulting to zero operands.\n */\n\nimport { OpCode } from \"@solve-js/parser/OpCode\";\n\n/**\n * Opcodes taking one operand byte.\n *\n * A constant-pool index, or a variable-name index.\n */\nconst ONE_OPERAND: readonly OpCode[] = [\n\tOpCode.PUSH_NUMBER,\n\tOpCode.PUSH_BIGINT,\n\tOpCode.PUSH_HEX,\n\tOpCode.PUSH_STRING,\n\tOpCode.PUSH_BOOLEAN,\n\tOpCode.LOAD_VAR,\n\tOpCode.STORE_VAR,\n\tOpCode.LOAD_GLOBAL_VAR,\n\tOpCode.STORE_GLOBAL_VAR,\n\tOpCode.DEFINE_USER_FUNCTION,\n];\n\n/**\n * Opcodes taking two operand bytes.\n *\n * A callable index plus an argument count, or a matrix's row and column counts.\n */\nconst TWO_OPERANDS: readonly OpCode[] = [\n\tOpCode.CALL_PLUGIN,\n\tOpCode.CALL_BUILTIN,\n\tOpCode.CALL_USER_FUNCTION,\n\tOpCode.MAT_NEW,\n];\n\n/**\n * Opcodes taking three operand bytes.\n *\n * The map and reduce invocations, which carry a body index alongside their\n * other operands.\n */\nconst THREE_OPERANDS: readonly OpCode[] = [OpCode.MAP_INVOKE, OpCode.REDUCE_INVOKE];\n\n/**\n * Operand byte count for every opcode, indexed by opcode value.\n *\n * A dense array rather than a map, because the preflight scanners run on every\n * keystroke and this is read once per instruction.\n */\nexport const OPERAND_BYTES: readonly number[] = (() => {\n\tconst widths = new Array<number>(256).fill(0);\n\tfor (const op of ONE_OPERAND) widths[op] = 1;\n\tfor (const op of TWO_OPERANDS) widths[op] = 2;\n\tfor (const op of THREE_OPERANDS) widths[op] = 3;\n\treturn widths;\n})();\n\n/**\n * Every opcode that takes at least one operand.\n *\n * Exported so a test can assert the table stays complete as opcodes are added.\n */\nexport const OPCODES_WITH_OPERANDS: readonly OpCode[] = [\n\t...ONE_OPERAND,\n\t...TWO_OPERANDS,\n\t...THREE_OPERANDS,\n];\n\n/**\n * Offset of the instruction after the one at `index`.\n *\n * @param opcodes - The bytecode stream.\n * @param index - Offset of an opcode, not of an operand byte. Passing an\n * operand offset yields nonsense, which is the failure mode this exists to\n * prevent: a caller stepping by hand and getting one width wrong reads the rest\n * of the stream misaligned.\n * @returns Offset of the next opcode. May be past the end when the instruction\n * at `index` is the last one, so callers loop while it is under `opcodes.length`.\n */\nexport function nextInstruction(opcodes: Uint8Array, index: number): number {\n\treturn index + 1 + (OPERAND_BYTES[opcodes[index]] ?? 0);\n}\n","/**\n * Currency async resolver, bridges CurrencyExchangeService to the\n * IAsyncResolver interface for the Suspense architecture.\n *\n * Uses TanStack Query (injected via queryClient) as the single cache layer.\n */\nimport type { QueryClient } from \"@tanstack/query-core\";\nimport type { Token } from \"@solve-js/lexer\";\nimport type { BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { numberValue } from \"@solve-js/vm/Value\";\nimport {\n\tcurrencyExchangeService,\n\tCurrencyExchangeService,\n} from \"@solve-js/uom/CurrencyExchange\";\nimport type { IAsyncResolver, AsyncCheckResult } from \"@solve-js/resolvers/ResolverRegistry\";\nimport { nextInstruction } from \"@solve-js/parser/OperandWidth\";\n\nconst CURRENCY_NS = \"currency\";\n\n/**\n * Fetches exchange rates before the VM runs, so a conversion has real numbers.\n *\n * Until rates arrive the line evaluates to a pending value rather than a\n * guessed one, and re-evaluates when they land.\n */\nexport class CurrencyAsyncResolver implements IAsyncResolver {\n\treadonly namespace = CURRENCY_NS;\n\n\tprivate exchange: CurrencyExchangeService;\n\n\tconstructor(exchange?: CurrencyExchangeService) {\n\t\tthis.exchange = exchange ?? currencyExchangeService;\n\t}\n\n\tpreflight(_tokens: Token[], bytecode: BytecodeProgram, packageId: string, signal: AbortSignal, queryClient: QueryClient): AsyncCheckResult | null {\n\t\tconst { opcodes, strings } = bytecode;\n\t\tconst len = opcodes.length;\n\t\tlet i = 0;\n\n\t\tlet lastStrIdx = -1;\n\t\tlet prevStrIdx = -1;\n\n\t\twhile (i < len) {\n\t\t\tconst op = opcodes[i] as OpCode;\n\n\t\t\tif (op === OpCode.PUSH_STRING) {\n\t\t\t\tprevStrIdx = lastStrIdx;\n\t\t\t\tlastStrIdx = opcodes[i + 1];\n\t\t\t}\n\n\t\t\t// Explicit \"X to Y\"/\"X in Y\" conversions (UOM_CONVERT_IN/_TO) are\n\t\t\t// the obvious case, but arithmetic directly on two differently-\n\t\t\t// denominated currency literals, \"0.01 BTC + 1 ETH\", needs the\n\t\t\t// exact same preflight fetch and previously never got it: this\n\t\t\t// scanner only looked for the CONVERT opcodes, so ADD/SUB/MUL/DIV\n\t\t\t// between two currency UOMs skipped preflight entirely, ran with\n\t\t\t// no cached rate, and fell through to the VM's silent-wrong-math\n\t\t\t// fallback instead of ever reaching a network fetch.\n\t\t\tconst isCurrencyCombiningOp =\n\t\t\t\top === OpCode.UOM_CONVERT_IN || op === OpCode.UOM_CONVERT_TO ||\n\t\t\t\top === OpCode.ADD || op === OpCode.SUB || op === OpCode.MUL || op === OpCode.DIV;\n\t\t\tif (isCurrencyCombiningOp) {\n\t\t\t\tif (prevStrIdx >= 0 && lastStrIdx >= 0) {\n\t\t\t\t\tconst fromUnit = strings[prevStrIdx];\n\t\t\t\t\tconst toUnit = strings[lastStrIdx];\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.exchange.isCurrency(fromUnit) &&\n\t\t\t\t\t\tthis.exchange.isCurrency(toUnit) &&\n\t\t\t\t\t\tfromUnit.toUpperCase() !== toUnit.toUpperCase()\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst syncRate = this.exchange.getRateSync(fromUnit, toUnit);\n\t\t\t\t\t\tif (syncRate === null) {\n\t\t\t\t\t\t\tconst fromUpper = fromUnit.toUpperCase();\n\t\t\t\t\t\t\tconst toUpper = toUnit.toUpperCase();\n\n\t\t\t\t\t\t\t// Check TanStack Query cache\n\t\t\t\t\t\t\tconst cacheKey = [CURRENCY_NS, fromUpper, toUpper];\n\t\t\t\t\t\t\tif (queryClient.getQueryData(cacheKey) !== undefined) {\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Fetch via TanStack Query (dedup + retry automatic)\n\t\t\t\t\t\t\tconst resolver = queryClient.fetchQuery({\n\t\t\t\t\t\t\t\tqueryKey: cacheKey,\n\t\t\t\t\t\t\t\tqueryFn: ({ signal: qSignal }) => {\n\t\t\t\t\t\t\t\t\treturn this.exchange.getRate(fromUnit, toUnit, qSignal).then((rate) => numberValue(rate));\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tstaleTime: 5 * 60 * 1000,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn { queryKey: cacheKey.join(\":\"), resolver, packageId, signal, metadata: { fromUnit, toUnit } };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Step over this instruction and its operands. Shared table, because\n\t\t\t// three hand-copied versions of this had already drifted.\n\t\t\ti = nextInstruction(opcodes, i);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tdestroy(): void {\n\t\t// Cache cleared by ResolverRegistry.unregister() via removeQueries({ queryKey: [\"currency\"] })\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkLR7YASZF_cjs = require('./chunk-LR7YASZF.cjs');
3
+ var chunkEAAHVJ4P_cjs = require('./chunk-EAAHVJ4P.cjs');
4
4
  require('./chunk-M4N5GA5Z.cjs');
5
5
  require('./chunk-B7LXJ6LC.cjs');
6
6
 
@@ -8,15 +8,15 @@ require('./chunk-B7LXJ6LC.cjs');
8
8
 
9
9
  Object.defineProperty(exports, "ConfigManager", {
10
10
  enumerable: true,
11
- get: function () { return chunkLR7YASZF_cjs.ConfigManager; }
11
+ get: function () { return chunkEAAHVJ4P_cjs.ConfigManager; }
12
12
  });
13
13
  Object.defineProperty(exports, "DEFAULT_CONFIG", {
14
14
  enumerable: true,
15
- get: function () { return chunkLR7YASZF_cjs.DEFAULT_CONFIG; }
15
+ get: function () { return chunkEAAHVJ4P_cjs.DEFAULT_CONFIG; }
16
16
  });
17
17
  Object.defineProperty(exports, "ENGINE_VERSION", {
18
18
  enumerable: true,
19
- get: function () { return chunkLR7YASZF_cjs.ENGINE_VERSION; }
19
+ get: function () { return chunkEAAHVJ4P_cjs.ENGINE_VERSION; }
20
20
  });
21
21
  //# sourceMappingURL=constants.cjs.map
22
22
  //# sourceMappingURL=constants.cjs.map
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export { ConfigManager, DEFAULT_CONFIG, ENGINE_VERSION } from './chunk-EIGTWK5N.js';
1
+ export { ConfigManager, DEFAULT_CONFIG, ENGINE_VERSION } from './chunk-OWRHDUJD.js';
2
2
  import './chunk-6RDSQURE.js';
3
3
  import './chunk-YLJ4XMA6.js';
4
4
  //# sourceMappingURL=constants.js.map
package/dist/engine.cjs CHANGED
@@ -1,35 +1,34 @@
1
1
  'use strict';
2
2
 
3
- var chunkJBSYC7BB_cjs = require('./chunk-JBSYC7BB.cjs');
4
- require('./chunk-NMCRQP3Z.cjs');
3
+ var chunkX2BWAZAU_cjs = require('./chunk-X2BWAZAU.cjs');
4
+ require('./chunk-MTX2KVU7.cjs');
5
5
  require('./chunk-NGBBNL4K.cjs');
6
6
  require('./chunk-X6K3HUOY.cjs');
7
7
  require('./chunk-5X2PTP6F.cjs');
8
- require('./chunk-6NTVRDQV.cjs');
8
+ require('./chunk-M4Q47KHF.cjs');
9
9
  require('./chunk-47LRVGOT.cjs');
10
- require('./chunk-RZCWSXTA.cjs');
11
- require('./chunk-C4XZV6E7.cjs');
12
- require('./chunk-EBSPLUW4.cjs');
10
+ require('./chunk-43G3JT2E.cjs');
11
+ require('./chunk-NZFKROS7.cjs');
12
+ require('./chunk-AHCLWAM5.cjs');
13
13
  require('./chunk-N5YFR4UP.cjs');
14
- require('./chunk-WQTTOGXC.cjs');
14
+ require('./chunk-4AVD7NZW.cjs');
15
15
  require('./chunk-Z2XP767T.cjs');
16
- require('./chunk-J73SJHR3.cjs');
16
+ require('./chunk-2NPS5DQ3.cjs');
17
17
  require('./chunk-FEAIOR7N.cjs');
18
- require('./chunk-XJCMXB2E.cjs');
18
+ require('./chunk-2MV4HBKC.cjs');
19
19
  require('./chunk-MZOVP3WI.cjs');
20
20
  require('./chunk-VEKIWQ3F.cjs');
21
- require('./chunk-OT6OJY7C.cjs');
22
- require('./chunk-HTXVVJRA.cjs');
21
+ require('./chunk-4CVLFLOB.cjs');
23
22
  require('./chunk-OC6LTXYS.cjs');
24
- require('./chunk-QNJ4ACRT.cjs');
25
- require('./chunk-LR7YASZF.cjs');
26
- require('./chunk-CLL7RUQV.cjs');
27
- require('./chunk-6BKTCEUP.cjs');
28
- require('./chunk-NMD5VRN4.cjs');
29
- require('./chunk-GW32KPCU.cjs');
30
- require('./chunk-3YNVWKR2.cjs');
31
- require('./chunk-EHAHVROS.cjs');
32
- require('./chunk-53B6KDDJ.cjs');
23
+ require('./chunk-NJTXJ5AG.cjs');
24
+ require('./chunk-EAAHVJ4P.cjs');
25
+ require('./chunk-WWOLFXTX.cjs');
26
+ require('./chunk-TY3TLZAW.cjs');
27
+ require('./chunk-M4F66R4O.cjs');
28
+ require('./chunk-R24DI24X.cjs');
29
+ require('./chunk-OUHT5Z36.cjs');
30
+ require('./chunk-CLVQBF5C.cjs');
31
+ require('./chunk-MBNQVDVC.cjs');
33
32
  require('./chunk-M4N5GA5Z.cjs');
34
33
  require('./chunk-B7LXJ6LC.cjs');
35
34
 
@@ -37,43 +36,43 @@ require('./chunk-B7LXJ6LC.cjs');
37
36
 
38
37
  Object.defineProperty(exports, "AsyncResolutionBatcher", {
39
38
  enumerable: true,
40
- get: function () { return chunkJBSYC7BB_cjs.AsyncResolutionBatcher; }
39
+ get: function () { return chunkX2BWAZAU_cjs.AsyncResolutionBatcher; }
41
40
  });
42
41
  Object.defineProperty(exports, "DocumentModel", {
43
42
  enumerable: true,
44
- get: function () { return chunkJBSYC7BB_cjs.DocumentModel; }
43
+ get: function () { return chunkX2BWAZAU_cjs.DocumentModel; }
45
44
  });
46
45
  Object.defineProperty(exports, "EvalTier", {
47
46
  enumerable: true,
48
- get: function () { return chunkJBSYC7BB_cjs.EvalTier; }
47
+ get: function () { return chunkX2BWAZAU_cjs.EvalTier; }
49
48
  });
50
49
  Object.defineProperty(exports, "ExpressionEngine", {
51
50
  enumerable: true,
52
- get: function () { return chunkJBSYC7BB_cjs.ExpressionEngine; }
51
+ get: function () { return chunkX2BWAZAU_cjs.ExpressionEngine; }
53
52
  });
54
53
  Object.defineProperty(exports, "ThreeTierEvaluator", {
55
54
  enumerable: true,
56
- get: function () { return chunkJBSYC7BB_cjs.ThreeTierEvaluator; }
55
+ get: function () { return chunkX2BWAZAU_cjs.ThreeTierEvaluator; }
57
56
  });
58
57
  Object.defineProperty(exports, "checkExpressionComplexity", {
59
58
  enumerable: true,
60
- get: function () { return chunkJBSYC7BB_cjs.checkExpressionComplexity; }
59
+ get: function () { return chunkX2BWAZAU_cjs.checkExpressionComplexity; }
61
60
  });
62
61
  Object.defineProperty(exports, "checkExpressionLength", {
63
62
  enumerable: true,
64
- get: function () { return chunkJBSYC7BB_cjs.checkExpressionLength; }
63
+ get: function () { return chunkX2BWAZAU_cjs.checkExpressionLength; }
65
64
  });
66
65
  Object.defineProperty(exports, "extractReadsAndWrites", {
67
66
  enumerable: true,
68
- get: function () { return chunkJBSYC7BB_cjs.extractReadsAndWrites; }
67
+ get: function () { return chunkX2BWAZAU_cjs.extractReadsAndWrites; }
69
68
  });
70
69
  Object.defineProperty(exports, "findInlineSolvesInLine", {
71
70
  enumerable: true,
72
- get: function () { return chunkJBSYC7BB_cjs.findInlineSolvesInLine; }
71
+ get: function () { return chunkX2BWAZAU_cjs.findInlineSolvesInLine; }
73
72
  });
74
73
  Object.defineProperty(exports, "isEmptyLine", {
75
74
  enumerable: true,
76
- get: function () { return chunkJBSYC7BB_cjs.isEmptyLine; }
75
+ get: function () { return chunkX2BWAZAU_cjs.isEmptyLine; }
77
76
  });
78
77
  //# sourceMappingURL=engine.cjs.map
79
78
  //# sourceMappingURL=engine.cjs.map
package/dist/engine.d.cts CHANGED
@@ -1,18 +1,18 @@
1
- import { D as DocumentModel, a as ExpressionEngine, V as ViewportRange, c as LineChange, d as InlineSolvePosition } from './PackageRegistry-D-Tv_7ca.cjs';
2
- export { A as ApplyChangesResult, e as AsyncCachePackageInfo, f as AsyncErrorEvent, g as AsyncResolutionBatcher, h as AsyncResolutionEvent, B as BatcherMetrics, i as BytecodeCacheEntry, C as CacheSnapshot, j as CheckpointSnapshot, E as EvalResults, k as LineCacheEntryInfo, L as LineEvaluation, l as LineState, m as LinesUpdatedEvent } from './PackageRegistry-D-Tv_7ca.cjs';
1
+ import { D as DocumentModel, a as ExpressionEngine, V as ViewportRange, c as LineChange, d as InlineSolvePosition } from './PackageRegistry-pHtKythi.cjs';
2
+ export { A as ApplyChangesResult, e as AsyncCachePackageInfo, f as AsyncErrorEvent, g as AsyncResolutionBatcher, h as AsyncResolutionEvent, B as BatcherMetrics, i as BytecodeCacheEntry, C as CacheSnapshot, j as CheckpointSnapshot, E as EvalResults, k as LineCacheEntryInfo, L as LineEvaluation, l as LineState, m as LinesUpdatedEvent } from './PackageRegistry-pHtKythi.cjs';
3
3
  import { V as Value } from './Value-KtAQNHur.cjs';
4
4
  import { a as VMCheckpointer } from './VMCheckpoints-CqFuLwrT.cjs';
5
- import { T as Token } from './Token-0jpvUdPY.cjs';
5
+ import { T as Token } from './Token-BzG5G4ja.cjs';
6
6
  import { E as EngineError } from './EngineError-DvPSnhZi.cjs';
7
7
  import { a as BytecodeProgram } from './BytecodeBuilder-3egMyuDi.cjs';
8
8
  export { a as DagSnapshot } from './ScopeManager-CKfQtl7l.cjs';
9
- import './Parselet-CK8cQu2a.cjs';
9
+ import './Parselet-Cu0bLSis.cjs';
10
10
  import './pipeline-DPUQt7yL.cjs';
11
11
  import './variables.cjs';
12
- import './Lexer-BJdhlnej.cjs';
12
+ import './Lexer-Cfm79Dak.cjs';
13
13
  import './resolvers.cjs';
14
14
  import '@tanstack/query-core';
15
- import './NormalizerRule-BrVoVjmP.cjs';
15
+ import './TokenNormalizer-DGVa24Q-.cjs';
16
16
  import './Configuration-fVpd-HC-.cjs';
17
17
 
18
18
  /**
package/dist/engine.d.ts CHANGED
@@ -1,18 +1,18 @@
1
- import { D as DocumentModel, a as ExpressionEngine, V as ViewportRange, c as LineChange, d as InlineSolvePosition } from './PackageRegistry-DaH4aIKP.js';
2
- export { A as ApplyChangesResult, e as AsyncCachePackageInfo, f as AsyncErrorEvent, g as AsyncResolutionBatcher, h as AsyncResolutionEvent, B as BatcherMetrics, i as BytecodeCacheEntry, C as CacheSnapshot, j as CheckpointSnapshot, E as EvalResults, k as LineCacheEntryInfo, L as LineEvaluation, l as LineState, m as LinesUpdatedEvent } from './PackageRegistry-DaH4aIKP.js';
1
+ import { D as DocumentModel, a as ExpressionEngine, V as ViewportRange, c as LineChange, d as InlineSolvePosition } from './PackageRegistry-CjDt-Jy_.js';
2
+ export { A as ApplyChangesResult, e as AsyncCachePackageInfo, f as AsyncErrorEvent, g as AsyncResolutionBatcher, h as AsyncResolutionEvent, B as BatcherMetrics, i as BytecodeCacheEntry, C as CacheSnapshot, j as CheckpointSnapshot, E as EvalResults, k as LineCacheEntryInfo, L as LineEvaluation, l as LineState, m as LinesUpdatedEvent } from './PackageRegistry-CjDt-Jy_.js';
3
3
  import { V as Value } from './Value-KtAQNHur.js';
4
4
  import { a as VMCheckpointer } from './VMCheckpoints-BmDwIXgK.js';
5
- import { T as Token } from './Token-0jpvUdPY.js';
5
+ import { T as Token } from './Token-BzG5G4ja.js';
6
6
  import { E as EngineError } from './EngineError-DvPSnhZi.js';
7
7
  import { a as BytecodeProgram } from './BytecodeBuilder-3egMyuDi.js';
8
8
  export { a as DagSnapshot } from './ScopeManager-B5k0nk05.js';
9
- import './Parselet-ConOIdRO.js';
9
+ import './Parselet-DEdF9I7n.js';
10
10
  import './pipeline-CrsRPmsv.js';
11
11
  import './variables.js';
12
- import './Lexer-D9l4Yrk2.js';
12
+ import './Lexer-W9MBOP0V.js';
13
13
  import './resolvers.js';
14
14
  import '@tanstack/query-core';
15
- import './NormalizerRule-CEjf1FyD.js';
15
+ import './TokenNormalizer-t_GotBxr.js';
16
16
  import './Configuration-fVpd-HC-.js';
17
17
 
18
18
  /**
package/dist/engine.js CHANGED
@@ -1,33 +1,32 @@
1
- export { AsyncResolutionBatcher, DocumentModel, EvalTier, ExpressionEngine, ThreeTierEvaluator, checkExpressionComplexity, checkExpressionLength, extractReadsAndWrites, findInlineSolvesInLine, isEmptyLine } from './chunk-M5LX5AOO.js';
2
- import './chunk-SDGRK7EP.js';
1
+ export { AsyncResolutionBatcher, DocumentModel, EvalTier, ExpressionEngine, ThreeTierEvaluator, checkExpressionComplexity, checkExpressionLength, extractReadsAndWrites, findInlineSolvesInLine, isEmptyLine } from './chunk-DDQVZGLO.js';
2
+ import './chunk-MEOHSQEH.js';
3
3
  import './chunk-2RWAXT6O.js';
4
4
  import './chunk-3VGDNEE3.js';
5
5
  import './chunk-IF532O7C.js';
6
- import './chunk-QWY3VEZN.js';
6
+ import './chunk-3MNKQZ77.js';
7
7
  import './chunk-G535KJEG.js';
8
- import './chunk-3PPFLFH4.js';
9
- import './chunk-5YEMOYSE.js';
10
- import './chunk-64W6GLLZ.js';
8
+ import './chunk-FIFQPKBA.js';
9
+ import './chunk-6GCKCWLB.js';
10
+ import './chunk-OFXOTECC.js';
11
11
  import './chunk-PFSDGGYL.js';
12
- import './chunk-EPOXXJBK.js';
12
+ import './chunk-YU2CUNFO.js';
13
13
  import './chunk-NLNDMWZC.js';
14
- import './chunk-4QADQTWS.js';
14
+ import './chunk-KHJUSHFU.js';
15
15
  import './chunk-GCM5JHMX.js';
16
- import './chunk-DM3LMRBC.js';
16
+ import './chunk-UKPGSAZW.js';
17
17
  import './chunk-75JP4BZX.js';
18
18
  import './chunk-Z4X2RWOF.js';
19
- import './chunk-RFYD5TJE.js';
20
- import './chunk-34RRD7PC.js';
19
+ import './chunk-CYFK5SY2.js';
21
20
  import './chunk-BVAR5J2F.js';
22
- import './chunk-NH2O2AUR.js';
23
- import './chunk-EIGTWK5N.js';
24
- import './chunk-HWSZJQCI.js';
25
- import './chunk-KVILKGMS.js';
26
- import './chunk-XVWCOTR6.js';
27
- import './chunk-RIN643A3.js';
28
- import './chunk-GOLDJNMZ.js';
29
- import './chunk-LIPPNDBE.js';
30
- import './chunk-4MG4XKO2.js';
21
+ import './chunk-WC5FFSHB.js';
22
+ import './chunk-OWRHDUJD.js';
23
+ import './chunk-2CS6OMZK.js';
24
+ import './chunk-AJA6LUI7.js';
25
+ import './chunk-SFQWJMKT.js';
26
+ import './chunk-GPPLSM2Z.js';
27
+ import './chunk-XBTEO4OB.js';
28
+ import './chunk-M5E34VG5.js';
29
+ import './chunk-PCPX42KL.js';
31
30
  import './chunk-6RDSQURE.js';
32
31
  import './chunk-YLJ4XMA6.js';
33
32
  //# sourceMappingURL=engine.js.map
package/dist/format.cjs CHANGED
@@ -1,10 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkCCJPSHGI_cjs = require('./chunk-CCJPSHGI.cjs');
4
- var chunkOT6OJY7C_cjs = require('./chunk-OT6OJY7C.cjs');
5
- var chunkHTXVVJRA_cjs = require('./chunk-HTXVVJRA.cjs');
4
+ var chunk4CVLFLOB_cjs = require('./chunk-4CVLFLOB.cjs');
6
5
  require('./chunk-OC6LTXYS.cjs');
7
- var chunk3YNVWKR2_cjs = require('./chunk-3YNVWKR2.cjs');
6
+ var chunkOUHT5Z36_cjs = require('./chunk-OUHT5Z36.cjs');
8
7
  require('./chunk-M4N5GA5Z.cjs');
9
8
  require('./chunk-B7LXJ6LC.cjs');
10
9
 
@@ -87,7 +86,7 @@ function formatUom(value, unit, locale, settings) {
87
86
  } else {
88
87
  formatted = value.toFixed(dp);
89
88
  }
90
- const currencyDisplay = unit ? chunkOT6OJY7C_cjs.CURRENCY_DISPLAY[unit.toUpperCase()] : void 0;
89
+ const currencyDisplay = unit ? chunk4CVLFLOB_cjs.CURRENCY_DISPLAY[unit.toUpperCase()] : void 0;
91
90
  if (currencyDisplay) {
92
91
  const sep = currencyDisplay.spaced ? " " : "";
93
92
  const withSymbol = currencyDisplay.position === "prefix" ? `${currencyDisplay.symbol}${sep}${formatted}` : `${formatted}${sep}${currencyDisplay.symbol}`;
@@ -98,14 +97,14 @@ function formatUom(value, unit, locale, settings) {
98
97
  }
99
98
  function formatMatrixEntry(entry, settings) {
100
99
  if (typeof entry === "boolean") return entry ? "true" : "false";
101
- if (typeof entry === "object" && entry !== null) return chunkHTXVVJRA_cjs.formatSymbolic(entry);
100
+ if (typeof entry === "object" && entry !== null) return chunk4CVLFLOB_cjs.formatSymbolic(entry);
102
101
  const dp = settings.floatResult.decimalPlaces;
103
102
  const sep = settings.floatResult.enableSeperator;
104
103
  const loc = settings.numberResult.decimalSeparatorLocale;
105
104
  return chunkCCJPSHGI_cjs.autoFormatIntegerOrFloat(entry, dp, sep, loc);
106
105
  }
107
106
  function formatMatrix(m, locale, settings) {
108
- const rowMajor = chunkHTXVVJRA_cjs.columnMajorToRowMajor(m);
107
+ const rowMajor = chunk4CVLFLOB_cjs.columnMajorToRowMajor(m);
109
108
  const rows = [];
110
109
  for (let r = 0; r < m.rows; r++) {
111
110
  const cells = [];
@@ -130,7 +129,7 @@ function formatUnit(value, unit) {
130
129
  function formatValue(value, settings) {
131
130
  const us = settings || DEFAULT_FORMATTING_SETTINGS;
132
131
  const localeCode = us.numberResult.decimalSeparatorLocale || "en";
133
- const locale = chunk3YNVWKR2_cjs.getLocale(localeCode);
132
+ const locale = chunkOUHT5Z36_cjs.getLocale(localeCode);
134
133
  switch (value.type) {
135
134
  case 0 /* Number */:
136
135
  return formatNumber(value.value, locale, us);
@@ -153,7 +152,7 @@ function formatValue(value, settings) {
153
152
  return formatRange(r.min, r.max, locale);
154
153
  }
155
154
  case 9 /* Symbolic */:
156
- return chunkHTXVVJRA_cjs.formatSymbolic(value.value);
155
+ return chunk4CVLFLOB_cjs.formatSymbolic(value.value);
157
156
  case 5 /* Percentage */:
158
157
  return formatPercentage(value.value, locale, us);
159
158
  case 11 /* Unit */:
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/format/FormattingSettings.ts","../src/format/FormatEngine.ts"],"names":["autoFormatIntegerOrFloat","CURRENCY_DISPLAY","formatSymbolic","columnMajorToRowMajor","getLocale"],"mappings":"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","file":"format.cjs","sourcesContent":["/**\n * Minimal formatting settings interface for the engine\n * This allows the engine to format values without depending on app-specific settings\n */\nexport interface FormattingSettings {\n floatResult: {\n decimalPlaces: number;\n enableSeperator: boolean;\n };\n numberResult: {\n decimalSeparatorLocale: string;\n };\n hexResult: {\n enablePadding: boolean;\n paddingZeros: number;\n };\n unitOfMeasurementResult: {\n decimalPlaces: number;\n unitNames: boolean;\n };\n percentageResult: {\n decimalPlaces: number;\n };\n}\n\n/** Formatting used when a host supplies none. */\nexport const DEFAULT_FORMATTING_SETTINGS: FormattingSettings = {\n floatResult: {\n decimalPlaces: 2,\n enableSeperator: true,\n },\n numberResult: {\n decimalSeparatorLocale: \"en-US\",\n },\n hexResult: {\n enablePadding: false,\n paddingZeros: 0,\n },\n unitOfMeasurementResult: {\n decimalPlaces: 2,\n unitNames: true,\n },\n percentageResult: {\n decimalPlaces: 2,\n },\n};\n","import { Value, ValueType, type MatrixData, type MatrixEntry, type RangeData } from \"@solve-js/vm/Value\";\nimport { getLocale, type ILocale } from \"@solve-js/constants/locales\";\nimport { autoFormatIntegerOrFloat } from \"@solve-js/utilities/Number\";\nimport { FormattingSettings, DEFAULT_FORMATTING_SETTINGS } from \"./FormattingSettings\";\nimport { CURRENCY_DISPLAY } from \"@solve-js/uom/CurrencyAliases\";\nimport { columnMajorToRowMajor } from \"@solve-js/vm/MatrixOps\";\nimport { formatSymbolic, type SymbolicNode } from \"@solve-js/symbolic\";\n\nfunction formatNumber(value: number, locale: ILocale, settings: FormattingSettings): string {\n const dp = settings.floatResult.decimalPlaces;\n const sep = settings.floatResult.enableSeperator;\n const loc = settings.numberResult.decimalSeparatorLocale;\n const formatted = autoFormatIntegerOrFloat(value, dp, sep, loc);\n return `${locale.display.resultPrefix}${formatted}`;\n}\n\n/**\n * Renders a number in whichever base it is tagged with.\n *\n * The zero padding is a hexadecimal setting and stays one. Applying it to a\n * binary rendering would pad `0b101` out to the same digit count as a hex\n * value, which is a different quantity of zeros and not what the setting asks\n * for.\n */\nfunction formatHex(value: number, settings: FormattingSettings, base?: string): string {\n // Truncate and take the sign off before converting. `Number.toString(radix)`\n // does neither: it renders -255 as \"-ff\", which lands the minus inside the\n // literal as `0x-FF`, and it renders 255.7 as \"ff.b3333333333\", inventing\n // fractional hex digits for a notation that has no use for them. Both were\n // visible on `as hex` until the builtins started sharing this path.\n const truncated = Math.trunc(value);\n const sign = truncated < 0 ? \"-\" : \"\";\n const magnitude = Math.abs(truncated);\n\n if (base === \"bin\") return `= ${sign}0b${magnitude.toString(2)}`;\n if (base === \"oct\") return `= ${sign}0o${magnitude.toString(8)}`;\n const padding = settings.hexResult.enablePadding ? settings.hexResult.paddingZeros : 0;\n const hex = magnitude.toString(16).toUpperCase().padStart(padding, \"0\");\n return `= ${sign}0x${hex}`;\n}\n\nfunction formatBigInt(value: bigint): string {\n return `= ${value}`;\n}\n\nfunction formatString(value: string): string {\n return `= ${value}`;\n}\n\nfunction formatBoolean(value: boolean): string {\n return `= ${value}`;\n}\n\n/**\n * Renders a Datetime value locale-aware, the previous implementation\n * called `d.toLocaleString()` with no arguments, which always uses the JS\n * runtime's own default locale and never actually consulted `locale.code`\n * despite receiving it as a parameter (both branches of its old\n * `dateFormat === \"default\"` check were byte-for-byte identical, dead\n * groundwork for a distinction that was never implemented). Concretely,\n * this meant every configured locale (including the shipped German one)\n * always displayed weekday/month names in English. See GitHub issue #77.\n *\n * Uses `weekday`/`month`: \"long\" for a spelled-out date (\"Monday,\n * November 17, 2025\" / \"lundi 17 novembre 2025\") since that's what a\n * literal weekday name is for; a bare numeric date doesn't need\n * localizing beyond the decimal/thousands separators `formatNumber()`\n * already handles. The time-of-day portion is only appended when it's\n * not exactly local midnight, bare date literals (\"today\", \"17/11/2025\")\n * always anchor to local midnight, and showing \"00:00:00\" on every one of\n * those would be noise, not information.\n */\nfunction formatDatetime(value: number, locale: ILocale): string {\n const d = new Date(value);\n const dateStr = d.toLocaleDateString(locale.code, { weekday: \"long\", year: \"numeric\", month: \"long\", day: \"numeric\" });\n const isMidnight = d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;\n if (isMidnight) return `= ${dateStr}`;\n return `= ${dateStr}, ${d.toLocaleTimeString(locale.code)}`;\n}\n\n/**\n * Renders a millisecond duration as clock-style `H:MM` (or `H:MM:SS` when\n * there's a non-zero seconds component). `ms` is never a user-typeable\n * unit (confirmed: it appears nowhere in `lexer/units.ts`), it's only\n * ever produced by subtracting two clock times/datetimes (`9:30 - 8:30`,\n * `VM.ts`'s Datetime SUB case), so this is a safe, narrow special case,\n * not a general change to how durations display.\n */\nfunction formatMsDuration(ms: number): string {\n const sign = ms < 0 ? \"-\" : \"\";\n const totalSeconds = Math.round(Math.abs(ms) / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, \"0\");\n if (seconds === 0) return `${sign}${hours}:${mm}`;\n const ss = String(seconds).padStart(2, \"0\");\n return `${sign}${hours}:${mm}:${ss}`;\n}\n\nfunction formatUom(value: number, unit: string | undefined, locale: ILocale, settings: FormattingSettings): string {\n if (unit === \"ms\") return `= ${formatMsDuration(value)}`;\n\n const dp = settings.unitOfMeasurementResult.decimalPlaces;\n const useUnitNames = settings.unitOfMeasurementResult.unitNames;\n\n // For TimeSpan values (days, weeks, hours, etc.), format as integer if the value is a whole number\n const timeSpanUnits = [\"days\", \"weeks\", \"hours\", \"minutes\", \"seconds\", \"day\", \"week\", \"hour\", \"minute\", \"second\"];\n const isTimeSpan = unit && timeSpanUnits.includes(unit);\n\n let formatted: string;\n if (isTimeSpan && value === Math.floor(value)) {\n // For whole number TimeSpan values, format as integer\n formatted = value.toString();\n } else {\n // For other values, use the configured decimal places\n formatted = value.toFixed(dp);\n }\n\n // Currency display: symbol + culturally-conventional placement (e.g.\n // \"$100.00\" prefix vs \"100.00 kr\" suffix) instead of the generic\n // \"amount CODE\" fallback below. See uom/CurrencyAliases.ts's\n // CURRENCY_DISPLAY table for the exact set covered and the reasoning\n // behind each placement choice. Any currency code NOT in that table\n // (most of the ~150 `CurrencyExchange.isCurrency()` recognizes) falls\n // through to the unchanged \"amount CODE\" format below.\n const currencyDisplay = unit ? CURRENCY_DISPLAY[unit.toUpperCase()] : undefined;\n if (currencyDisplay) {\n const sep = currencyDisplay.spaced ? \" \" : \"\";\n const withSymbol = currencyDisplay.position === \"prefix\"\n ? `${currencyDisplay.symbol}${sep}${formatted}`\n : `${formatted}${sep}${currencyDisplay.symbol}`;\n return `= ${withSymbol}`;\n }\n\n const unitLabel = useUnitNames ? (unit || \"\") : (unit || \"\");\n return `= ${formatted} ${unitLabel}`.trim();\n}\n\nfunction formatMatrixEntry(entry: MatrixEntry, settings: FormattingSettings): string {\n if (typeof entry === \"boolean\") return entry ? \"true\" : \"false\";\n if (typeof entry === \"object\" && entry !== null) return formatSymbolic(entry);\n const dp = settings.floatResult.decimalPlaces;\n const sep = settings.floatResult.enableSeperator;\n const loc = settings.numberResult.decimalSeparatorLocale;\n return autoFormatIntegerOrFloat(entry, dp, sep, loc);\n}\n\n/**\n * Renders a Matrix matching its own literal syntax: a single row (1xN,\n * including plain vectors) as `[a, b, c]`, a single column (Nx1) as\n * `[a; b; c]`, and a general shape as `[r0c0, r0c1; r1c0, r1c1]`, row-major\n * textual output read back out of the column-major storage\n * (`columnMajorToRowMajor()`), matching how `[1,2;3,4]` is written.\n */\nfunction formatMatrix(m: MatrixData, locale: ILocale, settings: FormattingSettings): string {\n const rowMajor = columnMajorToRowMajor(m);\n const rows: string[] = [];\n for (let r = 0; r < m.rows; r++) {\n const cells: string[] = [];\n for (let c = 0; c < m.cols; c++) {\n cells.push(formatMatrixEntry(rowMajor[r * m.cols + c], settings));\n }\n rows.push(cells.join(\", \"));\n }\n return `${locale.display.resultPrefix}[${rows.join(\"; \")}]`;\n}\n\nfunction formatRange(min: number, max: number, locale: ILocale): string {\n return `${locale.display.resultPrefix}${min}:${max}`;\n}\n\nfunction formatPercentage(value: number, locale: ILocale, settings: FormattingSettings): string {\n // ValueType.Percentage stores a fraction (0.25 for 25%). See Value.ts's\n // documented contract and the sole producer, VM.ts's TO_PERCENTAGE opcode\n // (`right/left - 1`, e.g. 0.25 for \"800 to 1000\"). Multiply by 100 before\n // formatting; without this every percentage-change result displayed as\n // e.g. \"0.25%\" instead of \"25.00%\".\n const dp = settings.percentageResult.decimalPlaces;\n const formatted = (value * 100).toFixed(dp);\n return `= ${formatted}${locale.display.percentageSuffix}`;\n}\n\nfunction formatUnit(value: number, unit: string | undefined): string {\n return `= ${value} ${unit || \"\"}`.trim();\n}\n\n/**\n * Render an evaluated {@link Value} as a display string, dispatching on\n * `value.type` to the type-specific formatter (number, hex, datetime, unit\n * of measurement, matrix, range, percentage, ...).\n *\n * Most branches produce a `\"= \"`-prefixed result string (matching the\n * plugin's inline-result convention); `ValueType.Error` is the one\n * exception, it returns the human-readable error message directly\n * (stored in `value.unit`), not an `\"= \"`-prefixed string.\n *\n * @param value - The evaluated value to format.\n * @param settings - Locale/precision/separator options; defaults to\n * {@link DEFAULT_FORMATTING_SETTINGS} when omitted.\n * @example\n * ```typescript\n * const [value] = engine.evaluateExpression(\"10 USD to GBP\");\n * formatValue(value); // \"= £7.85\" (exact output depends on live exchange rates)\n * ```\n */\nexport function formatValue(value: Value, settings?: FormattingSettings): string {\n const us = settings || DEFAULT_FORMATTING_SETTINGS;\n const localeCode = us.numberResult.decimalSeparatorLocale || \"en\";\n const locale = getLocale(localeCode);\n\n switch (value.type) {\n case ValueType.Number:\n return formatNumber(value.value as number, locale, us);\n case ValueType.Hex:\n return formatHex(value.value as number, us, value.unit);\n case ValueType.BigInt:\n return formatBigInt(value.value as bigint);\n case ValueType.String:\n return formatString(value.value as string);\n case ValueType.Boolean:\n return formatBoolean(value.value as boolean);\n case ValueType.Datetime:\n return formatDatetime(value.value as number, locale);\n case ValueType.Uom:\n return formatUom(value.value as number, value.unit, locale, us);\n case ValueType.Matrix:\n return formatMatrix(value.value as MatrixData, locale, us);\n case ValueType.Range: {\n const r = value.value as RangeData;\n return formatRange(r.min, r.max, locale);\n }\n case ValueType.Symbolic:\n return formatSymbolic(value.value as SymbolicNode);\n case ValueType.Percentage:\n return formatPercentage(value.value as number, locale, us);\n case ValueType.Unit:\n return formatUnit(value.value as number, value.unit);\n case ValueType.Error:\n // errorValue(code, message) stores the human-readable message in\n // `.unit` (code goes in `.value`), falling through to the default\n // case here previously displayed the raw code (e.g.\n // \"CURRENCY_RATE_UNAVAILABLE\") instead of the actual message.\n return value.unit ?? String(value.value);\n default:\n return `= ${String(value.value)}`;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/format/FormattingSettings.ts","../src/format/FormatEngine.ts"],"names":["autoFormatIntegerOrFloat","CURRENCY_DISPLAY","formatSymbolic","columnMajorToRowMajor","getLocale"],"mappings":"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","file":"format.cjs","sourcesContent":["/**\n * Minimal formatting settings interface for the engine\n * This allows the engine to format values without depending on app-specific settings\n */\nexport interface FormattingSettings {\n floatResult: {\n decimalPlaces: number;\n enableSeperator: boolean;\n };\n numberResult: {\n decimalSeparatorLocale: string;\n };\n hexResult: {\n enablePadding: boolean;\n paddingZeros: number;\n };\n unitOfMeasurementResult: {\n decimalPlaces: number;\n unitNames: boolean;\n };\n percentageResult: {\n decimalPlaces: number;\n };\n}\n\n/** Formatting used when a host supplies none. */\nexport const DEFAULT_FORMATTING_SETTINGS: FormattingSettings = {\n floatResult: {\n decimalPlaces: 2,\n enableSeperator: true,\n },\n numberResult: {\n decimalSeparatorLocale: \"en-US\",\n },\n hexResult: {\n enablePadding: false,\n paddingZeros: 0,\n },\n unitOfMeasurementResult: {\n decimalPlaces: 2,\n unitNames: true,\n },\n percentageResult: {\n decimalPlaces: 2,\n },\n};\n","import { Value, ValueType, type MatrixData, type MatrixEntry, type RangeData } from \"@solve-js/vm/Value\";\nimport { getLocale, type ILocale } from \"@solve-js/constants/locales\";\nimport { autoFormatIntegerOrFloat } from \"@solve-js/utilities/Number\";\nimport { FormattingSettings, DEFAULT_FORMATTING_SETTINGS } from \"./FormattingSettings\";\nimport { CURRENCY_DISPLAY } from \"@solve-js/uom/CurrencyAliases\";\nimport { columnMajorToRowMajor } from \"@solve-js/vm/MatrixOps\";\nimport { formatSymbolic, type SymbolicNode } from \"@solve-js/symbolic\";\n\nfunction formatNumber(value: number, locale: ILocale, settings: FormattingSettings): string {\n const dp = settings.floatResult.decimalPlaces;\n const sep = settings.floatResult.enableSeperator;\n const loc = settings.numberResult.decimalSeparatorLocale;\n const formatted = autoFormatIntegerOrFloat(value, dp, sep, loc);\n return `${locale.display.resultPrefix}${formatted}`;\n}\n\n/**\n * Renders a number in whichever base it is tagged with.\n *\n * The zero padding is a hexadecimal setting and stays one. Applying it to a\n * binary rendering would pad `0b101` out to the same digit count as a hex\n * value, which is a different quantity of zeros and not what the setting asks\n * for.\n */\nfunction formatHex(value: number, settings: FormattingSettings, base?: string): string {\n // Truncate and take the sign off before converting. `Number.toString(radix)`\n // does neither: it renders -255 as \"-ff\", which lands the minus inside the\n // literal as `0x-FF`, and it renders 255.7 as \"ff.b3333333333\", inventing\n // fractional hex digits for a notation that has no use for them. Both were\n // visible on `as hex` until the builtins started sharing this path.\n const truncated = Math.trunc(value);\n const sign = truncated < 0 ? \"-\" : \"\";\n const magnitude = Math.abs(truncated);\n\n if (base === \"bin\") return `= ${sign}0b${magnitude.toString(2)}`;\n if (base === \"oct\") return `= ${sign}0o${magnitude.toString(8)}`;\n const padding = settings.hexResult.enablePadding ? settings.hexResult.paddingZeros : 0;\n const hex = magnitude.toString(16).toUpperCase().padStart(padding, \"0\");\n return `= ${sign}0x${hex}`;\n}\n\nfunction formatBigInt(value: bigint): string {\n return `= ${value}`;\n}\n\nfunction formatString(value: string): string {\n return `= ${value}`;\n}\n\nfunction formatBoolean(value: boolean): string {\n return `= ${value}`;\n}\n\n/**\n * Renders a Datetime value locale-aware, the previous implementation\n * called `d.toLocaleString()` with no arguments, which always uses the JS\n * runtime's own default locale and never actually consulted `locale.code`\n * despite receiving it as a parameter (both branches of its old\n * `dateFormat === \"default\"` check were byte-for-byte identical, dead\n * groundwork for a distinction that was never implemented). Concretely,\n * this meant every configured locale (including the shipped German one)\n * always displayed weekday/month names in English. See GitHub issue #77.\n *\n * Uses `weekday`/`month`: \"long\" for a spelled-out date (\"Monday,\n * November 17, 2025\" / \"lundi 17 novembre 2025\") since that's what a\n * literal weekday name is for; a bare numeric date doesn't need\n * localizing beyond the decimal/thousands separators `formatNumber()`\n * already handles. The time-of-day portion is only appended when it's\n * not exactly local midnight, bare date literals (\"today\", \"17/11/2025\")\n * always anchor to local midnight, and showing \"00:00:00\" on every one of\n * those would be noise, not information.\n */\nfunction formatDatetime(value: number, locale: ILocale): string {\n const d = new Date(value);\n const dateStr = d.toLocaleDateString(locale.code, { weekday: \"long\", year: \"numeric\", month: \"long\", day: \"numeric\" });\n const isMidnight = d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;\n if (isMidnight) return `= ${dateStr}`;\n return `= ${dateStr}, ${d.toLocaleTimeString(locale.code)}`;\n}\n\n/**\n * Renders a millisecond duration as clock-style `H:MM` (or `H:MM:SS` when\n * there's a non-zero seconds component). `ms` is never a user-typeable\n * unit (confirmed: it appears nowhere in `lexer/units.ts`), it's only\n * ever produced by subtracting two clock times/datetimes (`9:30 - 8:30`,\n * `VM.ts`'s Datetime SUB case), so this is a safe, narrow special case,\n * not a general change to how durations display.\n */\nfunction formatMsDuration(ms: number): string {\n const sign = ms < 0 ? \"-\" : \"\";\n const totalSeconds = Math.round(Math.abs(ms) / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, \"0\");\n if (seconds === 0) return `${sign}${hours}:${mm}`;\n const ss = String(seconds).padStart(2, \"0\");\n return `${sign}${hours}:${mm}:${ss}`;\n}\n\nfunction formatUom(value: number, unit: string | undefined, locale: ILocale, settings: FormattingSettings): string {\n if (unit === \"ms\") return `= ${formatMsDuration(value)}`;\n\n const dp = settings.unitOfMeasurementResult.decimalPlaces;\n const useUnitNames = settings.unitOfMeasurementResult.unitNames;\n\n // For TimeSpan values (days, weeks, hours, etc.), format as integer if the value is a whole number\n const timeSpanUnits = [\"days\", \"weeks\", \"hours\", \"minutes\", \"seconds\", \"day\", \"week\", \"hour\", \"minute\", \"second\"];\n const isTimeSpan = unit && timeSpanUnits.includes(unit);\n\n let formatted: string;\n if (isTimeSpan && value === Math.floor(value)) {\n // For whole number TimeSpan values, format as integer\n formatted = value.toString();\n } else {\n // For other values, use the configured decimal places\n formatted = value.toFixed(dp);\n }\n\n // Currency display: symbol + culturally-conventional placement (e.g.\n // \"$100.00\" prefix vs \"100.00 kr\" suffix) instead of the generic\n // \"amount CODE\" fallback below. See uom/CurrencyAliases.ts's\n // CURRENCY_DISPLAY table for the exact set covered and the reasoning\n // behind each placement choice. Any currency code NOT in that table\n // (most of the ~150 `CurrencyExchange.isCurrency()` recognizes) falls\n // through to the unchanged \"amount CODE\" format below.\n const currencyDisplay = unit ? CURRENCY_DISPLAY[unit.toUpperCase()] : undefined;\n if (currencyDisplay) {\n const sep = currencyDisplay.spaced ? \" \" : \"\";\n const withSymbol = currencyDisplay.position === \"prefix\"\n ? `${currencyDisplay.symbol}${sep}${formatted}`\n : `${formatted}${sep}${currencyDisplay.symbol}`;\n return `= ${withSymbol}`;\n }\n\n const unitLabel = useUnitNames ? (unit || \"\") : (unit || \"\");\n return `= ${formatted} ${unitLabel}`.trim();\n}\n\nfunction formatMatrixEntry(entry: MatrixEntry, settings: FormattingSettings): string {\n if (typeof entry === \"boolean\") return entry ? \"true\" : \"false\";\n if (typeof entry === \"object\" && entry !== null) return formatSymbolic(entry);\n const dp = settings.floatResult.decimalPlaces;\n const sep = settings.floatResult.enableSeperator;\n const loc = settings.numberResult.decimalSeparatorLocale;\n return autoFormatIntegerOrFloat(entry, dp, sep, loc);\n}\n\n/**\n * Renders a Matrix matching its own literal syntax: a single row (1xN,\n * including plain vectors) as `[a, b, c]`, a single column (Nx1) as\n * `[a; b; c]`, and a general shape as `[r0c0, r0c1; r1c0, r1c1]`, row-major\n * textual output read back out of the column-major storage\n * (`columnMajorToRowMajor()`), matching how `[1,2;3,4]` is written.\n */\nfunction formatMatrix(m: MatrixData, locale: ILocale, settings: FormattingSettings): string {\n const rowMajor = columnMajorToRowMajor(m);\n const rows: string[] = [];\n for (let r = 0; r < m.rows; r++) {\n const cells: string[] = [];\n for (let c = 0; c < m.cols; c++) {\n cells.push(formatMatrixEntry(rowMajor[r * m.cols + c], settings));\n }\n rows.push(cells.join(\", \"));\n }\n return `${locale.display.resultPrefix}[${rows.join(\"; \")}]`;\n}\n\nfunction formatRange(min: number, max: number, locale: ILocale): string {\n return `${locale.display.resultPrefix}${min}:${max}`;\n}\n\nfunction formatPercentage(value: number, locale: ILocale, settings: FormattingSettings): string {\n // ValueType.Percentage stores a fraction (0.25 for 25%). See Value.ts's\n // documented contract and the sole producer, VM.ts's TO_PERCENTAGE opcode\n // (`right/left - 1`, e.g. 0.25 for \"800 to 1000\"). Multiply by 100 before\n // formatting; without this every percentage-change result displayed as\n // e.g. \"0.25%\" instead of \"25.00%\".\n const dp = settings.percentageResult.decimalPlaces;\n const formatted = (value * 100).toFixed(dp);\n return `= ${formatted}${locale.display.percentageSuffix}`;\n}\n\nfunction formatUnit(value: number, unit: string | undefined): string {\n return `= ${value} ${unit || \"\"}`.trim();\n}\n\n/**\n * Render an evaluated {@link Value} as a display string, dispatching on\n * `value.type` to the type-specific formatter (number, hex, datetime, unit\n * of measurement, matrix, range, percentage, ...).\n *\n * Most branches produce a `\"= \"`-prefixed result string (matching the\n * plugin's inline-result convention); `ValueType.Error` is the one\n * exception, it returns the human-readable error message directly\n * (stored in `value.unit`), not an `\"= \"`-prefixed string.\n *\n * @param value - The evaluated value to format.\n * @param settings - Locale/precision/separator options; defaults to\n * {@link DEFAULT_FORMATTING_SETTINGS} when omitted.\n * @example\n * ```typescript\n * const [value] = engine.evaluateExpression(\"10 USD to GBP\");\n * formatValue(value); // \"= £7.85\" (exact output depends on live exchange rates)\n * ```\n */\nexport function formatValue(value: Value, settings?: FormattingSettings): string {\n const us = settings || DEFAULT_FORMATTING_SETTINGS;\n const localeCode = us.numberResult.decimalSeparatorLocale || \"en\";\n const locale = getLocale(localeCode);\n\n switch (value.type) {\n case ValueType.Number:\n return formatNumber(value.value as number, locale, us);\n case ValueType.Hex:\n return formatHex(value.value as number, us, value.unit);\n case ValueType.BigInt:\n return formatBigInt(value.value as bigint);\n case ValueType.String:\n return formatString(value.value as string);\n case ValueType.Boolean:\n return formatBoolean(value.value as boolean);\n case ValueType.Datetime:\n return formatDatetime(value.value as number, locale);\n case ValueType.Uom:\n return formatUom(value.value as number, value.unit, locale, us);\n case ValueType.Matrix:\n return formatMatrix(value.value as MatrixData, locale, us);\n case ValueType.Range: {\n const r = value.value as RangeData;\n return formatRange(r.min, r.max, locale);\n }\n case ValueType.Symbolic:\n return formatSymbolic(value.value as SymbolicNode);\n case ValueType.Percentage:\n return formatPercentage(value.value as number, locale, us);\n case ValueType.Unit:\n return formatUnit(value.value as number, value.unit);\n case ValueType.Error:\n // errorValue(code, message) stores the human-readable message in\n // `.unit` (code goes in `.value`), falling through to the default\n // case here previously displayed the raw code (e.g.\n // \"CURRENCY_RATE_UNAVAILABLE\") instead of the actual message.\n return value.unit ?? String(value.value);\n default:\n return `= ${String(value.value)}`;\n }\n}\n"]}