nerdamer 2.0.0-rc.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/BREAKING_CHANGES.md +244 -0
  2. package/README.md +168 -229
  3. package/dist/bundle.js +1 -1
  4. package/dist/bundle.js.LICENSE.txt +6 -6
  5. package/output/algebra/adapters.d.ts +3 -33
  6. package/output/algebra/adapters.js +7 -105
  7. package/output/algebra/algorithms/arith.js +10 -9
  8. package/output/algebra/algorithms/groebnerBase.d.ts +24 -20
  9. package/output/algebra/algorithms/groebnerBase.js +486 -723
  10. package/output/algebra/dispatch.d.ts +1 -0
  11. package/output/algebra/dispatch.js +25 -0
  12. package/output/algebra/factor/factor.d.ts +15 -0
  13. package/output/algebra/factor/factor.js +99 -12
  14. package/output/algebra/gcd/gcd.d.ts +8 -7
  15. package/output/algebra/gcd/gcd.js +32 -78
  16. package/output/algebra/groebner.d.ts +2 -2
  17. package/output/algebra/groebner.js +6 -12
  18. package/output/algebra/partfrac.d.ts +3 -3
  19. package/output/algebra/partfrac.js +28 -61
  20. package/output/algebra/polynomial/ModularSparsePolynomial.d.ts +131 -0
  21. package/output/algebra/polynomial/ModularSparsePolynomial.js +378 -0
  22. package/output/algebra/polynomial/ModularSparsePolynomialFactor.d.ts +40 -0
  23. package/output/algebra/polynomial/ModularSparsePolynomialFactor.js +661 -0
  24. package/output/algebra/polynomial/SparsePolynomialFactor.d.ts +64 -0
  25. package/output/algebra/polynomial/SparsePolynomialFactor.js +492 -0
  26. package/output/algebra/polynomial/SparsePolynomialGcd.d.ts +29 -0
  27. package/output/algebra/polynomial/SparsePolynomialGcd.js +259 -0
  28. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.d.ts +82 -0
  29. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.js +604 -0
  30. package/output/algebra/polynomial/modularGcd.d.ts +40 -0
  31. package/output/algebra/polynomial/modularGcd.js +365 -0
  32. package/output/algebra/polynomialize.js +4 -2
  33. package/output/algebra/simplify/funcsimp.js +1 -1
  34. package/output/algebra/simplify/ratsimp.js +1 -1
  35. package/output/algebra/simplify/simplify.js +11 -2
  36. package/output/algebra/utils.d.ts +1 -1
  37. package/output/algebra/utils.js +3 -3
  38. package/output/api/advanced.d.ts +2 -1
  39. package/output/api/advanced.js +3 -3
  40. package/output/api/algebra.d.ts +21 -4
  41. package/output/api/algebra.js +22 -3
  42. package/output/api/assumptions.d.ts +1 -1
  43. package/output/api/assumptions.js +2 -1
  44. package/output/api/calculus.d.ts +2 -1
  45. package/output/api/calculus.js +2 -1
  46. package/output/api/core.d.ts +28 -7
  47. package/output/api/core.js +28 -2
  48. package/output/api/languages/deu.d.ts +3 -0
  49. package/output/api/languages/deu.js +266 -0
  50. package/output/api/languages/fra.d.ts +3 -0
  51. package/output/api/languages/fra.js +266 -0
  52. package/output/api/languages/ita.d.ts +3 -0
  53. package/output/api/languages/ita.js +266 -0
  54. package/output/api/languages/nld.d.ts +3 -0
  55. package/output/api/languages/nld.js +266 -0
  56. package/output/api/languages/por.d.ts +3 -0
  57. package/output/api/languages/por.js +266 -0
  58. package/output/api/languages/spa.d.ts +3 -0
  59. package/output/api/languages/spa.js +266 -0
  60. package/output/api/parser.d.ts +10 -2
  61. package/output/api/parser.js +2 -0
  62. package/output/api/solve.d.ts +1 -1
  63. package/output/api/solve.js +2 -1
  64. package/output/api/structures.d.ts +1 -1
  65. package/output/api/structures.js +2 -1
  66. package/output/calculus/adapters.d.ts +8 -0
  67. package/output/calculus/adapters.js +41 -0
  68. package/output/calculus/derivative/diff.js +6 -3
  69. package/output/calculus/dispatch.d.ts +1 -0
  70. package/output/calculus/dispatch.js +25 -0
  71. package/output/calculus/integrate/integrate.js +4 -4
  72. package/output/calculus/integrate/integrationTable.js +16 -16
  73. package/output/calculus/laplace/ilaplace.js +1 -1
  74. package/output/calculus/laplace/ilaplaceTable.js +18 -17
  75. package/output/calculus/laplace/laplaceTable.js +3 -2
  76. package/output/calculus/limit/limit.js +1 -1
  77. package/output/core/classes/assumption/Assumption.js +14 -10
  78. package/output/core/classes/assumption/assume.d.ts +6 -0
  79. package/output/core/classes/assumption/assume.js +9 -0
  80. package/output/core/classes/assumption/dispatch.d.ts +1 -0
  81. package/output/core/classes/assumption/dispatch.js +11 -0
  82. package/output/core/classes/collection/Collection.js +11 -2
  83. package/output/core/classes/complex/Complex.d.ts +10 -0
  84. package/output/core/classes/complex/Complex.js +19 -1
  85. package/output/core/classes/decimalSet/DecimalSet.js +5 -4
  86. package/output/core/classes/dictionary/Dictionary.js +4 -1
  87. package/output/core/classes/expression/CoeffObject.d.ts +1 -1
  88. package/output/core/classes/expression/CoeffObject.js +1 -2
  89. package/output/core/classes/expression/Expression.d.ts +35 -26
  90. package/output/core/classes/expression/Expression.js +77 -50
  91. package/output/core/classes/expression/analysis.d.ts +1 -1
  92. package/output/core/classes/expression/analysis.js +7 -7
  93. package/output/core/classes/expression/format.d.ts +9 -0
  94. package/output/core/classes/expression/format.js +130 -7
  95. package/output/core/classes/expression/utils.d.ts +9 -0
  96. package/output/core/classes/expression/utils.js +52 -6
  97. package/output/core/classes/matrix/Matrix.d.ts +2 -3
  98. package/output/core/classes/matrix/Matrix.js +26 -23
  99. package/output/core/classes/matrix/dispatch.d.ts +1 -0
  100. package/output/core/classes/matrix/dispatch.js +19 -0
  101. package/output/core/classes/matrix/functions.d.ts +2 -0
  102. package/output/core/classes/matrix/functions.js +5 -0
  103. package/output/core/classes/parser/Parser.d.ts +31 -5
  104. package/output/core/classes/parser/Parser.js +357 -444
  105. package/output/core/classes/parser/constants.d.ts +2 -0
  106. package/output/core/classes/parser/constants.js +4 -2
  107. package/output/core/classes/parser/controlFlowSignals.d.ts +38 -0
  108. package/output/core/classes/parser/controlFlowSignals.js +60 -0
  109. package/output/core/classes/parser/operations/add.js +14 -16
  110. package/output/core/classes/parser/operations/compare.js +13 -0
  111. package/output/core/classes/parser/operations/functions.d.ts +3 -4
  112. package/output/core/classes/parser/operations/functions.js +48 -102
  113. package/output/core/classes/parser/operations/multiply.js +22 -15
  114. package/output/core/classes/parser/operations/power.js +11 -11
  115. package/output/core/classes/parser/operations/subtract.js +2 -1
  116. package/output/core/classes/parser/preprocess.d.ts +0 -7
  117. package/output/core/classes/parser/preprocess.js +33 -39
  118. package/output/core/classes/parser/scripting/controlFlow.d.ts +4 -102
  119. package/output/core/classes/parser/scripting/controlFlow.js +134 -186
  120. package/output/core/classes/parser/scripting/deferred.d.ts +4 -0
  121. package/output/core/classes/parser/scripting/deferred.js +65 -0
  122. package/output/core/classes/parser/scripting/dispatch.d.ts +1 -0
  123. package/output/core/classes/parser/scripting/dispatch.js +62 -0
  124. package/output/core/classes/parser/scripting/evaluate.d.ts +13 -0
  125. package/output/core/classes/parser/scripting/evaluate.js +17 -1
  126. package/output/core/classes/parser/scripting/scope.d.ts +1 -28
  127. package/output/core/classes/parser/scripting/scope.js +36 -40
  128. package/output/core/classes/parser/types.d.ts +5 -5
  129. package/output/core/classes/parser/wrappers/IndexedReference.d.ts +4 -3
  130. package/output/core/classes/parser/wrappers/IndexedReference.js +8 -0
  131. package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +2 -2
  132. package/output/core/classes/polynomial/Polynomial.d.ts +5 -1
  133. package/output/core/classes/polynomial/Polynomial.js +53 -7
  134. package/output/core/classes/polynomial/SparsePolynomial.d.ts +221 -0
  135. package/output/core/classes/polynomial/SparsePolynomial.js +824 -0
  136. package/output/core/classes/polynomial/SparsePolynomialAdapter.d.ts +56 -0
  137. package/output/core/classes/polynomial/SparsePolynomialAdapter.js +241 -0
  138. package/output/core/classes/polynomial/Term.js +2 -2
  139. package/output/core/{adapters.d.ts → classes/polynomial/adapters.d.ts} +2 -2
  140. package/output/core/classes/polynomial/adapters.js +33 -0
  141. package/output/core/classes/polynomial/dispatch.d.ts +1 -0
  142. package/output/core/classes/polynomial/dispatch.js +14 -0
  143. package/output/core/classes/polynomial/functions.d.ts +8 -0
  144. package/output/core/classes/polynomial/functions.js +71 -8
  145. package/output/core/classes/polynomial/utils.js +2 -1
  146. package/output/core/classes/rational/Rational.d.ts +8 -11
  147. package/output/core/classes/rational/Rational.js +70 -20
  148. package/output/core/classes/seq/SEQ.js +4 -4
  149. package/output/core/classes/valuesSet/ValuesSet.d.ts +9 -1
  150. package/output/core/classes/valuesSet/ValuesSet.js +22 -4
  151. package/output/core/classes/vector/Vector.d.ts +2 -3
  152. package/output/core/classes/vector/Vector.js +11 -15
  153. package/output/core/classes/vector/dispatch.d.ts +1 -0
  154. package/output/core/classes/vector/dispatch.js +11 -0
  155. package/output/core/common/classes/MathematicalAggregate.js +11 -2
  156. package/output/core/common/classes/StructuredEntity.d.ts +0 -17
  157. package/output/core/common/classes/StructuredEntity.js +3 -64
  158. package/output/core/common/common.d.ts +0 -1
  159. package/output/core/common/common.js +29 -234
  160. package/output/core/converters/BaseConverter.js +3 -2
  161. package/output/core/converters/Converter.js +9 -5
  162. package/output/core/converters/Pattern.js +1 -1
  163. package/output/core/dispatch.d.ts +18 -0
  164. package/output/core/dispatch.js +3 -281
  165. package/output/core/errors.d.ts +259 -474
  166. package/output/core/errors.js +270 -542
  167. package/output/core/fullFunctions.d.ts +7 -0
  168. package/output/core/fullFunctions.js +31 -0
  169. package/output/core/functions/bigint/bigint.d.ts +13 -1
  170. package/output/core/functions/bigint/bigint.js +56 -4
  171. package/output/core/functions/bigint/primeFactor.d.ts +2 -0
  172. package/output/core/functions/bigint/primeFactor.js +13 -13
  173. package/output/core/functions/build/definitions.js +6 -0
  174. package/output/core/functions/complex.d.ts +2 -2
  175. package/output/core/functions/complex.dispatch.d.ts +1 -0
  176. package/output/core/functions/complex.dispatch.js +16 -0
  177. package/output/core/functions/complex.js +7 -7
  178. package/output/core/functions/decimal.js +2 -1
  179. package/output/core/functions/expand/expand.js +2 -2
  180. package/output/core/functions/numeric.d.ts +1 -1
  181. package/output/core/functions/string.js +2 -1
  182. package/output/core/functions/subst.js +21 -13
  183. package/output/core/parserFunctions.d.ts +7 -0
  184. package/output/core/parserFunctions.js +25 -0
  185. package/output/index.d.ts +50 -30
  186. package/output/index.js +147 -19
  187. package/output/math/defint/defint.d.ts +18 -0
  188. package/output/math/defint/defint.js +60 -0
  189. package/output/math/defint/defintDecimal.js +6 -5
  190. package/output/math/defint/defintNative.js +7 -18
  191. package/output/math/dispatch.d.ts +1 -0
  192. package/output/math/dispatch.js +101 -0
  193. package/output/math/geometry.d.ts +4 -0
  194. package/output/math/geometry.js +23 -0
  195. package/output/math/math.d.ts +59 -19
  196. package/output/math/math.js +244 -100
  197. package/output/math/trig.js +4 -4
  198. package/output/math/utils.d.ts +6 -0
  199. package/output/math/utils.js +39 -0
  200. package/output/solve/classes/PolynomialSolver.d.ts +33 -14
  201. package/output/solve/classes/PolynomialSolver.js +267 -67
  202. package/output/solve/classes/SolutionSet.d.ts +20 -1
  203. package/output/solve/classes/SolutionSet.js +82 -5
  204. package/output/solve/dispatch.d.ts +1 -0
  205. package/output/solve/dispatch.js +13 -0
  206. package/output/solve/linsolve.d.ts +2 -0
  207. package/output/solve/linsolve.js +13 -5
  208. package/output/solve/solve.d.ts +10 -0
  209. package/output/solve/solve.js +128 -20
  210. package/output/solve/solveSystem.d.ts +1 -1
  211. package/output/solve/solveSystem.js +8 -32
  212. package/output/solve/utils.d.ts +2 -1
  213. package/output/solve/utils.js +18 -22
  214. package/output/utils/array.d.ts +1 -1
  215. package/output/utils/debug.js +2 -1
  216. package/package.json +22 -38
  217. package/dist/parser.js +0 -2
  218. package/dist/parser.js.LICENSE.txt +0 -7
  219. package/docs-data/parser-functions.json +0 -1960
  220. package/output/algebra/algorithms/factor.d.ts +0 -3
  221. package/output/algebra/algorithms/factor.js +0 -5
  222. package/output/algebra/algorithms/factorMultivariate.d.ts +0 -23
  223. package/output/algebra/algorithms/factorMultivariate.js +0 -2393
  224. package/output/algebra/algorithms/factorUnivariate.d.ts +0 -72
  225. package/output/algebra/algorithms/factorUnivariate.js +0 -1072
  226. package/output/algebra/algorithms/gcd.d.ts +0 -22
  227. package/output/algebra/algorithms/gcd.js +0 -690
  228. package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +0 -137
  229. package/output/algebra/algorithms/multiPoly/MultiPoly.js +0 -346
  230. package/output/algebra/algorithms/poly.d.ts +0 -228
  231. package/output/algebra/algorithms/poly.js +0 -1299
  232. package/output/algebra/algorithms/rational.d.ts +0 -17
  233. package/output/algebra/algorithms/rational.js +0 -115
  234. package/output/core/adapters.js +0 -40
  235. package/output/core/classes/parser/operations/comma.d.ts +0 -7
  236. package/output/core/classes/parser/operations/comma.js +0 -11
