resolve.js (3322B)
1 "use strict"; 2 3 Object.defineProperty(exports, "__esModule", { 4 value: true 5 }); 6 exports.createResolve = void 0; 7 8 var _map = require("../../utils/map.js"); 9 10 var _is = require("../../utils/is.js"); 11 12 var _factory = require("../../utils/factory.js"); 13 14 var name = 'resolve'; 15 var dependencies = ['parse', 'ConstantNode', 'FunctionNode', 'OperatorNode', 'ParenthesisNode']; 16 var createResolve = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { 17 var parse = _ref.parse, 18 ConstantNode = _ref.ConstantNode, 19 FunctionNode = _ref.FunctionNode, 20 OperatorNode = _ref.OperatorNode, 21 ParenthesisNode = _ref.ParenthesisNode; 22 23 /** 24 * resolve(expr, scope) replaces variable nodes with their scoped values 25 * 26 * Syntax: 27 * 28 * resolve(expr, scope) 29 * 30 * Examples: 31 * 32 * math.resolve('x + y', {x:1, y:2}) // Node {1 + 2} 33 * math.resolve(math.parse('x+y'), {x:1, y:2}) // Node {1 + 2} 34 * math.simplify('x+y', {x:2, y:'x+x'}).toString() // "6" 35 * 36 * See also: 37 * 38 * simplify, evaluate 39 * 40 * @param {Node} node 41 * The expression tree to be simplified 42 * @param {Object} scope 43 * Scope specifying variables to be resolved 44 * @return {Node} Returns `node` with variables recursively substituted. 45 * @throws {ReferenceError} 46 * If there is a cyclic dependency among the variables in `scope`, 47 * resolution is impossible and a ReferenceError is thrown. 48 */ 49 function resolve(node, scope) { 50 var within = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Set(); 51 52 // note `within`: 53 // `within` is not documented, since it is for internal cycle 54 // detection only 55 if (!scope) { 56 return node; 57 } 58 59 if (!(0, _map.isMap)(scope)) { 60 scope = (0, _map.createMap)(scope); 61 } 62 63 if ((0, _is.isSymbolNode)(node)) { 64 if (within.has(node.name)) { 65 var variables = Array.from(within).join(', '); 66 throw new ReferenceError("recursive loop of variable definitions among {".concat(variables, "}")); 67 } 68 69 var value = scope.get(node.name); 70 71 if ((0, _is.isNode)(value)) { 72 var nextWithin = new Set(within); 73 nextWithin.add(node.name); 74 return resolve(value, scope, nextWithin); 75 } else if (typeof value === 'number') { 76 return parse(String(value)); 77 } else if (value !== undefined) { 78 return new ConstantNode(value); 79 } else { 80 return node; 81 } 82 } else if ((0, _is.isOperatorNode)(node)) { 83 var args = node.args.map(function (arg) { 84 return resolve(arg, scope, within); 85 }); 86 return new OperatorNode(node.op, node.fn, args, node.implicit); 87 } else if ((0, _is.isParenthesisNode)(node)) { 88 return new ParenthesisNode(resolve(node.content, scope, within)); 89 } else if ((0, _is.isFunctionNode)(node)) { 90 var _args = node.args.map(function (arg) { 91 return resolve(arg, scope, within); 92 }); 93 94 return new FunctionNode(node.name, _args); 95 } // Otherwise just recursively resolve any children (might also work 96 // for some of the above special cases) 97 98 99 return node.map(function (child) { 100 return resolve(child, scope, within); 101 }); 102 } 103 104 return resolve; 105 }); 106 exports.createResolve = createResolve;