@cortex-js/compute-engine 0.56.0 → 0.57.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 (258) hide show
  1. package/dist/compile.esm.js +450 -42
  2. package/dist/compile.min.esm.js +57 -57
  3. package/dist/compile.min.umd.cjs +58 -58
  4. package/dist/compile.umd.cjs +450 -42
  5. package/dist/compute-engine.esm.js +677 -49
  6. package/dist/compute-engine.min.esm.js +62 -62
  7. package/dist/compute-engine.min.umd.cjs +62 -62
  8. package/dist/compute-engine.umd.cjs +677 -49
  9. package/dist/core.esm.js +676 -48
  10. package/dist/core.min.esm.js +61 -61
  11. package/dist/core.min.umd.cjs +61 -61
  12. package/dist/core.umd.cjs +676 -48
  13. package/dist/interval.esm.js +228 -16
  14. package/dist/interval.min.esm.js +6 -6
  15. package/dist/interval.min.umd.cjs +6 -6
  16. package/dist/interval.umd.cjs +228 -16
  17. package/dist/latex-syntax.esm.js +269 -16
  18. package/dist/latex-syntax.min.esm.js +6 -6
  19. package/dist/latex-syntax.min.umd.cjs +6 -6
  20. package/dist/latex-syntax.umd.cjs +269 -16
  21. package/dist/math-json.esm.js +2 -2
  22. package/dist/math-json.min.esm.js +2 -2
  23. package/dist/math-json.min.umd.cjs +2 -2
  24. package/dist/math-json.umd.cjs +2 -2
  25. package/dist/numerics.esm.js +2 -2
  26. package/dist/numerics.min.esm.js +2 -2
  27. package/dist/numerics.min.umd.cjs +2 -2
  28. package/dist/numerics.umd.cjs +2 -2
  29. package/dist/types/big-decimal/big-decimal.d.ts +1 -1
  30. package/dist/types/big-decimal/index.d.ts +1 -1
  31. package/dist/types/big-decimal/transcendentals.d.ts +1 -1
  32. package/dist/types/big-decimal/utils.d.ts +1 -1
  33. package/dist/types/common/ansi-codes.d.ts +1 -1
  34. package/dist/types/common/configuration-change.d.ts +1 -1
  35. package/dist/types/common/fuzzy-string-match.d.ts +1 -1
  36. package/dist/types/common/grapheme-splitter.d.ts +1 -1
  37. package/dist/types/common/interruptible.d.ts +1 -1
  38. package/dist/types/common/one-of.d.ts +1 -1
  39. package/dist/types/common/signals.d.ts +1 -1
  40. package/dist/types/common/type/ast-nodes.d.ts +1 -1
  41. package/dist/types/common/type/boxed-type.d.ts +1 -1
  42. package/dist/types/common/type/lexer.d.ts +1 -1
  43. package/dist/types/common/type/parse.d.ts +1 -1
  44. package/dist/types/common/type/parser.d.ts +1 -1
  45. package/dist/types/common/type/primitive.d.ts +1 -1
  46. package/dist/types/common/type/reduce.d.ts +1 -1
  47. package/dist/types/common/type/serialize.d.ts +1 -1
  48. package/dist/types/common/type/subtype.d.ts +1 -1
  49. package/dist/types/common/type/type-builder.d.ts +1 -1
  50. package/dist/types/common/type/types.d.ts +1 -1
  51. package/dist/types/common/type/utils.d.ts +1 -1
  52. package/dist/types/common/utils.d.ts +1 -1
  53. package/dist/types/compile.d.ts +1 -1
  54. package/dist/types/compute-engine/assume.d.ts +1 -1
  55. package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +6 -1
  56. package/dist/types/compute-engine/boxed-expression/apply.d.ts +1 -1
  57. package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +1 -1
  58. package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +1 -1
  59. package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +1 -1
  60. package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
  61. package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
  62. package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
  63. package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
  64. package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
  65. package/dist/types/compute-engine/boxed-expression/boxed-operator-definition.d.ts +1 -1
  66. package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
  67. package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
  68. package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
  69. package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +1 -1
  70. package/dist/types/compute-engine/boxed-expression/boxed-value-definition.d.ts +1 -1
  71. package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
  72. package/dist/types/compute-engine/boxed-expression/canonical-utils.d.ts +1 -1
  73. package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
  74. package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
  75. package/dist/types/compute-engine/boxed-expression/constants.d.ts +1 -1
  76. package/dist/types/compute-engine/boxed-expression/expand.d.ts +1 -1
  77. package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
  78. package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -1
  79. package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
  80. package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
  81. package/dist/types/compute-engine/boxed-expression/inequality-bounds.d.ts +1 -1
  82. package/dist/types/compute-engine/boxed-expression/init-lazy-refs.d.ts +1 -1
  83. package/dist/types/compute-engine/boxed-expression/invisible-operator.d.ts +1 -1
  84. package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
  85. package/dist/types/compute-engine/boxed-expression/negate.d.ts +1 -1
  86. package/dist/types/compute-engine/boxed-expression/numerics.d.ts +1 -1
  87. package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
  88. package/dist/types/compute-engine/boxed-expression/pattern-utils.d.ts +1 -1
  89. package/dist/types/compute-engine/boxed-expression/polynomial-degree.d.ts +1 -1
  90. package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
  91. package/dist/types/compute-engine/boxed-expression/predicates.d.ts +1 -1
  92. package/dist/types/compute-engine/boxed-expression/rules.d.ts +1 -1
  93. package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
  94. package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
  95. package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
  96. package/dist/types/compute-engine/boxed-expression/solve-linear-system.d.ts +1 -1
  97. package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -1
  98. package/dist/types/compute-engine/boxed-expression/stochastic-equal.d.ts +1 -1
  99. package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +1 -1
  100. package/dist/types/compute-engine/boxed-expression/type-guards.d.ts +1 -1
  101. package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
  102. package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
  103. package/dist/types/compute-engine/collection-utils.d.ts +1 -1
  104. package/dist/types/compute-engine/compilation/base-compiler.d.ts +55 -6
  105. package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
  106. package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
  107. package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
  108. package/dist/types/compute-engine/compilation/gpu-target.d.ts +1 -1
  109. package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
  110. package/dist/types/compute-engine/compilation/javascript-target.d.ts +1 -1
  111. package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
  112. package/dist/types/compute-engine/compilation/types.d.ts +1 -1
  113. package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
  114. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  115. package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
  116. package/dist/types/compute-engine/engine-cache.d.ts +1 -1
  117. package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
  118. package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
  119. package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
  120. package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
  121. package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
  122. package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
  123. package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
  124. package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
  125. package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
  126. package/dist/types/compute-engine/engine-scope.d.ts +1 -1
  127. package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
  128. package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
  129. package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
  130. package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
  131. package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
  132. package/dist/types/compute-engine/free-functions.d.ts +1 -1
  133. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  134. package/dist/types/compute-engine/global-types.d.ts +1 -1
  135. package/dist/types/compute-engine/index.d.ts +3 -2
  136. package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
  137. package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
  138. package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
  139. package/dist/types/compute-engine/interval/index.d.ts +1 -1
  140. package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
  141. package/dist/types/compute-engine/interval/types.d.ts +1 -1
  142. package/dist/types/compute-engine/interval/util.d.ts +1 -1
  143. package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +1 -1
  144. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  145. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  146. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  147. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-colors.d.ts +1 -1
  148. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
  149. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
  150. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
  151. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
  152. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  153. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
  154. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  155. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
  156. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  157. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  158. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
  159. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
  160. package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +1 -1
  161. package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
  162. package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
  163. package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
  164. package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -1
  165. package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
  166. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
  167. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
  168. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
  169. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  170. package/dist/types/compute-engine/latex-syntax/types.d.ts +40 -1
  171. package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
  172. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  173. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  174. package/dist/types/compute-engine/library/collections.d.ts +5 -3
  175. package/dist/types/compute-engine/library/colors.d.ts +1 -1
  176. package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
  177. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  178. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  179. package/dist/types/compute-engine/library/core.d.ts +1 -1
  180. package/dist/types/compute-engine/library/fractals.d.ts +1 -1
  181. package/dist/types/compute-engine/library/library.d.ts +1 -1
  182. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  183. package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
  184. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  185. package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
  186. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  187. package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
  188. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  189. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  190. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  191. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  192. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  193. package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
  194. package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
  195. package/dist/types/compute-engine/library/units.d.ts +1 -1
  196. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  197. package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
  198. package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
  199. package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
  200. package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
  201. package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
  202. package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
  203. package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
  204. package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
  205. package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
  206. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  207. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  208. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  209. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  210. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  211. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
  212. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  213. package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
  214. package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
  215. package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
  216. package/dist/types/compute-engine/numerics/types.d.ts +1 -1
  217. package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
  218. package/dist/types/compute-engine/oeis.d.ts +1 -1
  219. package/dist/types/compute-engine/sequence.d.ts +1 -1
  220. package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
  221. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  222. package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
  223. package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
  224. package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
  225. package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
  226. package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
  227. package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
  228. package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
  229. package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
  230. package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
  231. package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
  232. package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
  233. package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
  234. package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
  235. package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
  236. package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
  237. package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
  238. package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
  239. package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
  240. package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
  241. package/dist/types/compute-engine/types-definitions.d.ts +1 -1
  242. package/dist/types/compute-engine/types-engine.d.ts +18 -1
  243. package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
  244. package/dist/types/compute-engine/types-expression.d.ts +1 -1
  245. package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
  246. package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
  247. package/dist/types/compute-engine/types-serialization.d.ts +1 -1
  248. package/dist/types/compute-engine/types.d.ts +1 -1
  249. package/dist/types/compute-engine.d.ts +1 -1
  250. package/dist/types/core.d.ts +1 -1
  251. package/dist/types/interval.d.ts +1 -1
  252. package/dist/types/latex-syntax.d.ts +2 -2
  253. package/dist/types/math-json/symbols.d.ts +1 -1
  254. package/dist/types/math-json/types.d.ts +1 -1
  255. package/dist/types/math-json/utils.d.ts +1 -1
  256. package/dist/types/math-json.d.ts +2 -2
  257. package/dist/types/numerics.d.ts +1 -1
  258. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /** Compute Engine 0.56.0 */
