UNPKG

6.74 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.createAccessorNode = void 0;
7
8var _is = require("../../utils/is");
9
10var _customs = require("../../utils/customs");
11
12var _factory = require("../../utils/factory");
13
14var _access = require("./utils/access");
15
16var name = 'AccessorNode';
17var dependencies = ['subset', 'Node'];
18var createAccessorNode =
19/* #__PURE__ */
20(0, _factory.factory)(name, dependencies, function (_ref) {
21 var subset = _ref.subset,
22 Node = _ref.Node;
23 var access = (0, _access.accessFactory)({
24 subset: subset
25 });
26 /**
27 * @constructor AccessorNode
28 * @extends {Node}
29 * Access an object property or get a matrix subset
30 *
31 * @param {Node} object The object from which to retrieve
32 * a property or subset.
33 * @param {IndexNode} index IndexNode containing ranges
34 */
35
36 function AccessorNode(object, index) {
37 if (!(this instanceof AccessorNode)) {
38 throw new SyntaxError('Constructor must be called with the new operator');
39 }
40
41 if (!(0, _is.isNode)(object)) {
42 throw new TypeError('Node expected for parameter "object"');
43 }
44
45 if (!(0, _is.isIndexNode)(index)) {
46 throw new TypeError('IndexNode expected for parameter "index"');
47 }
48
49 this.object = object || null;
50 this.index = index; // readonly property name
51
52 Object.defineProperty(this, 'name', {
53 get: function () {
54 if (this.index) {
55 return this.index.isObjectProperty() ? this.index.getObjectProperty() : '';
56 } else {
57 return this.object.name || '';
58 }
59 }.bind(this),
60 set: function set() {
61 throw new Error('Cannot assign a new name, name is read-only');
62 }
63 });
64 }
65
66 AccessorNode.prototype = new Node();
67 AccessorNode.prototype.type = 'AccessorNode';
68 AccessorNode.prototype.isAccessorNode = true;
69 /**
70 * Compile a node into a JavaScript function.
71 * This basically pre-calculates as much as possible and only leaves open
72 * calculations which depend on a dynamic scope with variables.
73 * @param {Object} math Math.js namespace with functions and constants.
74 * @param {Object} argNames An object with argument names as key and `true`
75 * as value. Used in the SymbolNode to optimize
76 * for arguments from user assigned functions
77 * (see FunctionAssignmentNode) or special symbols
78 * like `end` (see IndexNode).
79 * @return {function} Returns a function which can be called like:
80 * evalNode(scope: Object, args: Object, context: *)
81 */
82
83 AccessorNode.prototype._compile = function (math, argNames) {
84 var evalObject = this.object._compile(math, argNames);
85
86 var evalIndex = this.index._compile(math, argNames);
87
88 if (this.index.isObjectProperty()) {
89 var prop = this.index.getObjectProperty();
90 return function evalAccessorNode(scope, args, context) {
91 return (0, _customs.getSafeProperty)(evalObject(scope, args, context), prop);
92 };
93 } else {
94 return function evalAccessorNode(scope, args, context) {
95 var object = evalObject(scope, args, context);
96 var index = evalIndex(scope, args, object); // we pass object here instead of context
97
98 return access(object, index);
99 };
100 }
101 };
102 /**
103 * Execute a callback for each of the child nodes of this node
104 * @param {function(child: Node, path: string, parent: Node)} callback
105 */
106
107
108 AccessorNode.prototype.forEach = function (callback) {
109 callback(this.object, 'object', this);
110 callback(this.index, 'index', this);
111 };
112 /**
113 * Create a new AccessorNode having it's childs be the results of calling
114 * the provided callback function for each of the childs of the original node.
115 * @param {function(child: Node, path: string, parent: Node): Node} callback
116 * @returns {AccessorNode} Returns a transformed copy of the node
117 */
118
119
120 AccessorNode.prototype.map = function (callback) {
121 return new AccessorNode(this._ifNode(callback(this.object, 'object', this)), this._ifNode(callback(this.index, 'index', this)));
122 };
123 /**
124 * Create a clone of this node, a shallow copy
125 * @return {AccessorNode}
126 */
127
128
129 AccessorNode.prototype.clone = function () {
130 return new AccessorNode(this.object, this.index);
131 };
132 /**
133 * Get string representation
134 * @param {Object} options
135 * @return {string}
136 */
137
138
139 AccessorNode.prototype._toString = function (options) {
140 var object = this.object.toString(options);
141
142 if (needParenthesis(this.object)) {
143 object = '(' + object + ')';
144 }
145
146 return object + this.index.toString(options);
147 };
148 /**
149 * Get HTML representation
150 * @param {Object} options
151 * @return {string}
152 */
153
154
155 AccessorNode.prototype.toHTML = function (options) {
156 var object = this.object.toHTML(options);
157
158 if (needParenthesis(this.object)) {
159 object = '<span class="math-parenthesis math-round-parenthesis">(</span>' + object + '<span class="math-parenthesis math-round-parenthesis">)</span>';
160 }
161
162 return object + this.index.toHTML(options);
163 };
164 /**
165 * Get LaTeX representation
166 * @param {Object} options
167 * @return {string}
168 */
169
170
171 AccessorNode.prototype._toTex = function (options) {
172 var object = this.object.toTex(options);
173
174 if (needParenthesis(this.object)) {
175 object = '\\left(\' + object + \'\\right)';
176 }
177
178 return object + this.index.toTex(options);
179 };
180 /**
181 * Get a JSON representation of the node
182 * @returns {Object}
183 */
184
185
186 AccessorNode.prototype.toJSON = function () {
187 return {
188 mathjs: 'AccessorNode',
189 object: this.object,
190 index: this.index
191 };
192 };
193 /**
194 * Instantiate an AccessorNode from its JSON representation
195 * @param {Object} json An object structured like
196 * `{"mathjs": "AccessorNode", object: ..., index: ...}`,
197 * where mathjs is optional
198 * @returns {AccessorNode}
199 */
200
201
202 AccessorNode.fromJSON = function (json) {
203 return new AccessorNode(json.object, json.index);
204 };
205 /**
206 * Are parenthesis needed?
207 * @private
208 */
209
210
211 function needParenthesis(node) {
212 // TODO: maybe make a method on the nodes which tells whether they need parenthesis?
213 return !((0, _is.isAccessorNode)(node) || (0, _is.isArrayNode)(node) || (0, _is.isConstantNode)(node) || (0, _is.isFunctionNode)(node) || (0, _is.isObjectNode)(node) || (0, _is.isParenthesisNode)(node) || (0, _is.isSymbolNode)(node));
214 }
215
216 return AccessorNode;
217}, {
218 isClass: true,
219 isNode: true
220});
221exports.createAccessorNode = createAccessorNode;
\No newline at end of file