nerdamer 2.0.0-rc.2 → 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 (69) hide show
  1. package/README.md +11 -5
  2. package/dist/bundle.js +1 -1
  3. package/dist/bundle.js.LICENSE.txt +6 -6
  4. package/output/algebra/dispatch.js +1 -1
  5. package/output/algebra/partfrac.js +1 -1
  6. package/output/algebra/simplify/funcsimp.js +1 -1
  7. package/output/algebra/simplify/ratsimp.js +1 -1
  8. package/output/algebra/utils.d.ts +1 -1
  9. package/output/algebra/utils.js +3 -3
  10. package/output/api/algebra.d.ts +19 -2
  11. package/output/api/algebra.js +18 -2
  12. package/output/api/assumptions.d.ts +1 -1
  13. package/output/api/assumptions.js +2 -1
  14. package/output/api/core.d.ts +28 -7
  15. package/output/api/core.js +28 -2
  16. package/output/calculus/derivative/diff.js +1 -1
  17. package/output/calculus/dispatch.js +2 -2
  18. package/output/calculus/integrate/integrate.js +4 -4
  19. package/output/calculus/integrate/integrationTable.js +16 -16
  20. package/output/calculus/laplace/ilaplace.js +1 -1
  21. package/output/calculus/laplace/ilaplaceTable.js +18 -17
  22. package/output/calculus/laplace/laplaceTable.js +3 -2
  23. package/output/calculus/limit/limit.js +1 -1
  24. package/output/core/classes/assumption/assume.d.ts +6 -0
  25. package/output/core/classes/assumption/assume.js +9 -0
  26. package/output/core/classes/expression/CoeffObject.d.ts +1 -1
  27. package/output/core/classes/expression/Expression.d.ts +8 -16
  28. package/output/core/classes/expression/Expression.js +11 -33
  29. package/output/core/classes/matrix/Matrix.d.ts +2 -3
  30. package/output/core/classes/matrix/Matrix.js +7 -16
  31. package/output/core/classes/matrix/dispatch.js +1 -1
  32. package/output/core/classes/parser/Parser.d.ts +17 -4
  33. package/output/core/classes/parser/Parser.js +312 -450
  34. package/output/core/classes/parser/operations/functions.d.ts +3 -4
  35. package/output/core/classes/parser/operations/functions.js +35 -97
  36. package/output/core/classes/parser/operations/power.js +2 -2
  37. package/output/core/classes/parser/preprocess.js +14 -7
  38. package/output/core/classes/parser/scripting/controlFlow.js +49 -25
  39. package/output/core/classes/parser/scripting/deferred.d.ts +1 -1
  40. package/output/core/classes/parser/scripting/deferred.js +1 -1
  41. package/output/core/classes/parser/scripting/scope.js +38 -19
  42. package/output/core/classes/parser/types.d.ts +0 -5
  43. package/output/core/classes/parser/wrappers/IndexedReference.d.ts +4 -3
  44. package/output/core/classes/parser/wrappers/IndexedReference.js +8 -0
  45. package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +2 -2
  46. package/output/core/classes/polynomial/Polynomial.js +1 -1
  47. package/output/core/classes/polynomial/SparsePolynomial.d.ts +11 -11
  48. package/output/core/classes/polynomial/SparsePolynomial.js +65 -65
  49. package/output/core/classes/vector/Vector.d.ts +2 -3
  50. package/output/core/classes/vector/Vector.js +6 -14
  51. package/output/core/common/classes/StructuredEntity.d.ts +0 -17
  52. package/output/core/common/classes/StructuredEntity.js +3 -64
  53. package/output/core/converters/BaseConverter.js +2 -1
  54. package/output/core/fullFunctions.js +14 -14
  55. package/output/core/functions/bigint/bigint.d.ts +1 -1
  56. package/output/core/functions/numeric.d.ts +1 -1
  57. package/output/core/parserFunctions.js +10 -10
  58. package/output/index.d.ts +29 -29
  59. package/output/index.js +124 -20
  60. package/output/math/dispatch.js +1 -1
  61. package/output/math/math.js +21 -21
  62. package/output/math/trig.js +4 -4
  63. package/output/solve/solve.js +1 -1
  64. package/package.json +34 -15
  65. package/dist/parser.js +0 -2
  66. package/dist/parser.js.LICENSE.txt +0 -7
  67. package/docs-data/parser-functions.json +0 -2248
  68. package/output/core/classes/parser/operations/comma.d.ts +0 -7
  69. package/output/core/classes/parser/operations/comma.js +0 -11