1
+ /** Compute Engine 0.57.0 */
2
2
 
3
3
  // src/compute-engine/numerics/richardson.ts
4
4
  function extrapolate(f, x0, options = {}) {
@@ -5178,6 +5178,64 @@ function parseQuantifier(kind) {
5178
5178
  }
5179
5179
 
5180
5180
  // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
5181
+ var COMPONENT_ACCESS_HEADS = {
5182
+ x: "First",
5183
+ y: "Second",
5184
+ z: "Third",
5185
+ real: "Real",
5186
+ re: "Real",
5187
+ imag: "Imaginary",
5188
+ im: "Imaginary",
5189
+ count: "Length",
5190
+ total: "Sum",
5191
+ max: "Max",
5192
+ min: "Min"
5193
+ };
5194
+ function memberHead(name) {
5195
+ return COMPONENT_ACCESS_HEADS[name] ?? null;
5196
+ }
5197
+ function parseComponentAccess(parser, lhs) {
5198
+ parser.skipVisualSpace();
5199
+ if (parser.match("\\operatorname")) {
5200
+ const name = parser.parseStringGroup();
5201
+ if (name === null) return null;
5202
+ const head = memberHead(name.trim());
5203
+ if (head === null) return null;
5204
+ return [head, lhs];
5205
+ }
5206
+ const tok = parser.peek;
5207
+ if (typeof tok === "string" && tok.startsWith("\\")) {
5208
+ const bare = tok.slice(1);
5209
+ const head = memberHead(bare);
5210
+ if (head !== null) {
5211
+ parser.nextToken();
5212
+ return [head, lhs];
5213
+ }
5214
+ return null;
5215
+ }
5216
+ if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
5217
+ const head = memberHead(tok);
5218
+ if (head === null) return null;
5219
+ parser.nextToken();
5220
+ return [head, lhs];
5221
+ }
5222
+ return null;
5223
+ }
5224
+ function parseWhenRestriction(parser, lhs, close) {
5225
+ parser.addBoundary(close);
5226
+ parser.skipVisualSpace();
5227
+ const cond = parser.parseExpression({ minPrec: 0 });
5228
+ if (cond === null) {
5229
+ parser.removeBoundary();
5230
+ return null;
5231
+ }
5232
+ parser.skipVisualSpace();
5233
+ if (!parser.matchBoundary()) {
5234
+ parser.removeBoundary();
5235
+ return null;
5236
+ }
5237
+ return ["When", lhs, cond];
5238
+ }
5181
5239
  function parseSequence(parser, terminator, lhs, prec, sep) {
5182
5240
  if (terminator && terminator.minPrec >= prec) return null;
5183
5241
  const result = lhs ? [lhs] : ["Nothing"];
@@ -5649,6 +5707,15 @@ var DEFINITIONS_CORE = [
5649
5707
  }
5650
5708
  },
