simple-squiggle

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

BlockNode.js (5883B)


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