@@ -19,6 +19,7 @@ const Rational_1 = require("../rational/Rational");
19
19
  const ValuesSet_1 = require("../valuesSet/ValuesSet");
20
20
  const Vector_1 = require("../vector/Vector");
21
21
  const constants_1 = require("./constants");
22
+ const controlFlowSignals_1 = require("./controlFlowSignals");
22
23
  const functions_2 = require("./operations/functions");
23
24
  const preprocess_1 = require("./preprocess");
24
25
  const Token_1 = require("./Token");
@@ -91,6 +92,47 @@ class ExpressionParser {
91
92
  * result, so ordinary substitution does not hand out the stored object itself.
92
93
  */
93
94
  KNOWN_VALUES = {};
95
+ /**
96
+ * Resolves a Dictionary index through the active parser scope.
97
+ *
98
+ * A plain variable index is resolved directly instead of reparsing its square
99
+ * scope. This matters for deferred scripting bodies, where LET installs the
100
+ * current binding in KNOWN_VALUES while excluding that name from inherited
101
+ * call-scoped substitutions.
102
+ *
103
+ * An unresolved symbolic index remains its own textual key, so d[x] still
104
+ * addresses the literal key "x". Computed indices continue through the normal
105
+ * parser path.
106
+ */
107
+ extractDictionaryKey(scope, values, assertive) {
108
+ if (scope.length === 1 &&
109
+ Token_1.Token.isToken(scope[0]) &&
110
+ scope[0].type === Token_1.Token.VARIABLE) {
111
+ const token = scope[0];
112
+ const scopedValue = values?.[token.value];
113
+ if (scopedValue !== undefined) {
114
+ if (Expression_1.Expression.isExpression(scopedValue) ||
115
+ Equation_1.Equation.isEquation(scopedValue) ||
116
+ (0, structuredEntityUtils_1.isEnumerable)(scopedValue)) {
117
+ return scopedValue.text();
118
+ }
119
+ return Expression_1.Expression.create(scopedValue, undefined, true).text();
120
+ }
121
+ if (Settings_1.Settings.SUBSTITUTE && token.value in this.KNOWN_VALUES) {
122
+ return this.KNOWN_VALUES[token.value].text();
123
+ }
124
+ return token.value;
125
+ }
126
+ const parsed = this.parseRPN(scope, values, assertive);
127
+ let key = parsed;
128
+ if (Vector_1.Vector.isVector(parsed) && parsed.elements.length === 1) {
129
+ key = parsed.elements[0];
130
+ }
131
+ else if (Collection_1.Collection.isCollection(parsed) && parsed.getElements().length === 1) {
132
+ key = parsed.getElements()[0];
133
+ }
134
+ return key.text();
135
+ }
94
136
  /**
95
137
  * Converts an index scope to the zero-based indices used internally.
96
138
  *
@@ -155,32 +197,44 @@ class ExpressionParser {
155
197
  return retval;
156
198
  }
157
199
  /**
158
- * Extracts string keys from an index scope for Dictionary access.
159
- * For d[x], the scope contains a single variable token "x" → returns ["x"].
160
- * For d[myKey], returns ["myKey"].
200
+ * Resolves or preserves symbolic bracket access after the target and indices have
201
+ * been parsed. Vector and Matrix arity is checked here so direct bracket parsing
202
+ * and reevaluation of a preserved accessor follow the same rules.
161
203
  */
162
- extractStringKeys(scope) {
163
- const keys = [];
164
- for (let k = 0; k < scope.length; k++) {
165
- const item = scope[k];
166
- if (Scope_1.Scope.isScope(item)) {
167
- // Nested scope — not expected for dictionary keys
168
- continue;
204
+ resolveSymbolicAccess(symbolicTarget, resolvedTarget, indices) {
205
+ if (indices.length > 2) {
206
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessMaxIndices'));
207
+ }
208
+ if (Vector_1.Vector.isVector(resolvedTarget) && indices.length !== 1) {
209
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicVectorIndexCount'));
210
+ }
211
+ if (Matrix_1.Matrix.isMatrix(resolvedTarget) && indices.length !== 2) {
212
+ if (indices.length === 1) {
213
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicMatrixRowNonScalar'));
169
214
  }
170
- if (item.type === Token_1.Token.OPERATOR) {
171
- // Skip comma separators
172
- continue;
215
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicMatrixCellIndexCount'));
216
+ }
217
+ if (Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) {
218
+ const numericIndices = [];
219
+ for (const index of indices) {
220
+ const numericIndex = Number(index.text());
221
+ if (!Number.isFinite(numericIndex)) {
222
+ return Expression_1.Expression.toAccessor(symbolicTarget, indices);
223
+ }
224
+ numericIndices.push(numericIndex - Settings_1.Settings.INDEX_BASE);
173
225
  }
174
- // Use the token value as the string key
175
- keys.push(item.value);
226
+ return resolvedTarget.__get__(numericIndices);
227
+ }
228
+ if (Expression_1.Expression.isExpression(resolvedTarget) && resolvedTarget.isPlainVariable()) {
229
+ return Expression_1.Expression.toAccessor(symbolicTarget, indices);
176
230
  }
177
- return keys;
231
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessTargetType'));
178
232
  }
179
233
  /** Creates another spelling for an existing operator without changing its action. */
180
234
  aliasOperator(symbol, alias) {
181
235
  const source = this.operators[symbol];
182
236
  if (!source) {
183
- throw new errors_1.ParserError(`Unknown operator ${symbol}`);
237
+ throw new errors_1.ParserError((0, errors_1.message)('unknownOperator', { operator: symbol }));
184
238
  }
185
239
  this.operators[alias] = {
186
240
  ...source,
@@ -302,6 +356,21 @@ class ExpressionParser {
302
356
  getPrecision() {
303
357
  return Rational_1.Rational.getPrecision();
304
358
  }
359
+ /**
360
+ * Reports whether a name is reserved by Nerdamer's parser or solver conventions.
361
+ *
362
+ * @remarks
363
+ * The result reflects the current process-wide parser state. In particular, changing
364
+ * the imaginary-unit symbol through {@link setI} removes the previous symbol from the
365
+ * restricted-name list and reserves the replacement. Solver-specific names such as
366
+ * `_n` and `all` are also reserved.
367
+ *
368
+ * @param name - Variable or symbol name to test.
369
+ * @returns Whether Nerdamer currently reserves the name.
370
+ */
371
+ isReserved(name) {
372
+ return Settings_1.RESTRICTED.includes(name);
373
+ }
305
374
  /**
306
375
  * Parses supported expression input into a Nerdamer parser entity.
307
376
  *
@@ -364,7 +433,16 @@ class ExpressionParser {
364
433
  const source = (0, preprocess_1.preprocess)(String(str), dispatch_1.mathFunctionRegistry);
365
434
  const rpn = this.toRPN(this.tokenize(source));
366
435
  // Read it into an expression.
367
- const retval = this.parseRPN(rpn, values);
436
+ let retval;
437
+ try {
438
+ retval = this.parseRPN(rpn, values);
439
+ }
440
+ catch (error) {
441
+ if (controlFlowSignals_1.NullSignal.isNullSignal(error)) {
442
+ throw new errors_1.NullError((0, errors_1.message)('nullValue'));
443
+ }
444
+ throw error;
445
+ }
368
446
  return retval;
369
447
  }
370
448
  /**
@@ -395,15 +473,10 @@ class ExpressionParser {
395
473
  // The output stack
396
474
  const output = [];
397
475
  const operators = this.operators;
398
- // TODO: this needs to be applied at the operation level. It's somewhat clunky to apply this here.
399
- // const precision = this.getPrecision();
400
476
  function addToOutput(expression) {
401
477
  if (expression === undefined) {
402
478
  throw new errors_1.ParserError((0, errors_1.message)('malformedExpression'));
403
479
  }
404
- // Keep track of the precision used to make this calculation
405
- // TODO: this needs to be applied at the operation level. It's somewhat clunky to apply this here.
406
- // expression.precision = expression.precision || precision;
407
480
  output.push(expression);
408
481
  }
409
482
  function resolveStackValue(value) {
@@ -422,6 +495,16 @@ class ExpressionParser {
422
495
  }
423
496
  return resolved;
424
497
  }
498
+ const parseScope = (scope, scopeValues, scopeAssertive, substitute) => {
499
+ const parse = () => this.parseRPN(scope, scopeValues, scopeAssertive);
500
+ return typeof substitute === 'boolean'
501
+ ? (0, Settings_1.scopedBlock)('SUBSTITUTE', substitute, parse)
502
+ : parse();
503
+ };
504
+ const parseArguments = (scope, argumentValues, functionAssertive, substitute) => {
505
+ const parsed = parseScope(scope, argumentValues, functionAssertive, substitute);
506
+ return Collection_1.Collection.isCollection(parsed) ? parsed.getElements() : [parsed];
507
+ };
425
508
  const createDeferredArgument = (getArgumentRPN, inheritedValues, functionAssertive) => {
426
509
  let argumentRPN;
427
510
  return (options) => {
@@ -434,455 +517,271 @@ class ExpressionParser {
434
517
  delete argumentValues[name];
435
518
  }
436
519
  }
437
- let retval;
438
- if (typeof options?.substitute === 'boolean') {
439
- retval = (0, Settings_1.scopedBlock)('SUBSTITUTE', options.substitute, () => {
440
- return this.parseRPN(rpn, argumentValues, functionAssertive);
441
- });
442
- }
443
- else {
444
- retval = this.parseRPN(rpn, argumentValues, functionAssertive);
445
- }
446
- return retval;
520
+ return parseScope(rpn, argumentValues, functionAssertive, options?.substitute);
447
521
  };
448
522
  };
449
- // Begin parsing of tokens
450
- for (let i = 0; i < rpn.length; i++) {
451
- // Grab the token or Scope
452
- const token = rpn[i];
453
- if (Scope_1.Scope.isScope(token)) {
454
- const lastOutput = output[output.length - 1];
455
- if (token.deferRHSResolution) {
456
- addToOutput(createDeferredArgument(() => token, values, assertive));
457
- }
458
- else if (token.deferLHSResolution) {
459
- // Left-hand targets are parsed without substitution so assignment can update a
460
- // variable that already has a known value.
461
- const parsed = (0, Settings_1.scopedBlock)('SUBSTITUTE', false, () => {
462
- return this.parseRPN(token, undefined, assertive);
463
- });
464
- addToOutput(parsed);
523
+ const handleFunction = (token, argsScope) => {
524
+ if (token.value === constants_1.SYMBOLIC_ACCESSOR) {
525
+ const preservedArgs = parseArguments(argsScope, undefined, assertive, false);
526
+ const resolvedArgs = parseArguments(argsScope, values, assertive);
527
+ if (preservedArgs.length < 2 ||
528
+ preservedArgs.length !== resolvedArgs.length ||
529
+ !Expression_1.Expression.isExpression(preservedArgs[0]) ||
530
+ !preservedArgs[0].isPlainVariable()) {
531
+ throw new errors_1.ParserError((0, errors_1.message)('parserMalformedSymbolicAccessor'));
465
532
  }
466
- // A square scope is a candidate for indexing or implicit multiplication ONLY
467
- // when the tokenizer flagged it with implicitMultiply (meaning '[' directly
468
- // followed a non-operator/non-function token). Without that flag, the scope
469
- // is a standalone vector literal (e.g. in matrix([1,0],[2,3]) where commas
470
- // separate the square scopes).
471
- else if (token.type === 'square' && token.implicitMultiply && lastOutput) {
472
- if ((0, structuredEntityUtils_1.isEnumerable)(lastOutput) ||
473
- IndexedReference_1.IndexedReference.isIndexedReference(lastOutput)) {
474
- // Indexing: target[indices]
475
- const resolvedTarget = IndexedReference_1.IndexedReference.isIndexedReference(lastOutput)
476
- ? lastOutput.resolve()
477
- : lastOutput;
478
- const previousRPN = rpn[i - 1];
479
- let targetName;
480
- if (Token_1.Token.isToken(previousRPN) &&
481
- previousRPN.type === Token_1.Token.VARIABLE &&
482
- !(values && previousRPN.value in values) &&
483
- previousRPN.value in this.KNOWN_VALUES) {
484
- targetName = previousRPN.value;
485
- }
486
- let indices;
487
- if (Dictionary_1.Dictionary.isDictionary(resolvedTarget)) {
488
- // Dictionary indexing: extract string keys from the index scope.
489
- // d[x] → key "x"
490
- const keys = this.extractStringKeys(token);
491
- indices = keys[0];
492
- }
493
- else {
494
- // Numeric indexing for Vector, Matrix, etc.
495
- indices = this.extractIndices(token, values, assertive);
496
- }
497
- output.pop();
498
- if (Array.isArray(indices) &&
499
- indices.length > 0 &&
500
- Expression_1.Expression.isExpression(indices[0])) {
501
- const symbolicIndices = indices;
502
- let symbolicTarget;
503
- if ((Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) &&
504
- resolvedTarget.symbolicTarget) {
505
- symbolicTarget = resolvedTarget.symbolicTarget;
506
- }
507
- else if (Token_1.Token.isToken(previousRPN) &&
508
- previousRPN.type === Token_1.Token.VARIABLE) {
509
- symbolicTarget = Expression_1.Expression.Variable(previousRPN.value);
510
- }
511
- if (!symbolicTarget ||
512
- !(Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget))) {
513
- throw new errors_1.ParserError('Symbolic indexed access requires a named Vector or Matrix target.');
514
- }
515
- if (Vector_1.Vector.isVector(resolvedTarget) && symbolicIndices.length !== 1) {
516
- throw new errors_1.ParserError('Symbolic Vector access requires exactly one index.');
517
- }
518
- if (Matrix_1.Matrix.isMatrix(resolvedTarget) && symbolicIndices.length !== 2) {
519
- if (symbolicIndices.length === 1) {
520
- throw new errors_1.ParserError('Symbolic Matrix row access is not scalar and cannot be deferred as an Expression.');
521
- }
522
- throw new errors_1.ParserError('Symbolic Matrix cell access requires exactly two indices.');
523
- }
524
- addToOutput(resolvedTarget.withSymbolicAccessor(symbolicTarget, symbolicIndices));
525
- }
526
- else {
527
- addToOutput(new IndexedReference_1.IndexedReference(resolvedTarget, indices, targetName));
528
- }
529
- }
530
- else if (Expression_1.Expression.isExpression(lastOutput) && lastOutput.isPlainVariable()) {
531
- // An unresolved variable followed by symbolic indices cannot yet be
532
- // classified from runtime type information. Preserve the access in a
533
- // structured carrier; concrete bracket adjacency keeps its legacy
534
- // implicit-multiplication behavior.
535
- const indices = this.extractIndices(token, values, assertive);
536
- if (indices.length > 0 &&
537
- Expression_1.Expression.isExpression(indices[0])) {
538
- const symbolicIndices = indices;
539
- if (symbolicIndices.length > 2) {
540
- throw new errors_1.ParserError('Symbolic indexed access supports at most two unresolved indices.');
541
- }
542
- const carrier = symbolicIndices.length === 2 ? new Matrix_1.Matrix([]) : new Vector_1.Vector();
543
- output.pop();
544
- addToOutput(carrier.withSymbolicAccessor(lastOutput, symbolicIndices));
545
- }
546
- else if (Settings_1.Settings.ALLOW_IMPLICIT_MULTIPLICATION) {
547
- const indexExpr = this.parseRPN(token, values, assertive);
548
- const mulFn = functions_2._['multiply'];
549
- const a = resolveStackValue(output.pop());
550
- addToOutput(mulFn(a, indexExpr));
551
- }
552
- else {
553
- const parsed = this.parseRPN(token, values, assertive);
554
- addToOutput(parsed);
555
- }
533
+ const symbolicTarget = preservedArgs[0];
534
+ const resolvedTarget = resolvedArgs[0];
535
+ const symbolicIndices = [];
536
+ for (let j = 1; j < preservedArgs.length; j++) {
537
+ if (!Expression_1.Expression.isExpression(preservedArgs[j])) {
538
+ throw new errors_1.ParserError((0, errors_1.message)('parserMalformedSymbolicAccessorIndex'));
556
539
  }
557
- else if (token.implicitMultiply && Settings_1.Settings.ALLOW_IMPLICIT_MULTIPLICATION) {
558
- // Implicit multiplication: x[1,2] where x is not a structured entity.
559
- const indexExpr = this.parseRPN(token, values, assertive);
560
- const mulFn = functions_2._['multiply'];
561
- const a = resolveStackValue(output.pop());
562
- addToOutput(mulFn(a, indexExpr));
563
- }
564
- else {
565
- const parsed = this.parseRPN(token, values, assertive);
566
- addToOutput(parsed);
540
+ const resolvedIndex = resolvedArgs[j];
541
+ if (!Expression_1.Expression.isExpression(resolvedIndex)) {
542
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessIndexScalar'));
567
543
  }
544
+ symbolicIndices.push(resolvedIndex);
568
545
  }
569
- else {
570
- // Non-square scope or inside parentheses or nothing on output — parse normally
571
- const parsed = this.parseRPN(token, values, assertive);
572
- addToOutput(parsed);
573
- }
546
+ return this.resolveSymbolicAccess(symbolicTarget, resolvedTarget, symbolicIndices);
574
547
  }
575
- else {
576
- if (token.type === Token_1.Token.OPERATOR) {
577
- // Grab the operator. The action will be defined by the operation property
578
- const operator = token.resolvedOperator ?? this.operators[token.value];
579
- // Get the last element on output
580
- let b = output.pop();
581
- let result;
582
- // Comma is the only operation that passes parser stack markers through unchanged.
583
- // This allows KeyValuePair markers to survive until the enclosing curly scope is
584
- // converted to a Dictionary.
585
- if (operator.action === 'comma') {
586
- const a = output.pop();
587
- const fn = functions_2._[operator.action];
588
- result = fn(a, b);
589
- }
590
- // If it's a postfix operator then the operation occurs only on the previous element
591
- else if (operator.isPostfix) {
592
- b = resolveStackValue(b);
593
- b = Expression_1.Expression.fromSymbolicAccess(b) ?? b;
594
- const fn = functions_2._[operator.action];
595
- result = fn(b);
596
- }
597
- else {
598
- let a = output.pop();
599
- const previousRPN = rpn[i - 1];
600
- const possibleFunction = rpn[i - 2];
601
- if (token.position === -1 &&
602
- operator.action === 'times' &&
603
- Scope_1.Scope.isScope(previousRPN) &&
604
- Collection_1.Collection.isCollection(b) &&
605
- Token_1.Token.isToken(possibleFunction) &&
606
- possibleFunction.type === Token_1.Token.VARIABLE &&
607
- Expression_1.Expression.isExpression(a) &&
608
- a.isPlainVariable()) {
609
- throw new errors_1.ParserError(`Unsupported function ${possibleFunction.value}`);
610
- }
611
- // Handle indexed assignment before ordinary left-hand resolution so the
612
- // reference itself remains available to the setter.
613
- if (operator.action === 'assign' &&
614
- IndexedReference_1.IndexedReference.isIndexedReference(a)) {
615
- b = resolveStackValue(b);
616
- if (typeof a.indices === 'string') {
617
- a.target.__set__(a.indices, b);
618
- }
619
- else {
620
- a.target.__set__(a.indices, b);
621
- }
622
- if (a.targetName) {
623
- this.KNOWN_VALUES[a.targetName] = a.target;
624
- }
625
- result = a.target;
626
- }
627
- else if (operator.deferRHSResolution) {
628
- a = resolveStackValue(a);
629
- if (typeof b !== 'function') {
630
- throw new errors_1.ParserError((0, errors_1.message)('malformedExpression'));
631
- }
632
- const fn = functions_2._[operator.action];
633
- result = fn(a, b);
634
- }
635
- else if (operator.deferLHSResolution) {
636
- a = resolveStackValue(a);
637
- b = resolveStackValue(b);
638
- const fn = functions_2._[operator.action];
639
- result = fn(a, b);
640
- }
641
- else if (operator.action === 'mapTo') {
642
- // '=>' operator: create a key-value pair for Dictionary construction
643
- // 'a' is the key (should be a variable name), 'b' is the value
644
- a = resolveStackValue(a);
645
- b = resolveStackValue(b);
646
- const key = Expression_1.Expression.isExpression(a) ? a.text() : String(a.text());
647
- result = new KeyValuePair_1.KeyValuePair(key, b);
548
+ if (dispatch_1.mathFunctionRegistry[token.value]?.deferArguments) {
549
+ const argumentScopes = [];
550
+ if (argsScope.length > 0) {
551
+ let argumentScope = new Scope_1.Scope(argsScope.type, argsScope.column);
552
+ for (const argumentToken of argsScope) {
553
+ if (Token_1.Token.isToken(argumentToken) &&
554
+ argumentToken.type === Token_1.Token.OPERATOR &&
555
+ argumentToken.value === constants_1.COMMA) {
556
+ argumentScopes.push(argumentScope);
557
+ argumentScope = new Scope_1.Scope(argsScope.type, argsScope.column);
648
558
  }
649
559
  else {
650
- // Resolve concrete indexed references and normalize symbolic structured
651
- // access before ordinary scalar/aggregate operator routing.
652
- a = resolveStackValue(a);
653
- b = resolveStackValue(b);
654
- a = Expression_1.Expression.fromSymbolicAccess(a) ?? a;
655
- b = Expression_1.Expression.fromSymbolicAccess(b) ?? b;
656
- const action = assertive && operator.assertiveAction
657
- ? operator.assertiveAction
658
- : operator.action;
659
- const fn = functions_2._[action];
660
- if (a.isEnumerable ||
661
- b.isEnumerable ||
662
- Equation_1.Equation.isEquation(a) ||
663
- Equation_1.Equation.isEquation(b)) {
664
- // Delegate this to the router who can handle more
665
- result = (0, functions_2.route)(a, b, operator.action);
666
- }
667
- else {
668
- result = fn(a, b);
669
- }
560
+ argumentScope.push(argumentToken);
670
561
  }
671
562
  }
672
- if (Array.isArray(result)) {
673
- addToOutput(result[0]);
674
- addToOutput(result[1]);
563
+ argumentScopes.push(argumentScope);
564
+ }
565
+ const normalizeArguments = dispatch_1.mathFunctionRegistry[token.value].normalizeDeferredArguments;
566
+ const normalizedScopes = normalizeArguments
567
+ ? normalizeArguments(argumentScopes)
568
+ : argumentScopes;
569
+ const functionAssertive = common_1.ASSERTIVE_FUNCTIONS.includes(token.value);
570
+ const args = normalizedScopes.map(argumentScope => createDeferredArgument(() => this.toRPN(argumentScope), values, functionAssertive));
571
+ return (0, functions_2.callFunction)(token.value, args);
572
+ }
573
+ if (argsScope.deferLHSResolution) {
574
+ const args = argsScope.length > 0
575
+ ? [...parseArguments(argsScope, undefined, assertive, false)]
576
+ : [];
577
+ args.push(Expression_1.Expression.Variable(token.value));
578
+ return new Collection_1.Collection(args);
579
+ }
580
+ return (0, functions_2.callFunction)(token.value, parseArguments(argsScope, values, common_1.ASSERTIVE_FUNCTIONS.includes(token.value)));
581
+ };
582
+ const handleOperator = (token, index) => {
583
+ const operator = token.resolvedOperator ?? this.operators[token.value];
584
+ let b = output.pop();
585
+ if (operator.action === 'comma') {
586
+ addToOutput(b);
587
+ return undefined;
588
+ }
589
+ if (operator.isPostfix) {
590
+ b = resolveStackValue(b);
591
+ const fn = functions_2._[operator.action];
592
+ return fn(b);
593
+ }
594
+ let a = output.pop();
595
+ const previousRPN = rpn[index - 1];
596
+ const possibleFunction = rpn[index - 2];
597
+ if (token.position === -1 &&
598
+ operator.action === 'times' &&
599
+ Scope_1.Scope.isScope(previousRPN) &&
600
+ Collection_1.Collection.isCollection(b) &&
601
+ Token_1.Token.isToken(possibleFunction) &&
602
+ possibleFunction.type === Token_1.Token.VARIABLE &&
603
+ Expression_1.Expression.isExpression(a) &&
604
+ a.isPlainVariable()) {
605
+ throw new errors_1.ParserError((0, errors_1.message)('unsupportedFunction', { function: possibleFunction.value }));
606
+ }
607
+ if (operator.action === 'assign' && IndexedReference_1.IndexedReference.isIndexedReference(a)) {
608
+ let assignValue = true;
609
+ try {
610
+ b = typeof b === 'function' ? b() : resolveStackValue(b);
611
+ }
612
+ catch (error) {
613
+ if (controlFlowSignals_1.NullSignal.isNullSignal(error)) {
614
+ assignValue = false;
675
615
  }
676
616
  else {
677
- addToOutput(result);
617
+ throw error;
678
618
  }
679
619
  }
680
- else if (token.type === Token_1.Token.FUNCTION) {
681
- // Get the next token and move along
682
- const argsScope = rpn[++i];
683
- if (token.value === constants_1.SYMBOLIC_ACCESSOR) {
684
- // Preserve the original target and index expressions while resolving the
685
- // same RPN scope under the active values. This avoids serializing either
686
- // side back through tokenize/toRPN just to apply substitutions.
687
- const preserved = (0, Settings_1.scopedBlock)('SUBSTITUTE', false, () => {
688
- return this.parseRPN(argsScope, undefined, assertive);
689
- });
690
- const preservedArgs = Collection_1.Collection.isCollection(preserved)
691
- ? preserved.getElements()
692
- : [preserved];
693
- const resolved = this.parseRPN(argsScope, values, assertive);
694
- const resolvedArgs = Collection_1.Collection.isCollection(resolved)
695
- ? resolved.getElements()
696
- : [resolved];
697
- if (preservedArgs.length < 2 ||
698
- preservedArgs.length !== resolvedArgs.length ||
699
- !Expression_1.Expression.isExpression(preservedArgs[0]) ||
700
- !preservedArgs[0].isPlainVariable()) {
701
- throw new errors_1.ParserError('Malformed internal symbolic accessor.');
702
- }
703
- const symbolicTarget = preservedArgs[0];
704
- const resolvedTarget = resolvedArgs[0];
705
- const symbolicIndices = [];
706
- const numericIndices = [];
707
- let allResolved = true;
708
- for (let j = 1; j < preservedArgs.length; j++) {
709
- const preservedIndex = preservedArgs[j];
710
- const resolvedIndex = resolvedArgs[j];
711
- if (!Expression_1.Expression.isExpression(preservedIndex)) {
712
- throw new errors_1.ParserError('Malformed internal symbolic accessor index.');
713
- }
714
- if (!Expression_1.Expression.isExpression(resolvedIndex)) {
715
- throw new errors_1.ParserError('Symbolic accessor indices must evaluate to scalar expressions.');
716
- }
717
- symbolicIndices.push(resolvedIndex);
718
- const numericIndex = Number(resolvedIndex.text());
719
- if (Number.isFinite(numericIndex)) {
720
- numericIndices.push(numericIndex - Settings_1.Settings.INDEX_BASE);
721
- }
722
- else {
723
- allResolved = false;
724
- }
725
- }
726
- if (symbolicIndices.length > 2) {
727
- throw new errors_1.ParserError('Symbolic indexed access supports at most two unresolved indices.');
728
- }
729
- if (Vector_1.Vector.isVector(resolvedTarget) && symbolicIndices.length !== 1) {
730
- throw new errors_1.ParserError('Symbolic Vector access requires exactly one index.');
731
- }
732
- if (Matrix_1.Matrix.isMatrix(resolvedTarget) && symbolicIndices.length !== 2) {
733
- if (symbolicIndices.length === 1) {
734
- throw new errors_1.ParserError('Symbolic Matrix row access is not scalar and cannot be deferred as an Expression.');
735
- }
736
- throw new errors_1.ParserError('Symbolic Matrix cell access requires exactly two indices.');
737
- }
738
- let result;
739
- if ((Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) && allResolved) {
740
- result = resolvedTarget.__get__(numericIndices);
741
- }
742
- else {
743
- let carrier;
744
- if (Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) {
745
- carrier = resolvedTarget;
746
- }
747
- else if (Expression_1.Expression.isExpression(resolvedTarget) &&
748
- resolvedTarget.isPlainVariable()) {
749
- carrier = symbolicIndices.length === 2 ? new Matrix_1.Matrix([]) : new Vector_1.Vector();
750
- }
751
- else {
752
- throw new errors_1.ParserError('Symbolic indexed access target must resolve to a Vector or Matrix.');
753
- }
754
- result = carrier.withSymbolicAccessor(symbolicTarget, symbolicIndices);
755
- }
756
- addToOutput(result);
620
+ if (assignValue) {
621
+ a.set(b);
622
+ if (a.targetName) {
623
+ this.KNOWN_VALUES[a.targetName] = a.target;
757
624
  }
758
- else if (dispatch_1.mathFunctionRegistry[token.value]?.deferArguments) {
759
- // Deferred functions receive callable arguments and decide when, whether, and how
760
- // often each argument is evaluated.
761
- const argumentScopes = [];
762
- if (argsScope.length > 0) {
763
- let argumentScope = new Scope_1.Scope(argsScope.type, argsScope.column);
764
- for (const argumentToken of argsScope) {
765
- if (Token_1.Token.isToken(argumentToken) &&
766
- argumentToken.type === Token_1.Token.OPERATOR &&
767
- argumentToken.value === constants_1.COMMA) {
768
- argumentScopes.push(argumentScope);
769
- argumentScope = new Scope_1.Scope(argsScope.type, argsScope.column);
770
- }
771
- else {
772
- argumentScope.push(argumentToken);
773
- }
774
- }
775
- argumentScopes.push(argumentScope);
776
- }
777
- const normalizeArguments = dispatch_1.mathFunctionRegistry[token.value].normalizeDeferredArguments;
778
- const normalizedScopes = normalizeArguments
779
- ? normalizeArguments(argumentScopes)
780
- : argumentScopes;
781
- const functionAssertive = common_1.ASSERTIVE_FUNCTIONS.includes(token.value);
782
- const args = normalizedScopes.map(argumentScope => {
783
- return createDeferredArgument(() => this.toRPN(argumentScope), values, functionAssertive);
784
- });
785
- const result = (0, functions_2.callFunction)(token.value, args);
786
- addToOutput(result);
625
+ }
626
+ return a.target;
627
+ }
628
+ if (operator.deferRHSResolution) {
629
+ a = resolveStackValue(a);
630
+ if (typeof b !== 'function') {
631
+ throw new errors_1.ParserError((0, errors_1.message)('malformedExpression'));
632
+ }
633
+ const fn = functions_2._[operator.action];
634
+ return fn(a, b);
635
+ }
636
+ a = resolveStackValue(a);
637
+ b = resolveStackValue(b);
638
+ if (operator.action === 'mapTo') {
639
+ return new KeyValuePair_1.KeyValuePair(a.text(), b);
640
+ }
641
+ const action = assertive && operator.assertiveAction
642
+ ? operator.assertiveAction
643
+ : operator.action;
644
+ const fn = functions_2._[action];
645
+ if (a.isEnumerable ||
646
+ b.isEnumerable ||
647
+ Equation_1.Equation.isEquation(a) ||
648
+ Equation_1.Equation.isEquation(b)) {
649
+ return (0, functions_2.route)(a, b, operator.action);
650
+ }
651
+ return fn(a, b);
652
+ };
653
+ const handleScope = (token, index) => {
654
+ const lastOutput = output[output.length - 1];
655
+ if (token.deferRHSResolution) {
656
+ addToOutput(createDeferredArgument(() => token, values, assertive));
657
+ return;
658
+ }
659
+ if (token.type === 'square' && token.implicitMultiply && lastOutput) {
660
+ if ((0, structuredEntityUtils_1.isEnumerable)(lastOutput) ||
661
+ IndexedReference_1.IndexedReference.isIndexedReference(lastOutput)) {
662
+ const resolvedTarget = IndexedReference_1.IndexedReference.isIndexedReference(lastOutput)
663
+ ? lastOutput.resolve()
664
+ : lastOutput;
665
+ const previousRPN = rpn[index - 1];
666
+ let targetName;
667
+ if (Token_1.Token.isToken(previousRPN) &&
668
+ previousRPN.type === Token_1.Token.VARIABLE &&
669
+ !(values && previousRPN.value in values) &&
670
+ previousRPN.value in this.KNOWN_VALUES) {
671
+ targetName = previousRPN.value;
787
672
  }
788
- else if (argsScope.deferLHSResolution) {
789
- let args = [];
790
- if (argsScope.length > 0) {
791
- const parsed = (0, Settings_1.scopedBlock)('SUBSTITUTE', false, () => {
792
- return this.parseRPN(argsScope, undefined, assertive);
793
- });
794
- args = Collection_1.Collection.isCollection(parsed) ? [...parsed.getElements()] : [parsed];
673
+ const indices = Dictionary_1.Dictionary.isDictionary(resolvedTarget)
674
+ ? this.extractDictionaryKey(token, values, assertive)
675
+ : this.extractIndices(token, values, assertive);
676
+ output.pop();
677
+ if (Array.isArray(indices) &&
678
+ indices.length > 0 &&
679
+ Expression_1.Expression.isExpression(indices[0])) {
680
+ const symbolicIndices = indices;
681
+ if (!Token_1.Token.isToken(previousRPN) ||
682
+ previousRPN.type !== Token_1.Token.VARIABLE ||
683
+ !(Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget))) {
684
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessNamedTargetRequired'));
795
685
  }
796
- // Preserve the scoped values followed by their left-hand target. The operator
797
- // action is responsible for interpreting that structure.
798
- args.push(Expression_1.Expression.Variable(token.value));
799
- addToOutput(new Collection_1.Collection(args));
686
+ addToOutput(this.resolveSymbolicAccess(Expression_1.Expression.Variable(previousRPN.value), resolvedTarget, symbolicIndices));
800
687
  }
801
688
  else {
802
- // Parse it as an argument. If the value is of the token is an assertive function then parseRPN needs to
803
- // know so it can modify it's behavior accordingly. This would be in the case of functions like assume where
804
- // the operators assert a value rather than compare it.
805
- const parsed = this.parseRPN(argsScope, values, common_1.ASSERTIVE_FUNCTIONS.includes(token.value));
806
- const args = Collection_1.Collection.isCollection(parsed) ? parsed.getElements() : [parsed];
807
- const result = (0, functions_2.callFunction)(token.value, args);
808
- addToOutput(result);
689
+ addToOutput(new IndexedReference_1.IndexedReference(resolvedTarget, indices, targetName));
809
690
  }
691
+ return;
810
692
  }
811
- else if (token.type === Token_1.Token.PREFIX) {
812
- const resolved = resolveStackValue(output.pop());
813
- const e = Expression_1.Expression.fromSymbolicAccess(resolved) ?? resolved;
814
- const prefixAction = `${operators[token.value].action}Prefix`;
815
- const fn = functions_2._[prefixAction];
816
- // TODO: Rethink. What happens when a prefix is applied to a vector
817
- addToOutput(fn(e));
693
+ if (Expression_1.Expression.isExpression(lastOutput) && lastOutput.isPlainVariable()) {
694
+ const indices = this.extractIndices(token, values, assertive);
695
+ if (indices.length > 0 &&
696
+ Expression_1.Expression.isExpression(indices[0])) {
697
+ output.pop();
698
+ addToOutput(this.resolveSymbolicAccess(lastOutput, lastOutput, indices));
699
+ return;
700
+ }
701
+ }
702
+ const parsed = parseScope(token, values, assertive);
703
+ if (Settings_1.Settings.ALLOW_IMPLICIT_MULTIPLICATION) {
704
+ const mulFn = functions_2._['multiply'];
705
+ addToOutput(mulFn(resolveStackValue(output.pop()), parsed));
818
706
  }
819
707
  else {
820
- let expression;
821
- const constant = this.CONSTANTS[token.value];
822
- // User-defined constants are stored as strings and substitute during ordinary parsing.
823
- // They take precedence over scoped values, matching the public setConstant method.
824
- if (typeof constant === 'string') {
825
- expression = this.parse(constant);
826
- }
827
- // Substitute values from the values object. A number is not considered a proper LH value.
828
- else if (values && token.value in values && !token.is(Token_1.Token.NUMBER)) {
829
- // expression = this.parse(String(values[token.value]), values);
830
- const scopedValue = values[token.value];
831
- if (Expression_1.Expression.isExpression(scopedValue) ||
832
- Equation_1.Equation.isEquation(scopedValue) ||
833
- (0, structuredEntityUtils_1.isEnumerable)(scopedValue)) {
834
- expression = scopedValue.copy();
835
- }
836
- else {
837
- expression = Expression_1.Expression.create(scopedValue, undefined, true);
838
- }
839
- }
840
- else if (token.value in this.KNOWN_VALUES && Settings_1.Settings.SUBSTITUTE) {
841
- expression = this.KNOWN_VALUES[token.value].copy();
842
- }
843
- // Built-in constants are factories so they evaluate at the active precision.
844
- else if (Settings_1.Settings.EVALUATE && typeof constant === 'function') {
845
- expression = this.parse(constant(), values);
846
- }
847
- else {
848
- // At this point the expression type is variable or a number
849
- switch (token.type) {
850
- case Token_1.Token.FUNCTION:
851
- expression = Expression_1.Expression.Function(token.value);
852
- break;
853
- case Token_1.Token.VARIABLE:
854
- if (constants_1.INFINITY.includes(token.value)) {
855
- expression = Expression_1.Expression.Inf();
856
- }
857
- else {
858
- expression = Expression_1.Expression.Variable(token.value);
859
- }
860
- break;
861
- default:
862
- expression = Expression_1.Expression.Number(token.value);
863
- break;
864
- }
865
- }
866
- // Add it to output
867
- addToOutput(expression);
708
+ addToOutput(parsed);
709
+ }
710
+ return;
711
+ }
712
+ addToOutput(token.deferLHSResolution
713
+ ? parseScope(token, undefined, assertive, false)
714
+ : parseScope(token, values, assertive));
715
+ };
716
+ const resolveToken = (token) => {
717
+ const constant = this.CONSTANTS[token.value];
718
+ // User-defined constants take precedence over scoped values.
719
+ if (typeof constant === 'string') {
720
+ return this.parse(constant);
721
+ }
722
+ if (values && token.value in values && !token.is(Token_1.Token.NUMBER)) {
723
+ const scopedValue = values[token.value];
724
+ if (Expression_1.Expression.isExpression(scopedValue) ||
725
+ Equation_1.Equation.isEquation(scopedValue) ||
726
+ (0, structuredEntityUtils_1.isEnumerable)(scopedValue)) {
727
+ return scopedValue.copy();
868
728
  }
729
+ return Expression_1.Expression.create(scopedValue, undefined, true);
730
+ }
731
+ if (token.value in this.KNOWN_VALUES && Settings_1.Settings.SUBSTITUTE) {
732
+ return this.KNOWN_VALUES[token.value].copy();
733
+ }
734
+ // Built-in constants are factories so they evaluate at the active precision.
735
+ if (Settings_1.Settings.EVALUATE && typeof constant === 'function') {
736
+ return this.parse(constant(), values);
737
+ }
738
+ if (token.type === Token_1.Token.FUNCTION) {
739
+ return Expression_1.Expression.Function(token.value);
740
+ }
741
+ if (token.type === Token_1.Token.VARIABLE) {
742
+ return constants_1.INFINITY.includes(token.value)
743
+ ? Expression_1.Expression.Inf()
744
+ : Expression_1.Expression.Variable(token.value);
745
+ }
746
+ return Expression_1.Expression.Number(token.value);
747
+ };
748
+ const handlePrefix = (token) => {
749
+ const value = resolveStackValue(output.pop());
750
+ const prefixAction = `${operators[token.value].action}Prefix`;
751
+ const fn = functions_2._[prefixAction];
752
+ return fn(value);
753
+ };
754
+ for (let i = 0; i < rpn.length; i++) {
755
+ const token = rpn[i];
756
+ if (Scope_1.Scope.isScope(token)) {
757
+ handleScope(token, i);
758
+ continue;
759
+ }
760
+ if (token.type === Token_1.Token.OPERATOR) {
761
+ const result = handleOperator(token, i);
762
+ if (result !== undefined) {
763
+ addToOutput(result);
764
+ }
765
+ }
766
+ else if (token.type === Token_1.Token.FUNCTION) {
767
+ addToOutput(handleFunction(token, rpn[++i]));
768
+ }
769
+ else if (token.type === Token_1.Token.PREFIX) {
770
+ addToOutput(handlePrefix(token));
771
+ }
772
+ else {
773
+ addToOutput(resolveToken(token));
869
774
  }
870
775
  }
871
776
  let retval;
872
- // Since as function args can have multiple arguments in the output
873
- // the entire array gets returned. We do the same with
874
777
  if (rpn.type === 'square') {
875
778
  retval = new Vector_1.Vector(resolveStackValues(output));
876
779
  }
877
780
  else if (rpn.type === 'curly') {
878
- // If the output contains KeyValuePairs (from '=>' operators), build a Dictionary.
879
- // Otherwise build a ValuesSet as before.
880
781
  if (output.length > 0 && KeyValuePair_1.KeyValuePair.isKeyValuePair(output[0])) {
881
782
  const dict = new Dictionary_1.Dictionary();
882
783
  for (const item of output) {
883
- if (KeyValuePair_1.KeyValuePair.isKeyValuePair(item)) {
884
- dict.set(item.key, item.value);
885
- }
784
+ dict.set(item.key, item.value);
886
785
  }
887
786
  retval = dict;
888
787
  }
@@ -1234,7 +1133,7 @@ class ExpressionParser {
1234
1133
  functions_2._[operator.action] = action;
1235
1134
  }
1236
1135
  else if (!functions_2._[operator.action]) {
1237
- throw new errors_1.ParserError(`Unknown operator action ${operator.action}`);
1136
+ throw new errors_1.ParserError((0, errors_1.message)('unknownOperatorAction', { action: operator.action }));
1238
1137
  }
1239
1138
  this.operators[operator.operator] = operator;
1240
1139
  (0, Token_1.refreshOperatorSymbols)();
@@ -1350,13 +1249,19 @@ class ExpressionParser {
1350
1249
  // Get the character type for comparison. Search for changes in the character type to determine
1351
1250
  // the end of a token.
1352
1251
  const charType = Token_1.Token.getCharType(ch, col, tokenBuffer);
1252
+ if (charType === Token_1.Token.CHARACTER && ch !== terminator) {
1253
+ throw new errors_1.UnexpectedTokenError((0, errors_1.message)('unsupportedCharacter', {
1254
+ character: ch,
1255
+ position: String(col),
1256
+ }));
1257
+ }
1353
1258
  // Brackets point to a new scope. Once one is encountered, update the target and point to the new scope
1354
1259
  // Subsequent tokens are now pushed to that scope
1355
1260
  if (tokenBuffer.is(Token_1.Token.BRACKET)) {
1356
1261
  // Get the bracket.
1357
1262
  const bracketCharacter = tokenBuffer.last();
1358
1263
  if (bracketCharacter === undefined) {
1359
- throw new errors_1.ParserError('Bracket token is missing its character.');
1264
+ throw new errors_1.ParserError((0, errors_1.message)('parserBracketTokenMissingCharacter'));
1360
1265
  }
1361
1266
  const bracket = common_1.brackets[bracketCharacter];
1362
1267
  if (bracket.isOpen) {
@@ -1391,7 +1296,7 @@ class ExpressionParser {
1391
1296
  }
1392
1297
  }
1393
1298
  else {
1394
- throw new errors_1.UnexpectedTokenError(`Expected operator or function name but "${lastToken.value}" found!`);
1299
+ throw new errors_1.UnexpectedTokenError((0, errors_1.message)('expectedOperatorOrFunction', { value: lastToken.value }));
1395
1300
  }
1396
1301
  }
1397
1302
  // Go down in scope to the new bracket
@@ -1433,7 +1338,10 @@ class ExpressionParser {
1433
1338
  scope = scope.upperScope();
1434
1339
  // If there's not scope or the types don't match then we have a mismatched bracket
1435
1340
  if (scope === undefined || !bracketsMatch) {
1436
- throw new errors_1.UnexpectedTokenError(`Missing opening bracket for "${tokenBuffer.last()}":${col}`);
1341
+ throw new errors_1.UnexpectedTokenError((0, errors_1.message)('missingOpeningBracket', {
1342
+ bracket: String(tokenBuffer.last()),
1343
+ position: String(col),
1344
+ }));
1437
1345
  }
1438
1346
  }
1439
1347
  // Discard the bracket since it's no longer needed
@@ -1507,7 +1415,9 @@ class ExpressionParser {
1507
1415
  }
1508
1416
  }
1509
1417
  else {
1510
- throw new errors_1.UnexpectedTokenError(`Expected operator or function name but "${lastToken.value}" found!`);
1418
+ throw new errors_1.UnexpectedTokenError((0, errors_1.message)('expectedOperatorOrFunction', {
1419
+ value: lastToken.value,
1420
+ }));
1511
1421
  }
1512
1422
  }
1513
1423
  // Allows for each single letter in a variable to be treated like an individual variable
@@ -1538,7 +1448,10 @@ class ExpressionParser {
1538
1448
  // If the last item in the tokens array is a scope and it has a parent then it's missing a closing bracket
1539
1449
  const lastItem = tokens[tokens.length - 1];
1540
1450
  if (Scope_1.Scope.isScope(lastItem) && lastItem.isOpen) {
1541
- throw new errors_1.UnexpectedTokenError(`Missing closing bracket for "${str.charAt(lastItem.column - 1)}":${lastItem.column}`);
1451
+ throw new errors_1.UnexpectedTokenError((0, errors_1.message)('missingClosingBracket', {
1452
+ bracket: str.charAt(lastItem.column - 1),
1453
+ position: String(lastItem.column),
1454
+ }));
1542
1455
  }
1543
1456
  return tokens;
1544
1457
  }
@@ -1670,7 +1583,7 @@ class ExpressionParser {
1670
1583
  }
1671
1584
  // If the encountered operator is not a prefix then complain
1672
1585
  if (!this.operators[prefixOperator.value].isPrefix) {
1673
- throw new errors_1.ParserError(`Prefix operator expected but ${prefixOperator.value} encountered.`);
1586
+ throw new errors_1.ParserError((0, errors_1.message)('prefixOperatorExpected', { operator: prefixOperator.value }));
1674
1587
  }
1675
1588
  // We mark it so the next time it's encountered, it's placed to output immediately
1676
1589
  prefixOperator.type = Token_1.Token.PREFIX;