simple-squiggle

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

RelationalNode.js (7988B)


      1 "use strict";
      2 
      3 Object.defineProperty(exports, "__esModule", {
      4   value: true
      5 });
      6 exports.createRelationalNode = void 0;
      7 
      8 var _operators = require("../operators.js");
      9 
     10 var _string = require("../../utils/string.js");
     11 
     12 var _customs = require("../../utils/customs.js");
     13 
     14 var _latex = require("../../utils/latex.js");
     15 
     16 var _factory = require("../../utils/factory.js");
     17 
     18 var name = 'RelationalNode';
     19 var dependencies = ['Node'];
     20 var createRelationalNode = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
     21   var Node = _ref.Node;
     22 
     23   /**
     24    * A node representing a chained conditional expression, such as 'x > y > z'
     25    *
     26    * @param {String[]} conditionals   An array of conditional operators used to compare the parameters
     27    * @param {Node[]} params   The parameters that will be compared
     28    *
     29    * @constructor RelationalNode
     30    * @extends {Node}
     31    */
     32   function RelationalNode(conditionals, params) {
     33     if (!(this instanceof RelationalNode)) {
     34       throw new SyntaxError('Constructor must be called with the new operator');
     35     }
     36 
     37     if (!Array.isArray(conditionals)) throw new TypeError('Parameter conditionals must be an array');
     38     if (!Array.isArray(params)) throw new TypeError('Parameter params must be an array');
     39     if (conditionals.length !== params.length - 1) throw new TypeError('Parameter params must contain exactly one more element than parameter conditionals');
     40     this.conditionals = conditionals;
     41     this.params = params;
     42   }
     43 
     44   RelationalNode.prototype = new Node();
     45   RelationalNode.prototype.type = 'RelationalNode';
     46   RelationalNode.prototype.isRelationalNode = true;
     47   /**
     48    * Compile a node into a JavaScript function.
     49    * This basically pre-calculates as much as possible and only leaves open
     50    * calculations which depend on a dynamic scope with variables.
     51    * @param {Object} math     Math.js namespace with functions and constants.
     52    * @param {Object} argNames An object with argument names as key and `true`
     53    *                          as value. Used in the SymbolNode to optimize
     54    *                          for arguments from user assigned functions
     55    *                          (see FunctionAssignmentNode) or special symbols
     56    *                          like `end` (see IndexNode).
     57    * @return {function} Returns a function which can be called like:
     58    *                        evalNode(scope: Object, args: Object, context: *)
     59    */
     60 
     61   RelationalNode.prototype._compile = function (math, argNames) {
     62     var self = this;
     63     var compiled = this.params.map(function (p) {
     64       return p._compile(math, argNames);
     65     });
     66     return function evalRelationalNode(scope, args, context) {
     67       var evalLhs;
     68       var evalRhs = compiled[0](scope, args, context);
     69 
     70       for (var i = 0; i < self.conditionals.length; i++) {
     71         evalLhs = evalRhs;
     72         evalRhs = compiled[i + 1](scope, args, context);
     73         var condFn = (0, _customs.getSafeProperty)(math, self.conditionals[i]);
     74 
     75         if (!condFn(evalLhs, evalRhs)) {
     76           return false;
     77         }
     78       }
     79 
     80       return true;
     81     };
     82   };
     83   /**
     84    * Execute a callback for each of the child nodes of this node
     85    * @param {function(child: Node, path: string, parent: Node)} callback
     86    */
     87 
     88 
     89   RelationalNode.prototype.forEach = function (callback) {
     90     var _this = this;
     91 
     92     this.params.forEach(function (n, i) {
     93       return callback(n, 'params[' + i + ']', _this);
     94     }, this);
     95   };
     96   /**
     97    * Create a new RelationalNode having its childs be the results of calling
     98    * the provided callback function for each of the childs of the original node.
     99    * @param {function(child: Node, path: string, parent: Node): Node} callback
    100    * @returns {RelationalNode} Returns a transformed copy of the node
    101    */
    102 
    103 
    104   RelationalNode.prototype.map = function (callback) {
    105     var _this2 = this;
    106 
    107     return new RelationalNode(this.conditionals.slice(), this.params.map(function (n, i) {
    108       return _this2._ifNode(callback(n, 'params[' + i + ']', _this2));
    109     }, this));
    110   };
    111   /**
    112    * Create a clone of this node, a shallow copy
    113    * @return {RelationalNode}
    114    */
    115 
    116 
    117   RelationalNode.prototype.clone = function () {
    118     return new RelationalNode(this.conditionals, this.params);
    119   };
    120   /**
    121    * Get string representation.
    122    * @param {Object} options
    123    * @return {string} str
    124    */
    125 
    126 
    127   RelationalNode.prototype._toString = function (options) {
    128     var parenthesis = options && options.parenthesis ? options.parenthesis : 'keep';
    129     var precedence = (0, _operators.getPrecedence)(this, parenthesis);
    130     var paramStrings = this.params.map(function (p, index) {
    131       var paramPrecedence = (0, _operators.getPrecedence)(p, parenthesis);
    132       return parenthesis === 'all' || paramPrecedence !== null && paramPrecedence <= precedence ? '(' + p.toString(options) + ')' : p.toString(options);
    133     });
    134     var operatorMap = {
    135       equal: '==',
    136       unequal: '!=',
    137       smaller: '<',
    138       larger: '>',
    139       smallerEq: '<=',
    140       largerEq: '>='
    141     };
    142     var ret = paramStrings[0];
    143 
    144     for (var i = 0; i < this.conditionals.length; i++) {
    145       ret += ' ' + operatorMap[this.conditionals[i]] + ' ' + paramStrings[i + 1];
    146     }
    147 
    148     return ret;
    149   };
    150   /**
    151    * Get a JSON representation of the node
    152    * @returns {Object}
    153    */
    154 
    155 
    156   RelationalNode.prototype.toJSON = function () {
    157     return {
    158       mathjs: 'RelationalNode',
    159       conditionals: this.conditionals,
    160       params: this.params
    161     };
    162   };
    163   /**
    164    * Instantiate a RelationalNode from its JSON representation
    165    * @param {Object} json  An object structured like
    166    *                       `{"mathjs": "RelationalNode", "condition": ..., "trueExpr": ..., "falseExpr": ...}`,
    167    *                       where mathjs is optional
    168    * @returns {RelationalNode}
    169    */
    170 
    171 
    172   RelationalNode.fromJSON = function (json) {
    173     return new RelationalNode(json.conditionals, json.params);
    174   };
    175   /**
    176    * Get HTML representation
    177    * @param {Object} options
    178    * @return {string} str
    179    */
    180 
    181 
    182   RelationalNode.prototype.toHTML = function (options) {
    183     var parenthesis = options && options.parenthesis ? options.parenthesis : 'keep';
    184     var precedence = (0, _operators.getPrecedence)(this, parenthesis);
    185     var paramStrings = this.params.map(function (p, index) {
    186       var paramPrecedence = (0, _operators.getPrecedence)(p, parenthesis);
    187       return parenthesis === 'all' || paramPrecedence !== null && paramPrecedence <= precedence ? '<span class="math-parenthesis math-round-parenthesis">(</span>' + p.toHTML(options) + '<span class="math-parenthesis math-round-parenthesis">)</span>' : p.toHTML(options);
    188     });
    189     var operatorMap = {
    190       equal: '==',
    191       unequal: '!=',
    192       smaller: '<',
    193       larger: '>',
    194       smallerEq: '<=',
    195       largerEq: '>='
    196     };
    197     var ret = paramStrings[0];
    198 
    199     for (var i = 0; i < this.conditionals.length; i++) {
    200       ret += '<span class="math-operator math-binary-operator math-explicit-binary-operator">' + (0, _string.escape)(operatorMap[this.conditionals[i]]) + '</span>' + paramStrings[i + 1];
    201     }
    202 
    203     return ret;
    204   };
    205   /**
    206    * Get LaTeX representation
    207    * @param {Object} options
    208    * @return {string} str
    209    */
    210 
    211 
    212   RelationalNode.prototype._toTex = function (options) {
    213     var parenthesis = options && options.parenthesis ? options.parenthesis : 'keep';
    214     var precedence = (0, _operators.getPrecedence)(this, parenthesis);
    215     var paramStrings = this.params.map(function (p, index) {
    216       var paramPrecedence = (0, _operators.getPrecedence)(p, parenthesis);
    217       return parenthesis === 'all' || paramPrecedence !== null && paramPrecedence <= precedence ? '\\left(' + p.toTex(options) + '\right)' : p.toTex(options);
    218     });
    219     var ret = paramStrings[0];
    220 
    221     for (var i = 0; i < this.conditionals.length; i++) {
    222       ret += _latex.latexOperators[this.conditionals[i]] + paramStrings[i + 1];
    223     }
    224 
    225     return ret;
    226   };
    227 
    228   return RelationalNode;
    229 }, {
    230   isClass: true,
    231   isNode: true
    232 });
    233 exports.createRelationalNode = createRelationalNode;