@@ -19,10 +19,10 @@ 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");
25
- const controlFlowSignals_1 = require("./controlFlowSignals");
26
26
  const IndexedReference_1 = require("./wrappers/IndexedReference");
27
27
  const KeyValuePair_1 = require("./wrappers/KeyValuePair");
28
28
  function shouldPopOperator(stackOperator, incomingOperator) {
@@ -92,6 +92,47 @@ class ExpressionParser {
92
92
  * result, so ordinary substitution does not hand out the stored object itself.
93
93
  */
94
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
+ }
95
136
  /**
96
137
  * Converts an index scope to the zero-based indices used internally.
97
138
  *
@@ -156,26 +197,38 @@ class ExpressionParser {
156
197
  return retval;
157
198
  }
158
199
  /**
159
- * Extracts string keys from an index scope for Dictionary access.
160
- * For d[x], the scope contains a single variable token "x" → returns ["x"].
161
- * 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.
162
203
  */
163
- extractStringKeys(scope) {
164
- const keys = [];
165
- for (let k = 0; k < scope.length; k++) {
166
- const item = scope[k];
167
- if (Scope_1.Scope.isScope(item)) {
168
- // Nested scope — not expected for dictionary keys
169
- 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'));
170
214
  }
171
- if (item.type === Token_1.Token.OPERATOR) {
172
- // Skip comma separators
173
- 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);
174
225
  }
175
- // Use the token value as the string key
176
- keys.push(item.value);
226
+ return resolvedTarget.__get__(numericIndices);
177
227
  }
178
- return keys;
228
+ if (Expression_1.Expression.isExpression(resolvedTarget) && resolvedTarget.isPlainVariable()) {
229
+ return Expression_1.Expression.toAccessor(symbolicTarget, indices);
230
+ }
231
+ throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessTargetType'));
179
232
  }
180
233
  /** Creates another spelling for an existing operator without changing its action. */
