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.
- package/BREAKING_CHANGES.md +244 -0
- package/README.md +168 -229
- package/dist/bundle.js +1 -1
- package/dist/bundle.js.LICENSE.txt +6 -6
- package/output/algebra/adapters.d.ts +3 -33
- package/output/algebra/adapters.js +7 -105
- package/output/algebra/algorithms/arith.js +10 -9
- package/output/algebra/algorithms/groebnerBase.d.ts +24 -20
- package/output/algebra/algorithms/groebnerBase.js +486 -723
- package/output/algebra/dispatch.d.ts +1 -0
- package/output/algebra/dispatch.js +25 -0
- package/output/algebra/factor/factor.d.ts +15 -0
- package/output/algebra/factor/factor.js +99 -12
- package/output/algebra/gcd/gcd.d.ts +8 -7
- package/output/algebra/gcd/gcd.js +32 -78
- package/output/algebra/groebner.d.ts +2 -2
- package/output/algebra/groebner.js +6 -12
- package/output/algebra/partfrac.d.ts +3 -3
- package/output/algebra/partfrac.js +28 -61
- package/output/algebra/polynomial/ModularSparsePolynomial.d.ts +131 -0
- package/output/algebra/polynomial/ModularSparsePolynomial.js +378 -0
- package/output/algebra/polynomial/ModularSparsePolynomialFactor.d.ts +40 -0
- package/output/algebra/polynomial/ModularSparsePolynomialFactor.js +661 -0
- package/output/algebra/polynomial/SparsePolynomialFactor.d.ts +64 -0
- package/output/algebra/polynomial/SparsePolynomialFactor.js +492 -0
- package/output/algebra/polynomial/SparsePolynomialGcd.d.ts +29 -0
- package/output/algebra/polynomial/SparsePolynomialGcd.js +259 -0
- package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.d.ts +82 -0
- package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.js +604 -0
- package/output/algebra/polynomial/modularGcd.d.ts +40 -0
- package/output/algebra/polynomial/modularGcd.js +365 -0
- package/output/algebra/polynomialize.js +4 -2
- package/output/algebra/simplify/funcsimp.js +1 -1
- package/output/algebra/simplify/ratsimp.js +1 -1
- package/output/algebra/simplify/simplify.js +11 -2
- package/output/algebra/utils.d.ts +1 -1
- package/output/algebra/utils.js +3 -3
- package/output/api/advanced.d.ts +2 -1
- package/output/api/advanced.js +3 -3
- package/output/api/algebra.d.ts +21 -4
- package/output/api/algebra.js +22 -3
- package/output/api/assumptions.d.ts +1 -1
- package/output/api/assumptions.js +2 -1
- package/output/api/calculus.d.ts +2 -1
- package/output/api/calculus.js +2 -1
- package/output/api/core.d.ts +28 -7
- package/output/api/core.js +28 -2
- package/output/api/languages/deu.d.ts +3 -0
- package/output/api/languages/deu.js +266 -0
- package/output/api/languages/fra.d.ts +3 -0
- package/output/api/languages/fra.js +266 -0
- package/output/api/languages/ita.d.ts +3 -0
- package/output/api/languages/ita.js +266 -0
- package/output/api/languages/nld.d.ts +3 -0
- package/output/api/languages/nld.js +266 -0
- package/output/api/languages/por.d.ts +3 -0
- package/output/api/languages/por.js +266 -0
- package/output/api/languages/spa.d.ts +3 -0
- package/output/api/languages/spa.js +266 -0
- package/output/api/parser.d.ts +10 -2
- package/output/api/parser.js +2 -0
- package/output/api/solve.d.ts +1 -1
- package/output/api/solve.js +2 -1
- package/output/api/structures.d.ts +1 -1
- package/output/api/structures.js +2 -1
- package/output/calculus/adapters.d.ts +8 -0
- package/output/calculus/adapters.js +41 -0
- package/output/calculus/derivative/diff.js +6 -3
- package/output/calculus/dispatch.d.ts +1 -0
- package/output/calculus/dispatch.js +25 -0
- package/output/calculus/integrate/integrate.js +4 -4
- package/output/calculus/integrate/integrationTable.js +16 -16
- package/output/calculus/laplace/ilaplace.js +1 -1
- package/output/calculus/laplace/ilaplaceTable.js +18 -17
- package/output/calculus/laplace/laplaceTable.js +3 -2
- package/output/calculus/limit/limit.js +1 -1
- package/output/core/classes/assumption/Assumption.js +14 -10
- package/output/core/classes/assumption/assume.d.ts +6 -0
- package/output/core/classes/assumption/assume.js +9 -0
- package/output/core/classes/assumption/dispatch.d.ts +1 -0
- package/output/core/classes/assumption/dispatch.js +11 -0
- package/output/core/classes/collection/Collection.js +11 -2
- package/output/core/classes/complex/Complex.d.ts +10 -0
- package/output/core/classes/complex/Complex.js +19 -1
- package/output/core/classes/decimalSet/DecimalSet.js +5 -4
- package/output/core/classes/dictionary/Dictionary.js +4 -1
- package/output/core/classes/expression/CoeffObject.d.ts +1 -1
- package/output/core/classes/expression/CoeffObject.js +1 -2
- package/output/core/classes/expression/Expression.d.ts +35 -26
- package/output/core/classes/expression/Expression.js +77 -50
- package/output/core/classes/expression/analysis.d.ts +1 -1
- package/output/core/classes/expression/analysis.js +7 -7
- package/output/core/classes/expression/format.d.ts +9 -0
- package/output/core/classes/expression/format.js +130 -7
- package/output/core/classes/expression/utils.d.ts +9 -0
- package/output/core/classes/expression/utils.js +52 -6
- package/output/core/classes/matrix/Matrix.d.ts +2 -3
- package/output/core/classes/matrix/Matrix.js +26 -23
- package/output/core/classes/matrix/dispatch.d.ts +1 -0
- package/output/core/classes/matrix/dispatch.js +19 -0
- package/output/core/classes/matrix/functions.d.ts +2 -0
- package/output/core/classes/matrix/functions.js +5 -0
- package/output/core/classes/parser/Parser.d.ts +31 -5
- package/output/core/classes/parser/Parser.js +357 -444
- package/output/core/classes/parser/constants.d.ts +2 -0
- package/output/core/classes/parser/constants.js +4 -2
- package/output/core/classes/parser/controlFlowSignals.d.ts +38 -0
- package/output/core/classes/parser/controlFlowSignals.js +60 -0
- package/output/core/classes/parser/operations/add.js +14 -16
- package/output/core/classes/parser/operations/compare.js +13 -0
- package/output/core/classes/parser/operations/functions.d.ts +3 -4
- package/output/core/classes/parser/operations/functions.js +48 -102
- package/output/core/classes/parser/operations/multiply.js +22 -15
- package/output/core/classes/parser/operations/power.js +11 -11
- package/output/core/classes/parser/operations/subtract.js +2 -1
- package/output/core/classes/parser/preprocess.d.ts +0 -7
- package/output/core/classes/parser/preprocess.js +33 -39
- package/output/core/classes/parser/scripting/controlFlow.d.ts +4 -102
- package/output/core/classes/parser/scripting/controlFlow.js +134 -186
- package/output/core/classes/parser/scripting/deferred.d.ts +4 -0
- package/output/core/classes/parser/scripting/deferred.js +65 -0
- package/output/core/classes/parser/scripting/dispatch.d.ts +1 -0
- package/output/core/classes/parser/scripting/dispatch.js +62 -0
- package/output/core/classes/parser/scripting/evaluate.d.ts +13 -0
- package/output/core/classes/parser/scripting/evaluate.js +17 -1
- package/output/core/classes/parser/scripting/scope.d.ts +1 -28
- package/output/core/classes/parser/scripting/scope.js +36 -40
- package/output/core/classes/parser/types.d.ts +5 -5
- package/output/core/classes/parser/wrappers/IndexedReference.d.ts +4 -3
- package/output/core/classes/parser/wrappers/IndexedReference.js +8 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +2 -2
- package/output/core/classes/polynomial/Polynomial.d.ts +5 -1
- package/output/core/classes/polynomial/Polynomial.js +53 -7
- package/output/core/classes/polynomial/SparsePolynomial.d.ts +221 -0
- package/output/core/classes/polynomial/SparsePolynomial.js +824 -0
- package/output/core/classes/polynomial/SparsePolynomialAdapter.d.ts +56 -0
- package/output/core/classes/polynomial/SparsePolynomialAdapter.js +241 -0
- package/output/core/classes/polynomial/Term.js +2 -2
- package/output/core/{adapters.d.ts → classes/polynomial/adapters.d.ts} +2 -2
- package/output/core/classes/polynomial/adapters.js +33 -0
- package/output/core/classes/polynomial/dispatch.d.ts +1 -0
- package/output/core/classes/polynomial/dispatch.js +14 -0
- package/output/core/classes/polynomial/functions.d.ts +8 -0
- package/output/core/classes/polynomial/functions.js +71 -8
- package/output/core/classes/polynomial/utils.js +2 -1
- package/output/core/classes/rational/Rational.d.ts +8 -11
- package/output/core/classes/rational/Rational.js +70 -20
- package/output/core/classes/seq/SEQ.js +4 -4
- package/output/core/classes/valuesSet/ValuesSet.d.ts +9 -1
- package/output/core/classes/valuesSet/ValuesSet.js +22 -4
- package/output/core/classes/vector/Vector.d.ts +2 -3
- package/output/core/classes/vector/Vector.js +11 -15
- package/output/core/classes/vector/dispatch.d.ts +1 -0
- package/output/core/classes/vector/dispatch.js +11 -0
- package/output/core/common/classes/MathematicalAggregate.js +11 -2
- package/output/core/common/classes/StructuredEntity.d.ts +0 -17
- package/output/core/common/classes/StructuredEntity.js +3 -64
- package/output/core/common/common.d.ts +0 -1
- package/output/core/common/common.js +29 -234
- package/output/core/converters/BaseConverter.js +3 -2
- package/output/core/converters/Converter.js +9 -5
- package/output/core/converters/Pattern.js +1 -1
- package/output/core/dispatch.d.ts +18 -0
- package/output/core/dispatch.js +3 -281
- package/output/core/errors.d.ts +259 -474
- package/output/core/errors.js +270 -542
- package/output/core/fullFunctions.d.ts +7 -0
- package/output/core/fullFunctions.js +31 -0
- package/output/core/functions/bigint/bigint.d.ts +13 -1
- package/output/core/functions/bigint/bigint.js +56 -4
- package/output/core/functions/bigint/primeFactor.d.ts +2 -0
- package/output/core/functions/bigint/primeFactor.js +13 -13
- package/output/core/functions/build/definitions.js +6 -0
- package/output/core/functions/complex.d.ts +2 -2
- package/output/core/functions/complex.dispatch.d.ts +1 -0
- package/output/core/functions/complex.dispatch.js +16 -0
- package/output/core/functions/complex.js +7 -7
- package/output/core/functions/decimal.js +2 -1
- package/output/core/functions/expand/expand.js +2 -2
- package/output/core/functions/numeric.d.ts +1 -1
- package/output/core/functions/string.js +2 -1
- package/output/core/functions/subst.js +21 -13
- package/output/core/parserFunctions.d.ts +7 -0
- package/output/core/parserFunctions.js +25 -0
- package/output/index.d.ts +50 -30
- package/output/index.js +147 -19
- package/output/math/defint/defint.d.ts +18 -0
- package/output/math/defint/defint.js +60 -0
- package/output/math/defint/defintDecimal.js +6 -5
- package/output/math/defint/defintNative.js +7 -18
- package/output/math/dispatch.d.ts +1 -0
- package/output/math/dispatch.js +101 -0
- package/output/math/geometry.d.ts +4 -0
- package/output/math/geometry.js +23 -0
- package/output/math/math.d.ts +59 -19
- package/output/math/math.js +244 -100
- package/output/math/trig.js +4 -4
- package/output/math/utils.d.ts +6 -0
- package/output/math/utils.js +39 -0
- package/output/solve/classes/PolynomialSolver.d.ts +33 -14
- package/output/solve/classes/PolynomialSolver.js +267 -67
- package/output/solve/classes/SolutionSet.d.ts +20 -1
- package/output/solve/classes/SolutionSet.js +82 -5
- package/output/solve/dispatch.d.ts +1 -0
- package/output/solve/dispatch.js +13 -0
- package/output/solve/linsolve.d.ts +2 -0
- package/output/solve/linsolve.js +13 -5
- package/output/solve/solve.d.ts +10 -0
- package/output/solve/solve.js +128 -20
- package/output/solve/solveSystem.d.ts +1 -1
- package/output/solve/solveSystem.js +8 -32
- package/output/solve/utils.d.ts +2 -1
- package/output/solve/utils.js +18 -22
- package/output/utils/array.d.ts +1 -1
- package/output/utils/debug.js +2 -1
- package/package.json +22 -38
- package/dist/parser.js +0 -2
- package/dist/parser.js.LICENSE.txt +0 -7
- package/docs-data/parser-functions.json +0 -1960
- package/output/algebra/algorithms/factor.d.ts +0 -3
- package/output/algebra/algorithms/factor.js +0 -5
- package/output/algebra/algorithms/factorMultivariate.d.ts +0 -23
- package/output/algebra/algorithms/factorMultivariate.js +0 -2393
- package/output/algebra/algorithms/factorUnivariate.d.ts +0 -72
- package/output/algebra/algorithms/factorUnivariate.js +0 -1072
- package/output/algebra/algorithms/gcd.d.ts +0 -22
- package/output/algebra/algorithms/gcd.js +0 -690
- package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +0 -137
- package/output/algebra/algorithms/multiPoly/MultiPoly.js +0 -346
- package/output/algebra/algorithms/poly.d.ts +0 -228
- package/output/algebra/algorithms/poly.js +0 -1299
- package/output/algebra/algorithms/rational.d.ts +0 -17
- package/output/algebra/algorithms/rational.js +0 -115
- package/output/core/adapters.js +0 -40
- package/output/core/classes/parser/operations/comma.d.ts +0 -7
- 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
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
175
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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
|
-
|
|
558
|
-
|
|
559
|
-
|
|
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
|
-
|
|
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
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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
|
-
|
|
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
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
-
|
|
617
|
+
throw error;
|
|
678
618
|
}
|
|
679
619
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
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
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
812
|
-
const
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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;
|