AccessorNode.js 8.8 KB

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