@danielsimonjr/mathts-expression 0.10.3 → 0.11.1
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/README.md +18 -2
- package/dist/compiler/compile.d.ts.map +1 -1
- package/dist/evaluator/evaluate.d.ts.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +819 -256
- package/dist/limits.d.ts +18 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/node/ArrayNode.d.ts.map +1 -1
- package/dist/node/AssignmentNode.d.ts.map +1 -1
- package/dist/node/ConditionalNode.d.ts +124 -124
- package/dist/node/ConditionalNode.d.ts.map +1 -1
- package/dist/node/FunctionNode.d.ts.map +1 -1
- package/dist/node/IndexNode.d.ts.map +1 -1
- package/dist/node/Node.d.ts +15 -0
- package/dist/node/Node.d.ts.map +1 -1
- package/dist/node/ObjectNode.d.ts.map +1 -1
- package/dist/node/OperatorNode.d.ts +2 -2
- package/dist/node/OperatorNode.d.ts.map +1 -1
- package/dist/node/RangeNode.d.ts +70 -70
- package/dist/node/RangeNode.d.ts.map +1 -1
- package/dist/node/RelationalNode.d.ts +120 -120
- package/dist/node/RelationalNode.d.ts.map +1 -1
- package/dist/node/utils/stringSubset.d.ts +9 -2
- package/dist/node/utils/stringSubset.d.ts.map +1 -1
- package/dist/parse.d.ts.map +1 -1
- package/dist/scalar-builder.d.ts +4 -4
- package/dist/scalar-enumerate.d.ts +48 -0
- package/dist/scalar-enumerate.d.ts.map +1 -0
- package/dist/scalar-structure.d.ts +167 -0
- package/dist/scalar-structure.d.ts.map +1 -0
- package/dist/transform/and.transform.d.ts.map +1 -1
- package/dist/transform/bitAnd.transform.d.ts.map +1 -1
- package/dist/transform/bitOr.transform.d.ts.map +1 -1
- package/dist/transform/cumsum.transform.d.ts.map +1 -1
- package/dist/transform/filter.transform.d.ts +4 -4
- package/dist/transform/filter.transform.d.ts.map +1 -1
- package/dist/transform/forEach.transform.d.ts.map +1 -1
- package/dist/transform/mapSlices.transform.d.ts +1 -1
- package/dist/transform/mapSlices.transform.d.ts.map +1 -1
- package/dist/transform/or.transform.d.ts.map +1 -1
- package/dist/transform/utils/dimToZeroBase.d.ts +4 -1
- package/dist/transform/utils/dimToZeroBase.d.ts.map +1 -1
- package/dist/transform/utils/prepareTransformArgs.d.ts +23 -0
- package/dist/transform/utils/prepareTransformArgs.d.ts.map +1 -0
- package/dist/transform/utils/shortCircuitBinary.d.ts +21 -0
- package/dist/transform/utils/shortCircuitBinary.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -465,6 +465,9 @@ const safeNativeMethods = {
|
|
|
465
465
|
toLocaleString: true
|
|
466
466
|
};
|
|
467
467
|
//#endregion
|
|
468
|
+
//#region src/limits.ts
|
|
469
|
+
const MAX_EXPRESSION_LENGTH = 1e6;
|
|
470
|
+
//#endregion
|
|
468
471
|
//#region src/parse.ts
|
|
469
472
|
const name$45 = "parse";
|
|
470
473
|
const createParse = /* #__PURE__ */ factory(name$45, [
|
|
@@ -489,12 +492,14 @@ const createParse = /* #__PURE__ */ factory(name$45, [
|
|
|
489
492
|
], ({ typed, numeric, config, AccessorNode, ArrayNode, AssignmentNode, BlockNode, ConditionalNode, ConstantNode, FunctionAssignmentNode, FunctionNode, IndexNode, ObjectNode, OperatorNode, ParenthesisNode, RangeNode, RelationalNode, SymbolNode }) => {
|
|
490
493
|
const parse = typed(name$45, {
|
|
491
494
|
string: function(expression) {
|
|
495
|
+
if (expression.length > 1e6) throw new SyntaxError(`expression exceeds ${MAX_EXPRESSION_LENGTH} characters`);
|
|
492
496
|
return parseStart(expression, {});
|
|
493
497
|
},
|
|
494
498
|
"Array | Matrix": function(expressions) {
|
|
495
499
|
return parseMultiple(expressions, {});
|
|
496
500
|
},
|
|
497
501
|
"string, Object": function(expression, options) {
|
|
502
|
+
if (expression.length > 1e6) throw new SyntaxError(`expression exceeds ${MAX_EXPRESSION_LENGTH} characters`);
|
|
498
503
|
return parseStart(expression, options.nodes !== void 0 ? options.nodes : {});
|
|
499
504
|
},
|
|
500
505
|
"Array | Matrix, Object": parseMultiple
|
|
@@ -583,7 +588,8 @@ const createParse = /* #__PURE__ */ factory(name$45, [
|
|
|
583
588
|
token: "",
|
|
584
589
|
tokenType: 0,
|
|
585
590
|
nestingLevel: 0,
|
|
586
|
-
conditionalLevel: null
|
|
591
|
+
conditionalLevel: null,
|
|
592
|
+
recursionDepth: 0
|
|
587
593
|
};
|
|
588
594
|
}
|
|
589
595
|
function currentString(state, length) {
|
|
@@ -731,8 +737,12 @@ const createParse = /* #__PURE__ */ factory(name$45, [
|
|
|
731
737
|
while (state.token === "\n");
|
|
732
738
|
}
|
|
733
739
|
function openParams(state) {
|
|
740
|
+
if (state.nestingLevel >= 124) throw createSyntaxError(state, "expression exceeds nesting limit");
|
|
734
741
|
state.nestingLevel++;
|
|
735
742
|
}
|
|
743
|
+
function enterRecursion(state) {
|
|
744
|
+
if (++state.recursionDepth > 500) throw createSyntaxError(state, "expression exceeds nesting limit");
|
|
745
|
+
}
|
|
736
746
|
function closeParams(state) {
|
|
737
747
|
state.nestingLevel--;
|
|
738
748
|
}
|
|
@@ -810,6 +820,14 @@ const createParse = /* #__PURE__ */ factory(name$45, [
|
|
|
810
820
|
}
|
|
811
821
|
}
|
|
812
822
|
function parseAssignment(state) {
|
|
823
|
+
enterRecursion(state);
|
|
824
|
+
try {
|
|
825
|
+
return parseAssignmentRule(state);
|
|
826
|
+
} finally {
|
|
827
|
+
state.recursionDepth--;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
function parseAssignmentRule(state) {
|
|
813
831
|
let name;
|
|
814
832
|
let args;
|
|
815
833
|
let value;
|
|
@@ -1092,6 +1110,14 @@ const createParse = /* #__PURE__ */ factory(name$45, [
|
|
|
1092
1110
|
return node;
|
|
1093
1111
|
}
|
|
1094
1112
|
function parseUnary(state) {
|
|
1113
|
+
enterRecursion(state);
|
|
1114
|
+
try {
|
|
1115
|
+
return parseUnaryRule(state);
|
|
1116
|
+
} finally {
|
|
1117
|
+
state.recursionDepth--;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
function parseUnaryRule(state) {
|
|
1095
1121
|
let name;
|
|
1096
1122
|
let params;
|
|
1097
1123
|
let fn;
|
|
@@ -7140,7 +7166,7 @@ const embeddedDocs = {
|
|
|
7140
7166
|
//#endregion
|
|
7141
7167
|
//#region src/compiler/compile.ts
|
|
7142
7168
|
function compile(node, mathScope) {
|
|
7143
|
-
const evalFn = compileNode(node, mathScope, {});
|
|
7169
|
+
const evalFn = compileNode(node, mathScope, {}, 0);
|
|
7144
7170
|
return { evaluate(userScope) {
|
|
7145
7171
|
let scope;
|
|
7146
7172
|
if (!userScope) scope = new ObjectWrappingMap({});
|
|
@@ -7149,23 +7175,25 @@ function compile(node, mathScope) {
|
|
|
7149
7175
|
return evalFn(scope, {}, void 0);
|
|
7150
7176
|
} };
|
|
7151
7177
|
}
|
|
7152
|
-
function compileNode(node, math, argNames) {
|
|
7178
|
+
function compileNode(node, math, argNames, depth) {
|
|
7179
|
+
if (depth >= 512) throw new Error(`expression exceeds compile depth 512`);
|
|
7180
|
+
const nextDepth = depth + 1;
|
|
7153
7181
|
const n = node;
|
|
7154
7182
|
if (n.isConstantNode) return compileConstantNode(node);
|
|
7155
7183
|
if (n.isSymbolNode) return compileSymbolNode(node, math, argNames);
|
|
7156
|
-
if (n.isOperatorNode) return compileOperatorNode(node, math, argNames);
|
|
7157
|
-
if (n.isFunctionNode) return compileFunctionNode(node, math, argNames);
|
|
7158
|
-
if (n.isParenthesisNode) return compileNode(n.content, math, argNames);
|
|
7159
|
-
if (n.isArrayNode) return compileArrayNode(node, math, argNames);
|
|
7160
|
-
if (n.isAssignmentNode) return compileAssignmentNode(node, math, argNames);
|
|
7161
|
-
if (n.isBlockNode) return compileBlockNode(node, math, argNames);
|
|
7162
|
-
if (n.isConditionalNode) return compileConditionalNode(node, math, argNames);
|
|
7163
|
-
if (n.isObjectNode) return compileObjectNode(node, math, argNames);
|
|
7164
|
-
if (n.isRangeNode) return compileRangeNode(node, math, argNames);
|
|
7165
|
-
if (n.isRelationalNode) return compileRelationalNode(node, math, argNames);
|
|
7166
|
-
if (n.isFunctionAssignmentNode) return compileFunctionAssignmentNode(node, math, argNames);
|
|
7167
|
-
if (n.isAccessorNode) return compileAccessorNode(node, math, argNames);
|
|
7168
|
-
if (n.isIndexNode) return compileIndexNode(node, math, argNames);
|
|
7184
|
+
if (n.isOperatorNode) return compileOperatorNode(node, math, argNames, nextDepth);
|
|
7185
|
+
if (n.isFunctionNode) return compileFunctionNode(node, math, argNames, nextDepth);
|
|
7186
|
+
if (n.isParenthesisNode) return compileNode(n.content, math, argNames, nextDepth);
|
|
7187
|
+
if (n.isArrayNode) return compileArrayNode(node, math, argNames, nextDepth);
|
|
7188
|
+
if (n.isAssignmentNode) return compileAssignmentNode(node, math, argNames, nextDepth);
|
|
7189
|
+
if (n.isBlockNode) return compileBlockNode(node, math, argNames, nextDepth);
|
|
7190
|
+
if (n.isConditionalNode) return compileConditionalNode(node, math, argNames, nextDepth);
|
|
7191
|
+
if (n.isObjectNode) return compileObjectNode(node, math, argNames, nextDepth);
|
|
7192
|
+
if (n.isRangeNode) return compileRangeNode(node, math, argNames, nextDepth);
|
|
7193
|
+
if (n.isRelationalNode) return compileRelationalNode(node, math, argNames, nextDepth);
|
|
7194
|
+
if (n.isFunctionAssignmentNode) return compileFunctionAssignmentNode(node, math, argNames, nextDepth);
|
|
7195
|
+
if (n.isAccessorNode) return compileAccessorNode(node, math, argNames, nextDepth);
|
|
7196
|
+
if (n.isIndexNode) return compileIndexNode(node, math, argNames, nextDepth);
|
|
7169
7197
|
throw new Error(`Unknown node type: ${node.type || node.constructor?.name}`);
|
|
7170
7198
|
}
|
|
7171
7199
|
function compileConstantNode(node) {
|
|
@@ -7193,7 +7221,7 @@ function compileSymbolNode(node, math, argNames) {
|
|
|
7193
7221
|
throw new Error(`Undefined symbol "${name}"`);
|
|
7194
7222
|
};
|
|
7195
7223
|
}
|
|
7196
|
-
function compileOperatorNode(node, math, argNames) {
|
|
7224
|
+
function compileOperatorNode(node, math, argNames, depth) {
|
|
7197
7225
|
const opNode = node;
|
|
7198
7226
|
const fnName = opNode.fn;
|
|
7199
7227
|
if (typeof fnName !== "string" || !(fnName in math)) throw new Error(`Function "${fnName}" missing in provided namespace "math"`);
|
|
@@ -7204,7 +7232,7 @@ function compileOperatorNode(node, math, argNames) {
|
|
|
7204
7232
|
return fn(rawNodes, math, scope);
|
|
7205
7233
|
};
|
|
7206
7234
|
}
|
|
7207
|
-
const evalArgs = opNode.args.map((arg) => compileNode(arg, math, argNames));
|
|
7235
|
+
const evalArgs = opNode.args.map((arg) => compileNode(arg, math, argNames, depth));
|
|
7208
7236
|
if (evalArgs.length === 1) {
|
|
7209
7237
|
const evalArg0 = evalArgs[0];
|
|
7210
7238
|
return function evalOperatorNode(scope, args, context) {
|
|
@@ -7223,7 +7251,7 @@ function compileOperatorNode(node, math, argNames) {
|
|
|
7223
7251
|
return fn(...values);
|
|
7224
7252
|
};
|
|
7225
7253
|
}
|
|
7226
|
-
function compileFunctionNode(node, math, argNames) {
|
|
7254
|
+
function compileFunctionNode(node, math, argNames, depth) {
|
|
7227
7255
|
const fnNodeOuter = node;
|
|
7228
7256
|
const fnNode = fnNodeOuter.fn;
|
|
7229
7257
|
if (fnNode && fnNode.isSymbolNode) {
|
|
@@ -7233,11 +7261,11 @@ function compileFunctionNode(node, math, argNames) {
|
|
|
7233
7261
|
const rawNodes = fnNodeOuter.args;
|
|
7234
7262
|
return function evalFunctionNodeRaw(scope) {
|
|
7235
7263
|
const shadow = scope.has(name) ? scope.get(name) : void 0;
|
|
7236
|
-
if (typeof shadow === "function" && shadow.rawArgs !== true) return shadow(...rawNodes.map((rn) => compileNode(rn, math, argNames)(scope, {}, void 0)));
|
|
7264
|
+
if (typeof shadow === "function" && shadow.rawArgs !== true) return shadow(...rawNodes.map((rn) => compileNode(rn, math, argNames, depth)(scope, {}, void 0)));
|
|
7237
7265
|
return staticFn(rawNodes, math, scope);
|
|
7238
7266
|
};
|
|
7239
7267
|
}
|
|
7240
|
-
const evalArgs = fnNodeOuter.args.map((arg) => compileNode(arg, math, argNames));
|
|
7268
|
+
const evalArgs = fnNodeOuter.args.map((arg) => compileNode(arg, math, argNames, depth));
|
|
7241
7269
|
const resolveFn = (scope) => {
|
|
7242
7270
|
if (scope.has(name)) {
|
|
7243
7271
|
const value = scope.get(name);
|
|
@@ -7275,8 +7303,8 @@ function compileFunctionNode(node, math, argNames) {
|
|
|
7275
7303
|
}
|
|
7276
7304
|
}
|
|
7277
7305
|
if (fnNode && fnNode.isAccessorNode && fnNode.index && fnNode.index.isObjectProperty && fnNode.index.isObjectProperty()) {
|
|
7278
|
-
const evalArgs = fnNodeOuter.args.map((arg) => compileNode(arg, math, argNames));
|
|
7279
|
-
const evalObject = compileNode(fnNode.object, math, argNames);
|
|
7306
|
+
const evalArgs = fnNodeOuter.args.map((arg) => compileNode(arg, math, argNames, depth));
|
|
7307
|
+
const evalObject = compileNode(fnNode.object, math, argNames, depth);
|
|
7280
7308
|
const methodName = fnNode.index.getObjectProperty();
|
|
7281
7309
|
return function evalFunctionNode(scope, args, context) {
|
|
7282
7310
|
const obj = evalObject(scope, args, context);
|
|
@@ -7286,23 +7314,23 @@ function compileFunctionNode(node, math, argNames) {
|
|
|
7286
7314
|
return fn.apply(obj, values);
|
|
7287
7315
|
};
|
|
7288
7316
|
}
|
|
7289
|
-
const evalArgs = fnNodeOuter.args.map((arg) => compileNode(arg, math, argNames));
|
|
7290
|
-
const evalFn = compileNode(fnNode, math, argNames);
|
|
7317
|
+
const evalArgs = fnNodeOuter.args.map((arg) => compileNode(arg, math, argNames, depth));
|
|
7318
|
+
const evalFn = compileNode(fnNode, math, argNames, depth);
|
|
7291
7319
|
return function evalFunctionNode(scope, args, context) {
|
|
7292
7320
|
const fn = evalFn(scope, args, context);
|
|
7293
7321
|
if (typeof fn !== "function") throw new TypeError("Expression does not evaluate to a function");
|
|
7294
7322
|
return fn(...evalArgs.map((e) => e(scope, args, context)));
|
|
7295
7323
|
};
|
|
7296
7324
|
}
|
|
7297
|
-
function compileArrayNode(node, math, argNames) {
|
|
7298
|
-
const evalItems = node.items.map((item) => compileNode(item, math, argNames));
|
|
7325
|
+
function compileArrayNode(node, math, argNames, depth) {
|
|
7326
|
+
const evalItems = node.items.map((item) => compileNode(item, math, argNames, depth));
|
|
7299
7327
|
return function evalArrayNode(scope, args, context) {
|
|
7300
7328
|
return evalItems.map((e) => e(scope, args, context));
|
|
7301
7329
|
};
|
|
7302
7330
|
}
|
|
7303
|
-
function compileAssignmentNode(node, math, argNames) {
|
|
7331
|
+
function compileAssignmentNode(node, math, argNames, depth) {
|
|
7304
7332
|
const asgNode = node;
|
|
7305
|
-
const evalValue = compileNode(asgNode.value, math, argNames);
|
|
7333
|
+
const evalValue = compileNode(asgNode.value, math, argNames, depth);
|
|
7306
7334
|
if (asgNode.object && asgNode.object.isSymbolNode && !asgNode.index) {
|
|
7307
7335
|
const name = asgNode.object.name;
|
|
7308
7336
|
return function evalAssignmentNode(scope, args, context) {
|
|
@@ -7312,7 +7340,7 @@ function compileAssignmentNode(node, math, argNames) {
|
|
|
7312
7340
|
};
|
|
7313
7341
|
}
|
|
7314
7342
|
if (asgNode.object && asgNode.object.isAccessorNode) {
|
|
7315
|
-
const evalObject = compileNode(asgNode.object.object, math, argNames);
|
|
7343
|
+
const evalObject = compileNode(asgNode.object.object, math, argNames, depth);
|
|
7316
7344
|
if (asgNode.object.index && asgNode.object.index.isObjectProperty()) {
|
|
7317
7345
|
const prop = asgNode.object.index.getObjectProperty();
|
|
7318
7346
|
return function evalAssignmentNode(scope, args, context) {
|
|
@@ -7330,9 +7358,9 @@ function compileAssignmentNode(node, math, argNames) {
|
|
|
7330
7358
|
};
|
|
7331
7359
|
throw new Error("Unsupported assignment target");
|
|
7332
7360
|
}
|
|
7333
|
-
function compileBlockNode(node, math, argNames) {
|
|
7361
|
+
function compileBlockNode(node, math, argNames, depth) {
|
|
7334
7362
|
const evalBlocks = node.blocks.map((block) => ({
|
|
7335
|
-
evaluate: compileNode(block.node, math, argNames),
|
|
7363
|
+
evaluate: compileNode(block.node, math, argNames, depth),
|
|
7336
7364
|
visible: block.visible
|
|
7337
7365
|
}));
|
|
7338
7366
|
return function evalBlockNode(scope, args, context) {
|
|
@@ -7345,20 +7373,20 @@ function compileBlockNode(node, math, argNames) {
|
|
|
7345
7373
|
if (results.length > 1) return results;
|
|
7346
7374
|
};
|
|
7347
7375
|
}
|
|
7348
|
-
function compileConditionalNode(node, math, argNames) {
|
|
7376
|
+
function compileConditionalNode(node, math, argNames, depth) {
|
|
7349
7377
|
const condNode = node;
|
|
7350
|
-
const evalCondition = compileNode(condNode.condition, math, argNames);
|
|
7351
|
-
const evalTrueExpr = compileNode(condNode.trueExpr, math, argNames);
|
|
7352
|
-
const evalFalseExpr = compileNode(condNode.falseExpr, math, argNames);
|
|
7378
|
+
const evalCondition = compileNode(condNode.condition, math, argNames, depth);
|
|
7379
|
+
const evalTrueExpr = compileNode(condNode.trueExpr, math, argNames, depth);
|
|
7380
|
+
const evalFalseExpr = compileNode(condNode.falseExpr, math, argNames, depth);
|
|
7353
7381
|
return function evalConditionalNode(scope, args, context) {
|
|
7354
7382
|
return testCondition(evalCondition(scope, args, context)) ? evalTrueExpr(scope, args, context) : evalFalseExpr(scope, args, context);
|
|
7355
7383
|
};
|
|
7356
7384
|
}
|
|
7357
|
-
function compileObjectNode(node, math, argNames) {
|
|
7385
|
+
function compileObjectNode(node, math, argNames, depth) {
|
|
7358
7386
|
const properties = node.properties;
|
|
7359
7387
|
const evalProps = Object.keys(properties).map((key) => ({
|
|
7360
7388
|
key,
|
|
7361
|
-
evaluate: compileNode(properties[key], math, argNames)
|
|
7389
|
+
evaluate: compileNode(properties[key], math, argNames, depth)
|
|
7362
7390
|
}));
|
|
7363
7391
|
return function evalObjectNode(scope, args, context) {
|
|
7364
7392
|
const result = {};
|
|
@@ -7366,14 +7394,14 @@ function compileObjectNode(node, math, argNames) {
|
|
|
7366
7394
|
return result;
|
|
7367
7395
|
};
|
|
7368
7396
|
}
|
|
7369
|
-
function compileRangeNode(node, math, argNames) {
|
|
7397
|
+
function compileRangeNode(node, math, argNames, depth) {
|
|
7370
7398
|
const rangeFn = math.range;
|
|
7371
7399
|
if (!rangeFn) throw new Error("Function \"range\" missing in math namespace (required for range expressions)");
|
|
7372
7400
|
const rngNode = node;
|
|
7373
|
-
const evalStart = compileNode(rngNode.start, math, argNames);
|
|
7374
|
-
const evalEnd = compileNode(rngNode.end, math, argNames);
|
|
7401
|
+
const evalStart = compileNode(rngNode.start, math, argNames, depth);
|
|
7402
|
+
const evalEnd = compileNode(rngNode.end, math, argNames, depth);
|
|
7375
7403
|
if (rngNode.step) {
|
|
7376
|
-
const evalStep = compileNode(rngNode.step, math, argNames);
|
|
7404
|
+
const evalStep = compileNode(rngNode.step, math, argNames, depth);
|
|
7377
7405
|
return function evalRangeNode(scope, args, context) {
|
|
7378
7406
|
return rangeFn(evalStart(scope, args, context), evalEnd(scope, args, context), evalStep(scope, args, context));
|
|
7379
7407
|
};
|
|
@@ -7382,9 +7410,9 @@ function compileRangeNode(node, math, argNames) {
|
|
|
7382
7410
|
return rangeFn(evalStart(scope, args, context), evalEnd(scope, args, context));
|
|
7383
7411
|
};
|
|
7384
7412
|
}
|
|
7385
|
-
function compileRelationalNode(node, math, argNames) {
|
|
7413
|
+
function compileRelationalNode(node, math, argNames, depth) {
|
|
7386
7414
|
const relNode = node;
|
|
7387
|
-
const compiled = relNode.params.map((p) => compileNode(p, math, argNames));
|
|
7415
|
+
const compiled = relNode.params.map((p) => compileNode(p, math, argNames, depth));
|
|
7388
7416
|
const conditionals = relNode.conditionals;
|
|
7389
7417
|
return function evalRelationalNode(scope, args, context) {
|
|
7390
7418
|
let evalLhs;
|
|
@@ -7399,11 +7427,11 @@ function compileRelationalNode(node, math, argNames) {
|
|
|
7399
7427
|
return true;
|
|
7400
7428
|
};
|
|
7401
7429
|
}
|
|
7402
|
-
function compileFunctionAssignmentNode(node, math, argNames) {
|
|
7430
|
+
function compileFunctionAssignmentNode(node, math, argNames, depth) {
|
|
7403
7431
|
const faNode = node;
|
|
7404
7432
|
const childArgNames = Object.create(argNames);
|
|
7405
7433
|
for (const param of faNode.params) childArgNames[param] = true;
|
|
7406
|
-
const evalExpr = compileNode(faNode.expr, math, childArgNames);
|
|
7434
|
+
const evalExpr = compileNode(faNode.expr, math, childArgNames, depth);
|
|
7407
7435
|
const name = faNode.name;
|
|
7408
7436
|
const params = faNode.params;
|
|
7409
7437
|
return function evalFunctionAssignmentNode(scope, args, _context) {
|
|
@@ -7417,9 +7445,9 @@ function compileFunctionAssignmentNode(node, math, argNames) {
|
|
|
7417
7445
|
return fn;
|
|
7418
7446
|
};
|
|
7419
7447
|
}
|
|
7420
|
-
function compileAccessorNode(node, math, argNames) {
|
|
7448
|
+
function compileAccessorNode(node, math, argNames, depth) {
|
|
7421
7449
|
const accNode = node;
|
|
7422
|
-
const evalObject = compileNode(accNode.object, math, argNames);
|
|
7450
|
+
const evalObject = compileNode(accNode.object, math, argNames, depth);
|
|
7423
7451
|
if (accNode.index && accNode.index.isObjectProperty && accNode.index.isObjectProperty()) {
|
|
7424
7452
|
const prop = accNode.index.getObjectProperty();
|
|
7425
7453
|
return function evalAccessorNode(scope, args, context) {
|
|
@@ -7428,7 +7456,7 @@ function compileAccessorNode(node, math, argNames) {
|
|
|
7428
7456
|
return getSafeProperty(object, prop);
|
|
7429
7457
|
};
|
|
7430
7458
|
}
|
|
7431
|
-
const evalIndex = compileNode(accNode.index, math, argNames);
|
|
7459
|
+
const evalIndex = compileNode(accNode.index, math, argNames, depth);
|
|
7432
7460
|
return function evalAccessorNode(scope, args, context) {
|
|
7433
7461
|
const object = evalObject(scope, args, context);
|
|
7434
7462
|
if (accNode.optionalChaining && object == null) return void 0;
|
|
@@ -7438,16 +7466,16 @@ function compileAccessorNode(node, math, argNames) {
|
|
|
7438
7466
|
return getSafeProperty(object, index);
|
|
7439
7467
|
};
|
|
7440
7468
|
}
|
|
7441
|
-
function compileIndexNode(node, math, argNames) {
|
|
7469
|
+
function compileIndexNode(node, math, argNames, depth) {
|
|
7442
7470
|
const dimensionNodes = node.dimensions;
|
|
7443
7471
|
const usesEnd = dimensionNodes.map((dim) => dim.filter?.((n) => n.isSymbolNode === true && n.name === "end")?.length ?? 0);
|
|
7444
7472
|
const evalDimensions = dimensionNodes.map((dim, i) => {
|
|
7445
7473
|
if (usesEnd[i]) {
|
|
7446
7474
|
const childArgNames = Object.create(argNames);
|
|
7447
7475
|
childArgNames.end = true;
|
|
7448
|
-
return compileNode(dim, math, childArgNames);
|
|
7476
|
+
return compileNode(dim, math, childArgNames, depth);
|
|
7449
7477
|
}
|
|
7450
|
-
return compileNode(dim, math, argNames);
|
|
7478
|
+
return compileNode(dim, math, argNames, depth);
|
|
7451
7479
|
});
|
|
7452
7480
|
usesEnd.some((n) => n > 0);
|
|
7453
7481
|
return function evalIndexNode(scope, args, context) {
|
|
@@ -7491,8 +7519,9 @@ const FORBIDDEN_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
7491
7519
|
"help",
|
|
7492
7520
|
"chain"
|
|
7493
7521
|
]);
|
|
7494
|
-
function validateAst(node) {
|
|
7522
|
+
function validateAst(node, depth = 0) {
|
|
7495
7523
|
if (node === null || node === void 0 || typeof node !== "object") return;
|
|
7524
|
+
if (depth >= 512) throw new Error(`expression exceeds compile depth 512`);
|
|
7496
7525
|
const n = node;
|
|
7497
7526
|
if (n.isAssignmentNode === true) throw new Error("Security: assignment expressions are disabled. Pass `{ unsafe: true }` to opt out.");
|
|
7498
7527
|
if (n.isFunctionAssignmentNode === true) throw new Error("Security: function definitions (FunctionAssignmentNode) are disabled. Pass `{ unsafe: true }` to opt out.");
|
|
@@ -7502,10 +7531,10 @@ function validateAst(node) {
|
|
|
7502
7531
|
if (fnName && FORBIDDEN_FUNCTIONS.has(fnName)) throw new Error(`Security: call to forbidden function "${fnName}" is disabled. Pass \`{ unsafe: true }\` to opt out.`);
|
|
7503
7532
|
}
|
|
7504
7533
|
if (typeof n.forEach === "function") try {
|
|
7505
|
-
n.forEach((child) => validateAst(child));
|
|
7534
|
+
n.forEach((child) => validateAst(child, depth + 1));
|
|
7506
7535
|
return;
|
|
7507
7536
|
} catch (err) {
|
|
7508
|
-
if (err instanceof Error && err.message.startsWith("Security:")) throw err;
|
|
7537
|
+
if (err instanceof RangeError || err instanceof Error && (err.message.startsWith("Security:") || err.message.startsWith("expression exceeds"))) throw err;
|
|
7509
7538
|
}
|
|
7510
7539
|
for (const key of [
|
|
7511
7540
|
"object",
|
|
@@ -7520,19 +7549,19 @@ function validateAst(node) {
|
|
|
7520
7549
|
"start",
|
|
7521
7550
|
"end",
|
|
7522
7551
|
"step"
|
|
7523
|
-
]) if (key in n) validateAst(n[key]);
|
|
7552
|
+
]) if (key in n) validateAst(n[key], depth + 1);
|
|
7524
7553
|
for (const key of [
|
|
7525
7554
|
"args",
|
|
7526
7555
|
"items",
|
|
7527
7556
|
"params"
|
|
7528
7557
|
]) {
|
|
7529
7558
|
const arr = n[key];
|
|
7530
|
-
if (Array.isArray(arr)) for (const child of arr) validateAst(child);
|
|
7559
|
+
if (Array.isArray(arr)) for (const child of arr) validateAst(child, depth + 1);
|
|
7531
7560
|
}
|
|
7532
|
-
if (Array.isArray(n.blocks)) for (const b of n.blocks) validateAst(b && b.node);
|
|
7561
|
+
if (Array.isArray(n.blocks)) for (const b of n.blocks) validateAst(b && b.node, depth + 1);
|
|
7533
7562
|
if (n.properties && typeof n.properties === "object") {
|
|
7534
7563
|
const properties = n.properties;
|
|
7535
|
-
for (const k of Object.keys(properties)) validateAst(properties[k]);
|
|
7564
|
+
for (const k of Object.keys(properties)) validateAst(properties[k], depth + 1);
|
|
7536
7565
|
}
|
|
7537
7566
|
}
|
|
7538
7567
|
function createEvaluate(parseFn, mathScope) {
|
|
@@ -7836,6 +7865,11 @@ const createNode = /* #__PURE__ */ factory("Node", ["mathWithTransform"], ({ mat
|
|
|
7836
7865
|
isClass: true,
|
|
7837
7866
|
isNode: true
|
|
7838
7867
|
});
|
|
7868
|
+
function mapChildArray(parent, children, pathPrefix, callback) {
|
|
7869
|
+
const out = [];
|
|
7870
|
+
for (let i = 0; i < children.length; i++) out[i] = parent._ifNode(callback(children[i], pathPrefix + "[" + i + "]", parent));
|
|
7871
|
+
return out;
|
|
7872
|
+
}
|
|
7839
7873
|
//#endregion
|
|
7840
7874
|
//#region src/transform/utils/errorTransform.ts
|
|
7841
7875
|
function errorTransform(err) {
|
|
@@ -7845,8 +7879,8 @@ function errorTransform(err) {
|
|
|
7845
7879
|
}
|
|
7846
7880
|
//#endregion
|
|
7847
7881
|
//#region src/node/utils/stringSubset.ts
|
|
7848
|
-
function getStringSubset(str, index) {
|
|
7849
|
-
if (!isIndex(index)) throw new TypeError(
|
|
7882
|
+
function getStringSubset(str, index, invalidIndexMessage = "Index expected") {
|
|
7883
|
+
if (!isIndex(index)) throw new TypeError(invalidIndexMessage);
|
|
7850
7884
|
if (isEmptyIndex(index)) return "";
|
|
7851
7885
|
validateIndexSourceSize(Array.from(str), index);
|
|
7852
7886
|
if (index.size().length !== 1) throw new DimensionError(index.size().length, 1);
|
|
@@ -8050,8 +8084,7 @@ const createArrayNode = /* #__PURE__ */ factory(name$39, ["Node"], ({ Node }) =>
|
|
|
8050
8084
|
}
|
|
8051
8085
|
}
|
|
8052
8086
|
map(callback) {
|
|
8053
|
-
const items =
|
|
8054
|
-
for (let i = 0; i < this.items.length; i++) items[i] = this._ifNode(callback(this.items[i], "items[" + i + "]", this));
|
|
8087
|
+
const items = mapChildArray(this, this.items, "items", callback);
|
|
8055
8088
|
return new ArrayNode(items);
|
|
8056
8089
|
}
|
|
8057
8090
|
clone() {
|
|
@@ -8130,6 +8163,13 @@ const createAssignmentNode = /* #__PURE__ */ factory(name$38, ["subset", "Node"]
|
|
|
8130
8163
|
const exprPrecedence = getPrecedence(node.value, parenthesis, implicit, void 0);
|
|
8131
8164
|
return parenthesis === "all" || exprPrecedence !== null && exprPrecedence <= precedence;
|
|
8132
8165
|
}
|
|
8166
|
+
function renderAssignment(node, options, render, markup) {
|
|
8167
|
+
const object = render(node.object, options);
|
|
8168
|
+
const index = node.index ? render(node.index, options) : "";
|
|
8169
|
+
let value = render(node.value, options);
|
|
8170
|
+
if (needParenthesis(node, options && options.parenthesis, options && options.implicit)) value = markup.paren(value);
|
|
8171
|
+
return object + index + markup.eq + value;
|
|
8172
|
+
}
|
|
8133
8173
|
class AssignmentNode extends Node {
|
|
8134
8174
|
object;
|
|
8135
8175
|
index;
|
|
@@ -8224,11 +8264,10 @@ const createAssignmentNode = /* #__PURE__ */ factory(name$38, ["subset", "Node"]
|
|
|
8224
8264
|
return new AssignmentNode(this.object, this.index, this.value);
|
|
8225
8265
|
}
|
|
8226
8266
|
_toString(options) {
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
return object + index + " = " + value;
|
|
8267
|
+
return renderAssignment(this, options, (node, opts) => node.toString(opts), {
|
|
8268
|
+
paren: (value) => "(" + value + ")",
|
|
8269
|
+
eq: " = "
|
|
8270
|
+
});
|
|
8232
8271
|
}
|
|
8233
8272
|
toJSON() {
|
|
8234
8273
|
return {
|
|
@@ -8242,11 +8281,10 @@ const createAssignmentNode = /* #__PURE__ */ factory(name$38, ["subset", "Node"]
|
|
|
8242
8281
|
return new AssignmentNode(json.object, json.index, json.value);
|
|
8243
8282
|
}
|
|
8244
8283
|
_toHTML(options) {
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
return object + index + "<span class=\"math-operator math-assignment-operator math-variable-assignment-operator math-binary-operator\">=</span>" + value;
|
|
8284
|
+
return renderAssignment(this, options, (node, opts) => node.toHTML(opts), {
|
|
8285
|
+
paren: (value) => "<span class=\"math-paranthesis math-round-parenthesis\">(</span>" + value + "<span class=\"math-paranthesis math-round-parenthesis\">)</span>",
|
|
8286
|
+
eq: "<span class=\"math-operator math-assignment-operator math-variable-assignment-operator math-binary-operator\">=</span>"
|
|
8287
|
+
});
|
|
8250
8288
|
}
|
|
8251
8289
|
_toMathML() {
|
|
8252
8290
|
const obj = this.object;
|
|
@@ -8257,11 +8295,10 @@ const createAssignmentNode = /* #__PURE__ */ factory(name$38, ["subset", "Node"]
|
|
|
8257
8295
|
return `<mtext>${escapeMathML(this.toString())}</mtext>`;
|
|
8258
8296
|
}
|
|
8259
8297
|
_toTex(options) {
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
return object + index + "=" + value;
|
|
8298
|
+
return renderAssignment(this, options, (node, opts) => node.toTex(opts), {
|
|
8299
|
+
paren: (value) => `\\left(${value}\\right)`,
|
|
8300
|
+
eq: "="
|
|
8301
|
+
});
|
|
8265
8302
|
}
|
|
8266
8303
|
}
|
|
8267
8304
|
return AssignmentNode;
|
|
@@ -8380,6 +8417,17 @@ const createConditionalNode = /* #__PURE__ */ factory(name$36, ["Node"], ({ Node
|
|
|
8380
8417
|
if (condition === null || condition === void 0) return false;
|
|
8381
8418
|
throw new TypeError("Unsupported type of condition \"" + typeOf(condition) + "\"");
|
|
8382
8419
|
}
|
|
8420
|
+
function formatConditionalBranches(self, options, render, wrap, join) {
|
|
8421
|
+
const parenthesis = options && options.parenthesis ? options.parenthesis : "keep";
|
|
8422
|
+
const precedence = getPrecedence(self, parenthesis, options && options.implicit, void 0);
|
|
8423
|
+
function branchText(node) {
|
|
8424
|
+
let text = render(node);
|
|
8425
|
+
const nodePrecedence = getPrecedence(node, parenthesis, options && options.implicit, void 0);
|
|
8426
|
+
if (parenthesis === "all" || node.type === "OperatorNode" || nodePrecedence !== null && nodePrecedence <= precedence) text = wrap(text);
|
|
8427
|
+
return text;
|
|
8428
|
+
}
|
|
8429
|
+
return join(branchText(self.condition), branchText(self.trueExpr), branchText(self.falseExpr));
|
|
8430
|
+
}
|
|
8383
8431
|
class ConditionalNode extends Node {
|
|
8384
8432
|
condition;
|
|
8385
8433
|
trueExpr;
|
|
@@ -8420,18 +8468,7 @@ const createConditionalNode = /* #__PURE__ */ factory(name$36, ["Node"], ({ Node
|
|
|
8420
8468
|
return new ConditionalNode(this.condition, this.trueExpr, this.falseExpr);
|
|
8421
8469
|
}
|
|
8422
8470
|
_toString(options) {
|
|
8423
|
-
|
|
8424
|
-
const precedence = getPrecedence(this, parenthesis, options && options.implicit, void 0);
|
|
8425
|
-
let condition = this.condition.toString(options);
|
|
8426
|
-
const conditionPrecedence = getPrecedence(this.condition, parenthesis, options && options.implicit, void 0);
|
|
8427
|
-
if (parenthesis === "all" || this.condition.type === "OperatorNode" || conditionPrecedence !== null && conditionPrecedence <= precedence) condition = "(" + condition + ")";
|
|
8428
|
-
let trueExpr = this.trueExpr.toString(options);
|
|
8429
|
-
const truePrecedence = getPrecedence(this.trueExpr, parenthesis, options && options.implicit, void 0);
|
|
8430
|
-
if (parenthesis === "all" || this.trueExpr.type === "OperatorNode" || truePrecedence !== null && truePrecedence <= precedence) trueExpr = "(" + trueExpr + ")";
|
|
8431
|
-
let falseExpr = this.falseExpr.toString(options);
|
|
8432
|
-
const falsePrecedence = getPrecedence(this.falseExpr, parenthesis, options && options.implicit, void 0);
|
|
8433
|
-
if (parenthesis === "all" || this.falseExpr.type === "OperatorNode" || falsePrecedence !== null && falsePrecedence <= precedence) falseExpr = "(" + falseExpr + ")";
|
|
8434
|
-
return condition + " ? " + trueExpr + " : " + falseExpr;
|
|
8471
|
+
return formatConditionalBranches(this, options, (node) => node.toString(options), (inner) => "(" + inner + ")", (condition, trueExpr, falseExpr) => condition + " ? " + trueExpr + " : " + falseExpr);
|
|
8435
8472
|
}
|
|
8436
8473
|
toJSON() {
|
|
8437
8474
|
return {
|
|
@@ -8445,18 +8482,9 @@ const createConditionalNode = /* #__PURE__ */ factory(name$36, ["Node"], ({ Node
|
|
|
8445
8482
|
return new ConditionalNode(json.condition, json.trueExpr, json.falseExpr);
|
|
8446
8483
|
}
|
|
8447
8484
|
_toHTML(options) {
|
|
8448
|
-
const
|
|
8449
|
-
const
|
|
8450
|
-
|
|
8451
|
-
const conditionPrecedence = getPrecedence(this.condition, parenthesis, options && options.implicit, void 0);
|
|
8452
|
-
if (parenthesis === "all" || this.condition.type === "OperatorNode" || conditionPrecedence !== null && conditionPrecedence <= precedence) condition = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + condition + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
8453
|
-
let trueExpr = this.trueExpr.toHTML(options);
|
|
8454
|
-
const truePrecedence = getPrecedence(this.trueExpr, parenthesis, options && options.implicit, void 0);
|
|
8455
|
-
if (parenthesis === "all" || this.trueExpr.type === "OperatorNode" || truePrecedence !== null && truePrecedence <= precedence) trueExpr = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + trueExpr + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
8456
|
-
let falseExpr = this.falseExpr.toHTML(options);
|
|
8457
|
-
const falsePrecedence = getPrecedence(this.falseExpr, parenthesis, options && options.implicit, void 0);
|
|
8458
|
-
if (parenthesis === "all" || this.falseExpr.type === "OperatorNode" || falsePrecedence !== null && falsePrecedence <= precedence) falseExpr = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + falseExpr + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
8459
|
-
return condition + "<span class=\"math-operator math-conditional-operator\">?</span>" + trueExpr + "<span class=\"math-operator math-conditional-operator\">:</span>" + falseExpr;
|
|
8485
|
+
const parenOpen = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>";
|
|
8486
|
+
const parenClose = "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
8487
|
+
return formatConditionalBranches(this, options, (node) => node.toHTML(options), (inner) => parenOpen + inner + parenClose, (condition, trueExpr, falseExpr) => condition + "<span class=\"math-operator math-conditional-operator\">?</span>" + trueExpr + "<span class=\"math-operator math-conditional-operator\">:</span>" + falseExpr);
|
|
8460
8488
|
}
|
|
8461
8489
|
_toTex(options) {
|
|
8462
8490
|
return "\\begin{cases} {" + this.trueExpr.toTex(options) + "}, &\\quad{\\text{if }\\;" + this.condition.toTex(options) + "}\\\\{" + this.falseExpr.toTex(options) + "}, &\\quad{\\text{otherwise}}\\end{cases}";
|
|
@@ -9173,8 +9201,7 @@ const createFunctionNode = /* #__PURE__ */ factory(name$33, [
|
|
|
9173
9201
|
}
|
|
9174
9202
|
map(callback) {
|
|
9175
9203
|
const fn = this._ifNode(callback(this.fn, "fn", this));
|
|
9176
|
-
const args =
|
|
9177
|
-
for (let i = 0; i < this.args.length; i++) args[i] = this._ifNode(callback(this.args[i], "args[" + i + "]", this));
|
|
9204
|
+
const args = mapChildArray(this, this.args, "args", callback);
|
|
9178
9205
|
return new FunctionNode(fn, args);
|
|
9179
9206
|
}
|
|
9180
9207
|
clone() {
|
|
@@ -9315,8 +9342,7 @@ const createIndexNode = /* #__PURE__ */ factory(name$32, ["Node", "size"], ({ No
|
|
|
9315
9342
|
for (let i = 0; i < this.dimensions.length; i++) callback(this.dimensions[i], "dimensions[" + i + "]", this);
|
|
9316
9343
|
}
|
|
9317
9344
|
map(callback) {
|
|
9318
|
-
const dimensions =
|
|
9319
|
-
for (let i = 0; i < this.dimensions.length; i++) dimensions[i] = this._ifNode(callback(this.dimensions[i], "dimensions[" + i + "]", this));
|
|
9345
|
+
const dimensions = mapChildArray(this, this.dimensions, "dimensions", callback);
|
|
9320
9346
|
return new IndexNode(dimensions, this.dotNotation);
|
|
9321
9347
|
}
|
|
9322
9348
|
clone() {
|
|
@@ -9364,6 +9390,11 @@ const createIndexNode = /* #__PURE__ */ factory(name$32, ["Node", "size"], ({ No
|
|
|
9364
9390
|
//#region src/node/ObjectNode.ts
|
|
9365
9391
|
const name$31 = "ObjectNode";
|
|
9366
9392
|
const createObjectNode = /* #__PURE__ */ factory(name$31, ["Node"], ({ Node }) => {
|
|
9393
|
+
function renderObjectEntries(properties, entry, separator, wrap) {
|
|
9394
|
+
const entries = [];
|
|
9395
|
+
for (const key in properties) if (hasOwnProperty(properties, key)) entries.push(entry(key, properties[key]));
|
|
9396
|
+
return wrap(entries.join(separator));
|
|
9397
|
+
}
|
|
9367
9398
|
class ObjectNode extends Node {
|
|
9368
9399
|
properties;
|
|
9369
9400
|
constructor(properties) {
|
|
@@ -9399,18 +9430,16 @@ const createObjectNode = /* #__PURE__ */ factory(name$31, ["Node"], ({ Node }) =
|
|
|
9399
9430
|
}
|
|
9400
9431
|
map(callback) {
|
|
9401
9432
|
const properties = {};
|
|
9402
|
-
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) properties
|
|
9433
|
+
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) setSafeProperty(properties, key, this._ifNode(callback(this.properties[key], "properties[" + stringify(key) + "]", this)));
|
|
9403
9434
|
return new ObjectNode(properties);
|
|
9404
9435
|
}
|
|
9405
9436
|
clone() {
|
|
9406
9437
|
const properties = {};
|
|
9407
|
-
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) properties
|
|
9438
|
+
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) setSafeProperty(properties, key, this.properties[key]);
|
|
9408
9439
|
return new ObjectNode(properties);
|
|
9409
9440
|
}
|
|
9410
9441
|
_toString(options) {
|
|
9411
|
-
|
|
9412
|
-
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) entries.push(stringify(key) + ": " + this.properties[key].toString(options));
|
|
9413
|
-
return "{" + entries.join(", ") + "}";
|
|
9442
|
+
return renderObjectEntries(this.properties, (key, node) => stringify(key) + ": " + node.toString(options), ", ", (joined) => "{" + joined + "}");
|
|
9414
9443
|
}
|
|
9415
9444
|
toJSON() {
|
|
9416
9445
|
return {
|
|
@@ -9422,14 +9451,10 @@ const createObjectNode = /* #__PURE__ */ factory(name$31, ["Node"], ({ Node }) =
|
|
|
9422
9451
|
return new ObjectNode(json.properties);
|
|
9423
9452
|
}
|
|
9424
9453
|
_toHTML(options) {
|
|
9425
|
-
|
|
9426
|
-
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) entries.push("<span class=\"math-symbol math-property\">" + escape(key) + "</span><span class=\"math-operator math-assignment-operator math-property-assignment-operator math-binary-operator\">:</span>" + this.properties[key].toHTML(options));
|
|
9427
|
-
return "<span class=\"math-parenthesis math-curly-parenthesis\">{</span>" + entries.join("<span class=\"math-separator\">,</span>") + "<span class=\"math-parenthesis math-curly-parenthesis\">}</span>";
|
|
9454
|
+
return renderObjectEntries(this.properties, (key, node) => "<span class=\"math-symbol math-property\">" + escape(key) + "</span><span class=\"math-operator math-assignment-operator math-property-assignment-operator math-binary-operator\">:</span>" + node.toHTML(options), "<span class=\"math-separator\">,</span>", (joined) => "<span class=\"math-parenthesis math-curly-parenthesis\">{</span>" + joined + "<span class=\"math-parenthesis math-curly-parenthesis\">}</span>");
|
|
9428
9455
|
}
|
|
9429
9456
|
_toTex(options) {
|
|
9430
|
-
|
|
9431
|
-
for (const key in this.properties) if (hasOwnProperty(this.properties, key)) entries.push("\\mathbf{" + key + ":} & " + this.properties[key].toTex(options) + "\\\\");
|
|
9432
|
-
return "\\left\\{\\begin{array}{ll}" + entries.join("\n") + "\\end{array}\\right\\}";
|
|
9457
|
+
return renderObjectEntries(this.properties, (key, node) => "\\mathbf{" + key + ":} & " + node.toTex(options) + "\\\\", "\n", (joined) => "\\left\\{\\begin{array}{ll}" + joined + "\\end{array}\\right\\}");
|
|
9433
9458
|
}
|
|
9434
9459
|
}
|
|
9435
9460
|
return ObjectNode;
|
|
@@ -9448,10 +9473,19 @@ const createOperatorNode = /* #__PURE__ */ factory(name$30, ["Node"], ({ Node })
|
|
|
9448
9473
|
if (isOperatorNode(curNode)) return startsWithConstant(curNode.args[0], parenthesis);
|
|
9449
9474
|
return false;
|
|
9450
9475
|
}
|
|
9476
|
+
function isNegativeNumberConstant(arg) {
|
|
9477
|
+
const content = arg.getContent();
|
|
9478
|
+
if (!isConstantNode(content)) return false;
|
|
9479
|
+
const value = content.value;
|
|
9480
|
+
return typeof value === "number" && value < 0;
|
|
9481
|
+
}
|
|
9482
|
+
function parenthesizeNegativeConstants(args, parens) {
|
|
9483
|
+
return args.map((arg, i) => parens[i] === true || isNegativeNumberConstant(arg));
|
|
9484
|
+
}
|
|
9451
9485
|
function calculateNecessaryParentheses(root, parenthesis, implicit, args, latex) {
|
|
9452
9486
|
const precedence = getPrecedence(root, parenthesis, implicit, void 0);
|
|
9453
9487
|
const associativity = getAssociativity(root, parenthesis);
|
|
9454
|
-
if (parenthesis === "all" || args.length > 2 && root.getIdentifier() !== "OperatorNode:add" && root.getIdentifier() !== "OperatorNode:multiply") return args.map(function(arg) {
|
|
9488
|
+
if (parenthesis === "all" || args.length > 2 && root.getIdentifier() !== "OperatorNode:add" && root.getIdentifier() !== "OperatorNode:multiply") return parenthesizeNegativeConstants(args, args.map(function(arg) {
|
|
9455
9489
|
switch (arg.getContent().type) {
|
|
9456
9490
|
case "ArrayNode":
|
|
9457
9491
|
case "ConstantNode":
|
|
@@ -9459,7 +9493,7 @@ const createOperatorNode = /* #__PURE__ */ factory(name$30, ["Node"], ({ Node })
|
|
|
9459
9493
|
case "ParenthesisNode": return false;
|
|
9460
9494
|
default: return true;
|
|
9461
9495
|
}
|
|
9462
|
-
});
|
|
9496
|
+
}));
|
|
9463
9497
|
let result = [];
|
|
9464
9498
|
switch (args.length) {
|
|
9465
9499
|
case 0:
|
|
@@ -9552,7 +9586,7 @@ const createOperatorNode = /* #__PURE__ */ factory(name$30, ["Node"], ({ Node })
|
|
|
9552
9586
|
if (args.length >= 2 && root.getIdentifier() === "OperatorNode:multiply" && root.implicit && parenthesis !== "all" && implicit === "hide") {
|
|
9553
9587
|
for (let i = 1; i < result.length; ++i) if (startsWithConstant(args[i], parenthesis) && !result[i - 1] && (parenthesis !== "keep" || !isParenthesisNode(args[i - 1]))) result[i] = true;
|
|
9554
9588
|
}
|
|
9555
|
-
return result;
|
|
9589
|
+
return parenthesizeNegativeConstants(args, result);
|
|
9556
9590
|
}
|
|
9557
9591
|
class OperatorNode extends Node {
|
|
9558
9592
|
op;
|
|
@@ -9613,8 +9647,7 @@ const createOperatorNode = /* #__PURE__ */ factory(name$30, ["Node"], ({ Node })
|
|
|
9613
9647
|
for (let i = 0; i < this.args.length; i++) callback(this.args[i], "args[" + i + "]", this);
|
|
9614
9648
|
}
|
|
9615
9649
|
map(callback) {
|
|
9616
|
-
const args =
|
|
9617
|
-
for (let i = 0; i < this.args.length; i++) args[i] = this._ifNode(callback(this.args[i], "args[" + i + "]", this));
|
|
9650
|
+
const args = mapChildArray(this, this.args, "args", callback);
|
|
9618
9651
|
return new OperatorNode(this.op, this.fn, args, this.implicit, this.isPercentage);
|
|
9619
9652
|
}
|
|
9620
9653
|
clone() {
|
|
@@ -9857,6 +9890,21 @@ const createRangeNode = /* #__PURE__ */ factory(name$28, ["Node"], ({ Node }) =>
|
|
|
9857
9890
|
parens.end = endPrecedence !== null && endPrecedence <= precedence || parenthesis === "all";
|
|
9858
9891
|
return parens;
|
|
9859
9892
|
}
|
|
9893
|
+
function formatRangeDisplay(node, options, render, wrap, rangeSep) {
|
|
9894
|
+
const parens = calculateNecessaryParentheses(node, options && options.parenthesis ? options.parenthesis : "keep", options && options.implicit || "hide");
|
|
9895
|
+
let start = render(node.start);
|
|
9896
|
+
if (parens.start) start = wrap(start);
|
|
9897
|
+
let str = start;
|
|
9898
|
+
if (node.step) {
|
|
9899
|
+
let step = render(node.step);
|
|
9900
|
+
if (parens.step) step = wrap(step);
|
|
9901
|
+
str += rangeSep() + step;
|
|
9902
|
+
}
|
|
9903
|
+
let end = render(node.end);
|
|
9904
|
+
if (parens.end) end = wrap(end);
|
|
9905
|
+
str += rangeSep() + end;
|
|
9906
|
+
return str;
|
|
9907
|
+
}
|
|
9860
9908
|
class RangeNode extends Node {
|
|
9861
9909
|
start;
|
|
9862
9910
|
end;
|
|
@@ -9908,21 +9956,7 @@ const createRangeNode = /* #__PURE__ */ factory(name$28, ["Node"], ({ Node }) =>
|
|
|
9908
9956
|
return new RangeNode(this.start, this.end, this.step || void 0);
|
|
9909
9957
|
}
|
|
9910
9958
|
_toString(options) {
|
|
9911
|
-
|
|
9912
|
-
const parens = calculateNecessaryParentheses(this, parenthesis, options && options.implicit || "hide");
|
|
9913
|
-
let str;
|
|
9914
|
-
let start = this.start.toString(options);
|
|
9915
|
-
if (parens.start) start = "(" + start + ")";
|
|
9916
|
-
str = start;
|
|
9917
|
-
if (this.step) {
|
|
9918
|
-
let step = this.step.toString(options);
|
|
9919
|
-
if (parens.step) step = "(" + step + ")";
|
|
9920
|
-
str += ":" + step;
|
|
9921
|
-
}
|
|
9922
|
-
let end = this.end.toString(options);
|
|
9923
|
-
if (parens.end) end = "(" + end + ")";
|
|
9924
|
-
str += ":" + end;
|
|
9925
|
-
return str;
|
|
9959
|
+
return formatRangeDisplay(this, options, (child) => child.toString(options), (inner) => "(" + inner + ")", () => ":");
|
|
9926
9960
|
}
|
|
9927
9961
|
toJSON() {
|
|
9928
9962
|
return {
|
|
@@ -9936,21 +9970,9 @@ const createRangeNode = /* #__PURE__ */ factory(name$28, ["Node"], ({ Node }) =>
|
|
|
9936
9970
|
return new RangeNode(json.start, json.end, json.step);
|
|
9937
9971
|
}
|
|
9938
9972
|
_toHTML(options) {
|
|
9939
|
-
const
|
|
9940
|
-
const
|
|
9941
|
-
|
|
9942
|
-
let start = this.start.toHTML(options);
|
|
9943
|
-
if (parens.start) start = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + start + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
9944
|
-
str = start;
|
|
9945
|
-
if (this.step) {
|
|
9946
|
-
let step = this.step.toHTML(options);
|
|
9947
|
-
if (parens.step) step = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + step + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
9948
|
-
str += "<span class=\"math-operator math-range-operator\">:</span>" + step;
|
|
9949
|
-
}
|
|
9950
|
-
let end = this.end.toHTML(options);
|
|
9951
|
-
if (parens.end) end = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + end + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
9952
|
-
str += "<span class=\"math-operator math-range-operator\">:</span>" + end;
|
|
9953
|
-
return str;
|
|
9973
|
+
const parenOpen = "<span class=\"math-parenthesis math-round-parenthesis\">(</span>";
|
|
9974
|
+
const parenClose = "<span class=\"math-parenthesis math-round-parenthesis\">)</span>";
|
|
9975
|
+
return formatRangeDisplay(this, options, (child) => child.toHTML(options), (inner) => parenOpen + inner + parenClose, () => "<span class=\"math-operator math-range-operator\">:</span>");
|
|
9954
9976
|
}
|
|
9955
9977
|
_toTex(options) {
|
|
9956
9978
|
const parenthesis = options && options.parenthesis ? options.parenthesis : "keep";
|
|
@@ -9985,6 +10007,18 @@ const createRelationalNode = /* #__PURE__ */ factory(name$27, ["Node"], ({ Node
|
|
|
9985
10007
|
smallerEq: "<=",
|
|
9986
10008
|
largerEq: ">="
|
|
9987
10009
|
};
|
|
10010
|
+
function renderRelational(self, options, renderParam, wrapParam, join) {
|
|
10011
|
+
const parenthesis = options && options.parenthesis ? options.parenthesis : "keep";
|
|
10012
|
+
const precedence = getPrecedence(self, parenthesis, options && options.implicit || "hide", void 0);
|
|
10013
|
+
const paramStrings = self.params.map(function(p) {
|
|
10014
|
+
const paramPrecedence = getPrecedence(p, parenthesis, options && options.implicit || "hide", void 0);
|
|
10015
|
+
const text = renderParam(p);
|
|
10016
|
+
return parenthesis === "all" || paramPrecedence !== null && paramPrecedence <= precedence ? wrapParam(text) : text;
|
|
10017
|
+
});
|
|
10018
|
+
let ret = paramStrings[0];
|
|
10019
|
+
for (let i = 0; i < self.conditionals.length; i++) ret += join(self.conditionals[i], paramStrings[i + 1]);
|
|
10020
|
+
return ret;
|
|
10021
|
+
}
|
|
9988
10022
|
class RelationalNode extends Node {
|
|
9989
10023
|
conditionals;
|
|
9990
10024
|
params;
|
|
@@ -10027,18 +10061,7 @@ const createRelationalNode = /* #__PURE__ */ factory(name$27, ["Node"], ({ Node
|
|
|
10027
10061
|
return new RelationalNode(this.conditionals, this.params);
|
|
10028
10062
|
}
|
|
10029
10063
|
_toString(options) {
|
|
10030
|
-
|
|
10031
|
-
const precedence = getPrecedence(this, parenthesis, options && options.implicit || "hide", void 0);
|
|
10032
|
-
const paramStrings = this.params.map(function(p, _index) {
|
|
10033
|
-
const paramPrecedence = getPrecedence(p, parenthesis, options && options.implicit || "hide", void 0);
|
|
10034
|
-
return parenthesis === "all" || paramPrecedence !== null && paramPrecedence <= precedence ? "(" + p.toString(options) + ")" : p.toString(options);
|
|
10035
|
-
});
|
|
10036
|
-
let ret = paramStrings[0];
|
|
10037
|
-
for (let i = 0; i < this.conditionals.length; i++) {
|
|
10038
|
-
ret += " " + operatorMap[this.conditionals[i]];
|
|
10039
|
-
ret += " " + paramStrings[i + 1];
|
|
10040
|
-
}
|
|
10041
|
-
return ret;
|
|
10064
|
+
return renderRelational(this, options, (p) => p.toString(options), (inner) => "(" + inner + ")", (cond, rhs) => " " + operatorMap[cond] + " " + rhs);
|
|
10042
10065
|
}
|
|
10043
10066
|
toJSON() {
|
|
10044
10067
|
return {
|
|
@@ -10051,15 +10074,7 @@ const createRelationalNode = /* #__PURE__ */ factory(name$27, ["Node"], ({ Node
|
|
|
10051
10074
|
return new RelationalNode(json.conditionals, json.params);
|
|
10052
10075
|
}
|
|
10053
10076
|
_toHTML(options) {
|
|
10054
|
-
|
|
10055
|
-
const precedence = getPrecedence(this, parenthesis, options && options.implicit || "hide", void 0);
|
|
10056
|
-
const paramStrings = this.params.map(function(p, _index) {
|
|
10057
|
-
const paramPrecedence = getPrecedence(p, parenthesis, options && options.implicit || "hide", void 0);
|
|
10058
|
-
return parenthesis === "all" || paramPrecedence !== null && paramPrecedence <= precedence ? "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + p.toHTML(options) + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>" : p.toHTML(options);
|
|
10059
|
-
});
|
|
10060
|
-
let ret = paramStrings[0];
|
|
10061
|
-
for (let i = 0; i < this.conditionals.length; i++) ret += "<span class=\"math-operator math-binary-operator math-explicit-binary-operator\">" + escape(operatorMap[this.conditionals[i]]) + "</span>" + paramStrings[i + 1];
|
|
10062
|
-
return ret;
|
|
10077
|
+
return renderRelational(this, options, (param) => param.toHTML(options), (inner) => "<span class=\"math-parenthesis math-round-parenthesis\">(</span>" + inner + "<span class=\"math-parenthesis math-round-parenthesis\">)</span>", (conditional, rhs) => "<span class=\"math-operator math-binary-operator math-explicit-binary-operator\">" + escape(operatorMap[conditional]) + "</span>" + rhs);
|
|
10063
10078
|
}
|
|
10064
10079
|
_toMathML() {
|
|
10065
10080
|
const params = this.params;
|
|
@@ -10072,15 +10087,8 @@ const createRelationalNode = /* #__PURE__ */ factory(name$27, ["Node"], ({ Node
|
|
|
10072
10087
|
return `<mtext>${escapeMathML(this.toString())}</mtext>`;
|
|
10073
10088
|
}
|
|
10074
10089
|
_toTex(options) {
|
|
10075
|
-
const
|
|
10076
|
-
|
|
10077
|
-
const paramStrings = this.params.map(function(p, _index) {
|
|
10078
|
-
const paramPrecedence = getPrecedence(p, parenthesis, options && options.implicit || "hide", void 0);
|
|
10079
|
-
return parenthesis === "all" || paramPrecedence !== null && paramPrecedence <= precedence ? "\\left(" + p.toTex(options) + "\\right)" : p.toTex(options);
|
|
10080
|
-
});
|
|
10081
|
-
let ret = paramStrings[0];
|
|
10082
|
-
for (let i = 0; i < this.conditionals.length; i++) ret += latexOperators[this.conditionals[i]] + paramStrings[i + 1];
|
|
10083
|
-
return ret;
|
|
10090
|
+
const latex = latexOperators;
|
|
10091
|
+
return renderRelational(this, options, (p) => p.toTex(options), (inner) => "\\left(" + inner + "\\right)", (cond, rhs) => latex[cond] + rhs);
|
|
10084
10092
|
}
|
|
10085
10093
|
}
|
|
10086
10094
|
return RelationalNode;
|
|
@@ -10202,7 +10210,7 @@ const SCALAR_FUNCTIONS = [
|
|
|
10202
10210
|
"tanh",
|
|
10203
10211
|
"abs"
|
|
10204
10212
|
];
|
|
10205
|
-
const LOWERED_FUNCTIONS = new Set(Object.values(SCALAR_FUNCTION_LOWERING));
|
|
10213
|
+
const LOWERED_FUNCTIONS$1 = new Set(Object.values(SCALAR_FUNCTION_LOWERING));
|
|
10206
10214
|
var ScalarBuildError = class extends Error {
|
|
10207
10215
|
constructor(message) {
|
|
10208
10216
|
super(message);
|
|
@@ -10222,8 +10230,8 @@ function isOperator(op) {
|
|
|
10222
10230
|
function isScalarFunctionName(fn) {
|
|
10223
10231
|
return Object.prototype.hasOwnProperty.call(SCALAR_FUNCTION_LOWERING, fn);
|
|
10224
10232
|
}
|
|
10225
|
-
function isLoweredScalarFn(fn) {
|
|
10226
|
-
return LOWERED_FUNCTIONS.has(fn);
|
|
10233
|
+
function isLoweredScalarFn$1(fn) {
|
|
10234
|
+
return LOWERED_FUNCTIONS$1.has(fn);
|
|
10227
10235
|
}
|
|
10228
10236
|
function isCanonicalNode(value) {
|
|
10229
10237
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -10290,7 +10298,7 @@ function createScalarBuilder() {
|
|
|
10290
10298
|
}
|
|
10291
10299
|
case "call": {
|
|
10292
10300
|
const fn = record.fn;
|
|
10293
|
-
if (typeof fn !== "string" || !isLoweredScalarFn(fn)) throw new ScalarBuildError(`scalar call '${String(fn)}' must already use a lowered MathTS name`);
|
|
10301
|
+
if (typeof fn !== "string" || !isLoweredScalarFn$1(fn)) throw new ScalarBuildError(`scalar call '${String(fn)}' must already use a lowered MathTS name`);
|
|
10294
10302
|
return {
|
|
10295
10303
|
kind: "call",
|
|
10296
10304
|
fn,
|
|
@@ -10314,36 +10322,590 @@ function createScalarBuilder() {
|
|
|
10314
10322
|
from
|
|
10315
10323
|
};
|
|
10316
10324
|
}
|
|
10325
|
+
//#endregion
|
|
10326
|
+
//#region src/scalar-structure.ts
|
|
10327
|
+
const LOWERED_FUNCTIONS = new Set(Object.values(SCALAR_FUNCTION_LOWERING));
|
|
10328
|
+
function isLoweredScalarFn(fn) {
|
|
10329
|
+
return LOWERED_FUNCTIONS.has(fn);
|
|
10330
|
+
}
|
|
10331
|
+
function spell(value) {
|
|
10332
|
+
if (Number.isNaN(value)) return "NaN";
|
|
10333
|
+
if (Object.is(value, -0)) return "-0";
|
|
10334
|
+
if (value === Infinity) return "Infinity";
|
|
10335
|
+
if (value === -Infinity) return "-Infinity";
|
|
10336
|
+
return value.toString();
|
|
10337
|
+
}
|
|
10338
|
+
function assertPowerArity(args) {
|
|
10339
|
+
if (args.length !== 2) throw new ScalarBuildError(`'^' needs exactly 2 args, got ${args.length}`);
|
|
10340
|
+
}
|
|
10341
|
+
function assertCallFn(fn) {
|
|
10342
|
+
if (!isLoweredScalarFn(fn)) throw new ScalarBuildError(`unknown scalar function '${String(fn)}'`);
|
|
10343
|
+
return fn;
|
|
10344
|
+
}
|
|
10345
|
+
function forEachScalar(node, visit) {
|
|
10346
|
+
function walk(n, depth) {
|
|
10347
|
+
visit(n, depth);
|
|
10348
|
+
if (n.kind === "call") walk(n.arg, depth + 1);
|
|
10349
|
+
else if (n.kind === "op") for (const child of n.args) walk(child, depth + 1);
|
|
10350
|
+
}
|
|
10351
|
+
walk(node, 0);
|
|
10352
|
+
}
|
|
10353
|
+
function mapScalar(node, fn) {
|
|
10354
|
+
let rebuilt;
|
|
10355
|
+
if (node.kind === "number" || node.kind === "symbol") rebuilt = node;
|
|
10356
|
+
else if (node.kind === "call") {
|
|
10357
|
+
const newArg = mapScalar(node.arg, fn);
|
|
10358
|
+
rebuilt = newArg === node.arg ? node : {
|
|
10359
|
+
kind: "call",
|
|
10360
|
+
fn: node.fn,
|
|
10361
|
+
arg: newArg
|
|
10362
|
+
};
|
|
10363
|
+
} else {
|
|
10364
|
+
const newArgs = node.args.map((child) => mapScalar(child, fn));
|
|
10365
|
+
rebuilt = newArgs.every((child, i) => child === node.args[i]) ? node : {
|
|
10366
|
+
kind: "op",
|
|
10367
|
+
op: node.op,
|
|
10368
|
+
args: newArgs
|
|
10369
|
+
};
|
|
10370
|
+
}
|
|
10371
|
+
const result = fn(rebuilt);
|
|
10372
|
+
if (result === rebuilt && rebuilt === node) return node;
|
|
10373
|
+
return result;
|
|
10374
|
+
}
|
|
10375
|
+
function scalarSize(node) {
|
|
10376
|
+
let count = 0;
|
|
10377
|
+
forEachScalar(node, () => {
|
|
10378
|
+
count += 1;
|
|
10379
|
+
});
|
|
10380
|
+
return count;
|
|
10381
|
+
}
|
|
10382
|
+
function scalarDepth(node) {
|
|
10383
|
+
if (node.kind === "number" || node.kind === "symbol") return 1;
|
|
10384
|
+
if (node.kind === "call") return 1 + scalarDepth(node.arg);
|
|
10385
|
+
if (node.args.length === 0) return 1;
|
|
10386
|
+
let maxChild = 0;
|
|
10387
|
+
for (const child of node.args) {
|
|
10388
|
+
const d = scalarDepth(child);
|
|
10389
|
+
if (d > maxChild) maxChild = d;
|
|
10390
|
+
}
|
|
10391
|
+
return 1 + maxChild;
|
|
10392
|
+
}
|
|
10393
|
+
function ownWeight(record, key) {
|
|
10394
|
+
return record !== void 0 && hasOwnProperty(record, key) ? record[key] ?? 1 : 1;
|
|
10395
|
+
}
|
|
10396
|
+
function symbolWeight(name, weights) {
|
|
10397
|
+
const w = weights.symbol;
|
|
10398
|
+
if (w === void 0) return 1;
|
|
10399
|
+
if (typeof w === "number") return w;
|
|
10400
|
+
return ownWeight(w, name);
|
|
10401
|
+
}
|
|
10402
|
+
function nodeWeight(node, weights) {
|
|
10403
|
+
switch (node.kind) {
|
|
10404
|
+
case "number": return weights.number ?? 1;
|
|
10405
|
+
case "symbol": return symbolWeight(node.name, weights);
|
|
10406
|
+
case "call": return ownWeight(weights.call, node.fn);
|
|
10407
|
+
case "op": return ownWeight(weights.op, node.op);
|
|
10408
|
+
}
|
|
10409
|
+
}
|
|
10410
|
+
function scalarComplexity(node, weights = {}) {
|
|
10411
|
+
let sum = 0;
|
|
10412
|
+
forEachScalar(node, (n) => {
|
|
10413
|
+
sum += nodeWeight(n, weights);
|
|
10414
|
+
});
|
|
10415
|
+
return Math.round(sum);
|
|
10416
|
+
}
|
|
10417
|
+
function scalarSymbols(node) {
|
|
10418
|
+
const names = /* @__PURE__ */ new Set();
|
|
10419
|
+
forEachScalar(node, (n) => {
|
|
10420
|
+
if (n.kind === "symbol") names.add(n.name);
|
|
10421
|
+
});
|
|
10422
|
+
return [...names].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
10423
|
+
}
|
|
10424
|
+
function factorToPowerNode(f) {
|
|
10425
|
+
if (Object.is(f.exp, 1)) return f.base;
|
|
10426
|
+
return {
|
|
10427
|
+
kind: "op",
|
|
10428
|
+
op: "^",
|
|
10429
|
+
args: [f.base, {
|
|
10430
|
+
kind: "number",
|
|
10431
|
+
value: f.exp
|
|
10432
|
+
}]
|
|
10433
|
+
};
|
|
10434
|
+
}
|
|
10435
|
+
function collectFactors(node) {
|
|
10436
|
+
if (node.kind === "op" && node.op === "*") {
|
|
10437
|
+
const out = [];
|
|
10438
|
+
for (const child of node.args) out.push(...collectFactors(child));
|
|
10439
|
+
return out;
|
|
10440
|
+
}
|
|
10441
|
+
if (node.kind === "op" && node.op === "^") {
|
|
10442
|
+
assertPowerArity(node.args);
|
|
10443
|
+
const [base, expNode] = node.args;
|
|
10444
|
+
if (expNode.kind === "number" && Number.isFinite(expNode.value)) return collectFactors(base).map((f) => ({
|
|
10445
|
+
base: f.base,
|
|
10446
|
+
exp: f.exp * expNode.value
|
|
10447
|
+
}));
|
|
10448
|
+
return [{
|
|
10449
|
+
base: node,
|
|
10450
|
+
exp: 1
|
|
10451
|
+
}];
|
|
10452
|
+
}
|
|
10453
|
+
return [{
|
|
10454
|
+
base: node,
|
|
10455
|
+
exp: 1
|
|
10456
|
+
}];
|
|
10457
|
+
}
|
|
10458
|
+
function fullyFlattenFactors(factors) {
|
|
10459
|
+
const out = [];
|
|
10460
|
+
for (const f of factors) out.push(...collectFactors(factorToPowerNode(f)));
|
|
10461
|
+
return out;
|
|
10462
|
+
}
|
|
10463
|
+
function encodeCanonicalKey(node) {
|
|
10464
|
+
switch (node.kind) {
|
|
10465
|
+
case "number": return JSON.stringify({
|
|
10466
|
+
k: "n",
|
|
10467
|
+
v: spell(node.value)
|
|
10468
|
+
});
|
|
10469
|
+
case "symbol": return JSON.stringify({
|
|
10470
|
+
k: "s",
|
|
10471
|
+
v: node.name
|
|
10472
|
+
});
|
|
10473
|
+
case "call": {
|
|
10474
|
+
assertCallFn(node.fn);
|
|
10475
|
+
const argKey = encodeCanonicalKey(node.arg);
|
|
10476
|
+
const obj = {
|
|
10477
|
+
k: "c",
|
|
10478
|
+
f: node.fn,
|
|
10479
|
+
a: JSON.parse(argKey)
|
|
10480
|
+
};
|
|
10481
|
+
return JSON.stringify(obj);
|
|
10482
|
+
}
|
|
10483
|
+
case "op":
|
|
10484
|
+
if (node.op === "^") {
|
|
10485
|
+
assertPowerArity(node.args);
|
|
10486
|
+
const [base, exp] = node.args;
|
|
10487
|
+
const obj = {
|
|
10488
|
+
k: "^",
|
|
10489
|
+
b: JSON.parse(encodeCanonicalKey(base)),
|
|
10490
|
+
e: JSON.parse(encodeCanonicalKey(exp))
|
|
10491
|
+
};
|
|
10492
|
+
return JSON.stringify(obj);
|
|
10493
|
+
}
|
|
10494
|
+
if (node.op === "+" || node.op === "*") {
|
|
10495
|
+
const keys = node.args.map((arg) => encodeCanonicalKey(arg)).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
10496
|
+
const obj = {
|
|
10497
|
+
k: node.op,
|
|
10498
|
+
a: keys.map((k) => JSON.parse(k))
|
|
10499
|
+
};
|
|
10500
|
+
return JSON.stringify(obj);
|
|
10501
|
+
}
|
|
10502
|
+
throw new ScalarBuildError(`scalar canonical: unexpected operator '${node.op}'`);
|
|
10503
|
+
}
|
|
10504
|
+
}
|
|
10505
|
+
function baseKey(node) {
|
|
10506
|
+
return encodeCanonicalKey(node);
|
|
10507
|
+
}
|
|
10508
|
+
function fromProduct(factors) {
|
|
10509
|
+
const flat = fullyFlattenFactors(factors);
|
|
10510
|
+
const coefficients = [];
|
|
10511
|
+
const rest = [];
|
|
10512
|
+
for (const f of flat) if (f.base.kind === "number" && Object.is(f.exp, 1)) coefficients.push(f);
|
|
10513
|
+
else rest.push(f);
|
|
10514
|
+
let coeff = 1;
|
|
10515
|
+
for (const c of coefficients) if (c.base.kind === "number") coeff *= c.base.value;
|
|
10516
|
+
const groups = /* @__PURE__ */ new Map();
|
|
10517
|
+
const groupOrder = [];
|
|
10518
|
+
for (const f of rest) {
|
|
10519
|
+
const key = baseKey(f.base);
|
|
10520
|
+
const existing = groups.get(key);
|
|
10521
|
+
if (existing) existing.sum += f.exp;
|
|
10522
|
+
else {
|
|
10523
|
+
groups.set(key, {
|
|
10524
|
+
base: f.base,
|
|
10525
|
+
sum: f.exp
|
|
10526
|
+
});
|
|
10527
|
+
groupOrder.push(key);
|
|
10528
|
+
}
|
|
10529
|
+
}
|
|
10530
|
+
const materialized = [];
|
|
10531
|
+
for (const key of groupOrder) {
|
|
10532
|
+
const { base, sum } = groups.get(key);
|
|
10533
|
+
if (Object.is(sum, 1)) materialized.push(base);
|
|
10534
|
+
else materialized.push({
|
|
10535
|
+
kind: "op",
|
|
10536
|
+
op: "^",
|
|
10537
|
+
args: [base, {
|
|
10538
|
+
kind: "number",
|
|
10539
|
+
value: sum
|
|
10540
|
+
}]
|
|
10541
|
+
});
|
|
10542
|
+
}
|
|
10543
|
+
const hasOther = materialized.length > 0;
|
|
10544
|
+
if (coefficients.length > 0) {
|
|
10545
|
+
if (!Object.is(coeff, 1) || !hasOther) materialized.push({
|
|
10546
|
+
kind: "number",
|
|
10547
|
+
value: coeff
|
|
10548
|
+
});
|
|
10549
|
+
}
|
|
10550
|
+
if (materialized.length === 0) return {
|
|
10551
|
+
kind: "number",
|
|
10552
|
+
value: 1
|
|
10553
|
+
};
|
|
10554
|
+
if (materialized.length === 1) return materialized[0];
|
|
10555
|
+
return {
|
|
10556
|
+
kind: "op",
|
|
10557
|
+
op: "*",
|
|
10558
|
+
args: materialized.map((node) => ({
|
|
10559
|
+
node,
|
|
10560
|
+
key: encodeCanonicalKey(node)
|
|
10561
|
+
})).sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0).map((entry) => entry.node)
|
|
10562
|
+
};
|
|
10563
|
+
}
|
|
10564
|
+
function fromSum(parts) {
|
|
10565
|
+
const inlined = [];
|
|
10566
|
+
for (const part of parts) if (part.kind === "op" && part.op === "+") inlined.push(...part.args);
|
|
10567
|
+
else inlined.push(part);
|
|
10568
|
+
let numericSum;
|
|
10569
|
+
const nonNumbers = [];
|
|
10570
|
+
for (const part of inlined) if (part.kind === "number") numericSum = numericSum === void 0 ? part.value : numericSum + part.value;
|
|
10571
|
+
else nonNumbers.push(part);
|
|
10572
|
+
const addends = [...nonNumbers];
|
|
10573
|
+
if (numericSum !== void 0) addends.push({
|
|
10574
|
+
kind: "number",
|
|
10575
|
+
value: numericSum
|
|
10576
|
+
});
|
|
10577
|
+
if (addends.length === 0) return {
|
|
10578
|
+
kind: "number",
|
|
10579
|
+
value: 0
|
|
10580
|
+
};
|
|
10581
|
+
if (addends.length === 1) return addends[0];
|
|
10582
|
+
return {
|
|
10583
|
+
kind: "op",
|
|
10584
|
+
op: "+",
|
|
10585
|
+
args: addends.map((node) => ({
|
|
10586
|
+
node,
|
|
10587
|
+
key: encodeCanonicalKey(node)
|
|
10588
|
+
})).sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0).map((entry) => entry.node)
|
|
10589
|
+
};
|
|
10590
|
+
}
|
|
10591
|
+
function canonProductByNumber(node, coeff) {
|
|
10592
|
+
return fromProduct([{
|
|
10593
|
+
base: {
|
|
10594
|
+
kind: "number",
|
|
10595
|
+
value: coeff
|
|
10596
|
+
},
|
|
10597
|
+
exp: 1
|
|
10598
|
+
}, ...collectFactors(node)]);
|
|
10599
|
+
}
|
|
10600
|
+
function inversePower(t) {
|
|
10601
|
+
return {
|
|
10602
|
+
kind: "op",
|
|
10603
|
+
op: "^",
|
|
10604
|
+
args: [t, {
|
|
10605
|
+
kind: "number",
|
|
10606
|
+
value: -1
|
|
10607
|
+
}]
|
|
10608
|
+
};
|
|
10609
|
+
}
|
|
10610
|
+
function canon(node) {
|
|
10611
|
+
switch (node.kind) {
|
|
10612
|
+
case "number":
|
|
10613
|
+
case "symbol": return node;
|
|
10614
|
+
case "call": return {
|
|
10615
|
+
kind: "call",
|
|
10616
|
+
fn: assertCallFn(node.fn),
|
|
10617
|
+
arg: canon(node.arg)
|
|
10618
|
+
};
|
|
10619
|
+
case "op": {
|
|
10620
|
+
const op = node.op;
|
|
10621
|
+
const args = node.args;
|
|
10622
|
+
if (op === "+") {
|
|
10623
|
+
if (args.length === 0) return {
|
|
10624
|
+
kind: "number",
|
|
10625
|
+
value: 0
|
|
10626
|
+
};
|
|
10627
|
+
if (args.length === 1) return canon(args[0]);
|
|
10628
|
+
return fromSum(args.map((a) => canon(a)));
|
|
10629
|
+
}
|
|
10630
|
+
if (op === "-") {
|
|
10631
|
+
if (args.length === 0) return {
|
|
10632
|
+
kind: "number",
|
|
10633
|
+
value: 0
|
|
10634
|
+
};
|
|
10635
|
+
if (args.length === 1) return canon(args[0]);
|
|
10636
|
+
const parts = [canon(args[0])];
|
|
10637
|
+
for (let i = 1; i < args.length; i++) parts.push(canonProductByNumber(canon(args[i]), -1));
|
|
10638
|
+
return fromSum(parts);
|
|
10639
|
+
}
|
|
10640
|
+
if (op === "*") {
|
|
10641
|
+
if (args.length === 0) return {
|
|
10642
|
+
kind: "number",
|
|
10643
|
+
value: 1
|
|
10644
|
+
};
|
|
10645
|
+
if (args.length === 1) return canon(args[0]);
|
|
10646
|
+
const factors = [];
|
|
10647
|
+
for (const a of args) factors.push(...collectFactors(canon(a)));
|
|
10648
|
+
return fromProduct(factors);
|
|
10649
|
+
}
|
|
10650
|
+
if (op === "/") {
|
|
10651
|
+
if (args.length === 0) return {
|
|
10652
|
+
kind: "number",
|
|
10653
|
+
value: 1
|
|
10654
|
+
};
|
|
10655
|
+
if (args.length === 1) return canon(args[0]);
|
|
10656
|
+
let factors = collectFactors(canon(args[0]));
|
|
10657
|
+
for (let i = 1; i < args.length; i++) factors = factors.concat(collectFactors(inversePower(canon(args[i]))));
|
|
10658
|
+
return fromProduct(factors);
|
|
10659
|
+
}
|
|
10660
|
+
if (op === "^") {
|
|
10661
|
+
assertPowerArity(args);
|
|
10662
|
+
const base = canon(args[0]);
|
|
10663
|
+
const expCanon = canon(args[1]);
|
|
10664
|
+
if (expCanon.kind === "number" && Number.isFinite(expCanon.value)) return fromProduct(collectFactors(base).map((f) => ({
|
|
10665
|
+
base: f.base,
|
|
10666
|
+
exp: f.exp * expCanon.value
|
|
10667
|
+
})));
|
|
10668
|
+
return {
|
|
10669
|
+
kind: "op",
|
|
10670
|
+
op: "^",
|
|
10671
|
+
args: [base, expCanon]
|
|
10672
|
+
};
|
|
10673
|
+
}
|
|
10674
|
+
throw new ScalarBuildError(`unknown scalar operator '${String(op)}'`);
|
|
10675
|
+
}
|
|
10676
|
+
}
|
|
10677
|
+
}
|
|
10678
|
+
function scalarCanonical(node) {
|
|
10679
|
+
return canon(node);
|
|
10680
|
+
}
|
|
10681
|
+
function scalarCanonicalKey(node) {
|
|
10682
|
+
return encodeCanonicalKey(scalarCanonical(node));
|
|
10683
|
+
}
|
|
10684
|
+
function scalarEquals(a, b) {
|
|
10685
|
+
return scalarCanonicalKey(a) === scalarCanonicalKey(b);
|
|
10686
|
+
}
|
|
10687
|
+
//#endregion
|
|
10688
|
+
//#region src/scalar-enumerate.ts
|
|
10689
|
+
function nodeOperatorName(node) {
|
|
10690
|
+
if (node.kind === "op") return node.op;
|
|
10691
|
+
if (node.kind === "call") return node.fn;
|
|
10692
|
+
return null;
|
|
10693
|
+
}
|
|
10694
|
+
function countNamedInSubtree(root, inner) {
|
|
10695
|
+
let count = 0;
|
|
10696
|
+
function walk(n, isRoot) {
|
|
10697
|
+
if (!isRoot && nodeOperatorName(n) === inner) count += 1;
|
|
10698
|
+
if (n.kind === "call") walk(n.arg, false);
|
|
10699
|
+
else if (n.kind === "op") for (const child of n.args) walk(child, false);
|
|
10700
|
+
}
|
|
10701
|
+
walk(root, true);
|
|
10702
|
+
return count;
|
|
10703
|
+
}
|
|
10704
|
+
function argumentLimitsOk(node, argumentLimits) {
|
|
10705
|
+
const name = nodeOperatorName(node);
|
|
10706
|
+
if (name === null || !hasOwnProperty(argumentLimits, name)) return true;
|
|
10707
|
+
const limits = argumentLimits[name];
|
|
10708
|
+
if (node.kind === "call") {
|
|
10709
|
+
const cap = limits[0];
|
|
10710
|
+
if (cap !== void 0 && cap !== -1 && scalarSize(node.arg) > cap) return false;
|
|
10711
|
+
return true;
|
|
10712
|
+
}
|
|
10713
|
+
if (node.kind === "op") for (let i = 0; i < node.args.length; i += 1) {
|
|
10714
|
+
const cap = limits[i];
|
|
10715
|
+
if (cap !== void 0 && cap !== -1 && scalarSize(node.args[i]) > cap) return false;
|
|
10716
|
+
}
|
|
10717
|
+
return true;
|
|
10718
|
+
}
|
|
10719
|
+
function nestingOk(node, nesting) {
|
|
10720
|
+
let ok = true;
|
|
10721
|
+
forEachScalar(node, (sub) => {
|
|
10722
|
+
const outer = nodeOperatorName(sub);
|
|
10723
|
+
if (outer === null || !hasOwnProperty(nesting, outer)) return;
|
|
10724
|
+
const innerLimits = nesting[outer];
|
|
10725
|
+
for (const inner of Object.keys(innerLimits)) {
|
|
10726
|
+
if (!hasOwnProperty(innerLimits, inner)) continue;
|
|
10727
|
+
const max = innerLimits[inner];
|
|
10728
|
+
if (countNamedInSubtree(sub, inner) > max) ok = false;
|
|
10729
|
+
}
|
|
10730
|
+
});
|
|
10731
|
+
return ok;
|
|
10732
|
+
}
|
|
10733
|
+
function symbolAllowed(grammar, name) {
|
|
10734
|
+
if (grammar.variables.includes(name)) return true;
|
|
10735
|
+
const params = grammar.parameters;
|
|
10736
|
+
return params !== void 0 && params.includes(name);
|
|
10737
|
+
}
|
|
10738
|
+
function nodeStructureOk(grammar, node) {
|
|
10739
|
+
switch (node.kind) {
|
|
10740
|
+
case "number": return Number.isFinite(node.value);
|
|
10741
|
+
case "symbol": return symbolAllowed(grammar, node.name);
|
|
10742
|
+
case "call":
|
|
10743
|
+
if (!grammar.unary.includes(node.fn)) return false;
|
|
10744
|
+
return nodeStructureOk(grammar, node.arg);
|
|
10745
|
+
case "op":
|
|
10746
|
+
if (!grammar.binary.includes(node.op)) return false;
|
|
10747
|
+
if (node.args.length !== 2) return false;
|
|
10748
|
+
return nodeStructureOk(grammar, node.args[0]) && nodeStructureOk(grammar, node.args[1]);
|
|
10749
|
+
}
|
|
10750
|
+
}
|
|
10751
|
+
function scalarGrammarAccepts(grammar, node) {
|
|
10752
|
+
if (!nodeStructureOk(grammar, node)) return false;
|
|
10753
|
+
if (!(scalarSize(node) <= grammar.maxSize)) return false;
|
|
10754
|
+
const maxDepth = grammar.maxDepth;
|
|
10755
|
+
if (maxDepth !== void 0 && !(scalarDepth(node) <= maxDepth)) return false;
|
|
10756
|
+
if (grammar.argumentLimits !== void 0) {
|
|
10757
|
+
let limitsOk = true;
|
|
10758
|
+
forEachScalar(node, (sub) => {
|
|
10759
|
+
if (!argumentLimitsOk(sub, grammar.argumentLimits)) limitsOk = false;
|
|
10760
|
+
});
|
|
10761
|
+
if (!limitsOk) return false;
|
|
10762
|
+
}
|
|
10763
|
+
if (grammar.nesting !== void 0 && !nestingOk(node, grammar.nesting)) return false;
|
|
10764
|
+
return true;
|
|
10765
|
+
}
|
|
10766
|
+
const INTERRUPT_CHECK_INTERVAL = 128;
|
|
10767
|
+
function assertEnumerationInputs(grammar, budget) {
|
|
10768
|
+
if (Number.isNaN(grammar.maxSize)) throw new RangeError("enumerateScalars: grammar.maxSize must not be NaN");
|
|
10769
|
+
if (grammar.maxDepth !== void 0 && Number.isNaN(grammar.maxDepth)) throw new RangeError("enumerateScalars: grammar.maxDepth must not be NaN");
|
|
10770
|
+
if (Number.isNaN(budget.maxCandidates) || budget.maxCandidates < 0) throw new RangeError("enumerateScalars: budget.maxCandidates must be a number >= 0");
|
|
10771
|
+
if (budget.maxWallClockMs !== void 0 && Number.isNaN(budget.maxWallClockMs)) throw new RangeError("enumerateScalars: budget.maxWallClockMs must not be NaN");
|
|
10772
|
+
}
|
|
10773
|
+
function* enumerateScalars(grammar, budget, signal) {
|
|
10774
|
+
assertEnumerationInputs(grammar, budget);
|
|
10775
|
+
const b = createScalarBuilder();
|
|
10776
|
+
const yieldedKeys = /* @__PURE__ */ new Set();
|
|
10777
|
+
const pooledKeys = /* @__PURE__ */ new Set();
|
|
10778
|
+
const pool = [];
|
|
10779
|
+
const bySize = [];
|
|
10780
|
+
let yieldCount = 0;
|
|
10781
|
+
let sinceCheck = 0;
|
|
10782
|
+
const start = performance.now();
|
|
10783
|
+
const admitMonotone = grammar.admitMonotone === true;
|
|
10784
|
+
const interrupted = () => {
|
|
10785
|
+
if (signal?.aborted) return "cancelled";
|
|
10786
|
+
if (budget.maxWallClockMs !== void 0 && performance.now() - start >= budget.maxWallClockMs) return "time-limit";
|
|
10787
|
+
return null;
|
|
10788
|
+
};
|
|
10789
|
+
const addToPool = (node, size, key) => {
|
|
10790
|
+
if (pooledKeys.has(key)) return;
|
|
10791
|
+
pooledKeys.add(key);
|
|
10792
|
+
const entry = {
|
|
10793
|
+
node,
|
|
10794
|
+
size
|
|
10795
|
+
};
|
|
10796
|
+
pool.push(entry);
|
|
10797
|
+
(bySize[size] ??= []).push(entry);
|
|
10798
|
+
};
|
|
10799
|
+
const consider = function* (node, size) {
|
|
10800
|
+
sinceCheck += 1;
|
|
10801
|
+
if (sinceCheck >= INTERRUPT_CHECK_INTERVAL) {
|
|
10802
|
+
sinceCheck = 0;
|
|
10803
|
+
const stop = interrupted();
|
|
10804
|
+
if (stop !== null) return stop;
|
|
10805
|
+
}
|
|
10806
|
+
if (!scalarGrammarAccepts(grammar, node)) return "ok";
|
|
10807
|
+
const key = scalarCanonicalKey(node);
|
|
10808
|
+
if (yieldedKeys.has(key)) return "ok";
|
|
10809
|
+
if (!(grammar.admit === void 0 || grammar.admit(node))) {
|
|
10810
|
+
if (!admitMonotone) addToPool(node, size, key);
|
|
10811
|
+
return "ok";
|
|
10812
|
+
}
|
|
10813
|
+
const stop = interrupted() ?? (yieldCount >= budget.maxCandidates ? "candidate-limit" : null);
|
|
10814
|
+
if (stop !== null) return stop;
|
|
10815
|
+
sinceCheck = 0;
|
|
10816
|
+
addToPool(node, size, key);
|
|
10817
|
+
yieldedKeys.add(key);
|
|
10818
|
+
yieldCount += 1;
|
|
10819
|
+
yield node;
|
|
10820
|
+
return "ok";
|
|
10821
|
+
};
|
|
10822
|
+
for (let size = 1; size <= grammar.maxSize; size += 1) {
|
|
10823
|
+
if (size === 1) {
|
|
10824
|
+
const leaves = [];
|
|
10825
|
+
for (const name of grammar.variables) leaves.push(b.symbol(name));
|
|
10826
|
+
for (const name of grammar.parameters ?? []) leaves.push(b.symbol(name));
|
|
10827
|
+
for (const value of grammar.literals ?? []) leaves.push(b.number(value));
|
|
10828
|
+
for (const leaf of leaves) {
|
|
10829
|
+
const stop = yield* consider(leaf, 1);
|
|
10830
|
+
if (stop !== "ok") return stop;
|
|
10831
|
+
}
|
|
10832
|
+
continue;
|
|
10833
|
+
}
|
|
10834
|
+
const poolAtStart = pool.length;
|
|
10835
|
+
for (const op of grammar.binary) for (let i = 0; i < poolAtStart; i += 1) {
|
|
10836
|
+
const left = pool[i];
|
|
10837
|
+
const rightSize = size - 1 - left.size;
|
|
10838
|
+
if (rightSize < 1) continue;
|
|
10839
|
+
for (const right of bySize[rightSize] ?? []) {
|
|
10840
|
+
const stop = yield* consider(b.op(op, [left.node, right.node]), size);
|
|
10841
|
+
if (stop !== "ok") return stop;
|
|
10842
|
+
}
|
|
10843
|
+
}
|
|
10844
|
+
for (const fn of grammar.unary) for (const arg of bySize[size - 1] ?? []) {
|
|
10845
|
+
const stop = yield* consider({
|
|
10846
|
+
kind: "call",
|
|
10847
|
+
fn,
|
|
10848
|
+
arg: arg.node
|
|
10849
|
+
}, size);
|
|
10850
|
+
if (stop !== "ok") return stop;
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
return "exhausted-space";
|
|
10854
|
+
}
|
|
10855
|
+
//#endregion
|
|
10856
|
+
//#region src/transform/utils/shortCircuitBinary.ts
|
|
10857
|
+
function evalShortCircuitBinary(args, scope, op, absorb) {
|
|
10858
|
+
const left = args[0].compile().evaluate(scope);
|
|
10859
|
+
if (!isCollection(left)) {
|
|
10860
|
+
const early = absorb(left);
|
|
10861
|
+
if (early.take) return early.value;
|
|
10862
|
+
}
|
|
10863
|
+
return op(left, args[1].compile().evaluate(scope));
|
|
10864
|
+
}
|
|
10317
10865
|
const createAndTransform = /* #__PURE__ */ factory("and", ["and"], ({ and }) => {
|
|
10318
10866
|
function andTransform(args, _math, scope) {
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10867
|
+
return evalShortCircuitBinary(args, scope, and, (left) => !and(left, true) ? {
|
|
10868
|
+
take: true,
|
|
10869
|
+
value: false
|
|
10870
|
+
} : { take: false });
|
|
10322
10871
|
}
|
|
10323
10872
|
andTransform.rawArgs = true;
|
|
10324
10873
|
return andTransform;
|
|
10325
10874
|
}, { isTransformFunction: true });
|
|
10326
10875
|
const createBitAndTransform = /* #__PURE__ */ factory("bitAnd", ["bitAnd"], ({ bitAnd }) => {
|
|
10327
10876
|
function bitAndTransform(args, _math, scope) {
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10877
|
+
return evalShortCircuitBinary(args, scope, bitAnd, (left) => {
|
|
10878
|
+
if (isNaN(left)) return {
|
|
10879
|
+
take: true,
|
|
10880
|
+
value: NaN
|
|
10881
|
+
};
|
|
10882
|
+
if (left === 0 || left === false) return {
|
|
10883
|
+
take: true,
|
|
10884
|
+
value: 0
|
|
10885
|
+
};
|
|
10886
|
+
return { take: false };
|
|
10887
|
+
});
|
|
10334
10888
|
}
|
|
10335
10889
|
bitAndTransform.rawArgs = true;
|
|
10336
10890
|
return bitAndTransform;
|
|
10337
10891
|
}, { isTransformFunction: true });
|
|
10338
10892
|
const createBitOrTransform = /* #__PURE__ */ factory("bitOr", ["bitOr"], ({ bitOr }) => {
|
|
10339
10893
|
function bitOrTransform(args, _math, scope) {
|
|
10340
|
-
|
|
10341
|
-
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
|
|
10894
|
+
return evalShortCircuitBinary(args, scope, bitOr, (left) => {
|
|
10895
|
+
if (isNaN(left)) return {
|
|
10896
|
+
take: true,
|
|
10897
|
+
value: NaN
|
|
10898
|
+
};
|
|
10899
|
+
if (left === -1) return {
|
|
10900
|
+
take: true,
|
|
10901
|
+
value: -1
|
|
10902
|
+
};
|
|
10903
|
+
if (left === true) return {
|
|
10904
|
+
take: true,
|
|
10905
|
+
value: 1
|
|
10906
|
+
};
|
|
10907
|
+
return { take: false };
|
|
10908
|
+
});
|
|
10347
10909
|
}
|
|
10348
10910
|
bitOrTransform.rawArgs = true;
|
|
10349
10911
|
return bitOrTransform;
|
|
@@ -10374,28 +10936,15 @@ const createConcatTransform = /* #__PURE__ */ factory("concat", ["typed", "conca
|
|
|
10374
10936
|
} });
|
|
10375
10937
|
}, { isTransformFunction: true });
|
|
10376
10938
|
//#endregion
|
|
10377
|
-
//#region src/transform/cumsum.transform.ts
|
|
10378
|
-
const name$20 = "cumsum";
|
|
10379
|
-
const createCumSumTransform = /* #__PURE__ */ factory(name$20, ["typed", "cumsum"], ({ typed, cumsum }) => {
|
|
10380
|
-
return typed(name$20, { "...any": function(args) {
|
|
10381
|
-
if (args.length === 2 && isCollection(args[0])) {
|
|
10382
|
-
const dim = args[1];
|
|
10383
|
-
if (isNumber(dim)) args[1] = dim - 1;
|
|
10384
|
-
else if (isBigNumber(dim)) args[1] = dim.minus(1);
|
|
10385
|
-
}
|
|
10386
|
-
try {
|
|
10387
|
-
return cumsum(...args);
|
|
10388
|
-
} catch (err) {
|
|
10389
|
-
throw errorTransform(err);
|
|
10390
|
-
}
|
|
10391
|
-
} });
|
|
10392
|
-
}, { isTransformFunction: true });
|
|
10393
|
-
//#endregion
|
|
10394
10939
|
//#region src/transform/utils/dimToZeroBase.ts
|
|
10395
10940
|
function dimToZeroBase(dim) {
|
|
10396
10941
|
if (isNumber(dim)) return dim - 1;
|
|
10397
|
-
else if (isBigNumber(dim))
|
|
10398
|
-
|
|
10942
|
+
else if (isBigNumber(dim)) {
|
|
10943
|
+
const bn = dim;
|
|
10944
|
+
if (typeof bn.sub === "function") return bn.sub(1);
|
|
10945
|
+
if (typeof bn.minus === "function") return bn.minus(1);
|
|
10946
|
+
return dim;
|
|
10947
|
+
} else return dim;
|
|
10399
10948
|
}
|
|
10400
10949
|
function isNumberOrBigNumber(n) {
|
|
10401
10950
|
return isNumber(n) || isBigNumber(n);
|
|
@@ -10411,6 +10960,19 @@ function lastDimToZeroBase(args) {
|
|
|
10411
10960
|
return args;
|
|
10412
10961
|
}
|
|
10413
10962
|
//#endregion
|
|
10963
|
+
//#region src/transform/cumsum.transform.ts
|
|
10964
|
+
const name$20 = "cumsum";
|
|
10965
|
+
const createCumSumTransform = /* #__PURE__ */ factory(name$20, ["typed", "cumsum"], ({ typed, cumsum }) => {
|
|
10966
|
+
return typed(name$20, { "...any": function(args) {
|
|
10967
|
+
args = lastDimToZeroBase(args);
|
|
10968
|
+
try {
|
|
10969
|
+
return cumsum(...args);
|
|
10970
|
+
} catch (err) {
|
|
10971
|
+
throw errorTransform(err);
|
|
10972
|
+
}
|
|
10973
|
+
} });
|
|
10974
|
+
}, { isTransformFunction: true });
|
|
10975
|
+
//#endregion
|
|
10414
10976
|
//#region src/transform/diff.transform.ts
|
|
10415
10977
|
const name$19 = "diff";
|
|
10416
10978
|
const createDiffTransform = /* #__PURE__ */ factory(name$19, ["typed", "diff"], ({ typed, diff }) => {
|
|
@@ -10440,6 +11002,33 @@ function compileInlineExpression(expression, math, scope) {
|
|
|
10440
11002
|
return eq.evaluate(subScope);
|
|
10441
11003
|
};
|
|
10442
11004
|
}
|
|
11005
|
+
//#endregion
|
|
11006
|
+
//#region src/transform/utils/prepareTransformArgs.ts
|
|
11007
|
+
function compileAndEvaluate(arg, scope) {
|
|
11008
|
+
return arg.compile().evaluate(scope);
|
|
11009
|
+
}
|
|
11010
|
+
function prepareTransformArrayAndCallback(args, math, scope) {
|
|
11011
|
+
const callbackArity = args.length - 1;
|
|
11012
|
+
let x = args[0];
|
|
11013
|
+
let callback = args[callbackArity];
|
|
11014
|
+
if (x) x = compileAndEvaluate(x, scope);
|
|
11015
|
+
if (callback) {
|
|
11016
|
+
if (isSymbolNode(callback) || isFunctionAssignmentNode(callback)) callback = compileAndEvaluate(callback, scope);
|
|
11017
|
+
else callback = compileInlineExpression(callback, math, scope);
|
|
11018
|
+
}
|
|
11019
|
+
return {
|
|
11020
|
+
x,
|
|
11021
|
+
callback,
|
|
11022
|
+
callbackArity
|
|
11023
|
+
};
|
|
11024
|
+
}
|
|
11025
|
+
function applyArrayCallbackTransform(args, math, scope, op, transformCallback) {
|
|
11026
|
+
if (args.length === 0) return op();
|
|
11027
|
+
const x = args[0];
|
|
11028
|
+
if (args.length === 1) return op(x);
|
|
11029
|
+
const prepared = prepareTransformArrayAndCallback(args, math, scope);
|
|
11030
|
+
return op(prepared.x, transformCallback(prepared.callback, prepared.callbackArity));
|
|
11031
|
+
}
|
|
10443
11032
|
const createTransformCallback = /* #__PURE__ */ factory("transformCallback", ["typed"], ({ typed }) => {
|
|
10444
11033
|
return function(callback, numberOfArrays) {
|
|
10445
11034
|
if (typed.isTypedFunction(callback)) return _transformTypedCallbackFunction(callback, numberOfArrays);
|
|
@@ -10479,45 +11068,19 @@ function _transformDims(dims) {
|
|
|
10479
11068
|
return dims.map((dim) => dim + 1);
|
|
10480
11069
|
}
|
|
10481
11070
|
const createFilterTransform = /* #__PURE__ */ factory("filter", ["typed", "filter"], ({ typed, filter }) => {
|
|
11071
|
+
const transformCallback = createTransformCallback({ typed });
|
|
10482
11072
|
function filterTransform(args, math, scope) {
|
|
10483
|
-
|
|
10484
|
-
if (args.length === 0) return filter();
|
|
10485
|
-
let x = args[0];
|
|
10486
|
-
if (args.length === 1) return filter(x);
|
|
10487
|
-
const N = args.length - 1;
|
|
10488
|
-
let callback = args[N];
|
|
10489
|
-
if (x) x = _compileAndEvaluate(x, scope);
|
|
10490
|
-
if (callback) {
|
|
10491
|
-
if (isSymbolNode(callback) || isFunctionAssignmentNode(callback)) callback = _compileAndEvaluate(callback, scope);
|
|
10492
|
-
else callback = compileInlineExpression(callback, math, scope);
|
|
10493
|
-
}
|
|
10494
|
-
return filter(x, transformCallback(callback, N));
|
|
11073
|
+
return applyArrayCallbackTransform(args, math, scope, filter, transformCallback);
|
|
10495
11074
|
}
|
|
10496
11075
|
filterTransform.rawArgs = true;
|
|
10497
|
-
function _compileAndEvaluate(arg, scope) {
|
|
10498
|
-
return arg.compile().evaluate(scope);
|
|
10499
|
-
}
|
|
10500
11076
|
return filterTransform;
|
|
10501
11077
|
}, { isTransformFunction: true });
|
|
10502
11078
|
const createForEachTransform = /* #__PURE__ */ factory("forEach", ["typed", "forEach"], ({ typed, forEach }) => {
|
|
10503
11079
|
const transformCallback = createTransformCallback({ typed });
|
|
10504
11080
|
function forEachTransform(args, math, scope) {
|
|
10505
|
-
|
|
10506
|
-
let x = args[0];
|
|
10507
|
-
if (args.length === 1) return forEach(x);
|
|
10508
|
-
const N = args.length - 1;
|
|
10509
|
-
let callback = args[N];
|
|
10510
|
-
if (x) x = _compileAndEvaluate(x, scope);
|
|
10511
|
-
if (callback) {
|
|
10512
|
-
if (isSymbolNode(callback) || isFunctionAssignmentNode(callback)) callback = _compileAndEvaluate(callback, scope);
|
|
10513
|
-
else callback = compileInlineExpression(callback, math, scope);
|
|
10514
|
-
}
|
|
10515
|
-
return forEach(x, transformCallback(callback, N));
|
|
11081
|
+
return applyArrayCallbackTransform(args, math, scope, forEach, transformCallback);
|
|
10516
11082
|
}
|
|
10517
11083
|
forEachTransform.rawArgs = true;
|
|
10518
|
-
function _compileAndEvaluate(arg, scope) {
|
|
10519
|
-
return arg.compile().evaluate(scope);
|
|
10520
|
-
}
|
|
10521
11084
|
return forEachTransform;
|
|
10522
11085
|
}, { isTransformFunction: true });
|
|
10523
11086
|
const createIndexTransform = /* #__PURE__ */ factory("index", ["Index", "getMatrixDataType"], ({ Index, getMatrixDataType }) => {
|
|
@@ -10567,8 +11130,7 @@ const createMapTransform = /* #__PURE__ */ factory("map", ["typed", "map"], ({ t
|
|
|
10567
11130
|
const createMapSlicesTransform = /* #__PURE__ */ factory("mapSlices", ["typed", "mapSlices"], ({ typed, mapSlices }) => {
|
|
10568
11131
|
return typed("mapSlices", { "...any": function(args) {
|
|
10569
11132
|
const dim = args[1];
|
|
10570
|
-
if (
|
|
10571
|
-
else if (isBigNumber(dim)) args[1] = dim.minus(1);
|
|
11133
|
+
if (isNumberOrBigNumber(dim)) args[1] = dimToZeroBase(dim);
|
|
10572
11134
|
try {
|
|
10573
11135
|
return mapSlices(...args);
|
|
10574
11136
|
} catch (err) {
|
|
@@ -10617,9 +11179,10 @@ const createNullishTransform = /* #__PURE__ */ factory("nullish", ["nullish"], (
|
|
|
10617
11179
|
}, { isTransformFunction: true });
|
|
10618
11180
|
const createOrTransform = /* #__PURE__ */ factory("or", ["or"], ({ or }) => {
|
|
10619
11181
|
function orTransform(args, _math, scope) {
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
11182
|
+
return evalShortCircuitBinary(args, scope, or, (left) => or(left, false) ? {
|
|
11183
|
+
take: true,
|
|
11184
|
+
value: true
|
|
11185
|
+
} : { take: false });
|
|
10623
11186
|
}
|
|
10624
11187
|
orTransform.rawArgs = true;
|
|
10625
11188
|
return orTransform;
|
|
@@ -10727,4 +11290,4 @@ const createVarianceTransform = /* #__PURE__ */ factory(name, ["typed", "varianc
|
|
|
10727
11290
|
} });
|
|
10728
11291
|
}, { isTransformFunction: true });
|
|
10729
11292
|
//#endregion
|
|
10730
|
-
export { SCALAR_FUNCTIONS, SCALAR_FUNCTION_LOWERING, ScalarBuildError, compile, compileExpression, createAccessorNode, createAndTransform, createArrayNode, createAssignmentNode, createBitAndTransform, createBitOrTransform, createBlockNode, createColumnTransform, createConcatTransform, createConditionalNode, createConstantNode, createCumSumTransform, createDiffTransform, createEvaluate, createFilterTransform, createForEachTransform, createFunctionAssignmentNode, createFunctionNode, createHelpClass, createIndexNode, createIndexTransform, createMapSlicesTransform, createMapTransform, createMaxTransform, createMeanTransform, createMinTransform, createNode, createNullishTransform, createObjectNode, createOperatorNode, createOrTransform, createParenthesisNode, createParse, createParser, createParserClass, createPrintTransform, createQuantileSeqTransform, createRangeNode, createRangeTransform, createRelationalNode, createRowTransform, createScalarBuilder, createStdTransform, createSubsetTransform, createSumTransform, createSymbolNode, createVarianceTransform, embeddedDocs, escapeMathML, getAssociativity, getOperator, getPrecedence, isAssociativeWith, keywords, mathMLDocument, mathMLError, properties, toMathMLSymbol };
|
|
11293
|
+
export { SCALAR_FUNCTIONS, SCALAR_FUNCTION_LOWERING, ScalarBuildError, compile, compileExpression, createAccessorNode, createAndTransform, createArrayNode, createAssignmentNode, createBitAndTransform, createBitOrTransform, createBlockNode, createColumnTransform, createConcatTransform, createConditionalNode, createConstantNode, createCumSumTransform, createDiffTransform, createEvaluate, createFilterTransform, createForEachTransform, createFunctionAssignmentNode, createFunctionNode, createHelpClass, createIndexNode, createIndexTransform, createMapSlicesTransform, createMapTransform, createMaxTransform, createMeanTransform, createMinTransform, createNode, createNullishTransform, createObjectNode, createOperatorNode, createOrTransform, createParenthesisNode, createParse, createParser, createParserClass, createPrintTransform, createQuantileSeqTransform, createRangeNode, createRangeTransform, createRelationalNode, createRowTransform, createScalarBuilder, createStdTransform, createSubsetTransform, createSumTransform, createSymbolNode, createVarianceTransform, embeddedDocs, enumerateScalars, escapeMathML, forEachScalar, getAssociativity, getOperator, getPrecedence, getStringSubset, isAssociativeWith, keywords, mapScalar, mathMLDocument, mathMLError, properties, scalarCanonical, scalarCanonicalKey, scalarComplexity, scalarDepth, scalarEquals, scalarGrammarAccepts, scalarSize, scalarSymbols, setStringSubset, toMathMLSymbol };
|