simple-squiggle

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

ObjectNode.js (7183B)


      1 "use strict";
      2 
      3 var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
      4 
      5 Object.defineProperty(exports, "__esModule", {
      6   value: true
      7 });
      8 exports.createObjectNode = void 0;
      9 
     10 var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
     11 
     12 var _is = require("../../utils/is.js");
     13 
     14 var _string = require("../../utils/string.js");
     15 
     16 var _customs = require("../../utils/customs.js");
     17 
     18 var _object = require("../../utils/object.js");
     19 
     20 var _factory = require("../../utils/factory.js");
     21 
     22 var name = 'ObjectNode';
     23 var dependencies = ['Node'];
     24 var createObjectNode = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
     25   var Node = _ref.Node;
     26 
     27   /**
     28    * @constructor ObjectNode
     29    * @extends {Node}
     30    * Holds an object with keys/values
     31    * @param {Object.<string, Node>} [properties]   object with key/value pairs
     32    */
     33   function ObjectNode(properties) {
     34     if (!(this instanceof ObjectNode)) {
     35       throw new SyntaxError('Constructor must be called with the new operator');
     36     }
     37 
     38     this.properties = properties || {}; // validate input
     39 
     40     if (properties) {
     41       if (!((0, _typeof2.default)(properties) === 'object') || !Object.keys(properties).every(function (key) {
     42         return (0, _is.isNode)(properties[key]);
     43       })) {
     44         throw new TypeError('Object containing Nodes expected');
     45       }
     46     }
     47   }
     48 
     49   ObjectNode.prototype = new Node();
     50   ObjectNode.prototype.type = 'ObjectNode';
     51   ObjectNode.prototype.isObjectNode = true;
     52   /**
     53    * Compile a node into a JavaScript function.
     54    * This basically pre-calculates as much as possible and only leaves open
     55    * calculations which depend on a dynamic scope with variables.
     56    * @param {Object} math     Math.js namespace with functions and constants.
     57    * @param {Object} argNames An object with argument names as key and `true`
     58    *                          as value. Used in the SymbolNode to optimize
     59    *                          for arguments from user assigned functions
     60    *                          (see FunctionAssignmentNode) or special symbols
     61    *                          like `end` (see IndexNode).
     62    * @return {function} Returns a function which can be called like:
     63    *                        evalNode(scope: Object, args: Object, context: *)
     64    */
     65 
     66   ObjectNode.prototype._compile = function (math, argNames) {
     67     var evalEntries = {};
     68 
     69     for (var key in this.properties) {
     70       if ((0, _object.hasOwnProperty)(this.properties, key)) {
     71         // we stringify/parse the key here to resolve unicode characters,
     72         // so you cannot create a key like {"co\\u006Estructor": null}
     73         var stringifiedKey = (0, _string.stringify)(key);
     74         var parsedKey = JSON.parse(stringifiedKey);
     75 
     76         if (!(0, _customs.isSafeProperty)(this.properties, parsedKey)) {
     77           throw new Error('No access to property "' + parsedKey + '"');
     78         }
     79 
     80         evalEntries[parsedKey] = this.properties[key]._compile(math, argNames);
     81       }
     82     }
     83 
     84     return function evalObjectNode(scope, args, context) {
     85       var obj = {};
     86 
     87       for (var _key in evalEntries) {
     88         if ((0, _object.hasOwnProperty)(evalEntries, _key)) {
     89           obj[_key] = evalEntries[_key](scope, args, context);
     90         }
     91       }
     92 
     93       return obj;
     94     };
     95   };
     96   /**
     97    * Execute a callback for each of the child nodes of this node
     98    * @param {function(child: Node, path: string, parent: Node)} callback
     99    */
    100 
    101 
    102   ObjectNode.prototype.forEach = function (callback) {
    103     for (var key in this.properties) {
    104       if ((0, _object.hasOwnProperty)(this.properties, key)) {
    105         callback(this.properties[key], 'properties[' + (0, _string.stringify)(key) + ']', this);
    106       }
    107     }
    108   };
    109   /**
    110    * Create a new ObjectNode having it's childs be the results of calling
    111    * the provided callback function for each of the childs of the original node.
    112    * @param {function(child: Node, path: string, parent: Node): Node} callback
    113    * @returns {ObjectNode} Returns a transformed copy of the node
    114    */
    115 
    116 
    117   ObjectNode.prototype.map = function (callback) {
    118     var properties = {};
    119 
    120     for (var key in this.properties) {
    121       if ((0, _object.hasOwnProperty)(this.properties, key)) {
    122         properties[key] = this._ifNode(callback(this.properties[key], 'properties[' + (0, _string.stringify)(key) + ']', this));
    123       }
    124     }
    125 
    126     return new ObjectNode(properties);
    127   };
    128   /**
    129    * Create a clone of this node, a shallow copy
    130    * @return {ObjectNode}
    131    */
    132 
    133 
    134   ObjectNode.prototype.clone = function () {
    135     var properties = {};
    136 
    137     for (var key in this.properties) {
    138       if ((0, _object.hasOwnProperty)(this.properties, key)) {
    139         properties[key] = this.properties[key];
    140       }
    141     }
    142 
    143     return new ObjectNode(properties);
    144   };
    145   /**
    146    * Get string representation
    147    * @param {Object} options
    148    * @return {string} str
    149    * @override
    150    */
    151 
    152 
    153   ObjectNode.prototype._toString = function (options) {
    154     var entries = [];
    155 
    156     for (var key in this.properties) {
    157       if ((0, _object.hasOwnProperty)(this.properties, key)) {
    158         entries.push((0, _string.stringify)(key) + ': ' + this.properties[key].toString(options));
    159       }
    160     }
    161 
    162     return '{' + entries.join(', ') + '}';
    163   };
    164   /**
    165    * Get a JSON representation of the node
    166    * @returns {Object}
    167    */
    168 
    169 
    170   ObjectNode.prototype.toJSON = function () {
    171     return {
    172       mathjs: 'ObjectNode',
    173       properties: this.properties
    174     };
    175   };
    176   /**
    177    * Instantiate an OperatorNode from its JSON representation
    178    * @param {Object} json  An object structured like
    179    *                       `{"mathjs": "ObjectNode", "properties": {...}}`,
    180    *                       where mathjs is optional
    181    * @returns {ObjectNode}
    182    */
    183 
    184 
    185   ObjectNode.fromJSON = function (json) {
    186     return new ObjectNode(json.properties);
    187   };
    188   /**
    189    * Get HTML representation
    190    * @param {Object} options
    191    * @return {string} str
    192    * @override
    193    */
    194 
    195 
    196   ObjectNode.prototype.toHTML = function (options) {
    197     var entries = [];
    198 
    199     for (var key in this.properties) {
    200       if ((0, _object.hasOwnProperty)(this.properties, key)) {
    201         entries.push('<span class="math-symbol math-property">' + (0, _string.escape)(key) + '</span>' + '<span class="math-operator math-assignment-operator math-property-assignment-operator math-binary-operator">:</span>' + this.properties[key].toHTML(options));
    202       }
    203     }
    204 
    205     return '<span class="math-parenthesis math-curly-parenthesis">{</span>' + entries.join('<span class="math-separator">,</span>') + '<span class="math-parenthesis math-curly-parenthesis">}</span>';
    206   };
    207   /**
    208    * Get LaTeX representation
    209    * @param {Object} options
    210    * @return {string} str
    211    */
    212 
    213 
    214   ObjectNode.prototype._toTex = function (options) {
    215     var entries = [];
    216 
    217     for (var key in this.properties) {
    218       if ((0, _object.hasOwnProperty)(this.properties, key)) {
    219         entries.push('\\mathbf{' + key + ':} & ' + this.properties[key].toTex(options) + '\\\\');
    220       }
    221     }
    222 
    223     return "\\left\\{\\begin{array}{ll}".concat(entries.join('\n'), "\\end{array}\\right\\}");
    224   };
    225 
    226   return ObjectNode;
    227 }, {
    228   isClass: true,
    229   isNode: true
    230 });
    231 exports.createObjectNode = createObjectNode;