RelationalNode.js (7988B)
1 "use strict"; 2 3 Object.defineProperty(exports, "__esModule", { 4 value: true 5 }); 6 exports.createRelationalNode = void 0; 7 8 var _operators = require("../operators.js"); 9 10 var _string = require("../../utils/string.js"); 11 12 var _customs = require("../../utils/customs.js"); 13 14 var _latex = require("../../utils/latex.js"); 15 16 var _factory = require("../../utils/factory.js"); 17 18 var name = 'RelationalNode'; 19 var dependencies = ['Node']; 20 var createRelationalNode = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { 21 var Node = _ref.Node; 22 23 /** 24 * A node representing a chained conditional expression, such as 'x > y > z' 25 * 26 * @param {String[]} conditionals An array of conditional operators used to compare the parameters 27 * @param {Node[]} params The parameters that will be compared 28 * 29 * @constructor RelationalNode 30 * @extends {Node} 31 */ 32 function RelationalNode(conditionals, params) { 33 if (!(this instanceof RelationalNode)) { 34 throw new SyntaxError('Constructor must be called with the new operator'); 35 } 36 37 if (!Array.isArray(conditionals)) throw new TypeError('Parameter conditionals must be an array'); 38 if (!Array.isArray(params)) throw new TypeError('Parameter params must be an array'); 39 if (conditionals.length !== params.length - 1) throw new TypeError('Parameter params must contain exactly one more element than parameter conditionals'); 40 this.conditionals = conditionals; 41 this.params = params; 42 } 43 44 RelationalNode.prototype = new Node(); 45 RelationalNode.prototype.type = 'RelationalNode'; 46 RelationalNode.prototype.isRelationalNode = true; 47 /** 48 * Compile a node into a JavaScript function. 49 * This basically pre-calculates as much as possible and only leaves open 50 * calculations which depend on a dynamic scope with variables. 51 * @param {Object} math Math.js namespace with functions and constants. 52 * @param {Object} argNames An object with argument names as key and `true` 53 * as value. Used in the SymbolNode to optimize 54 * for arguments from user assigned functions 55 * (see FunctionAssignmentNode) or special symbols 56 * like `end` (see IndexNode). 57 * @return {function} Returns a function which can be called like: 58 * evalNode(scope: Object, args: Object, context: *) 59 */ 60 61 RelationalNode.prototype._compile = function (math, argNames) { 62 var self = this; 63 var compiled = this.params.map(function (p) { 64 return p._compile(math, argNames); 65 }); 66 return function evalRelationalNode(scope, args, context) { 67 var evalLhs; 68 var evalRhs = compiled[0](scope, args, context); 69 70 for (var i = 0; i < self.conditionals.length; i++) { 71 evalLhs = evalRhs; 72 evalRhs = compiled[i + 1](scope, args, context); 73 var condFn = (0, _customs.getSafeProperty)(math, self.conditionals[i]); 74 75 if (!condFn(evalLhs, evalRhs)) { 76 return false; 77 } 78 } 79 80 return true; 81 }; 82 }; 83 /** 84 * Execute a callback for each of the child nodes of this node 85 * @param {function(child: Node, path: string, parent: Node)} callback 86 */ 87 88 89 RelationalNode.prototype.forEach = function (callback) { 90 var _this = this; 91 92 this.params.forEach(function (n, i) { 93 return callback(n, 'params[' + i + ']', _this); 94 }, this); 95 }; 96 /** 97 * Create a new RelationalNode having its childs be the results of calling 98 * the provided callback function for each of the childs of the original node. 99 * @param {function(child: Node, path: string, parent: Node): Node} callback 100 * @returns {RelationalNode} Returns a transformed copy of the node 101 */ 102 103 104 RelationalNode.prototype.map = function (callback) { 105 var _this2 = this; 106 107 return new RelationalNode(this.conditionals.slice(), this.params.map(function (n, i) { 108 return _this2._ifNode(callback(n, 'params[' + i + ']', _this2)); 109 }, this)); 110 }; 111 /** 112 * Create a clone of this node, a shallow copy 113 * @return {RelationalNode} 114 */ 115 116 117 RelationalNode.prototype.clone = function () { 118 return new RelationalNode(this.conditionals, this.params); 119 }; 120 /** 121 * Get string representation. 122 * @param {Object} options 123 * @return {string} str 124 */ 125 126 127 RelationalNode.prototype._toString = function (options) { 128 var parenthesis = options && options.parenthesis ? options.parenthesis : 'keep'; 129 var precedence = (0, _operators.getPrecedence)(this, parenthesis); 130 var paramStrings = this.params.map(function (p, index) { 131 var paramPrecedence = (0, _operators.getPrecedence)(p, parenthesis); 132 return parenthesis === 'all' || paramPrecedence !== null && paramPrecedence <= precedence ? '(' + p.toString(options) + ')' : p.toString(options); 133 }); 134 var operatorMap = { 135 equal: '==', 136 unequal: '!=', 137 smaller: '<', 138 larger: '>', 139 smallerEq: '<=', 140 largerEq: '>=' 141 }; 142 var ret = paramStrings[0]; 143 144 for (var i = 0; i < this.conditionals.length; i++) { 145 ret += ' ' + operatorMap[this.conditionals[i]] + ' ' + paramStrings[i + 1]; 146 } 147 148 return ret; 149 }; 150 /** 151 * Get a JSON representation of the node 152 * @returns {Object} 153 */ 154 155 156 RelationalNode.prototype.toJSON = function () { 157 return { 158 mathjs: 'RelationalNode', 159 conditionals: this.conditionals, 160 params: this.params 161 }; 162 }; 163 /** 164 * Instantiate a RelationalNode from its JSON representation 165 * @param {Object} json An object structured like 166 * `{"mathjs": "RelationalNode", "condition": ..., "trueExpr": ..., "falseExpr": ...}`, 167 * where mathjs is optional 168 * @returns {RelationalNode} 169 */ 170 171 172 RelationalNode.fromJSON = function (json) { 173 return new RelationalNode(json.conditionals, json.params); 174 }; 175 /** 176 * Get HTML representation 177 * @param {Object} options 178 * @return {string} str 179 */ 180 181 182 RelationalNode.prototype.toHTML = function (options) { 183 var parenthesis = options && options.parenthesis ? options.parenthesis : 'keep'; 184 var precedence = (0, _operators.getPrecedence)(this, parenthesis); 185 var paramStrings = this.params.map(function (p, index) { 186 var paramPrecedence = (0, _operators.getPrecedence)(p, parenthesis); 187 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); 188 }); 189 var operatorMap = { 190 equal: '==', 191 unequal: '!=', 192 smaller: '<', 193 larger: '>', 194 smallerEq: '<=', 195 largerEq: '>=' 196 }; 197 var ret = paramStrings[0]; 198 199 for (var i = 0; i < this.conditionals.length; i++) { 200 ret += '<span class="math-operator math-binary-operator math-explicit-binary-operator">' + (0, _string.escape)(operatorMap[this.conditionals[i]]) + '</span>' + paramStrings[i + 1]; 201 } 202 203 return ret; 204 }; 205 /** 206 * Get LaTeX representation 207 * @param {Object} options 208 * @return {string} str 209 */ 210 211 212 RelationalNode.prototype._toTex = function (options) { 213 var parenthesis = options && options.parenthesis ? options.parenthesis : 'keep'; 214 var precedence = (0, _operators.getPrecedence)(this, parenthesis); 215 var paramStrings = this.params.map(function (p, index) { 216 var paramPrecedence = (0, _operators.getPrecedence)(p, parenthesis); 217 return parenthesis === 'all' || paramPrecedence !== null && paramPrecedence <= precedence ? '\\left(' + p.toTex(options) + '\right)' : p.toTex(options); 218 }); 219 var ret = paramStrings[0]; 220 221 for (var i = 0; i < this.conditionals.length; i++) { 222 ret += _latex.latexOperators[this.conditionals[i]] + paramStrings[i + 1]; 223 } 224 225 return ret; 226 }; 227 228 return RelationalNode; 229 }, { 230 isClass: true, 231 isNode: true 232 }); 233 exports.createRelationalNode = createRelationalNode;