181
234
  aliasOperator(symbol, alias) {
@@ -385,8 +438,9 @@ class ExpressionParser {
385
438
  retval = this.parseRPN(rpn, values);
386
439
  }
387
440
  catch (error) {
388
- if (controlFlowSignals_1.NullSignal.isNullSignal(error))
441
+ if (controlFlowSignals_1.NullSignal.isNullSignal(error)) {
389
442
  throw new errors_1.NullError((0, errors_1.message)('nullValue'));
443
+ }
390
444
  throw error;
391
445
  }
392
446
  return retval;
@@ -419,15 +473,10 @@ class ExpressionParser {
419
473
  // The output stack
420
474
  const output = [];
421
475
  const operators = this.operators;
422
- // TODO: this needs to be applied at the operation level. It's somewhat clunky to apply this here.
423
- // const precision = this.getPrecision();
424
476
  function addToOutput(expression) {
425
477
  if (expression === undefined) {
426
478
  throw new errors_1.ParserError((0, errors_1.message)('malformedExpression'));
427
479
  }
428
- // Keep track of the precision used to make this calculation
429
- // TODO: this needs to be applied at the operation level. It's somewhat clunky to apply this here.
430
- // expression.precision = expression.precision || precision;
431
480
  output.push(expression);
432
481
  }
433
482
  function resolveStackValue(value) {
@@ -446,6 +495,16 @@ class ExpressionParser {
446
495
  }
447
496
  return resolved;
448
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
+ };
449
508
  const createDeferredArgument = (getArgumentRPN, inheritedValues, functionAssertive) => {
450
509
  let argumentRPN;
451
510
  return (options) => {
@@ -458,468 +517,271 @@ class ExpressionParser {
458
517
  delete argumentValues[name];
459
518
  }
460
519
  }
461
- let retval;
462
- if (typeof options?.substitute === 'boolean') {
463
- retval = (0, Settings_1.scopedBlock)('SUBSTITUTE', options.substitute, () => {
464
- return this.parseRPN(rpn, argumentValues, functionAssertive);
465
- });
466
- }
467
- else {
468
- retval = this.parseRPN(rpn, argumentValues, functionAssertive);
469
- }
470
- return retval;
520
+ return parseScope(rpn, argumentValues, functionAssertive, options?.substitute);
471
521
  };
472
522
  };
473
- // Begin parsing of tokens
474
- for (let i = 0; i < rpn.length; i++) {
475
- // Grab the token or Scope
476
- const token = rpn[i];
477
- if (Scope_1.Scope.isScope(token)) {
478
- const lastOutput = output[output.length - 1];
479
- if (token.deferRHSResolution) {
480
- addToOutput(createDeferredArgument(() => token, values, assertive));
481
- }
482
- else if (token.deferLHSResolution) {
483
- // Left-hand targets are parsed without substitution so assignment can update a
484
- // variable that already has a known value.
485
- const parsed = (0, Settings_1.scopedBlock)('SUBSTITUTE', false, () => {
486
- return this.parseRPN(token, undefined, assertive);
487
- });
488
- 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'));
489
532
  }
490
- // A square scope is a candidate for indexing or implicit multiplication ONLY
491
- // when the tokenizer flagged it with implicitMultiply (meaning '[' directly
492
- // followed a non-operator/non-function token). Without that flag, the scope
493
- // is a standalone vector literal (e.g. in matrix([1,0],[2,3]) where commas
494
- // separate the square scopes).
495
- else if (token.type === 'square' && token.implicitMultiply && lastOutput) {
496
- if ((0, structuredEntityUtils_1.isEnumerable)(lastOutput) ||
497
- IndexedReference_1.IndexedReference.isIndexedReference(lastOutput)) {
498
- // Indexing: target[indices]
499
- const resolvedTarget = IndexedReference_1.IndexedReference.isIndexedReference(lastOutput)
500
- ? lastOutput.resolve()
501
- : lastOutput;
502
- const previousRPN = rpn[i - 1];
503
- let targetName;
504
- if (Token_1.Token.isToken(previousRPN) &&
505
- previousRPN.type === Token_1.Token.VARIABLE &&
506
- !(values && previousRPN.value in values) &&
507
- previousRPN.value in this.KNOWN_VALUES) {
508
- targetName = previousRPN.value;
509
- }
510
- let indices;
511
- if (Dictionary_1.Dictionary.isDictionary(resolvedTarget)) {
512
- // Dictionary indexing: extract string keys from the index scope.
513
- // d[x] → key "x"
514
- const keys = this.extractStringKeys(token);
515
- indices = keys[0];
516
- }
517
- else {
518
- // Numeric indexing for Vector, Matrix, etc.
519
- indices = this.extractIndices(token, values, assertive);
520
- }
521
- output.pop();
522
- if (Array.isArray(indices) &&
523
- indices.length > 0 &&
524
- Expression_1.Expression.isExpression(indices[0])) {
525
- const symbolicIndices = indices;
526
- let symbolicTarget;
527
- if ((Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) &&
528
- resolvedTarget.symbolicTarget) {
529
- symbolicTarget = resolvedTarget.symbolicTarget;
530
- }
531
- else if (Token_1.Token.isToken(previousRPN) &&
532
- previousRPN.type === Token_1.Token.VARIABLE) {
533
- symbolicTarget = Expression_1.Expression.Variable(previousRPN.value);
534
- }
535
- if (!symbolicTarget ||
536
- !(Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget))) {
537
- throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessNamedTargetRequired'));
538
- }
539
- if (Vector_1.Vector.isVector(resolvedTarget) && symbolicIndices.length !== 1) {
540
- throw new errors_1.ParserError((0, errors_1.message)('symbolicVectorIndexCount'));
541
- }
542
- if (Matrix_1.Matrix.isMatrix(resolvedTarget) && symbolicIndices.length !== 2) {
543
- if (symbolicIndices.length === 1) {
544
- throw new errors_1.ParserError((0, errors_1.message)('symbolicMatrixRowNonScalar'));
545
- }
546
- throw new errors_1.ParserError((0, errors_1.message)('symbolicMatrixCellIndexCount'));
547
- }
548
- addToOutput(resolvedTarget.withSymbolicAccessor(symbolicTarget, symbolicIndices));
549
- }
550
- else {
551
- addToOutput(new IndexedReference_1.IndexedReference(resolvedTarget, indices, targetName));
552
- }
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'));
553
539
  }
554
- else if (Expression_1.Expression.isExpression(lastOutput) && lastOutput.isPlainVariable()) {
555
- // An unresolved variable followed by symbolic indices cannot yet be
556
- // classified from runtime type information. Preserve the access in a
557
- // structured carrier; concrete bracket adjacency keeps its legacy
558
- // implicit-multiplication behavior.
559
- const indices = this.extractIndices(token, values, assertive);
560
- if (indices.length > 0 &&
561
- Expression_1.Expression.isExpression(indices[0])) {
562
- const symbolicIndices = indices;
563
- if (symbolicIndices.length > 2) {
564
- throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessMaxIndices'));
565
- }
566
- const carrier = symbolicIndices.length === 2 ? new Matrix_1.Matrix([]) : new Vector_1.Vector();
567
- output.pop();
568
- addToOutput(carrier.withSymbolicAccessor(lastOutput, symbolicIndices));
569
- }
570
- else if (Settings_1.Settings.ALLOW_IMPLICIT_MULTIPLICATION) {
571
- const indexExpr = this.parseRPN(token, values, assertive);
572
- const mulFn = functions_2._['multiply'];
573
- const a = resolveStackValue(output.pop());
574
- addToOutput(mulFn(a, indexExpr));
575
- }
576
- else {
577
- const parsed = this.parseRPN(token, values, assertive);
578
- addToOutput(parsed);
579
- }
580
- }
581
- else if (token.implicitMultiply && Settings_1.Settings.ALLOW_IMPLICIT_MULTIPLICATION) {
582
- // Implicit multiplication: x[1,2] where x is not a structured entity.
583
- const indexExpr = this.parseRPN(token, values, assertive);
584
- const mulFn = functions_2._['multiply'];
585
- const a = resolveStackValue(output.pop());
586
- addToOutput(mulFn(a, indexExpr));
587
- }
588
- else {
589
- const parsed = this.parseRPN(token, values, assertive);
590
- 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'));
591
543
  }
544
+ symbolicIndices.push(resolvedIndex);
592
545
  }
593
- else {
594
- // Non-square scope or inside parentheses or nothing on output — parse normally
595
- const parsed = this.parseRPN(token, values, assertive);
596
- addToOutput(parsed);
597
- }
546
+ return this.resolveSymbolicAccess(symbolicTarget, resolvedTarget, symbolicIndices);
598
547
  }
599
- else {
600
- if (token.type === Token_1.Token.OPERATOR) {
601
- // Grab the operator. The action will be defined by the operation property
602
- const operator = token.resolvedOperator ?? this.operators[token.value];
603
- // Get the last element on output
604
- let b = output.pop();
605
- let result;
606
- // Comma is the only operation that passes parser stack markers through unchanged.
607
- // This allows KeyValuePair markers to survive until the enclosing curly scope is
608
- // converted to a Dictionary.
609
- if (operator.action === 'comma') {
610
- const a = output.pop();
611
- const fn = functions_2._[operator.action];
612
- result = fn(a, b);
613
- }
614
- // If it's a postfix operator then the operation occurs only on the previous element
615
- else if (operator.isPostfix) {
616
- b = resolveStackValue(b);
617
- b = Expression_1.Expression.fromSymbolicAccess(b) ?? b;
618
- const fn = functions_2._[operator.action];
619
- result = fn(b);
620
- }
621
- else {
622
- let a = output.pop();
623
- const previousRPN = rpn[i - 1];
624
- const possibleFunction = rpn[i - 2];
625
- if (token.position === -1 &&
626
- operator.action === 'times' &&
627
- Scope_1.Scope.isScope(previousRPN) &&
628
- Collection_1.Collection.isCollection(b) &&
629
- Token_1.Token.isToken(possibleFunction) &&
630
- possibleFunction.type === Token_1.Token.VARIABLE &&
631
- Expression_1.Expression.isExpression(a) &&
632
- a.isPlainVariable()) {
633
- throw new errors_1.ParserError((0, errors_1.message)('unsupportedFunction', { function: possibleFunction.value }));
634
- }
635
- // Handle indexed assignment before ordinary left-hand resolution so the
636
- // reference itself remains available to the setter.
637
- if (operator.action === 'assign' &&
638
- IndexedReference_1.IndexedReference.isIndexedReference(a)) {
639
- let assignValue = true;
640
- try {
641
- b = typeof b === 'function' ? b() : resolveStackValue(b);
642
- }
643
- catch (error) {
644
- if (controlFlowSignals_1.NullSignal.isNullSignal(error)) {
645
- assignValue = false;
646
- }
647
- else {
648
- throw error;
649
- }
650
- }
651
- if (assignValue) {
652
- if (typeof a.indices === 'string') {
653
- a.target.__set__(a.indices, b);
654
- }
655
- else {
656
- a.target.__set__(a.indices, b);
657
- }
658
- if (a.targetName) {
659
- this.KNOWN_VALUES[a.targetName] = a.target;
660
- }
661
- }
662
- result = a.target;
663
- }
664
- else if (operator.deferRHSResolution) {
665
- a = resolveStackValue(a);
666
- if (typeof b !== 'function') {
667
- throw new errors_1.ParserError((0, errors_1.message)('malformedExpression'));
668
- }
669
- const fn = functions_2._[operator.action];
670
- result = fn(a, b);
671
- }
672
- else if (operator.deferLHSResolution) {
673
- a = resolveStackValue(a);
674
- b = resolveStackValue(b);
675
- const fn = functions_2._[operator.action];
676
- result = fn(a, b);
677
- }
678
- else if (operator.action === 'mapTo') {
679
- // '=>' operator: create a key-value pair for Dictionary construction
680
- // 'a' is the key (should be a variable name), 'b' is the value
681
- a = resolveStackValue(a);
682
- b = resolveStackValue(b);
683
- const key = Expression_1.Expression.isExpression(a) ? a.text() : String(a.text());
684
- 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);
685
558
  }
686
559
  else {
687
- // Resolve concrete indexed references and normalize symbolic structured
688
- // access before ordinary scalar/aggregate operator routing.
689
- a = resolveStackValue(a);
690
- b = resolveStackValue(b);
691
- a = Expression_1.Expression.fromSymbolicAccess(a) ?? a;
692
- b = Expression_1.Expression.fromSymbolicAccess(b) ?? b;
693
- const action = assertive && operator.assertiveAction
694
- ? operator.assertiveAction
695
- : operator.action;
696
- const fn = functions_2._[action];
697
- if (a.isEnumerable ||
698
- b.isEnumerable ||
699
- Equation_1.Equation.isEquation(a) ||
700
- Equation_1.Equation.isEquation(b)) {
701
- // Delegate this to the router who can handle more
702
- result = (0, functions_2.route)(a, b, operator.action);
703
- }
704
- else {
705
- result = fn(a, b);
706
- }
560
+ argumentScope.push(argumentToken);
707
561
  }
708
562
  }
709
- if (Array.isArray(result)) {
710
- addToOutput(result[0]);
711
- 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;
712
615
  }
713
616
  else {
714
- addToOutput(result);
617
+ throw error;
715
618
  }
716
619
  }
717
- else if (token.type === Token_1.Token.FUNCTION) {
718
- // Get the next token and move along
719
- const argsScope = rpn[++i];
720
- if (token.value === constants_1.SYMBOLIC_ACCESSOR) {
721
- // Preserve the original target and index expressions while resolving the
722
- // same RPN scope under the active values. This avoids serializing either
723
- // side back through tokenize/toRPN just to apply substitutions.
724
- const preserved = (0, Settings_1.scopedBlock)('SUBSTITUTE', false, () => {
725
- return this.parseRPN(argsScope, undefined, assertive);
726
- });
727
- const preservedArgs = Collection_1.Collection.isCollection(preserved)
728
- ? preserved.getElements()
729
- : [preserved];
730
- const resolved = this.parseRPN(argsScope, values, assertive);
731
- const resolvedArgs = Collection_1.Collection.isCollection(resolved)
732
- ? resolved.getElements()
733
- : [resolved];
734
- if (preservedArgs.length < 2 ||
735
- preservedArgs.length !== resolvedArgs.length ||
736
- !Expression_1.Expression.isExpression(preservedArgs[0]) ||
737
- !preservedArgs[0].isPlainVariable()) {
738
- throw new errors_1.ParserError((0, errors_1.message)('parserMalformedSymbolicAccessor'));
739
- }
740
- const symbolicTarget = preservedArgs[0];
741
- const resolvedTarget = resolvedArgs[0];
742
- const symbolicIndices = [];
743
- const numericIndices = [];
744
- let allResolved = true;
745
- for (let j = 1; j < preservedArgs.length; j++) {
746
- const preservedIndex = preservedArgs[j];
747
- const resolvedIndex = resolvedArgs[j];
748
- if (!Expression_1.Expression.isExpression(preservedIndex)) {
749
- throw new errors_1.ParserError((0, errors_1.message)('parserMalformedSymbolicAccessorIndex'));
750
- }
751
- if (!Expression_1.Expression.isExpression(resolvedIndex)) {
752
- throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessIndexScalar'));
753
- }
754
- symbolicIndices.push(resolvedIndex);
755
- const numericIndex = Number(resolvedIndex.text());
756
- if (Number.isFinite(numericIndex)) {
757
- numericIndices.push(numericIndex - Settings_1.Settings.INDEX_BASE);
758
- }
759
- else {
760
- allResolved = false;
761
- }
762
- }
763
- if (symbolicIndices.length > 2) {
764
- throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessMaxIndices'));
765
- }
766
- if (Vector_1.Vector.isVector(resolvedTarget) && symbolicIndices.length !== 1) {
767
- throw new errors_1.ParserError((0, errors_1.message)('symbolicVectorIndexCount'));
768
- }
769
- if (Matrix_1.Matrix.isMatrix(resolvedTarget) && symbolicIndices.length !== 2) {
770
- if (symbolicIndices.length === 1) {
771
- throw new errors_1.ParserError((0, errors_1.message)('symbolicMatrixRowNonScalar'));
772
- }
773
- throw new errors_1.ParserError((0, errors_1.message)('symbolicMatrixCellIndexCount'));
774
- }
775
- let result;
776
- if ((Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) && allResolved) {
777
- result = resolvedTarget.__get__(numericIndices);
778
- }
779
- else {
780
- let carrier;
781
- if (Vector_1.Vector.isVector(resolvedTarget) || Matrix_1.Matrix.isMatrix(resolvedTarget)) {
782
- carrier = resolvedTarget;
783
- }
784
- else if (Expression_1.Expression.isExpression(resolvedTarget) &&
785
- resolvedTarget.isPlainVariable()) {
786
- carrier = symbolicIndices.length === 2 ? new Matrix_1.Matrix([]) : new Vector_1.Vector();
787
- }
788
- else {
789
- throw new errors_1.ParserError((0, errors_1.message)('symbolicAccessTargetType'));
790
- }
791
- result = carrier.withSymbolicAccessor(symbolicTarget, symbolicIndices);
792
- }
793
- addToOutput(result);
620
+ if (assignValue) {
621
+ a.set(b);
622
+ if (a.targetName) {
623
+ this.KNOWN_VALUES[a.targetName] = a.target;
794
624
  }
795
- else if (dispatch_1.mathFunctionRegistry[token.value]?.deferArguments) {
796
- // Deferred functions receive callable arguments and decide when, whether, and how
797
- // often each argument is evaluated.
798
- const argumentScopes = [];
799
- if (argsScope.length > 0) {
800
- let argumentScope = new Scope_1.Scope(argsScope.type, argsScope.column);
801
- for (const argumentToken of argsScope) {
802
- if (Token_1.Token.isToken(argumentToken) &&
803
- argumentToken.type === Token_1.Token.OPERATOR &&
804
- argumentToken.value === constants_1.COMMA) {
805
- argumentScopes.push(argumentScope);
806
- argumentScope = new Scope_1.Scope(argsScope.type, argsScope.column);
807
- }
808
- else {
809
- argumentScope.push(argumentToken);
810
- }
811
- }
812
- argumentScopes.push(argumentScope);
813
- }
814
- const normalizeArguments = dispatch_1.mathFunctionRegistry[token.value].normalizeDeferredArguments;
815
- const normalizedScopes = normalizeArguments
816
- ? normalizeArguments(argumentScopes)
817
- : argumentScopes;
818
- const functionAssertive = common_1.ASSERTIVE_FUNCTIONS.includes(token.value);
819
- const args = normalizedScopes.map(argumentScope => {
820
- return createDeferredArgument(() => this.toRPN(argumentScope), values, functionAssertive);
821
- });
822
- const result = (0, functions_2.callFunction)(token.value, args);
823
- 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;
824
672
  }
825
- else if (argsScope.deferLHSResolution) {
826
- let args = [];
827
- if (argsScope.length > 0) {
828
- const parsed = (0, Settings_1.scopedBlock)('SUBSTITUTE', false, () => {
829
- return this.parseRPN(argsScope, undefined, assertive);
830
- });
831
- 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'));
832
685
  }
833
- // Preserve the scoped values followed by their left-hand target. The operator
834
- // action is responsible for interpreting that structure.
835
- args.push(Expression_1.Expression.Variable(token.value));
836
- addToOutput(new Collection_1.Collection(args));
686
+ addToOutput(this.resolveSymbolicAccess(Expression_1.Expression.Variable(previousRPN.value), resolvedTarget, symbolicIndices));
837
687
  }
838
688
  else {
839
- // Parse it as an argument. If the value is of the token is an assertive function then parseRPN needs to
840
- // know so it can modify it's behavior accordingly. This would be in the case of functions like assume where
841
- // the operators assert a value rather than compare it.
842
- const parsed = this.parseRPN(argsScope, values, common_1.ASSERTIVE_FUNCTIONS.includes(token.value));
843
- const args = Collection_1.Collection.isCollection(parsed) ? parsed.getElements() : [parsed];
844
- const result = (0, functions_2.callFunction)(token.value, args);
845
- addToOutput(result);
689
+ addToOutput(new IndexedReference_1.IndexedReference(resolvedTarget, indices, targetName));
846
690
  }
691
+ return;
847
692
  }
848
- else if (token.type === Token_1.Token.PREFIX) {
849
- const resolved = resolveStackValue(output.pop());
850
- const e = Expression_1.Expression.fromSymbolicAccess(resolved) ?? resolved;
851
- const prefixAction = `${operators[token.value].action}Prefix`;
852
- const fn = functions_2._[prefixAction];
853
- // TODO: Rethink. What happens when a prefix is applied to a vector
854
- 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));
855
706
  }
856
707
  else {
857
- let expression;
858
- const constant = this.CONSTANTS[token.value];
859
- // User-defined constants are stored as strings and substitute during ordinary parsing.
860
- // They take precedence over scoped values, matching the public setConstant method.
861
- if (typeof constant === 'string') {
862
- expression = this.parse(constant);
863
- }
864
- // Substitute values from the values object. A number is not considered a proper LH value.
865
- else if (values && token.value in values && !token.is(Token_1.Token.NUMBER)) {
866
- // expression = this.parse(String(values[token.value]), values);
867
- const scopedValue = values[token.value];
868
- if (Expression_1.Expression.isExpression(scopedValue) ||
869
- Equation_1.Equation.isEquation(scopedValue) ||
870
- (0, structuredEntityUtils_1.isEnumerable)(scopedValue)) {
871
- expression = scopedValue.copy();
872
- }
873
- else {
874
- expression = Expression_1.Expression.create(scopedValue, undefined, true);
875
- }
876
- }
877
- else if (token.value in this.KNOWN_VALUES && Settings_1.Settings.SUBSTITUTE) {
878
- expression = this.KNOWN_VALUES[token.value].copy();
879
- }
880
- // Built-in constants are factories so they evaluate at the active precision.
881
- else if (Settings_1.Settings.EVALUATE && typeof constant === 'function') {
882
- expression = this.parse(constant(), values);
883
- }
884
- else {
885
- // At this point the expression type is variable or a number
886
- switch (token.type) {
887
- case Token_1.Token.FUNCTION:
888
- expression = Expression_1.Expression.Function(token.value);
889
- break;
890
- case Token_1.Token.VARIABLE:
891
- if (constants_1.INFINITY.includes(token.value)) {
892
- expression = Expression_1.Expression.Inf();
893
- }
894
- else {
895
- expression = Expression_1.Expression.Variable(token.value);
896
- }
897
- break;
898
- default:
899
- expression = Expression_1.Expression.Number(token.value);
900
- break;
901
- }
902
- }
903
- // Add it to output
904
- addToOutput(expression);
708
+ addToOutput(parsed);
905
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();
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));
906
774
  }
907
775
  }
908
776
  let retval;
909
- // Since as function args can have multiple arguments in the output
910
- // the entire array gets returned. We do the same with
911
777
  if (rpn.type === 'square') {
912
778
  retval = new Vector_1.Vector(resolveStackValues(output));
913
779
  }
914
780
  else if (rpn.type === 'curly') {
915
- // If the output contains KeyValuePairs (from '=>' operators), build a Dictionary.
916
- // Otherwise build a ValuesSet as before.
917
781
  if (output.length > 0 && KeyValuePair_1.KeyValuePair.isKeyValuePair(output[0])) {
918
782
  const dict = new Dictionary_1.Dictionary();
919
783
  for (const item of output) {
920
- if (KeyValuePair_1.KeyValuePair.isKeyValuePair(item)) {
921
- dict.set(item.key, item.value);
922
- }
784
+ dict.set(item.key, item.value);
923
785
  }
924
786
  retval = dict;
925
787
  }