simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

ArrayNode.js (5653B)


      1 import { isArrayNode, isNode } from '../../utils/is.js';
      2 import { map } from '../../utils/array.js';
      3 import { factory } from '../../utils/factory.js';
      4 var name = 'ArrayNode';
      5 var dependencies = ['Node'];
      6 export var createArrayNode = /* #__PURE__ */factory(name, dependencies, _ref => {
      7   var {
      8     Node
      9   } = _ref;
     10 
     11   /**
     12    * @constructor ArrayNode
     13    * @extends {Node}
     14    * Holds an 1-dimensional array with items
     15    * @param {Node[]} [items]   1 dimensional array with items
     16    */
     17   function ArrayNode(items) {
     18     if (!(this instanceof ArrayNode)) {
     19       throw new SyntaxError('Constructor must be called with the new operator');
     20     }
     21 
     22     this.items = items || []; // validate input
     23 
     24     if (!Array.isArray(this.items) || !this.items.every(isNode)) {
     25       throw new TypeError('Array containing Nodes expected');
     26     }
     27   }
     28 
     29   ArrayNode.prototype = new Node();
     30   ArrayNode.prototype.type = 'ArrayNode';
     31   ArrayNode.prototype.isArrayNode = true;
     32   /**
     33    * Compile a node into a JavaScript function.
     34    * This basically pre-calculates as much as possible and only leaves open
     35    * calculations which depend on a dynamic scope with variables.
     36    * @param {Object} math     Math.js namespace with functions and constants.
     37    * @param {Object} argNames An object with argument names as key and `true`
     38    *                          as value. Used in the SymbolNode to optimize
     39    *                          for arguments from user assigned functions
     40    *                          (see FunctionAssignmentNode) or special symbols
     41    *                          like `end` (see IndexNode).
     42    * @return {function} Returns a function which can be called like:
     43    *                        evalNode(scope: Object, args: Object, context: *)
     44    */
     45 
     46   ArrayNode.prototype._compile = function (math, argNames) {
     47     var evalItems = map(this.items, function (item) {
     48       return item._compile(math, argNames);
     49     });
     50     var asMatrix = math.config.matrix !== 'Array';
     51 
     52     if (asMatrix) {
     53       var matrix = math.matrix;
     54       return function evalArrayNode(scope, args, context) {
     55         return matrix(map(evalItems, function (evalItem) {
     56           return evalItem(scope, args, context);
     57         }));
     58       };
     59     } else {
     60       return function evalArrayNode(scope, args, context) {
     61         return map(evalItems, function (evalItem) {
     62           return evalItem(scope, args, context);
     63         });
     64       };
     65     }
     66   };
     67   /**
     68    * Execute a callback for each of the child nodes of this node
     69    * @param {function(child: Node, path: string, parent: Node)} callback
     70    */
     71 
     72 
     73   ArrayNode.prototype.forEach = function (callback) {
     74     for (var i = 0; i < this.items.length; i++) {
     75       var node = this.items[i];
     76       callback(node, 'items[' + i + ']', this);
     77     }
     78   };
     79   /**
     80    * Create a new ArrayNode having it's childs be the results of calling
     81    * the provided callback function for each of the childs of the original node.
     82    * @param {function(child: Node, path: string, parent: Node): Node} callback
     83    * @returns {ArrayNode} Returns a transformed copy of the node
     84    */
     85 
     86 
     87   ArrayNode.prototype.map = function (callback) {
     88     var items = [];
     89 
     90     for (var i = 0; i < this.items.length; i++) {
     91       items[i] = this._ifNode(callback(this.items[i], 'items[' + i + ']', this));
     92     }
     93 
     94     return new ArrayNode(items);
     95   };
     96   /**
     97    * Create a clone of this node, a shallow copy
     98    * @return {ArrayNode}
     99    */
    100 
    101 
    102   ArrayNode.prototype.clone = function () {
    103     return new ArrayNode(this.items.slice(0));
    104   };
    105   /**
    106    * Get string representation
    107    * @param {Object} options
    108    * @return {string} str
    109    * @override
    110    */
    111 
    112 
    113   ArrayNode.prototype._toString = function (options) {
    114     var items = this.items.map(function (node) {
    115       return node.toString(options);
    116     });
    117     return '[' + items.join(', ') + ']';
    118   };
    119   /**
    120    * Get a JSON representation of the node
    121    * @returns {Object}
    122    */
    123 
    124 
    125   ArrayNode.prototype.toJSON = function () {
    126     return {
    127       mathjs: 'ArrayNode',
    128       items: this.items
    129     };
    130   };
    131   /**
    132    * Instantiate an ArrayNode from its JSON representation
    133    * @param {Object} json  An object structured like
    134    *                       `{"mathjs": "ArrayNode", items: [...]}`,
    135    *                       where mathjs is optional
    136    * @returns {ArrayNode}
    137    */
    138 
    139 
    140   ArrayNode.fromJSON = function (json) {
    141     return new ArrayNode(json.items);
    142   };
    143   /**
    144    * Get HTML representation
    145    * @param {Object} options
    146    * @return {string} str
    147    * @override
    148    */
    149 
    150 
    151   ArrayNode.prototype.toHTML = function (options) {
    152     var items = this.items.map(function (node) {
    153       return node.toHTML(options);
    154     });
    155     return '<span class="math-parenthesis math-square-parenthesis">[</span>' + items.join('<span class="math-separator">,</span>') + '<span class="math-parenthesis math-square-parenthesis">]</span>';
    156   };
    157   /**
    158    * Get LaTeX representation
    159    * @param {Object} options
    160    * @return {string} str
    161    */
    162 
    163 
    164   ArrayNode.prototype._toTex = function (options) {
    165     function itemsToTex(items, nested) {
    166       var mixedItems = items.some(isArrayNode) && !items.every(isArrayNode);
    167       var itemsFormRow = nested || mixedItems;
    168       var itemSep = itemsFormRow ? '&' : '\\\\';
    169       var itemsTex = items.map(function (node) {
    170         if (node.items) {
    171           return itemsToTex(node.items, !nested);
    172         } else {
    173           return node.toTex(options);
    174         }
    175       }).join(itemSep);
    176       return mixedItems || !itemsFormRow || itemsFormRow && !nested ? '\\begin{bmatrix}' + itemsTex + '\\end{bmatrix}' : itemsTex;
    177     }
    178 
    179     return itemsToTex(this.items, false);
    180   };
    181 
    182   return ArrayNode;
    183 }, {
    184   isClass: true,
    185   isNode: true
    186 });