SymbolNode.js (6372B)
1 "use strict"; 2 3 Object.defineProperty(exports, "__esModule", { 4 value: true 5 }); 6 exports.createSymbolNode = void 0; 7 8 var _string = require("../../utils/string.js"); 9 10 var _customs = require("../../utils/customs.js"); 11 12 var _factory = require("../../utils/factory.js"); 13 14 var _latex = require("../../utils/latex.js"); 15 16 var name = 'SymbolNode'; 17 var dependencies = ['math', '?Unit', 'Node']; 18 var createSymbolNode = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { 19 var math = _ref.math, 20 Unit = _ref.Unit, 21 Node = _ref.Node; 22 23 /** 24 * Check whether some name is a valueless unit like "inch". 25 * @param {string} name 26 * @return {boolean} 27 */ 28 function isValuelessUnit(name) { 29 return Unit ? Unit.isValuelessUnit(name) : false; 30 } 31 /** 32 * @constructor SymbolNode 33 * @extends {Node} 34 * A symbol node can hold and resolve a symbol 35 * @param {string} name 36 * @extends {Node} 37 */ 38 39 40 function SymbolNode(name) { 41 if (!(this instanceof SymbolNode)) { 42 throw new SyntaxError('Constructor must be called with the new operator'); 43 } // validate input 44 45 46 if (typeof name !== 'string') throw new TypeError('String expected for parameter "name"'); 47 this.name = name; 48 } 49 50 SymbolNode.prototype = new Node(); 51 SymbolNode.prototype.type = 'SymbolNode'; 52 SymbolNode.prototype.isSymbolNode = true; 53 /** 54 * Compile a node into a JavaScript function. 55 * This basically pre-calculates as much as possible and only leaves open 56 * calculations which depend on a dynamic scope with variables. 57 * @param {Object} math Math.js namespace with functions and constants. 58 * @param {Object} argNames An object with argument names as key and `true` 59 * as value. Used in the SymbolNode to optimize 60 * for arguments from user assigned functions 61 * (see FunctionAssignmentNode) or special symbols 62 * like `end` (see IndexNode). 63 * @return {function} Returns a function which can be called like: 64 * evalNode(scope: Object, args: Object, context: *) 65 */ 66 67 SymbolNode.prototype._compile = function (math, argNames) { 68 var name = this.name; 69 70 if (argNames[name] === true) { 71 // this is a FunctionAssignment argument 72 // (like an x when inside the expression of a function assignment `f(x) = ...`) 73 return function (scope, args, context) { 74 return args[name]; 75 }; 76 } else if (name in math) { 77 return function (scope, args, context) { 78 return scope.has(name) ? scope.get(name) : (0, _customs.getSafeProperty)(math, name); 79 }; 80 } else { 81 var isUnit = isValuelessUnit(name); 82 return function (scope, args, context) { 83 return scope.has(name) ? scope.get(name) : isUnit ? new Unit(null, name) : SymbolNode.onUndefinedSymbol(name); 84 }; 85 } 86 }; 87 /** 88 * Execute a callback for each of the child nodes of this node 89 * @param {function(child: Node, path: string, parent: Node)} callback 90 */ 91 92 93 SymbolNode.prototype.forEach = function (callback) {// nothing to do, we don't have childs 94 }; 95 /** 96 * Create a new SymbolNode having it's childs be the results of calling 97 * the provided callback function for each of the childs of the original node. 98 * @param {function(child: Node, path: string, parent: Node) : Node} callback 99 * @returns {SymbolNode} Returns a clone of the node 100 */ 101 102 103 SymbolNode.prototype.map = function (callback) { 104 return this.clone(); 105 }; 106 /** 107 * Throws an error 'Undefined symbol {name}' 108 * @param {string} name 109 */ 110 111 112 SymbolNode.onUndefinedSymbol = function (name) { 113 throw new Error('Undefined symbol ' + name); 114 }; 115 /** 116 * Create a clone of this node, a shallow copy 117 * @return {SymbolNode} 118 */ 119 120 121 SymbolNode.prototype.clone = function () { 122 return new SymbolNode(this.name); 123 }; 124 /** 125 * Get string representation 126 * @param {Object} options 127 * @return {string} str 128 * @override 129 */ 130 131 132 SymbolNode.prototype._toString = function (options) { 133 return this.name; 134 }; 135 /** 136 * Get HTML representation 137 * @param {Object} options 138 * @return {string} str 139 * @override 140 */ 141 142 143 SymbolNode.prototype.toHTML = function (options) { 144 var name = (0, _string.escape)(this.name); 145 146 if (name === 'true' || name === 'false') { 147 return '<span class="math-symbol math-boolean">' + name + '</span>'; 148 } else if (name === 'i') { 149 return '<span class="math-symbol math-imaginary-symbol">' + name + '</span>'; 150 } else if (name === 'Infinity') { 151 return '<span class="math-symbol math-infinity-symbol">' + name + '</span>'; 152 } else if (name === 'NaN') { 153 return '<span class="math-symbol math-nan-symbol">' + name + '</span>'; 154 } else if (name === 'null') { 155 return '<span class="math-symbol math-null-symbol">' + name + '</span>'; 156 } else if (name === 'undefined') { 157 return '<span class="math-symbol math-undefined-symbol">' + name + '</span>'; 158 } 159 160 return '<span class="math-symbol">' + name + '</span>'; 161 }; 162 /** 163 * Get a JSON representation of the node 164 * @returns {Object} 165 */ 166 167 168 SymbolNode.prototype.toJSON = function () { 169 return { 170 mathjs: 'SymbolNode', 171 name: this.name 172 }; 173 }; 174 /** 175 * Instantiate a SymbolNode from its JSON representation 176 * @param {Object} json An object structured like 177 * `{"mathjs": "SymbolNode", name: "x"}`, 178 * where mathjs is optional 179 * @returns {SymbolNode} 180 */ 181 182 183 SymbolNode.fromJSON = function (json) { 184 return new SymbolNode(json.name); 185 }; 186 /** 187 * Get LaTeX representation 188 * @param {Object} options 189 * @return {string} str 190 * @override 191 */ 192 193 194 SymbolNode.prototype._toTex = function (options) { 195 var isUnit = false; 196 197 if (typeof math[this.name] === 'undefined' && isValuelessUnit(this.name)) { 198 isUnit = true; 199 } 200 201 var symbol = (0, _latex.toSymbol)(this.name, isUnit); 202 203 if (symbol[0] === '\\') { 204 // no space needed if the symbol starts with '\' 205 return symbol; 206 } // the space prevents symbols from breaking stuff like '\cdot' if it's written right before the symbol 207 208 209 return ' ' + symbol; 210 }; 211 212 return SymbolNode; 213 }, { 214 isClass: true, 215 isNode: true 216 }); 217 exports.createSymbolNode = createSymbolNode;