5651
5709
  { name: "LatexTokens", serialize: serializeLatexTokens },
5710
+ // Component-access postfix: expr.member (C3)
5711
+ // The '.' trigger is consumed before the parse function is called.
5712
+ // Precedence 850 > 810 (At/indexing) so .x chains tightly.
5713
+ {
5714
+ kind: "postfix",
5715
+ precedence: 850,
5716
+ latexTrigger: ["."],
5717
+ parse: parseComponentAccess
5718
+ },
5652
5719
  {
5653
5720
  name: "At",
5654
5721
  kind: "postfix",
@@ -5669,6 +5736,29 @@ var DEFINITIONS_CORE = [
5669
5736
  latexTrigger: ["\\left", "\\lbrack"],
5670
5737
  parse: parseAt("\\right", "\\rbrack")
5671
5738
  },
5739
+ // When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
5740
+ {
5741
+ name: "When",
5742
+ kind: "postfix",
5743
+ precedence: 800,
5744
+ latexTrigger: ["\\left", "\\{"],
5745
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
5746
+ serialize: (serializer, expr) => {
5747
+ const e = operand(expr, 1);
5748
+ const cond = operand(expr, 2);
5749
+ if (!e || !cond) return "";
5750
+ const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
5751
+ const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
5752
+ return `${serializer.serialize(e)}${inner}`;
5753
+ }
5754
+ },
5755
+ // When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
5756
+ {
5757
+ kind: "postfix",
5758
+ precedence: 800,
5759
+ latexTrigger: ["\\{"],
5760
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
5761
+ },
5672
5762
  {
5673
5763
  kind: "postfix",
5674
5764
  latexTrigger: ["_"],
@@ -5751,6 +5841,29 @@ var DEFINITIONS_CORE = [
5751
5841
  return "";
5752
5842
  }
5753
5843
  },
5844
+ // Additional triggers for Range: `...`, `\ldots`, and `\dots` are
5845
+ // equivalent to `..` when used as infix operators (e.g. `[1...9]`).
5846
+ // No `name` field here — names must be unique per the dictionary rules;
5847
+ // the first Range entry owns the name. When there is no LHS the symbol
5848
+ // entries near the top of the file still fire (ContinuationPlaceholder).
5849
+ {
5850
+ latexTrigger: [".", ".", "."],
5851
+ kind: "infix",
5852
+ precedence: 800,
5853
+ parse: parseRange
5854
+ },
5855
+ {
5856
+ latexTrigger: ["\\ldots"],
5857
+ kind: "infix",
5858
+ precedence: 800,
5859
+ parse: parseRange
5860
+ },
5861
+ {
5862
+ latexTrigger: ["\\dots"],
5863
+ kind: "infix",
5864
+ precedence: 800,
5865
+ parse: parseRange
5866
+ },
5754
5867
  {
5755
5868
  latexTrigger: [";"],
5756
5869
  kind: "infix",
@@ -5935,13 +6048,24 @@ var DEFINITIONS_CORE = [
5935
6048
  const args = operands(expr);
5936
6049
  if (!args || args.length < 2) return "";
5937
6050
  const body = args[0];
5938
- const indexing = args[1];
5939
- if (operator(indexing) === "Element") {
5940
- const index = operand(indexing, 1);
5941
- const range2 = operand(indexing, 2);
5942
- if (operator(range2) === "Range") {
5943
- const lo = operand(range2, 1);
5944
- const hi = operand(range2, 2);
6051
+ const elements = args.slice(1);
6052
+ const allElements = elements.every((e) => operator(e) === "Element");
6053
+ if (!allElements) {
6054
+ return joinLatex([
6055
+ "\\operatorname{Loop}(",
6056
+ serializer.serialize(body),
6057
+ ", ",
6058
+ serializer.serialize(elements[0]),
6059
+ ")"
6060
+ ]);
6061
+ }
6062
+ if (elements.length === 1) {
6063
+ const elem = elements[0];
6064
+ const index = operand(elem, 1);
6065
+ const coll = operand(elem, 2);
6066
+ if (operator(coll) === "Range") {
6067
+ const lo = operand(coll, 1);
6068
+ const hi = operand(coll, 2);
5945
6069
  return joinLatex([
5946
6070
  "\\text{for }",
5947
6071
  serializer.serialize(index),
@@ -5953,13 +6077,27 @@ var DEFINITIONS_CORE = [
5953
6077
  serializer.serialize(body)
5954
6078
  ]);
5955
6079
  }
6080
+ return joinLatex([
6081
+ serializer.serialize(body),
6082
+ " \\operatorname{for} ",
6083
+ serializer.serialize(index),
6084
+ " = ",
6085
+ serializer.serialize(coll)
6086
+ ]);
5956
6087
  }
6088
+ const bindings = elements.map((elem) => {
6089
+ const name = operand(elem, 1);
6090
+ const coll = operand(elem, 2);
6091
+ return joinLatex([
6092
+ serializer.serialize(name),
6093
+ " = ",
6094
+ serializer.serialize(coll)
6095
+ ]);
6096
+ }).join(", ");
5957
6097
  return joinLatex([
5958
- "\\operatorname{Loop}(",
5959
6098
  serializer.serialize(body),
5960
- ", ",
5961
- serializer.serialize(indexing),
5962
- ")"
6099
+ " \\operatorname{for} ",
6100
+ bindings
5963
6101
  ]);
5964
6102
  }
5965
6103
  },
@@ -5992,6 +6130,18 @@ var DEFINITIONS_CORE = [
5992
6130
  precedence: 245,
5993
6131
  parse: (parser, until) => parseForExpression(parser, until)
5994
6132
  },
6133
+ // \operatorname{for} as postfix infix (list comprehension):
6134
+ // `body \operatorname{for} x = L_1, y = L_2`
6135
+ // Precedence 19 — just below comma (20) so the body is allowed to use
6136
+ // any operator (including comma sequencing) up to the keyword, and the
6137
+ // bindings can be comma-separated below us.
6138
+ {
6139
+ symbolTrigger: "for",
6140
+ kind: "infix",
6141
+ associativity: "none",
6142
+ precedence: 19,
6143
+ parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
6144
+ },
5995
6145
  // \operatorname{break}
5996
6146
  {
5997
6147
  symbolTrigger: "break",
@@ -6196,7 +6346,10 @@ var DEFINITIONS_CORE = [
6196
6346
  if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
6197
6347
  parser.addBoundary([")"]);
6198
6348
  const expr = parser.parseExpression(until);
6199
- if (!parser.matchBoundary()) return null;
6349
+ if (!parser.matchBoundary()) {
6350
+ parser.removeBoundary();
6351
+ return null;
6352
+ }
6200
6353
  if (!parser.match("<}>")) return null;
6201
6354
  return ["Derivative", lhs, expr];
6202
6355
  }
@@ -6637,7 +6790,12 @@ function parseBrackets(parser, body) {
6637
6790
  if (isEmptySequence(body)) return ["List"];
6638
6791
  const h = operator(body);
6639
6792
  if (h === "Range" || h === "Linspace") return body;
6640
- if (h === "Sequence") return ["List", ...operands(body)];
6793
+ if (h === "Sequence") {
6794
+ const elems = operands(body);
6795
+ const inferred = tryInferRangeFromElements(elems, parser);
6796
+ if (inferred) return inferred;
6797
+ return ["List", ...elems];
6798
+ }
6641
6799
  if (h === "Delimiter") {
6642
6800
  const delim = stringValue(operand(body, 2)) ?? "...";
6643
6801
  if (delim === ";" || delim === ".;.") {
@@ -6650,12 +6808,37 @@ function parseBrackets(parser, body) {
6650
6808
  }
6651
6809
  if (delim === "," || delim === ".,.") {
6652
6810
  body = operand(body, 1);
6653
- if (operator(body) === "Sequence") return ["List", ...operands(body)];
6811
+ if (operator(body) === "Sequence") {
6812
+ const elems = operands(body);
6813
+ const inferred = tryInferRangeFromElements(elems, parser);
6814
+ if (inferred) return inferred;
6815
+ return ["List", ...elems];
6816
+ }
6654
6817
  return ["List", body ?? "Nothing"];
6655
6818
  }
6656
6819
  }
6657
6820
  return ["List", body];
6658
6821
  }
6822
+ function tryInferRangeFromElements(elems, parser) {
6823
+ if (elems.length < 4) return null;
6824
+ const penultimate = elems[elems.length - 2];
6825
+ if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
6826
+ const samples = elems.slice(0, -2);
6827
+ const endExpr = elems[elems.length - 1];
6828
+ if (samples.length < 2) return null;
6829
+ const sampleNums = samples.map(machineValue);
6830
+ if (sampleNums.some((n) => n === null)) return null;
6831
+ const nums = sampleNums;
6832
+ const step = nums[nums.length - 1] - nums[nums.length - 2];
6833
+ const tol = parser.options.tolerance;
6834
+ if (Math.abs(step) < tol)
6835
+ return parser.error("degenerate-range-step", parser.index);
6836
+ for (let i = 1; i < nums.length; i++) {
6837
+ if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
6838
+ return parser.error("inconsistent-range-samples", parser.index);
6839
+ }
6840
+ return ["Range", nums[0], endExpr, step];
6841
+ }
6659
6842
  function serializeList(serializer, expr) {
6660
6843
  if (nops(expr) > 1 && operands(expr).every((x) => {
6661
6844
  const op = operator(x);
@@ -6907,6 +7090,35 @@ function parseForExpression(parser, until) {
6907
7090
  ["Element", index, ["Range", lower, upper]]
6908
7091
  ];
6909
7092
  }
7093
+ function parseForComprehension(parser, lhs, until) {
7094
+ const bindingTerminator = {
7095
+ minPrec: 21,
7096
+ // Above comma (20) and ; (19), so `x = L_1` is captured whole
7097
+ condition: (p) => {
7098
+ if (until?.condition?.(p)) return true;
7099
+ const saved = p.index;
7100
+ p.skipVisualSpace();
7101
+ const isComma = p.peek === ",";
7102
+ p.index = saved;
7103
+ return isComma;
7104
+ }
7105
+ };
7106
+ const elements = [];
7107
+ do {
7108
+ parser.skipVisualSpace();
7109
+ const binding = parser.parseExpression(bindingTerminator);
7110
+ if (binding === null) break;
7111
+ const op = operator(binding);
7112
+ if (op !== "Equal" && op !== "Assign") return null;
7113
+ const name = operand(binding, 1);
7114
+ const list = operand(binding, 2);
7115
+ if (!name || !list) return null;
7116
+ elements.push(["Element", name, list]);
7117
+ parser.skipVisualSpace();
7118
+ } while (parser.match(","));
7119
+ if (elements.length === 0) return null;
7120
+ return ["Loop", lhs, ...elements];
7121
+ }
6910
7122
  function parseWhereExpression(parser, lhs, until) {
6911
7123
  const bindingTerminator = {
6912
7124
  minPrec: 21,
@@ -12803,7 +13015,11 @@ var COLLECTIONS_LIBRARY = {
12803
13015
  //
12804
13016
  Range: {
12805
13017
  complexity: 8200,
12806
- signature: "(number, number?, step: number?) -> indexed_collection<integer>",
13018
+ signature: "(number, number?, step: number?) -> indexed_collection<number>",
13019
+ type: (ops) => {
13020
+ const allInt = ops.every((op) => op.isInteger);
13021
+ return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
13022
+ },
12807
13023
  canonical: (ops, { engine: ce }) => {
12808
13024
  if (ops.length === 0) return null;
12809
13025
  if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
@@ -12827,19 +13043,26 @@ var COLLECTIONS_LIBRARY = {
12827
13043
  const [lower, upper, step] = range(expr);
12828
13044
  if (step === 0) return 0;
12829
13045
  if (!isFinite(lower) || !isFinite(upper)) return Infinity;
12830
- return 1 + Math.max(0, Math.floor((upper - lower) / step));
13046
+ return Math.max(0, Math.floor((upper - lower) / step) + 1);
12831
13047
  },
12832
13048
  contains: (expr, target) => {
12833
- if (!target.type.matches("integer")) return false;
12834
13049
  const t = target.re;
13050
+ if (!isFinite(t)) return false;
12835
13051
  const [lower, upper, step] = range(expr);
12836
13052
  if (step === 0) return false;
12837
- if (step > 0) return t >= lower && t <= upper;
12838
- return t <= lower && t >= upper;
13053
+ if (step > 0) {
13054
+ if (t < lower || t > upper) return false;
13055
+ } else {
13056
+ if (t > lower || t < upper) return false;
13057
+ }
13058
+ const k = (t - lower) / step;
13059
+ const tol = expr.engine.tolerance;
13060
+ const kRounded = Math.round(k);
13061
+ return kRounded >= 0 && Math.abs(k - kRounded) < tol;
12839
13062
  },
12840
13063
  iterator: (expr) => {
12841
13064
  const [lower, upper, step] = range(expr);
12842
- const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
13065
+ const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
12843
13066
  let index = 1;
12844
13067
  return {
12845
13068
  next: () => {
@@ -12857,7 +13080,9 @@ var COLLECTIONS_LIBRARY = {
12857
13080
  at: (expr, index) => {
12858
13081
  if (typeof index !== "number") return void 0;
12859
13082
  const [lower, upper, step] = range(expr);
12860
- if (index < 1 || index > 1 + (upper - lower) / step) return void 0;
13083
+ if (step === 0) return void 0;
13084
+ const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
13085
+ if (index < 1 || index > maxCount) return void 0;
12861
13086
  return expr.engine.number(lower + step * (index - 1));
12862
13087
  },
12863
13088
  indexWhere: void 0,
@@ -12882,7 +13107,13 @@ var COLLECTIONS_LIBRARY = {
12882
13107
  if (step > 0) return lower <= upper ? "positive" : "negative";
12883
13108
  return lower >= upper ? "positive" : "negative";
12884
13109
  },
12885
- elttype: (_expr) => "finite_integer"
13110
+ elttype: (expr) => {
13111
+ if (!isFunction2(expr)) return "finite_integer";
13112
+ for (let i = 1; i <= expr.nops; i++) {
13113
+ if (!expr[`op${i}`].isInteger) return "finite_real";
13114
+ }
13115
+ return "finite_integer";
13116
+ }
12886
13117
  }
12887
13118
  },
12888
13119
  Interval: {
@@ -13480,15 +13711,45 @@ var COLLECTIONS_LIBRARY = {
13480
13711
  },
13481
13712
  First: {
13482
13713
  complexity: 8200,
13483
- signature: "(collection) -> any",
13714
+ signature: "(any) -> any",
13484
13715
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
13485
- evaluate: ([xs], { engine: ce }) => xs.at(1) ?? ce.Nothing
13716
+ evaluate: ([xs], { engine: ce }) => {
13717
+ if (!xs.isCollection)
13718
+ return ce.error([
13719
+ "incompatible-type",
13720
+ `'collection'`,
13721
+ xs.type.toString()
13722
+ ]);
13723
+ return xs.at(1) ?? ce.Nothing;
13724
+ }
13486
13725
  },
13487
13726
  Second: {
13488
13727
  complexity: 8200,
13489
- signature: "(collection) -> any",
13728
+ signature: "(any) -> any",
13490
13729
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
13491
- evaluate: ([xs], { engine: ce }) => xs.at(2) ?? ce.Nothing
13730
+ evaluate: ([xs], { engine: ce }) => {
13731
+ if (!xs.isCollection)
13732
+ return ce.error([
13733
+ "incompatible-type",
13734
+ `'collection'`,
13735
+ xs.type.toString()
13736
+ ]);
13737
+ return xs.at(2) ?? ce.Nothing;
13738
+ }
13739
+ },
13740
+ Third: {
13741
+ complexity: 8200,
13742
+ signature: "(any) -> any",
13743
+ type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
13744
+ evaluate: ([xs], { engine: ce }) => {
13745
+ if (!xs.isCollection)
13746
+ return ce.error([
13747
+ "incompatible-type",
13748
+ `'collection'`,
13749
+ xs.type.toString()
13750
+ ]);
13751
+ return xs.at(3) ?? ce.Nothing;
13752
+ }
13492
13753
  },
13493
13754
  Last: {
13494
13755
  complexity: 8200,
@@ -14467,17 +14728,14 @@ function range(expr) {
14467
14728
  if (!isFunction2(expr)) return [1, 0, 0];
14468
14729
  if (expr.nops === 0) return [1, 0, 0];
14469
14730
  let op1 = expr.op1.re;
14470
- if (!isFinite(op1)) op1 = 1;
14471
- else op1 = Math.round(op1);
14731
+ if (!isFinite(op1) && !op1) op1 = 1;
14472
14732
  if (expr.nops === 1) return [1, op1, 1];
14473
14733
  let op2 = expr.op2.re;
14474
14734
  if (!isFinite(op2) && !op2) op2 = 1;
14475
- else if (isFinite(op2)) op2 = Math.round(op2);
14476
- if (expr.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
14735
+ if (expr.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
14477
14736
  let op3 = expr.op3.re;
14478
- if (!isFinite(op3)) op3 = 1;
14479
- else op3 = Math.abs(Math.round(op3));
14480
- return [op1, op2, op1 < op2 ? op3 : -op3];
14737
+ if (!isFinite(op3) && !op3) op3 = 1;
14738
+ return [op1, op2, op3];
14481
14739
  }
14482
14740
  function canonicalList(ops, { engine: ce }) {
14483
14741
  const op1 = ops[0];
@@ -14826,6 +15084,23 @@ var BaseCompiler = class _BaseCompiler {
14826
15084
  };
14827
15085
  return compilePair(0);
14828
15086
  }
15087
+ if (h === "When") {
15088
+ if (args.length !== 2)
15089
+ throw new Error("When: expected exactly 2 arguments (expr, cond)");
15090
+ const fn2 = target.functions?.(h);
15091
+ if (fn2) {
15092
+ if (typeof fn2 === "function") {
15093
+ return fn2(args, (expr) => _BaseCompiler.compile(expr, target), target);
15094
+ }
15095
+ return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
15096
+ }
15097
+ if (isSymbol2(args[1], "True"))
15098
+ return `(${_BaseCompiler.compile(args[0], target)})`;
15099
+ if (isSymbol2(args[1], "False")) return "NaN";
15100
+ const val = _BaseCompiler.compile(args[0], target);
15101
+ const cond = _BaseCompiler.compile(args[1], target);
15102
+ return `((${cond}) ? (${val}) : NaN)`;
15103
+ }
14829
15104
  if (h === "Block") {
14830
15105
  return _BaseCompiler.compileBlock(args, target);
14831
15106
  }
@@ -14900,17 +15175,91 @@ var BaseCompiler = class _BaseCompiler {
14900
15175
  )}${target.ws("\n")}})()`;
14901
15176
  }
14902
15177
  /**
14903
- * Compile a Loop expression with Element(index, Range(lo, hi)) indexing.
14904
- * Generates: (() => { for (let i = lo; i <= hi; i++) { body } })()
15178
+ * Compile a Loop expression.
15179
+ *
15180
+ * Two forms are supported:
15181
+ *
15182
+ * 1. **Imperative / single-Element form** (existing behaviour):
15183
+ * `Loop(body, Element(i, Range(lo, hi)))`
15184
+ * Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
15185
+ * in an IIFE. The loop counter is always a plain number. For targets
15186
+ * that wrap numeric values (e.g. interval-js uses `_IA.point()`),
15187
+ * references to the loop index inside the body are re-wrapped via
15188
+ * `target.number`. `break` / `continue` / `return` are preserved.
15189
+ *
15190
+ * 2. **Comprehension / variadic-Element form** (new):
15191
+ * `Loop(body, Element(x, coll1), Element(y, coll2), …)`
15192
+ * When two or more `Element` clauses are present — or when the single
15193
+ * Element's collection is not a `Range` — the loop is compiled as a
15194
+ * comprehension that collects results into an array. Each clause
15195
+ * produces a `for (const name of collection)` loop, nested
15196
+ * outermost-to-innermost, and the innermost body pushes into `result`.
15197
+ *
15198
+ * Example output (JS):
15199
+ * ```js
15200
+ * (() => { const result = [];
15201
+ * for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
15202
+ * return result; })()
15203
+ * ```
14905
15204
  *
14906
- * The loop counter is always a raw number. For targets that wrap numeric
14907
- * values (e.g. interval-js wraps with `_IA.point()`), references to the
14908
- * loop index inside the body are wrapped via `target.number`.
15205
+ * GLSL: multi-Element comprehension is not trivially representable in
15206
+ * GLSL (no dynamic arrays, no push). A compile-time error is thrown.
15207
+ * TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
15208
+ * array or by unrolling when bounds are known at compile time.
14909
15209
  */
14910
15210
  static compileForLoop(args, target) {
14911
15211
  if (!args[0]) throw new Error("Loop: no body");
14912
15212
  if (!args[1]) throw new Error("Loop: no indexing set");
14913
- const indexing = args[1];
15213
+ const body = args[0];
15214
+ const elements = args.slice(1);
15215
+ const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
15216
+ if (useComprehension) {
15217
+ const lang = target.language ?? "";
15218
+ if (lang === "glsl" || lang === "wgsl") {
15219
+ throw new Error(
15220
+ `${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
15221
+ );
15222
+ }
15223
+ const narrowedElements = [];
15224
+ for (let i = 0; i < elements.length; i++) {
15225
+ const elem = elements[i];
15226
+ if (!isFunction2(elem, "Element"))
15227
+ throw new Error(
15228
+ `Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
15229
+ );
15230
+ if (!isSymbol2(elem.ops[0]))
15231
+ throw new Error(
15232
+ `Loop: Element index (argument ${i + 1}) must be a symbol`
15233
+ );
15234
+ narrowedElements.push(elem);
15235
+ }
15236
+ const loopVarSet = new Set(
15237
+ narrowedElements.map(
15238
+ (e) => e.ops[0].symbol
15239
+ )
15240
+ );
15241
+ const needsWrap2 = target.number(0) !== "0";
15242
+ const bodyTarget2 = needsWrap2 ? {
15243
+ ...target,
15244
+ var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
15245
+ } : target;
15246
+ const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
15247
+ let inner = `result.push(${bodyCode});`;
15248
+ for (let i = narrowedElements.length - 1; i >= 0; i--) {
15249
+ const elem = narrowedElements[i];
15250
+ const name = elem.ops[0].symbol;
15251
+ const collExpr = elem.ops[1];
15252
+ let collection;
15253
+ if (isFunction2(collExpr, "Range")) {
15254
+ collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
15255
+ } else {
15256
+ collection = _BaseCompiler.compile(collExpr, bodyTarget2);
15257
+ }
15258
+ inner = `for (const ${name} of ${collection}) { ${inner} }`;
15259
+ }
15260
+ return `(() => { const result = []; ${inner} return result; })()`;
15261
+ }
15262
+ const indexing = elements[0];
14914
15263
  if (!isFunction2(indexing, "Element"))
14915
15264
  throw new Error("Loop: expected Element(index, Range(lo, hi))");
14916
15265
  const indexExpr = indexing.ops[0];
@@ -14928,13 +15277,72 @@ var BaseCompiler = class _BaseCompiler {
14928
15277
  ...target,
14929
15278
  var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
14930
15279
  };
14931
- const bodyStmts = _BaseCompiler.compileLoopBody(args[0], bodyTarget);
15280
+ const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
14932
15281
  return `(() => {${target.ws(
14933
15282
  "\n"
14934
15283
  )}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
14935
15284
  "\n"
14936
15285
  )}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
14937
15286
  }
15287
+ /**
15288
+ * Returns `true` when the given collection expression is a `Range` whose
15289
+ * runtime semantics match the legacy imperative for-loop shape
15290
+ * `for (let i = lo; i <= hi; i++)`.
15291
+ *
15292
+ * Concretely: integer-ascending bounds and step omitted-or-1. When bounds
15293
+ * are not statically numeric we accept the Range (the historical
15294
+ * behaviour) — runtime mismatch in the descending-unknown-bounds case is
15295
+ * left as a known limitation; callers can force the iterable path by
15296
+ * supplying an explicit step.
15297
+ */
15298
+ static isLegacyCompatibleRange(coll) {
15299
+ if (!isFunction2(coll, "Range")) return false;
15300
+ if (coll.ops.length >= 3) {
15301
+ const stepExpr = coll.ops[2];
15302
+ if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
15303
+ }
15304
+ const lo = coll.ops[0];
15305
+ const hi = coll.ops[1];
15306
+ if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
15307
+ if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
15308
+ if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
15309
+ return true;
15310
+ }
15311
+ /**
15312
+ * Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
15313
+ * iterable expression. Mirrors the runtime semantics in
15314
+ * `library/collections.ts` Range:
15315
+ * count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
15316
+ * element = lo + step * k (0-indexed)
15317
+ * Default step is 1 when omitted. Bounds and step may be fractional.
15318
+ *
15319
+ * Only used from the comprehension path in `compileForLoop`.
15320
+ * Caller must have already verified `isFunction(rangeExpr, 'Range')`.
15321
+ */
15322
+ static compileRangeIterable(rangeExpr, target) {
15323
+ const loExpr = rangeExpr.ops[0];
15324
+ const hiExpr = rangeExpr.ops[1];
15325
+ const stepExpr = rangeExpr.ops[2];
15326
+ if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
15327
+ const lo2 = loExpr.re;
15328
+ const hi2 = hiExpr.re;
15329
+ const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
15330
+ if (step2 === 0) return "[]";
15331
+ const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
15332
+ if (step2 === 1) {
15333
+ if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
15334
+ return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
15335
+ }
15336
+ return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
15337
+ }
15338
+ const lo = _BaseCompiler.compile(loExpr, target);
15339
+ const hi = _BaseCompiler.compile(hiExpr, target);
15340
+ if (stepExpr === void 0) {
15341
+ return `((_lo,_hi)=>{const _st=_hi>=_lo?1:-1;return Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k);})(${lo},${hi})`;
15342
+ }
15343
+ const step = _BaseCompiler.compile(stepExpr, target);
15344
+ return `((_lo,_hi,_st)=>_st===0?[]:Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k))(${lo},${hi},${step})`;
15345
+ }
14938
15346
  /**
14939
15347
  * Compile a loop body expression as statements (not wrapped in IIFE).
14940
15348
  * Handles Break, Continue, Return as statements, and If as if-else when
@@ -25501,7 +25909,7 @@ function compileToIntervalTarget(expr, target) {
25501
25909
  }
25502
25910
 
25503
25911
  // src/compile.ts
25504
- var version = "0.56.0";
25912
+ var version = "0.57.0";
25505
25913
  export {
25506
25914
  BaseCompiler,
25507
25915
  GLSLTarget,