1 /* 2 JessieCode Interpreter and Compiler 3 4 Copyright 2011-2026 5 Michael Gerhaeuser, 6 Alfred Wassermann 7 8 JessieCode is free software dual licensed under the GNU LGPL or MIT License. 9 10 You can redistribute it and/or modify it under the terms of the 11 12 * GNU Lesser General Public License as published by 13 the Free Software Foundation, either version 3 of the License, or 14 (at your option) any later version 15 OR 16 * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT 17 18 JessieCode is distributed in the hope that it will be useful, 19 but WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 GNU Lesser General Public License for more details. 22 23 You should have received a copy of the GNU Lesser General Public License and 24 the MIT License along with JessieCode. If not, see <https://www.gnu.org/licenses/> 25 and <https://opensource.org/licenses/MIT/>. 26 */ 27 28 /*global JXG: true, define: true, window: true, console: true, self: true, document: true, parser: true*/ 29 /*jslint nomen: true, plusplus: true*/ 30 31 /** 32 * @fileoverview JessieCode is a scripting language designed to provide a 33 * simple scripting language to build constructions 34 * with JSXGraph. It is similar to JavaScript, but prevents access to the DOM. 35 * Hence, it can be used in community driven math portals which want to use 36 * JSXGraph to display interactive math graphics. 37 */ 38 39 import JXG from "../jxg.js"; 40 import Const from "../base/constants.js"; 41 import Text from "../base/text.js"; 42 import Mat from "../math/math.js"; 43 import Interval from "../math/ia.js"; 44 import Geometry from "../math/geometry.js"; 45 import Statistics from "../math/statistics.js"; 46 import Type from "../utils/type.js"; 47 import Env from "../utils/env.js"; 48 49 // IE 6-8 compatibility 50 if (!Object.create) { 51 Object.create = function (o, properties) { 52 if (typeof o !== 'object' && typeof o !== 'function') throw new TypeError('Object prototype may only be an Object: ' + o); 53 else if (o === null) throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument."); 54 55 if (typeof properties != 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument."); 56 57 function F() { } 58 59 F.prototype = o; 60 61 return new F(); 62 }; 63 } 64 65 var priv = { 66 modules: { 67 'math': Mat, 68 'math/geometry': Geometry, 69 'math/statistics': Statistics, 70 'math/numerics': Mat.Numerics 71 } 72 }; 73 74 /** 75 * A JessieCode object provides an interface to the parser and stores all variables and objects used within a JessieCode script. 76 * The optional argument <tt>code</tt> is interpreted after initializing. To evaluate more code after initializing a JessieCode instance 77 * please use {@link JXG.JessieCode#parse}. For code snippets like single expressions use {@link JXG.JessieCode#snippet}. 78 * @constructor 79 * @param {String} [code] Code to parse. 80 * @param {Boolean} [geonext=false] Geonext compatibility mode. 81 */ 82 JXG.JessieCode = function (code, geonext) { 83 // Control structures 84 85 /** 86 * The global scope. 87 * @type Object 88 */ 89 this.scope = { 90 id: 0, 91 hasChild: true, 92 args: [], 93 locals: {}, 94 context: null, 95 previous: null 96 }; 97 98 /** 99 * Keeps track of all possible scopes every required. 100 * @type Array 101 */ 102 this.scopes = []; 103 this.scopes.push(this.scope); 104 105 /** 106 * A stack to store debug information (like line and column where it was defined) of a parameter 107 * @type Array 108 * @private 109 */ 110 this.dpstack = [[]]; 111 112 /** 113 * Determines the parameter stack scope. 114 * @type Number 115 * @private 116 */ 117 this.pscope = 0; 118 119 /** 120 * Used to store the property-value definition while parsing an object literal. 121 * @type Array 122 * @private 123 */ 124 this.propstack = [{}]; 125 126 /** 127 * The current scope of the object literal stack {@link JXG.JessieCode#propstack}. 128 * @type Number 129 * @private 130 */ 131 this.propscope = 0; 132 133 /** 134 * Store the left hand side of an assignment. If an element is constructed and no attributes are given, this is 135 * used as the element's name. 136 * @type Array 137 * @private 138 */ 139 this.lhs = []; 140 141 /** 142 * lhs flag, used by JXG.JessieCode#replaceNames 143 * @type Boolean 144 * @default false 145 */ 146 this.isLHS = false; 147 148 /** 149 * The id of an HTML node in which innerText all warnings are stored (if no <tt>console</tt> object is available). 150 * @type String 151 * @default 'jcwarn' 152 */ 153 this.warnLog = 'jcwarn'; 154 155 /** 156 * Store $log messages in case there's no console. 157 * @type Array 158 */ 159 this.$log = []; 160 161 /** 162 * Built-in functions and constants 163 * @type Object 164 */ 165 this.builtIn = this.defineBuiltIn(); 166 167 /** 168 * List of all possible operands in JessieCode (except of JSXGraph objects). 169 * @type Object 170 */ 171 this.operands = this.getPossibleOperands(); 172 173 /** 174 * The board which currently is used to create and look up elements. 175 * @type JXG.Board 176 */ 177 this.board = null; 178 179 /** 180 * Force slider names to return value instead of node 181 * @type Boolean 182 */ 183 this.forceValueCall = false; 184 185 /** 186 * Keep track of which element is created in which line. 187 * @type Object 188 */ 189 this.lineToElement = {}; 190 191 this.parCurLine = 1; 192 this.parCurColumn = 0; 193 this.line = 1; 194 this.col = 1; 195 196 if (JXG.CA) { 197 // Old simplifier 198 this.CA = new JXG.CA(this.node, this.createNode, this); 199 } 200 if (JXG.CAS) { 201 // New simplifier 202 this.CAS = new JXG.CAS(this.node, this.createNode, this); 203 } 204 205 this.code = ''; 206 207 if (typeof code === 'string') { 208 this.parse(code, geonext); 209 } 210 }; 211 212 JXG.extend(JXG.JessieCode.prototype, /** @lends JXG.JessieCode.prototype */ { 213 /** 214 * Create a new parse tree node. 215 * @param {String} type Type of node, e.g. node_op, node_var, or node_const 216 * @param value The nodes value, e.g. a variables value or a functions body. 217 * @param {Array} children Arbitrary number of child nodes. 218 */ 219 node: function (type, value, children) { 220 return { 221 type: type, 222 value: value, 223 children: children 224 }; 225 }, 226 227 /** 228 * Create a new parse tree node. Basically the same as node(), but this builds 229 * the children part out of an arbitrary number of parameters, instead of one 230 * array parameter. 231 * @param {String} type Type of node, e.g. node_op, node_var, or node_const 232 * @param value The nodes value, e.g. a variables value or a functions body. 233 * @param children Arbitrary number of parameters; define the child nodes. 234 */ 235 createNode: function (type, value, children) { 236 var n = this.node(type, value, []), 237 i; 238 239 for (i = 2; i < arguments.length; i++) { 240 n.children.push(arguments[i]); 241 } 242 243 if (n.type === 'node_const' && Type.isNumber(n.value)) { 244 n.isMath = true; 245 } 246 247 n.line = this.parCurLine; 248 n.col = this.parCurColumn; 249 250 return n; 251 }, 252 253 /** 254 * Create a new scope. 255 * @param {Array} args 256 * @returns {Object} 257 */ 258 pushScope: function (args) { 259 var scope = { 260 args: args, 261 locals: {}, 262 context: null, 263 previous: this.scope 264 }; 265 266 this.scope.hasChild = true; 267 this.scope = scope; 268 scope.id = this.scopes.push(scope) - 1; 269 270 return scope; 271 }, 272 273 /** 274 * Remove the current scope and reinstate the previous scope 275 * @returns {Object} 276 */ 277 popScope: function () { 278 var s = this.scope.previous; 279 280 // make sure the global scope is not lost 281 this.scope = (s !== null) ? s : this.scope; 282 283 return this.scope; 284 }, 285 286 /** 287 * Looks up an {@link JXG.GeometryElement} by its id. 288 * @param {String} id 289 * @returns {JXG.GeometryElement} 290 */ 291 getElementById: function (id) { 292 return this.board.objects[id]; 293 }, 294 295 log: function () { 296 this.$log.push(arguments); 297 298 if (typeof console === 'object' && console.log) { 299 console.log.apply(console, arguments); 300 } 301 }, 302 303 /** 304 * Returns a element creator function which takes two parameters: the parents array and the attributes object. 305 * @param {String} vname The element type, e.g. 'point', 'line', 'midpoint' 306 * @returns {function} 307 */ 308 creator: (function () { 309 // stores the already defined creators 310 var _ccache = {}, r; 311 312 r = function (vname) { 313 var f; 314 315 // _ccache is global, i.e. it is the same for ALL JessieCode instances. 316 // That's why we need the board id here 317 if (typeof _ccache[this.board.id + vname] === 'function') { 318 f = _ccache[this.board.id + vname]; 319 } else { 320 f = (function (that) { 321 return function (parameters, attributes) { 322 var attr; 323 324 if (Type.exists(attributes)) { 325 attr = attributes; 326 } else { 327 attr = {}; 328 } 329 if (attr.name === undefined && attr.id === undefined) { 330 attr.name = ((that.lhs[that.scope.id] !== 0) ? that.lhs[that.scope.id] : ''); 331 } 332 return that.board.create(vname, parameters, attr); 333 }; 334 }(this)); 335 336 f.creator = true; 337 _ccache[this.board.id + vname] = f; 338 } 339 340 return f; 341 }; 342 343 r.clearCache = function () { 344 _ccache = {}; 345 }; 346 347 return r; 348 }()), 349 350 /** 351 * Assigns a value to a variable in the current scope. 352 * @param {String} vname Variable name 353 * @param value Anything 354 * @see JXG.JessieCode#sstack 355 * @see JXG.JessieCode#scope 356 */ 357 letvar: function (vname, value) { 358 if (this.builtIn[vname]) { 359 this._warn('"' + vname + '" is a predefined value.'); 360 } 361 362 this.scope.locals[vname] = value; 363 }, 364 365 /** 366 * Checks if the given variable name can be found in the current scope chain. 367 * @param {String} vname 368 * @returns {Object} A reference to the scope object the variable can be found in or null if it can't be found. 369 */ 370 isLocalVariable: function (vname) { 371 var s = this.scope; 372 373 while (s !== null) { 374 if (Type.exists(s.locals[vname])) { 375 return s; 376 } 377 378 s = s.previous; 379 } 380 381 return null; 382 }, 383 384 /** 385 * Checks if the given variable name is a parameter in any scope from the current to the global scope. 386 * @param {String} vname 387 * @returns {Object} A reference to the scope object that contains the variable in its arg list. 388 */ 389 isParameter: function (vname) { 390 var s = this.scope; 391 392 while (s !== null) { 393 if (Type.indexOf(s.args, vname) > -1) { 394 return s; 395 } 396 397 s = s.previous; 398 } 399 400 return null; 401 }, 402 403 /** 404 * Checks if the given variable name is a valid creator method. 405 * @param {String} vname 406 * @returns {Boolean} 407 */ 408 isCreator: function (vname) { 409 // check for an element with this name 410 return !!JXG.elements[vname]; 411 }, 412 413 /** 414 * Checks if the given variable identifier is a valid member of the JavaScript Math Object. 415 * @param {String} vname 416 * @returns {Boolean} 417 */ 418 isMathMethod: function (vname) { 419 return vname !== 'E' && !!Math[vname]; 420 }, 421 422 /** 423 * Returns true if the given identifier is a builtIn variable/function. 424 * @param {String} vname 425 * @returns {Boolean} 426 */ 427 isBuiltIn: function (vname) { 428 return !!this.builtIn[vname]; 429 }, 430 431 /** 432 * Looks up the value of the given variable. We use a simple type inspection. 433 * 434 * @param {String} vname Name of the variable 435 * @param {Boolean} [local=false] Only look up the internal symbol table and don't look for 436 * the <tt>vname</tt> in Math or the element list. 437 * @param {Boolean} [isFunctionName=false] Lookup function of type builtIn, Math.*, creator. 438 * 439 * @see JXG.JessieCode#resolveType 440 */ 441 getvar: function (vname, local, isFunctionName) { 442 var s; 443 444 local = Type.def(local, false); 445 446 // Local scope has always precedence 447 s = this.isLocalVariable(vname); 448 449 if (s !== null) { 450 return s.locals[vname]; 451 } 452 453 // Handle the - so far only - few constants by hard coding them. 454 if (vname === '$board' || vname === 'EULER' || vname === 'PI') { 455 return this.builtIn[vname]; 456 } 457 458 if (isFunctionName) { 459 if (this.isBuiltIn(vname)) { 460 return this.builtIn[vname]; 461 } 462 463 if (this.isMathMethod(vname)) { 464 return Math[vname]; 465 } 466 467 // check for an element with this name 468 if (this.isCreator(vname)) { 469 return this.creator(vname); 470 } 471 } 472 473 if (!local) { 474 s = this.board.select(vname); 475 if (s !== vname) { 476 return s; 477 } 478 } 479 }, 480 481 /** 482 * Look up the value of a local variable. 483 * @param {string} vname 484 * @returns {*} 485 */ 486 resolve: function (vname) { 487 var s = this.scope; 488 489 while (s !== null) { 490 if (Type.exists(s.locals[vname])) { 491 return s.locals[vname]; 492 } 493 494 s = s.previous; 495 } 496 }, 497 498 /** 499 * TODO this needs to be called from JS and should not generate JS code 500 * Looks up a variable identifier in various tables and generates JavaScript code that could be eval'd to get the value. 501 * @param {String} vname Identifier 502 * @param {Boolean} [local=false] Don't resolve ids and names of elements 503 * @param {Boolean} [withProps=false] 504 */ 505 getvarJS: function (vname, local, withProps) { 506 var s, r = '', re; 507 508 local = Type.def(local, false); 509 withProps = Type.def(withProps, false); 510 511 s = this.isParameter(vname); 512 if (s !== null) { 513 return vname; 514 } 515 516 s = this.isLocalVariable(vname); 517 if (s !== null && !withProps) { 518 return '$jc$.resolve(\'' + vname + '\')'; 519 } 520 521 // check for an element with this name 522 if (this.isCreator(vname)) { 523 return '(function () { var a = Array.prototype.slice.call(arguments, 0), props = ' + (withProps ? 'a.pop()' : '{}') + '; return $jc$.board.create.apply($jc$.board, [\'' + vname + '\'].concat([a, props])); })'; 524 } 525 526 if (withProps) { 527 this._error('Syntax error (attribute values are allowed with element creators only)'); 528 } 529 530 if (this.isBuiltIn(vname)) { 531 // If src does not exist, it is a number. In that case, just return the value. 532 r = this.builtIn[vname].src || this.builtIn[vname]; 533 534 // Get the "real" name of the function 535 if (Type.isNumber(r)) { 536 return r; 537 } 538 // Search a JSXGraph object in board 539 if (r.match(/board\.select/)) { 540 return r; 541 } 542 543 /* eslint-disable no-useless-escape */ 544 vname = r.split('.').pop(); 545 if (Type.exists(this.board.mathLib)) { 546 // Handle builtin case: ln(x) -> Math.log 547 re = new RegExp('^Math\.' + vname); 548 if (re.exec(r) !== null) { 549 return r.replace(re, '$jc$.board.mathLib.' + vname); 550 } 551 } 552 if (Type.exists(this.board.mathLibJXG)) { 553 // Handle builtin case: factorial(x) -> JXG.Math.factorial 554 re = new RegExp('^JXG\.Math\.'); 555 if (re.exec(r) !== null) { 556 return r.replace(re, '$jc$.board.mathLibJXG.'); 557 } 558 return r; 559 } 560 /* eslint-enable no-useless-escape */ 561 return r; 562 563 // return this.builtIn[vname].src || this.builtIn[vname]; 564 } 565 566 if (this.isMathMethod(vname)) { 567 return '$jc$.board.mathLib.' + vname; 568 // return 'Math.' + vname; 569 } 570 571 // if (!local) { 572 // if (Type.isId(this.board, vname)) { 573 // r = '$jc$.board.objects[\'' + vname + '\']'; 574 // } else if (Type.isName(this.board, vname)) { 575 // r = '$jc$.board.elementsByName[\'' + vname + '\']'; 576 // } else if (Type.isGroup(this.board, vname)) { 577 // r = '$jc$.board.groups[\'' + vname + '\']'; 578 // } 579 580 // return r; 581 // } 582 if (!local) { 583 if (Type.isId(this.board, vname)) { 584 r = '$jc$.board.objects[\'' + vname + '\']'; 585 if (this.board.objects[vname].elType === 'slider') { 586 r += '.Value()'; 587 } 588 } else if (Type.isName(this.board, vname)) { 589 r = '$jc$.board.elementsByName[\'' + vname + '\']'; 590 if (this.board.elementsByName[vname].elType === 'slider') { 591 r += '.Value()'; 592 } 593 } else if (Type.isGroup(this.board, vname)) { 594 r = '$jc$.board.groups[\'' + vname + '\']'; 595 } 596 597 return r; 598 } 599 600 return ''; 601 }, 602 603 /** 604 * Adds the property <tt>isMap</tt> to a function and sets it to true. 605 * @param {function} f 606 * @returns {function} 607 */ 608 makeMap: function (f) { 609 f.isMap = true; 610 611 return f; 612 }, 613 614 functionCodeJS: function (node) { 615 var p = node.children[0].join(', '), 616 bo = '', 617 bc = ''; 618 619 if (node.value === 'op_map') { 620 bo = '{ return '; 621 bc = ' }'; 622 } 623 624 return 'function (' + p + ') {\n' + 625 'var $oldscope$ = $jc$.scope;\n' + 626 '$jc$.scope = $jc$.scopes[' + this.scope.id + '];\n' + 627 'var r = (function () ' + bo + this.compile(node.children[1], true) + bc + ')();\n' + 628 '$jc$.scope = $oldscope$;\n' + 629 'return r;\n' + 630 '}'; 631 }, 632 633 /** 634 * Converts a node type <tt>node_op</tt> and value <tt>op_map</tt> or <tt>op_function</tt> into a executable 635 * function. Does a simple type inspection. 636 * @param {Object} node 637 * @returns {function} 638 * @see JXG.JessieCode#resolveType 639 */ 640 defineFunction: function (node) { 641 var fun, i, that = this, 642 list = node.children[0], 643 scope = this.pushScope(list); 644 645 if (this.board.options.jc.compile) { 646 this.isLHS = false; 647 648 // we currently need to put the parameters into the local scope 649 // until the compiled JS variable lookup code is fixed 650 for (i = 0; i < list.length; i++) { 651 scope.locals[list[i]] = list[i]; 652 } 653 654 this.replaceNames(node.children[1]); 655 656 /** @ignore */ 657 fun = (function (jc) { 658 var fun, 659 // str = 'var f = ' + $jc$.functionCodeJS(node) + '; f;'; 660 str = 'var f = function($jc$) { return ' + 661 jc.functionCodeJS(node) + 662 '}; f;'; 663 664 try { 665 // yeah, eval is evil, but we don't have much choice here. 666 // the str is well defined and there is no user input in it that we didn't check before 667 668 /*jslint evil:true*/ 669 // fun = eval(str); 670 fun = eval(str)(jc); 671 /*jslint evil:false*/ 672 673 scope.argtypes = []; 674 for (i = 0; i < list.length; i++) { 675 scope.argtypes.push(that.resolveType(list[i], node)); 676 } 677 678 return fun; 679 } catch (e) { 680 // $jc$._warn('error compiling function\n\n' + str + '\n\n' + e.toString()); 681 jc._warn("error compiling function\n\n" + str + "\n\n" + e.toString()); 682 return function () { }; 683 } 684 }(this)); 685 686 // clean up scope 687 this.popScope(); 688 } else { 689 /** @ignore */ 690 fun = (function (_pstack, that, id) { 691 return function () { 692 var r, oldscope; 693 694 oldscope = that.scope; 695 that.scope = that.scopes[id]; 696 697 for (r = 0; r < _pstack.length; r++) { 698 that.scope.locals[_pstack[r]] = arguments[r]; 699 } 700 701 r = that.execute(node.children[1]); 702 that.scope = oldscope; 703 704 return r; 705 }; 706 }(list, this, scope.id)); 707 } 708 709 fun.node = node; 710 fun.scope = scope; 711 fun.toJS = fun.toString; 712 fun.toString = (function (_that) { 713 return function () { 714 return _that.compile(_that.replaceIDs(Type.deepCopy(node))); 715 }; 716 }(this)); 717 718 fun.deps = {}; 719 this.collectDependencies(node.children[1], node.children[0], fun.deps); 720 721 return fun; 722 }, 723 724 /** 725 * Merge all attribute values given with an element creator into one object. 726 * @param {Object} o An arbitrary number of objects 727 * @returns {Object} All given objects merged into one. If properties appear in more (case sensitive) than one 728 * object the last value is taken. 729 */ 730 mergeAttributes: function (o) { 731 var i, attr = {}; 732 733 for (i = 0; i < arguments.length; i++) { 734 attr = Type.deepCopy(attr, arguments[i], true); 735 } 736 737 return attr; 738 }, 739 740 /** 741 * Sets the property <tt>what</tt> of <tt>o</tt> to <tt>value</tt> 742 * @param {JXG.Point|JXG.Text} o 743 * @param {String} what 744 * @param value 745 */ 746 setProp: function (o, what, value) { 747 var par = {}, x, y; 748 749 if (o.elementClass === Const.OBJECT_CLASS_POINT && (what === 'X' || what === 'Y')) { 750 // set coords 751 752 what = what.toLowerCase(); 753 754 // we have to deal with three cases here: 755 // o.isDraggable && typeof value === number: 756 // stay draggable, just set the new coords (e.g. via moveTo) 757 // o.isDraggable && typeof value === function: 758 // convert to !o.isDraggable, set the new coords via o.addConstraint() 759 // !o.isDraggable: 760 // stay !o.isDraggable, update the given coord by overwriting X/YEval 761 762 if (o.isDraggable && typeof value === 'number') { 763 x = (what === 'x') ? value : o.X(); 764 y = (what === 'y') ? value : o.Y(); 765 766 o.setPosition(Const.COORDS_BY_USER, [x, y]); 767 } else if (o.isDraggable && (typeof value === 'function' || typeof value === 'string')) { 768 x = (what === 'x') ? value : o.coords.usrCoords[1]; 769 y = (what === 'y') ? value : o.coords.usrCoords[2]; 770 771 o.addConstraint([x, y]); 772 } else if (!o.isDraggable) { 773 x = (what === 'x') ? value : o.XEval.origin; 774 y = (what === 'y') ? value : o.YEval.origin; 775 776 o.addConstraint([x, y]); 777 } 778 779 this.board.update(); 780 } else if (o.elementClass === Const.OBJECT_CLASS_TEXT && (what === 'X' || what === 'Y')) { 781 if (typeof value === 'number') { 782 o[what] = function () { return value; }; 783 } else if (typeof value === 'function') { 784 o.isDraggable = false; 785 o[what] = value; 786 } else if (typeof value === 'string') { 787 o.isDraggable = false; 788 o[what] = Type.createFunction(value, this.board); 789 o[what + 'jc'] = value; 790 } 791 792 o[what].origin = value; 793 794 this.board.update(); 795 } else if (o.type && o.elementClass && o.visProp) { 796 if (Type.exists(o[o.methodMap[what]]) && typeof o[o.methodMap[what]] !== 'function') { 797 o[o.methodMap[what]] = value; 798 } else { 799 par[what] = value; 800 o.setAttribute(par); 801 } 802 } else { 803 o[what] = value; 804 } 805 }, 806 807 /** 808 * Generic method to parse JessieCode. 809 * This consists of generating an AST with parser.parse, 810 * apply simplifying rules from CA and 811 * manipulate the AST according to the second parameter "cmd". 812 * @param {String} code JessieCode code to be parsed 813 * @param {String} cmd Type of manipulation to be done with AST 814 * @param {Object} [options] Object with attributes <ul> 815 * <li>{Boolean} [geonext=false] Geonext compatibility mode.</li> 816 * <li>{Boolean} [dontstore=false] If false, the code string is stored in this.code, i.e. in the JessieCode object, e.g. in board.jc.</li> 817 * </ul> 818 * @return {Object} Returns result of computation as directed in cmd. 819 */ 820 _genericParse: function (code, cmd, options) { 821 var i, setTextBackup, ast, result, 822 ccode = code.replace(/\r\n/g, '\n').split('\n'), 823 cleaned = []; 824 825 if (!Type.exists(options)) { 826 options = {}; 827 } 828 829 if (!options.dontstore) { 830 this.code += code + '\n'; 831 } 832 833 if (Text) { 834 setTextBackup = Text.prototype.setText; 835 Text.prototype.setText = Text.prototype.setTextJessieCode; 836 } 837 838 try { 839 for (i = 0; i < ccode.length; i++) { 840 if (!!options.geonext) { 841 ccode[i] = JXG.GeonextParser.geonext2JS(ccode[i], this.board); 842 } 843 cleaned.push(ccode[i]); 844 } 845 846 code = cleaned.join('\n'); 847 ast = parser.parse(code); 848 if (this.CA) { 849 ast = this.CA.expandDerivatives(ast, null, ast); 850 ast = this.CA.removeTrivialNodes(ast); 851 } 852 if (this.CAS) { 853 // Search for expression of form `D(f, x)` and determine the 854 // the derivative symbolically. 855 ast = this.CAS.expandDerivatives(ast, null, ast); 856 857 // options.method = options.method || "strong"; 858 // options.form = options.form || "fractions"; 859 // options.steps = options.steps || []; 860 // options.iterations = options.iterations || 1000; 861 // ast = this.CAS._simplify_aux(ast, options); 862 } 863 switch (cmd) { 864 case 'parse': 865 result = this.execute(ast); 866 break; 867 case 'manipulate': 868 result = this.compile(ast); 869 break; 870 case 'simplify': 871 if (Type.exists(this.CAS)) { 872 options.method = options.method || "strong"; 873 options.form = options.form || "fractions"; 874 options.steps = options.steps || []; 875 options.iterations = options.iterations || 1000; 876 ast = this.CAS.simplify(ast, options); 877 result = this.CAS.compile(ast); 878 } else { 879 result = this.compile(ast); 880 } 881 break; 882 case 'format': 883 result = this.compile(ast, false, options); 884 break; 885 case 'getAst': 886 result = ast; 887 break; 888 default: 889 result = false; 890 } 891 } catch (e) { // catch is mandatory in old IEs 892 // console.log(e); 893 // We throw the error again, 894 // so the user can catch it. 895 throw e; 896 } finally { 897 // make sure the original text method is back in place 898 if (Text) { 899 Text.prototype.setText = setTextBackup; 900 } 901 } 902 903 return result; 904 }, 905 906 /** 907 * Parses JessieCode. 908 * This consists of generating an AST with parser.parse, apply simplifying rules 909 * from CA and executing the ast by calling this.execute(ast). 910 * 911 * @param {String} code JessieCode code to be parsed 912 * @param {Boolean} [geonext=false] Geonext compatibility mode. 913 * @param {Boolean} [dontstore=false] If false, the code string is stored in this.code. 914 * @return {Object} Parse JessieCode code and execute it. 915 */ 916 parse: function (code, geonext, dontstore) { 917 return this._genericParse(code, 'parse', {geonext: geonext, dontstore: dontstore}); 918 }, 919 920 /** 921 * Manipulate JessieCode. 922 * This consists of generating an AST with parser.parse, 923 * apply simplifying rules from CA 924 * and compile the AST back to JessieCode. 925 * 926 * @param {String} code JessieCode code to be parsed 927 * @param {Boolean} [geonext=false] Geonext compatibility mode. 928 * @param {Boolean} [dontstore=false] If false, the code string is stored in this.code. 929 * @return {String} Simplified JessieCode code 930 */ 931 manipulate: function (code, geonext, dontstore) { 932 return this._genericParse(code, 'manipulate', {geonext: geonext, dontstore: dontstore}); 933 }, 934 935 /** 936 * Manipulate JessieCode. 937 * This consists of generating an AST with parser.parse, 938 * apply simplifying rules from CAS 939 * and compile the AST back to JessieCode with minimal number of parentheses. 940 * 941 * @param {String} code JessieCode code to be parsed 942 * @return {String} Simplified JessieCode code 943 */ 944 simplify: function (code) { 945 return this._genericParse(code, 'simplify'); 946 }, 947 948 /** 949 * Format JessieCode. 950 * This consists of generating an AST with parser.parse, 951 * and compile the AST back to JessieCode with options. 952 * 953 * @param {String} code JessieCode code to be parsed. 954 * @param {Object} options For possible options see param "format" in {@link JXG.JessieCode#compile}. 955 * @return {String} Manipulated JessieCode string. This is no necessarily a parsable JessieCode code! 956 */ 957 format: function (code, options) { 958 return this._genericParse(code, 'format', options); 959 }, 960 961 /** 962 * Get abstract syntax tree (AST) from JessieCode code. 963 * This consists of generating an AST with parser.parse. 964 * 965 * @param {String} code 966 * @param {Boolean} [geonext=false] Geonext compatibility mode. 967 * @param {Boolean} [dontstore=false] If false, the code string is stored in this.code. 968 * @return {Node} AST 969 */ 970 getAST: function (code, geonext, dontstore) { 971 return this._genericParse(code, 'getAst', {geonext: geonext, dontstore: dontstore}); 972 }, 973 974 /** 975 * Parses a JessieCode snippet, e.g. "3+4", and wraps it into a function, if desired. 976 * @param {String} code A small snippet of JessieCode. Must not be an assignment. 977 * @param {Boolean} [funwrap=true] If true, the code is wrapped in a function. 978 * @param {String} [varname=''] Name of the parameter(s) 979 * @param {Boolean} [geonext=false] Geonext compatibility mode. 980 * @param {Boolean} [forceValueCall=true] Force evaluation of value method of sliders. 981 */ 982 snippet: function (code, funwrap, varname, geonext, forceValueCall) { 983 var c; 984 985 funwrap = Type.def(funwrap, true); 986 varname = Type.def(varname, ''); 987 geonext = Type.def(geonext, false); 988 this.forceValueCall = Type.def(forceValueCall, true); 989 990 c = (funwrap ? ' function (' + varname + ') { return ' : '') + 991 code + 992 (funwrap ? '; }' : '') + ';'; 993 994 return this.parse(c, geonext, true); 995 }, 996 997 /** 998 * Traverses through the given subtree and changes all values of nodes with the replaced flag set by 999 * {@link JXG.JessieCode#replaceNames} to the name of the element (if not empty). 1000 * @param {Object} node 1001 */ 1002 replaceIDs: function (node) { 1003 var i, v; 1004 1005 if (node.replaced) { 1006 // These children exist, if node.replaced is set. 1007 v = this.board.objects[node.children[1][0].value]; 1008 1009 if (Type.exists(v) && v.name !== "") { 1010 node.type = 'node_var'; 1011 node.value = v.name; 1012 1013 // Maybe it's not necessary, but just to be sure that everything is cleaned up we better delete all 1014 // children and the replaced flag 1015 node.children.length = 0; 1016 delete node.replaced; 1017 } 1018 } 1019 1020 if (Type.isArray(node)) { 1021 for (i = 0; i < node.length; i++) { 1022 node[i] = this.replaceIDs(node[i]); 1023 } 1024 } 1025 1026 if (node.children) { 1027 // assignments are first evaluated on the right hand side 1028 for (i = node.children.length; i > 0; i--) { 1029 if (Type.exists(node.children[i - 1])) { 1030 node.children[i - 1] = this.replaceIDs(node.children[i - 1]); 1031 } 1032 1033 } 1034 } 1035 1036 return node; 1037 }, 1038 1039 /** 1040 * Traverses through the given subtree and changes all elements referenced by names through referencing them by ID. 1041 * An identifier is only replaced if it is not found in all scopes above the current scope and if it 1042 * has not been blacklisted within the codeblock determined by the given subtree. 1043 * @param {Object} node 1044 * @param {Boolean} [callValuePar=false] if true, uses $value() instead of $() in createReplacementNode 1045 */ 1046 replaceNames: function (node, callValuePar) { 1047 var i, v, 1048 callValue = false; 1049 1050 if (callValuePar !== undefined) { 1051 callValue = callValuePar; 1052 } 1053 1054 v = node.value; 1055 1056 // We are interested only in nodes of type node_var and node_op > op_lhs. 1057 // Currently, we are not checking if the id is a local variable. in this case, we're stuck anyway. 1058 1059 if (node.type === 'node_op' && v === 'op_lhs' && node.children.length === 1) { 1060 this.isLHS = true; 1061 } else if (node.type === 'node_var') { 1062 if (this.isLHS) { 1063 this.letvar(v, true); 1064 } else if (!Type.exists(this.getvar(v, true)) && Type.exists(this.board.elementsByName[v])) { 1065 if (callValue && this.board.elementsByName[v].elType !== 'slider') { 1066 callValue = false; 1067 } 1068 node = this.createReplacementNode(node, callValue); 1069 } 1070 } 1071 1072 if (Type.isArray(node)) { 1073 for (i = 0; i < node.length; i++) { 1074 node[i] = this.replaceNames(node[i], callValue); 1075 } 1076 } 1077 1078 if (node.children) { 1079 // Replace slider reference by call of slider.Value() 1080 if (this.forceValueCall && // It must be enforced, see snippet. 1081 ( 1082 // 1. case: sin(a), max(a, 0), ... 1083 (node.value === "op_execfun" && 1084 // Not in cases V(a), $(a) 1085 node.children[0].value !== 'V' && node.children[0].value !== '$' && 1086 // Function must be a math function. This ensures that a number is required as input. 1087 (Type.exists(Math[node.children[0].value]) || Type.exists(Mat[node.children[0].value])) && 1088 // node.children[1].length === 1 && 1089 node.children[1][0].type === 'node_var' 1090 ) || 1091 // 2. case: slider is the whole expression: 'a' 1092 (node.value === "op_return" && 1093 node.children.length === 1 && 1094 node.children[0].type === 'node_var' 1095 ) 1096 ) 1097 ) { 1098 callValue = true; 1099 } 1100 1101 // Assignments are first evaluated on the right hand side 1102 for (i = node.children.length; i > 0; i--) { 1103 if (Type.exists(node.children[i - 1])) { 1104 node.children[i - 1] = this.replaceNames(node.children[i - 1], callValue); 1105 } 1106 } 1107 } 1108 1109 if (node.type === 'node_op' && node.value === 'op_lhs' && node.children.length === 1) { 1110 this.isLHS = false; 1111 } 1112 1113 return node; 1114 }, 1115 1116 /** 1117 * Replaces node_var nodes with node_op>op_execfun nodes, calling the internal $() function with the id of the 1118 * element accessed by the node_var node. 1119 * @param {Object} node 1120 * @param {Boolean} [callValue=undefined] if true, uses $value() instead of $() 1121 * @returns {Object} op_execfun node 1122 */ 1123 createReplacementNode: function (node, callValue) { 1124 var v = node.value, 1125 el = this.board.elementsByName[v]; 1126 1127 // If callValue: get handle to this node_var and call its Value method. 1128 // Otherwise return the object. 1129 node = this.createNode('node_op', 'op_execfun', 1130 this.createNode('node_var', ((callValue === true) ? '$value' : '$')), 1131 [this.createNode('node_str', el.id)]); 1132 1133 node.replaced = true; 1134 1135 return node; 1136 }, 1137 1138 /** 1139 * Search the parse tree below <tt>node</tt> for <em>stationary</em> dependencies, i.e. dependencies hard coded into 1140 * the function. 1141 * @param {Object} node 1142 * @param {Array} varnames List of variable names of the function 1143 * @param {Object} result An object where the referenced elements will be stored. Access key is their id. 1144 */ 1145 collectDependencies: function (node, varnames, result) { 1146 var i, v, e, le; 1147 1148 if (Type.isArray(node)) { 1149 le = node.length; 1150 for (i = 0; i < le; i++) { 1151 this.collectDependencies(node[i], varnames, result); 1152 } 1153 return; 1154 } 1155 1156 v = node.value; 1157 1158 if (node.type === 'node_var' && 1159 varnames.indexOf(v) < 0 // v is not contained in the list of variables of that function 1160 ) { 1161 e = this.getvar(v); 1162 if (e && e.visProp && e.elType && e.elementClass && e.id 1163 // Sliders are the only elements which are given by names. 1164 // Wrong, a counter example is: circle(c, function() { return p1.Dist(p2); }) 1165 // && e.elType === 'slider' 1166 ) { 1167 result[e.id] = e; 1168 } 1169 } 1170 1171 // The $()-function-calls are special because their parameter is given as a string, not as a node_var. 1172 if (node.type === 'node_op' && node.value === 'op_execfun' && 1173 node.children.length > 1 && 1174 (node.children[0].value === '$' || node.children[0].value === '$value') && 1175 node.children[1].length > 0) { 1176 1177 e = node.children[1][0].value; 1178 result[e] = this.board.objects[e]; 1179 } 1180 1181 if (node.children) { 1182 for (i = node.children.length; i > 0; i--) { 1183 if (Type.exists(node.children[i - 1])) { 1184 this.collectDependencies(node.children[i - 1], varnames, result); 1185 } 1186 } 1187 } 1188 }, 1189 1190 resolveProperty: function (e, v, compile) { 1191 compile = Type.def(compile, false); 1192 1193 // is it a geometry element or a board? 1194 if (e /*&& e.type && e.elementClass*/ && e.methodMap) { 1195 // yeah, it is. but what does the user want? 1196 if (Type.exists(e.subs) && Type.exists(e.subs[v])) { 1197 // a subelement it is, good sir. 1198 e = e.subs; 1199 } else if (Type.exists(e.methodMap[v])) { 1200 // the user wants to call a method 1201 v = e.methodMap[v]; 1202 } else { 1203 // the user wants to change an attribute 1204 e = e.visProp; 1205 v = v.toLowerCase(); 1206 } 1207 } 1208 1209 if (Type.isFunction(e)) { 1210 this._error('Accessing function properties is not allowed.'); 1211 } 1212 1213 if (!Type.exists(e)) { 1214 this._error(e + ' is not an object'); 1215 } 1216 1217 if (!Type.exists(e[v])) { 1218 this._error('unknown property ' + v); 1219 } 1220 1221 if (compile && typeof e[v] === 'function') { 1222 return function () { return e[v].apply(e, arguments); }; 1223 } 1224 1225 return e[v]; 1226 }, 1227 1228 /** 1229 * Type inspection: check if the string vname appears as function name in the 1230 * AST node. Used in "op_execfun". This allows the JessieCode examples below. 1231 * 1232 * @private 1233 * @param {String} vname 1234 * @param {Object} node 1235 * @returns 'any' or 'function' 1236 * @see JXG.JessieCode#execute 1237 * @see JXG.JessieCode#getvar 1238 * 1239 * @example 1240 * var p = board.create('point', [2, 0], {name: 'X'}); 1241 * var txt = 'X(X)'; 1242 * console.log(board.jc.parse(txt)); 1243 * 1244 * @example 1245 * var p = board.create('point', [2, 0], {name: 'X'}); 1246 * var txt = 'f = function(el, X) { return X(el); }; f(X, X);'; 1247 * console.log(board.jc.parse(txt)); 1248 * 1249 * @example 1250 * var p = board.create('point', [2, 0], {name: 'point'}); 1251 * var txt = 'B = point(1,3); X(point);'; 1252 * console.log(board.jc.parse(txt)); 1253 * 1254 * @example 1255 * var p = board.create('point', [2, 0], {name: 'A'}); 1256 * var q = board.create('point', [-2, 0], {name: 'X'}); 1257 * var txt = 'getCoord=function(p, f){ return f(p); }; getCoord(A, X);'; 1258 * console.log(board.jc.parse(txt)); 1259 */ 1260 resolveType: function (vname, node) { 1261 var i, t, 1262 type = 'any'; // Possible values: 'function', 'any' 1263 1264 if (Type.isArray(node)) { 1265 // node contains the parameters of a function call or function declaration 1266 for (i = 0; i < node.length; i++) { 1267 t = this.resolveType(vname, node[i]); 1268 if (t !== 'any') { 1269 type = t; 1270 return type; 1271 } 1272 } 1273 } 1274 1275 if (node.type === 'node_op' && node.value === 'op_execfun' && 1276 node.children[0].type === 'node_var' && node.children[0].value === vname) { 1277 return 'function'; 1278 } 1279 1280 if (node.type === 'node_op') { 1281 for (i = 0; i < node.children.length; i++) { 1282 if (node.children[0].type === 'node_var' && node.children[0].value === vname && 1283 (node.value === 'op_add' || node.value === 'op_sub' || node.value === 'op_mul' || 1284 node.value === 'op_div' || node.value === 'op_mod' || node.value === 'op_exp' || 1285 node.value === 'op_neg')) { 1286 return 'any'; 1287 } 1288 } 1289 1290 for (i = 0; i < node.children.length; i++) { 1291 t = this.resolveType(vname, node.children[i]); 1292 if (t !== 'any') { 1293 type = t; 1294 return type; 1295 } 1296 } 1297 } 1298 1299 return 'any'; 1300 }, 1301 1302 /** 1303 * Resolves the lefthand side of an assignment operation 1304 * @param node 1305 * @returns {Object} An object with two properties. <strong>o</strong> which contains the object, and 1306 * a string <strong>what</strong> which contains the property name. 1307 */ 1308 getLHS: function (node) { 1309 var res; 1310 1311 if (node.type === 'node_var') { 1312 res = { 1313 o: this.scope.locals, 1314 what: node.value 1315 }; 1316 } else if (node.type === 'node_op' && node.value === 'op_property') { 1317 res = { 1318 o: this.execute(node.children[0]), 1319 what: node.children[1] 1320 }; 1321 } else if (node.type === 'node_op' && node.value === 'op_extvalue') { 1322 res = { 1323 o: this.execute(node.children[0]), 1324 what: this.execute(node.children[1]) 1325 }; 1326 } else { 1327 throw new Error('Syntax error: Invalid left-hand side of assignment.'); 1328 } 1329 1330 return res; 1331 }, 1332 1333 getLHSCompiler: function (node, js) { 1334 var res; 1335 1336 if (node.type === 'node_var') { 1337 res = node.value; 1338 } else if (node.type === 'node_op' && node.value === 'op_property') { 1339 res = [ 1340 this.compile(node.children[0], js), 1341 "'" + node.children[1] + "'" 1342 ]; 1343 } else if (node.type === 'node_op' && node.value === 'op_extvalue') { 1344 res = [ 1345 this.compile(node.children[0], js), 1346 (node.children[1].type === 'node_const') ? node.children[1].value : this.compile(node.children[1], js) 1347 ]; 1348 } else { 1349 throw new Error('Syntax error: Invalid left-hand side of assignment.'); 1350 } 1351 1352 return res; 1353 }, 1354 1355 /** 1356 * Executes a parse subtree. 1357 * @param {Object} node 1358 * @returns {Number|String|Object|Boolean} Something 1359 * @private 1360 */ 1361 execute: function (node) { 1362 var ret, v, i, e, l, undef, list, ilist, 1363 parents = [], 1364 // exec fun 1365 fun, attr, sc; 1366 1367 ret = 0; 1368 1369 if (!node) { 1370 return ret; 1371 } 1372 1373 this.line = node.line; 1374 this.col = node.col; 1375 1376 switch (node.type) { 1377 case 'node_op': 1378 switch (node.value) { 1379 case 'op_none': 1380 if (node.children[0]) { 1381 this.execute(node.children[0]); 1382 } 1383 if (node.children[1]) { 1384 ret = this.execute(node.children[1]); 1385 } 1386 break; 1387 case 'op_block': 1388 ret = this.execute(node.children[0]); 1389 break; 1390 case 'op_assign': 1391 v = this.getLHS(node.children[0]); 1392 this.lhs[this.scope.id] = v.what; 1393 1394 if (v.o.type && v.o.elementClass && v.o.methodMap && v.what === 'label') { 1395 this._error('Left-hand side of assignment is read-only.'); 1396 } 1397 1398 ret = this.execute(node.children[1]); 1399 if (v.o !== this.scope.locals || (Type.isArray(v.o) && typeof v.what === 'number')) { 1400 // it is either an array component being set or a property of an object. 1401 this.setProp(v.o, v.what, ret); 1402 } else { 1403 // this is just a local variable inside JessieCode 1404 this.letvar(v.what, ret); 1405 } 1406 this.lhs[this.scope.id] = 0; 1407 break; 1408 case 'op_if': 1409 if (this.execute(node.children[0])) { 1410 ret = this.execute(node.children[1]); 1411 } 1412 break; 1413 case 'op_conditional': 1414 // fall through 1415 case 'op_if_else': 1416 if (this.execute(node.children[0])) { 1417 ret = this.execute(node.children[1]); 1418 } else { 1419 ret = this.execute(node.children[2]); 1420 } 1421 break; 1422 case 'op_while': 1423 while (this.execute(node.children[0])) { 1424 this.execute(node.children[1]); 1425 } 1426 break; 1427 case 'op_do': 1428 do { 1429 this.execute(node.children[0]); 1430 } while (this.execute(node.children[1])); 1431 break; 1432 case 'op_for': 1433 for (this.execute(node.children[0]); this.execute(node.children[1]); this.execute(node.children[2])) { 1434 this.execute(node.children[3]); 1435 } 1436 break; 1437 case 'op_proplst': 1438 if (node.children[0]) { 1439 this.execute(node.children[0]); 1440 } 1441 if (node.children[1]) { 1442 this.execute(node.children[1]); 1443 } 1444 break; 1445 case 'op_emptyobject': 1446 ret = {}; 1447 break; 1448 case 'op_proplst_val': 1449 this.propstack.push({}); 1450 this.propscope++; 1451 1452 this.execute(node.children[0]); 1453 ret = this.propstack[this.propscope]; 1454 1455 this.propstack.pop(); 1456 this.propscope--; 1457 break; 1458 case 'op_prop': 1459 // child 0: Identifier 1460 // child 1: Value 1461 this.propstack[this.propscope][node.children[0]] = this.execute(node.children[1]); 1462 break; 1463 case 'op_array': 1464 ret = []; 1465 l = node.children[0].length; 1466 1467 for (i = 0; i < l; i++) { 1468 ret.push(this.execute(node.children[0][i])); 1469 } 1470 1471 break; 1472 case 'op_extvalue': 1473 ret = this.execute(node.children[0]); 1474 i = this.execute(node.children[1]); 1475 1476 if (typeof i === 'number' && Math.abs(Math.round(i) - i) < 1.e-12) { 1477 ret = ret[i]; 1478 } else { 1479 ret = undef; 1480 } 1481 break; 1482 case 'op_return': 1483 if (this.scope === 0) { 1484 this._error('Unexpected return.'); 1485 } else { 1486 return this.execute(node.children[0]); 1487 } 1488 break; 1489 case 'op_map': 1490 if (!node.children[1].isMath && node.children[1].type !== 'node_var') { 1491 this._error('execute: In a map only function calls and mathematical expressions are allowed.'); 1492 } 1493 1494 /** @ignore */ 1495 fun = this.defineFunction(node); 1496 fun.isMap = true; 1497 1498 ret = fun; 1499 break; 1500 case 'op_function': 1501 // parse the parameter list 1502 // after this, the parameters are in pstack 1503 1504 /** @ignore */ 1505 fun = this.defineFunction(node); 1506 fun.isMap = false; 1507 1508 ret = fun; 1509 break; 1510 case 'op_execfun': 1511 // node.children: 1512 // [0]: Name of the function 1513 // [1]: Parameter list as a parse subtree 1514 // [2]: Properties, only used in case of a create function 1515 this.dpstack.push([]); 1516 this.pscope++; 1517 1518 // parameter parsing is done below 1519 list = node.children[1]; 1520 1521 // parse the properties only if given 1522 if (Type.exists(node.children[2])) { 1523 if (node.children[3]) { 1524 ilist = node.children[2]; 1525 attr = {}; 1526 1527 for (i = 0; i < ilist.length; i++) { 1528 attr = Type.deepCopy(attr, this.execute(ilist[i]), true); 1529 } 1530 } else { 1531 attr = this.execute(node.children[2]); 1532 } 1533 } 1534 1535 // look up the variables name in the variable table 1536 node.children[0]._isFunctionName = true; 1537 fun = this.execute(node.children[0]); 1538 delete node.children[0]._isFunctionName; 1539 1540 // determine the scope the function wants to run in 1541 if (Type.exists(fun) && Type.exists(fun.sc)) { 1542 sc = fun.sc; 1543 } else { 1544 sc = this; 1545 } 1546 1547 if (!fun.creator && Type.exists(node.children[2])) { 1548 this._error('Unexpected value. Only element creators are allowed to have a value after the function call.'); 1549 } 1550 1551 // interpret ALL the parameters 1552 for (i = 0; i < list.length; i++) { 1553 if (Type.exists(fun.scope) && Type.exists(fun.scope.argtypes) && fun.scope.argtypes[i] === 'function') { 1554 // Type inspection 1555 list[i]._isFunctionName = true; 1556 parents[i] = this.execute(list[i]); 1557 delete list[i]._isFunctionName; 1558 } else { 1559 parents[i] = this.execute(list[i]); 1560 } 1561 //parents[i] = Type.evalSlider(this.execute(list[i])); 1562 this.dpstack[this.pscope].push({ 1563 line: node.children[1][i].line, 1564 // SketchBin currently works only if the last column of the 1565 // parent position is taken. This is due to how I patched JS/CC 1566 // to count the lines and columns. So, ecol will do for now 1567 col: node.children[1][i].ecol 1568 }); 1569 } 1570 1571 // check for the function in the variable table 1572 if (typeof fun === 'function' && !fun.creator) { 1573 ret = fun.apply(sc, parents); 1574 } else if (typeof fun === 'function' && !!fun.creator) { 1575 e = this.line; 1576 1577 // creator methods are the only ones that take properties, hence this special case 1578 try { 1579 ret = fun(parents, attr); 1580 ret.jcLineStart = e; 1581 ret.jcLineEnd = node.eline; 1582 1583 for (i = e; i <= node.line; i++) { 1584 this.lineToElement[i] = ret; 1585 } 1586 1587 ret.debugParents = this.dpstack[this.pscope]; 1588 } catch (ex) { 1589 this._error(ex.toString()); 1590 } 1591 } else { 1592 this._error('Function \'' + fun + '\' is undefined.'); 1593 } 1594 1595 // clear parameter stack 1596 this.dpstack.pop(); 1597 this.pscope--; 1598 break; 1599 case 'op_property': 1600 e = this.execute(node.children[0]); 1601 v = node.children[1]; 1602 1603 ret = this.resolveProperty(e, v, false); 1604 1605 // set the scope, in case this is a method the user wants to call 1606 if (Type.exists(ret) && ['number', 'string', 'boolean'].indexOf(typeof ret) < 0) { 1607 ret.sc = e; 1608 } 1609 1610 break; 1611 case 'op_use': 1612 this._warn('Use of the \'use\' operator is deprecated.'); 1613 this.use(node.children[0].toString()); 1614 break; 1615 case 'op_delete': 1616 this._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.'); 1617 v = this.getvar(node.children[0]); 1618 ret = this.del(v); 1619 break; 1620 case 'op_eq': 1621 // == is intentional 1622 /*jslint eqeq:true*/ 1623 /* eslint-disable eqeqeq */ 1624 ret = this.execute(node.children[0]) == this.execute(node.children[1]); 1625 /*jslint eqeq:false*/ 1626 /* eslint-enable eqeqeq */ 1627 break; 1628 case 'op_neq': 1629 // != is intentional 1630 /*jslint eqeq:true*/ 1631 /* eslint-disable eqeqeq */ 1632 ret = this.execute(node.children[0]) != this.execute(node.children[1]); 1633 /*jslint eqeq:true*/ 1634 /* eslint-enable eqeqeq */ 1635 break; 1636 case 'op_approx': 1637 ret = Math.abs(this.execute(node.children[0]) - this.execute(node.children[1])) < Mat.eps; 1638 break; 1639 case 'op_gt': 1640 ret = this.execute(node.children[0]) > this.execute(node.children[1]); 1641 break; 1642 case 'op_lt': 1643 ret = this.execute(node.children[0]) < this.execute(node.children[1]); 1644 break; 1645 case 'op_geq': 1646 ret = this.execute(node.children[0]) >= this.execute(node.children[1]); 1647 break; 1648 case 'op_leq': 1649 ret = this.execute(node.children[0]) <= this.execute(node.children[1]); 1650 break; 1651 case 'op_or': 1652 ret = this.execute(node.children[0]) || this.execute(node.children[1]); 1653 break; 1654 case 'op_and': 1655 ret = this.execute(node.children[0]) && this.execute(node.children[1]); 1656 break; 1657 case 'op_not': 1658 ret = !this.execute(node.children[0]); 1659 break; 1660 case 'op_add': 1661 ret = this.add(this.execute(node.children[0]), this.execute(node.children[1])); 1662 break; 1663 case 'op_sub': 1664 ret = this.sub(this.execute(node.children[0]), this.execute(node.children[1])); 1665 break; 1666 case 'op_div': 1667 ret = this.div(this.execute(node.children[0]), this.execute(node.children[1])); 1668 break; 1669 case 'op_mod': 1670 // use mathematical modulo, JavaScript implements the symmetric modulo. 1671 ret = this.mod(this.execute(node.children[0]), this.execute(node.children[1]), true); 1672 break; 1673 case 'op_mul': 1674 ret = this.mul(this.execute(node.children[0]), this.execute(node.children[1])); 1675 break; 1676 case 'op_exp': 1677 ret = this.pow(this.execute(node.children[0]), this.execute(node.children[1])); 1678 break; 1679 case 'op_neg': 1680 ret = this.neg(this.execute(node.children[0])); 1681 break; 1682 } 1683 break; 1684 1685 case 'node_var': 1686 // node._isFunctionName is set in execute: at op_execfun. 1687 ret = this.getvar(node.value, false, node._isFunctionName); 1688 break; 1689 1690 case 'node_const': 1691 if (node.value === null) { 1692 ret = null; 1693 } else { 1694 ret = Number(node.value); 1695 } 1696 break; 1697 1698 case 'node_const_bool': 1699 ret = node.value; 1700 break; 1701 1702 case 'node_str': 1703 //ret = node.value.replace(/\\'/, "'").replace(/\\"/, '"').replace(/\\\\/, '\\'); 1704 /*jslint regexp:true*/ 1705 ret = node.value.replace(/\\(.)/g, '$1'); // Remove backslash, important in JessieCode tags 1706 /*jslint regexp:false*/ 1707 break; 1708 } 1709 1710 return ret; 1711 }, 1712 1713 /** 1714 * Compiles a parse tree back to JessieCode. 1715 * @param {Object} ast 1716 * @param {Boolean} [js=false] Compile either to JavaScript or back to JessieCode (required for the UI). 1717 * @param {Object} [format] Options for formatting the output. Depending on some options, the function might return a not re-parsable string. This format options have only effect on JessieCode output.<ul> 1718 * <li>{Boolean} [minParentheses=false] Use minimal amount of parentheses?</li> 1719 * <li>{Boolean|Number|Function} [constToFixed=false] Use this number or function to format constant values.</li> 1720 * <li>{Boolean} [printable=false] Adds additional signs or parentheses, e.g. x^0.5 --> x^{0.5}.</li> 1721 * </ul> 1722 * @returns Something 1723 * @private 1724 */ 1725 compile: function (ast, js, format) { 1726 var that = this; 1727 1728 if (!Type.exists(js)) { 1729 js = false; 1730 } 1731 if (!Type.exists(format) || !Type.isObject(format)) { 1732 format = {}; 1733 } 1734 format = Type.deepCopy({ 1735 minParentheses: false, 1736 constToFixed: false, 1737 printable: false 1738 }, format); 1739 1740 // node_const/node_var >> op_execfun >> op_neg >> op_exp >> op_mul/op_div >> op_add/op_sub >> op_map >> op_assign 1741 function prio(node) { 1742 switch (node.type) { 1743 case "node_const": 1744 case "node_const_bool": 1745 case "node_str": 1746 case "node_var": 1747 return 10; 1748 case "node_op": 1749 switch (node.value) { 1750 case "op_none": 1751 return 0; 1752 case "op_assign": 1753 return 1; 1754 case "op_map": 1755 case "op_function": 1756 case "op_return": 1757 return 2; 1758 case "op_add": 1759 case "op_sub": 1760 return 3; 1761 case "op_mul": 1762 case "op_div": 1763 case "op_mod": 1764 return 5; 1765 case "op_neg": 1766 return 4; 1767 case "op_exp": 1768 return 6; 1769 case "op_array": 1770 case "op_execfun": 1771 return 7; 1772 default: 1773 return 0; 1774 } 1775 default: 1776 return 0; 1777 } 1778 } 1779 1780 function compile(node, prevOp, position = -1) { 1781 var e, i, c, list, scope, prioParent, prioChild, 1782 ret = ''; 1783 1784 if (!node) { 1785 return ret; 1786 } 1787 1788 switch (node.type) { 1789 case 'node_op': 1790 switch (node.value) { 1791 case 'op_none': 1792 if (node.children[0]) { 1793 ret = compile(node.children[0], "op_none"); 1794 } 1795 if (node.children[1]) { 1796 ret += compile(node.children[1], "op_none"); 1797 } 1798 break; 1799 case 'op_block': 1800 ret = '{\n' + compile(node.children[0], "op_block") + ' }\n'; 1801 break; 1802 case 'op_assign': 1803 if (js) { 1804 e = that.getLHSCompiler(node.children[0], js); 1805 if (Type.isArray(e)) { 1806 ret = '$jc$.setProp(' + e[0] + ', ' + e[1] + ', ' + compile(node.children[1], "op_assign") + ');\n'; 1807 } else { 1808 if (that.isLocalVariable(e) !== that.scope) { 1809 that.scope.locals[e] = true; 1810 } 1811 ret = '$jc$.scopes[' + that.scope.id + '].locals[\'' + e + '\'] = ' + compile(node.children[1], "op_assign") + ';\n'; 1812 } 1813 } else { 1814 e = compile(node.children[0], "op_assign"); 1815 ret = e + ' = ' + compile(node.children[1], "op_assign") + ';\n'; 1816 } 1817 break; 1818 case 'op_if': 1819 ret = ' if (' + compile(node.children[0], "op_if") + ') ' + compile(node.children[1], "op_if"); 1820 break; 1821 case 'op_if_else': 1822 ret = ' if (' + compile(node.children[0], "op_if_else") + ')' + compile(node.children[1], "op_if_else"); 1823 ret += ' else ' + compile(node.children[2], "op_if_else"); 1824 break; 1825 case 'op_conditional': 1826 ret = '((' + compile(node.children[0], "op_conditional") + ')?(' + compile(node.children[1], "op_conditional"); 1827 ret += '):(' + compile(node.children[2], "op_conditional") + '))'; 1828 break; 1829 case 'op_while': 1830 ret = ' while (' + compile(node.children[0], "op_while") + ') {\n' + compile(node.children[1], "op_while") + '}\n'; 1831 break; 1832 case 'op_do': 1833 ret = ' do {\n' + compile(node.children[0], "op_do") + '} while (' + compile(node.children[1], "op_do") + ');\n'; 1834 break; 1835 case 'op_for': 1836 //ret = ' for (' + compile(node.children[0]) + '; ' + compile(node.children[1]) + '; ' + compile(node.children[2]) + ') {\n' + compile(node.children[3]) + '\n}\n'; 1837 ret = ' for (' + compile(node.children[0], "op_for") + // Assignment ends with ";" 1838 compile(node.children[1], "op_for") + '; ' + // Logical test comes without ";" 1839 compile(node.children[2], "op_for").slice(0, -2) + // Counting comes with ";" which has to be removed 1840 ') {\n' + compile(node.children[3], "op_for") + '\n}\n'; 1841 break; 1842 case 'op_proplst': 1843 if (node.children[0]) { 1844 ret = compile(node.children[0], "op_proplst") + ', '; 1845 } 1846 1847 ret += compile(node.children[1], "op_proplst"); 1848 break; 1849 case 'op_prop': 1850 // child 0: Identifier 1851 // child 1: Value 1852 ret = node.children[0] + ': ' + compile(node.children[1], "op_prop"); 1853 break; 1854 case 'op_emptyobject': 1855 ret = js ? '{}' : '<< >>'; 1856 break; 1857 case 'op_proplst_val': 1858 ret = compile(node.children[0], "op_proplst_val"); 1859 break; 1860 case 'op_array': 1861 list = []; 1862 for (i = 0; i < node.children[0].length; i++) { 1863 list.push(compile(node.children[0][i], "op_array")); 1864 } 1865 ret = '[' + list.join(', ') + ']'; 1866 break; 1867 case 'op_extvalue': 1868 ret = compile(node.children[0], "op_extvalue") + '[' + compile(node.children[1], "op_extvalue") + ']'; 1869 break; 1870 case 'op_return': 1871 ret = ' return ' + compile(node.children[0], "op_return") + ';\n'; 1872 break; 1873 case 'op_map': 1874 if (!node.children[1].isMath && node.children[1].type !== 'node_var') { 1875 that._error('compile: In a map only function calls and mathematical expressions are allowed.'); 1876 } 1877 1878 list = node.children[0]; 1879 if (js) { 1880 ret = ' $jc$.makeMap(function (' + list.join(', ') + ') { return ' + compile(node.children[1], "op_map") + '; })'; 1881 } else { 1882 ret = 'map (' + list.join(', ') + ') -> ' + compile(node.children[1], "op_map"); 1883 } 1884 1885 break; 1886 case 'op_function': 1887 list = node.children[0]; 1888 scope = that.pushScope(list); 1889 if (js) { 1890 ret = that.functionCodeJS(node); 1891 } else { 1892 ret = ' function (' + list.join(', ') + ') ' + compile(node.children[1], "op_function"); 1893 } 1894 that.popScope(); 1895 break; 1896 case 'op_execfunmath': 1897 console.log('op_execfunmath: TODO'); 1898 ret = '-1'; 1899 break; 1900 case 'op_execfun': 1901 // parse the properties only if given 1902 if (node.children[2]) { 1903 list = []; 1904 for (i = 0; i < node.children[2].length; i++) { 1905 list.push(compile(node.children[2][i], "op_execfun")); 1906 } 1907 1908 if (js) { 1909 e = '$jc$.mergeAttributes(' + list.join(', ') + ')'; 1910 } else { 1911 e = list.join(', '); 1912 } 1913 } 1914 node.children[0].withProps = !!node.children[2]; 1915 list = []; 1916 for (i = 0; i < node.children[1].length; i++) { 1917 list.push(compile(node.children[1][i], "op_execfun")); 1918 } 1919 ret = compile(node.children[0], "op_execfun") + '(' + list.join(', ') + (node.children[2] && js ? ', ' + e : '') + ')' + ((node.children[2] && !js) ? ' ' + e : ''); 1920 if (js) { 1921 // Inserting a newline here allows simultaneously 1922 // - procedural calls like Q.moveTo(...); and 1923 // - function calls in expressions like log(x) + 1; 1924 // Problem: procedural calls will not be ended by a semicolon. 1925 ret += '\n'; 1926 } 1927 1928 // save us a function call when compiled to javascript 1929 if (js && node.children[0].value === '$') { 1930 ret = '$jc$.board.objects[' + compile(node.children[1][0], "op_execfun") + ']'; 1931 } 1932 break; 1933 case 'op_property': 1934 if (js && node.children[1] !== 'X' && node.children[1] !== 'Y') { 1935 ret = '$jc$.resolveProperty(' + compile(node.children[0], "op_property") + ', \'' + node.children[1] + '\', true)'; 1936 } else { 1937 ret = compile(node.children[0], "op_property") + '.' + node.children[1]; 1938 } 1939 break; 1940 case 'op_use': 1941 that._warn('Use of the \'use\' operator is deprecated.'); 1942 if (js) { 1943 ret = '$jc$.use(\''; 1944 } else { 1945 ret = 'use(\''; 1946 } 1947 1948 ret += node.children[0].toString() + '\');'; 1949 break; 1950 case 'op_delete': 1951 that._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.'); 1952 if (js) { 1953 ret = '$jc$.del('; 1954 } else { 1955 ret = 'remove('; 1956 } 1957 1958 ret += compile(node.children[0], "op_delete") + ')'; 1959 break; 1960 case 'op_eq': 1961 ret = '(' + compile(node.children[0], "op_eq") + ' === ' + compile(node.children[1], "op_eq") + ')'; 1962 break; 1963 case 'op_neq': 1964 ret = '(' + compile(node.children[0], "op_neq") + ' !== ' + compile(node.children[1], "op_neq") + ')'; 1965 break; 1966 case 'op_approx': 1967 ret = '(' + compile(node.children[0], "op_approx") + ' ~= ' + compile(node.children[1], "op_approx") + ')'; 1968 break; 1969 case 'op_gt': 1970 if (js) { 1971 ret = '$jc$.gt(' + compile(node.children[0], "op_gt") + ', ' + compile(node.children[1], "op_gt") + ')'; 1972 } else { 1973 ret = '(' + compile(node.children[0], "op_gt") + ' > ' + compile(node.children[1], "op_gt") + ')'; 1974 } 1975 break; 1976 case 'op_lt': 1977 if (js) { 1978 ret = '$jc$.lt(' + compile(node.children[0], "op_lt") + ', ' + compile(node.children[1], "op_lt") + ')'; 1979 } else { 1980 ret = '(' + compile(node.children[0], "op_lt") + ' < ' + compile(node.children[1], "op_lt") + ')'; 1981 } 1982 break; 1983 case 'op_geq': 1984 if (js) { 1985 ret = '$jc$.geq(' + compile(node.children[0], "op_geq") + ', ' + compile(node.children[1], "op_geq") + ')'; 1986 } else { 1987 ret = '(' + compile(node.children[0], "op_geq") + ' >= ' + compile(node.children[1], "op_geq") + ')'; 1988 } 1989 break; 1990 case 'op_leq': 1991 if (js) { 1992 ret = '$jc$.leq(' + compile(node.children[0], "op_leq") + ', ' + compile(node.children[1], "op_leq") + ')'; 1993 } else { 1994 ret = '(' + compile(node.children[0], "op_leq") + ' <= ' + compile(node.children[1], "op_leq") + ')'; 1995 } 1996 break; 1997 case 'op_or': 1998 ret = '(' + compile(node.children[0], "op_or") + ' || ' + compile(node.children[1], "op_or") + ')'; 1999 break; 2000 case 'op_and': 2001 ret = '(' + compile(node.children[0], "op_and") + ' && ' + compile(node.children[1], "op_and") + ')'; 2002 break; 2003 case 'op_not': 2004 ret = '!(' + compile(node.children[0], "op_not") + ')'; 2005 break; 2006 case "op_add": 2007 if (js) { 2008 ret = '$jc$.add(' + compile(node.children[0], "op_add") + ', ' + compile(node.children[1], "op_add") + ')'; 2009 } else if (!format.minParentheses) { 2010 ret = '(' + compile(node.children[0], "op_add") + ' + ' + compile(node.children[1], "op_add") + ')'; 2011 } else { 2012 prioParent = prio(node); 2013 2014 e = compile(node.children[0], "op_add"); 2015 prioChild = prio(node.children[0]); 2016 ret = (prioParent > prioChild) ? "(" + e + ")" : e; 2017 2018 ret += ' + '; 2019 2020 e = compile(node.children[1], "op_add"); 2021 prioChild = prio(node.children[1]); 2022 ret += (prioParent > prioChild) ? "(" + e + ")" : e; 2023 } 2024 break; 2025 case 'op_sub': 2026 if (js) { 2027 ret = '$jc$.sub(' + compile(node.children[0], "op_sub") + ', ' + compile(node.children[1], "op_sub") + ')'; 2028 } else if (!format.minParentheses) { 2029 ret = '(' + compile(node.children[0], "op_sub") + ' - ' + compile(node.children[1], "op_sub") + ')'; 2030 } else { 2031 prioParent = prio(node); 2032 2033 e = compile(node.children[0], "op_sub"); 2034 prioChild = prio(node.children[0]); 2035 ret = (prioParent > prioChild) ? "(" + e + ")" : e; 2036 2037 ret += ' - '; 2038 2039 e = compile(node.children[1], "op_sub"); 2040 prioChild = prio(node.children[1]); 2041 ret += (prioParent >= prioChild) ? "(" + e + ")" : e; 2042 } 2043 break; 2044 case 'op_div': 2045 if (js) { 2046 ret = '$jc$.div(' + compile(node.children[0], "op_div") + ', ' + compile(node.children[1], "op_div") + ')'; 2047 } else if (!format.minParentheses) { 2048 ret = '(' + compile(node.children[0], "op_div") + ' / ' + compile(node.children[1], "op_div") + ')'; 2049 } else { 2050 prioParent = prio(node); 2051 2052 e = compile(node.children[0], "op_div"); 2053 prioChild = prio(node.children[0]); 2054 ret = (prioParent > prioChild) ? "(" + e + ")" : e; 2055 2056 ret += ' / '; 2057 2058 e = compile(node.children[1], "op_div"); 2059 prioChild = prio(node.children[1]); 2060 ret += (prioParent >= prioChild) ? "(" + e + ")" : e; 2061 } 2062 break; 2063 case 'op_mod': 2064 if (js) { 2065 ret = '$jc$.mod(' + compile(node.children[0], "op_mod") + ', ' + compile(node.children[1], "op_mod") + ', true)'; 2066 } else if (!format.minParentheses) { 2067 ret = '(' + compile(node.children[0], "op_mod") + ' % ' + compile(node.children[1], "op_mod") + ')'; 2068 } else { 2069 prioParent = prio(node); 2070 2071 e = compile(node.children[0], "op_mod"); 2072 prioChild = prio(node.children[0]); 2073 ret = (prioParent > prioChild) ? "(" + e + ")" : e; 2074 2075 ret += ' % '; 2076 2077 e = compile(node.children[1], "op_mod"); 2078 prioChild = prio(node.children[1]); 2079 ret += (prioParent >= prioChild) ? "(" + e + ")" : e; 2080 } 2081 break; 2082 case 'op_mul': 2083 if (js) { 2084 ret = '$jc$.mul(' + compile(node.children[0], "op_mul") + ', ' + compile(node.children[1], "op_mul") + ')'; 2085 } else if (!format.minParentheses) { 2086 ret = '(' + compile(node.children[0], "op_mul") + ' * ' + compile(node.children[1], "op_mul") + ')'; 2087 } else { 2088 prioParent = prio(node); 2089 2090 e = compile(node.children[0], "op_mul"); 2091 prioChild = prio(node.children[0]); 2092 ret = (prioParent > prioChild) ? "(" + e + ")" : e; 2093 2094 ret += ' * '; 2095 2096 e = compile(node.children[1], "op_mul"); 2097 prioChild = prio(node.children[1]); 2098 ret += (prioParent > prioChild) ? "(" + e + ")" : e; 2099 } 2100 break; 2101 case 'op_exp': 2102 if (js) { 2103 ret = '$jc$.pow(' + compile(node.children[0], "op_exp", 0) + ', ' + compile(node.children[1], "op_exp", 1) + ')'; 2104 } else if (!format.minParentheses) { 2105 ret = '(' 2106 + compile(node.children[0], "op_exp", 0) 2107 + '^' + compile(node.children[1], "op_exp", 1) 2108 + ')'; 2109 } else { 2110 prioParent = prio(node); 2111 2112 e = compile(node.children[0], "op_exp", 0); 2113 prioChild = prio(node.children[0]); 2114 ret = (prioParent >= prioChild) 2115 ? "(" + e + ")" 2116 : e; 2117 2118 ret += '^'; 2119 2120 e = compile(node.children[1], "op_exp", 1); 2121 prioChild = prio(node.children[1]); 2122 ret += (prioParent > prioChild && !(format.printable && e[0] === '{' && e[e.length - 1] === '}')) 2123 ? "(" + e + ")" 2124 : e; 2125 } 2126 break; 2127 case 'op_neg': 2128 if (js) { 2129 ret = '$jc$.neg(' + compile(node.children[0], "op_neg") + ')'; 2130 } else if (!format.minParentheses) { 2131 ret = '(-' + compile(node.children[0], "op_neg") + ')'; 2132 } else { 2133 prioParent = prio(node); 2134 prioChild = prio(node.children[0]); 2135 e = compile(node.children[0], "op_neg"); 2136 if (prioParent >= prioChild) { 2137 ret = '-(' + e + ')'; 2138 } else { 2139 ret = '-' + e; 2140 } 2141 } 2142 break; 2143 } 2144 break; 2145 2146 case 'node_var': 2147 if (js) { 2148 ret = that.getvarJS(node.value, false, node.withProps); 2149 } else { 2150 ret = node.value; 2151 } 2152 break; 2153 2154 case 'node_const': 2155 if (js) { 2156 ret = node.value; 2157 break; 2158 } 2159 2160 c = node.value; 2161 if ( 2162 format.constToFixed !== false && 2163 Type.isNumber(c) && 2164 !(prevOp === "op_exp" && position === 1) // exponents will not be formatted 2165 ) { 2166 c = parseFloat(c); 2167 if (Type.isNumber(format.constToFixed)) { 2168 c = Type.toFixed(c, format.constToFixed); 2169 } else if (Type.isFunction(format.constToFixed)) { 2170 c = format.constToFixed(c); 2171 } else { 2172 c = node.value; 2173 } 2174 } 2175 if (format.minParentheses && parseFloat(c) < 0 && prevOp !== "op_execfun" && position !== 0) { 2176 ret = "(" + c + ")"; 2177 } else { 2178 ret = c; 2179 } 2180 break; 2181 2182 case 'node_const_bool': 2183 ret = node.value; 2184 break; 2185 2186 case 'node_str': 2187 ret = '\'' + node.value + '\''; 2188 break; 2189 } 2190 2191 if (node.needsAngleBrackets) { 2192 if (js) { 2193 ret = '{\n' + ret + ' }\n'; 2194 } else { 2195 ret = '<< ' + ret + ' >>\n'; 2196 } 2197 } 2198 2199 if (format.printable && prevOp === "op_exp" && position === 1) { 2200 ret = '{' + ret + '}'; 2201 } 2202 2203 if (format.printable && Type.isString(ret)) { 2204 ret = ret.replaceAll('\n', ''); 2205 } 2206 2207 return ret; 2208 } 2209 2210 return compile(ast, ""); 2211 }, 2212 2213 /** 2214 * This is used as the global getName() function. 2215 * @param {JXG.GeometryElement} obj 2216 * @param {Boolean} useId 2217 * @returns {String} 2218 */ 2219 getName: function (obj, useId) { 2220 var name = ''; 2221 2222 if (Type.exists(obj) && Type.exists(obj.getName)) { 2223 name = obj.getName(); 2224 if ((!Type.exists(name) || name === '') && useId) { 2225 name = obj.id; 2226 } 2227 } else if (useId) { 2228 name = obj.id; 2229 } 2230 2231 return name; 2232 }, 2233 2234 /** 2235 * This is used as the global X() function. 2236 * @param {JXG.Point|JXG.Text} e 2237 * @returns {Number} 2238 */ 2239 X: function (e) { 2240 return e.X(); 2241 }, 2242 2243 /** 2244 * This is used as the global Y() function. 2245 * @param {JXG.Point|JXG.Text} e 2246 * @returns {Number} 2247 */ 2248 Y: function (e) { 2249 return e.Y(); 2250 }, 2251 2252 /** 2253 * This is used as the global V() function. 2254 * @param {Glider|Slider} e 2255 * @returns {Number} 2256 */ 2257 V: function (e) { 2258 return e.Value(); 2259 }, 2260 2261 /** 2262 * This is used as the global L() function. 2263 * @param {JXG.Line} e 2264 * @returns {Number} 2265 */ 2266 L: function (e) { 2267 return e.L(); 2268 }, 2269 2270 /** 2271 * This is used as the global area() function. 2272 * @param {JXG.Circle|JXG.Polygon} obj 2273 * @returns {Number} 2274 */ 2275 area: function (obj) { 2276 if (!Type.exists(obj) || !Type.exists(obj.Area)) { 2277 this._error('Error: Can\'t calculate area.'); 2278 } 2279 2280 return obj.Area(); 2281 }, 2282 2283 /** 2284 * This is used as the global perimeter() function. 2285 * @param {JXG.Circle|JXG.Polygon} obj 2286 * @returns {Number} 2287 */ 2288 perimeter: function (obj) { 2289 if (!Type.exists(obj) || !Type.exists(obj.Perimeter)) { 2290 this._error('Error: Can\'t calculate perimeter.'); 2291 } 2292 2293 return obj.Perimeter(); 2294 }, 2295 2296 /** 2297 * This is used as the global dist() function. 2298 * @param {JXG.Point} p1 2299 * @param {JXG.Point} p2 2300 * @returns {Number} 2301 */ 2302 dist: function (p1, p2) { 2303 if (!Type.exists(p1) || !Type.exists(p1.Dist)) { 2304 this._error('Error: Can\'t calculate distance.'); 2305 } 2306 2307 return p1.Dist(p2); 2308 }, 2309 2310 /** 2311 * This is used as the global radius() function. 2312 * @param {JXG.Circle|Sector} obj 2313 * @returns {Number} 2314 */ 2315 radius: function (obj) { 2316 if (!Type.exists(obj) || !Type.exists(obj.Radius)) { 2317 this._error('Error: Can\'t calculate radius.'); 2318 } 2319 2320 return obj.Radius(); 2321 }, 2322 2323 /** 2324 * This is used as the global slope() function. 2325 * @param {JXG.Line} obj 2326 * @returns {Number} 2327 */ 2328 slope: function (obj) { 2329 if (!Type.exists(obj) || !Type.exists(obj.Slope)) { 2330 this._error('Error: Can\'t calculate slope.'); 2331 } 2332 2333 return obj.Slope(); 2334 }, 2335 2336 /** 2337 * + operator implementation 2338 * @param {Number|Array|JXG.Point} a 2339 * @param {Number|Array|JXG.Point} b 2340 * @returns {Number|Array} 2341 */ 2342 add: function (a, b) { 2343 var i, len, res; 2344 2345 a = Type.evalSlider(a); 2346 b = Type.evalSlider(b); 2347 2348 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2349 res = Interval.add(a, b); 2350 } else if (Type.isArray(a) && Type.isArray(b)) { 2351 len = Math.min(a.length, b.length); 2352 res = []; 2353 2354 for (i = 0; i < len; i++) { 2355 res[i] = a[i] + b[i]; 2356 } 2357 } else if (Type.isNumber(a) && Type.isNumber(b)) { 2358 res = a + b; 2359 } else if (Type.isString(a) || Type.isString(b)) { 2360 res = a.toString() + b.toString(); 2361 } else { 2362 this._error('Operation + not defined on operands ' + typeof a + ' and ' + typeof b); 2363 } 2364 2365 return res; 2366 }, 2367 2368 /** 2369 * - operator implementation 2370 * @param {Number|Array|JXG.Point} a 2371 * @param {Number|Array|JXG.Point} b 2372 * @returns {Number|Array} 2373 */ 2374 sub: function (a, b) { 2375 var i, len, res; 2376 2377 a = Type.evalSlider(a); 2378 b = Type.evalSlider(b); 2379 2380 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2381 res = Interval.sub(a, b); 2382 } else if (Type.isArray(a) && Type.isArray(b)) { 2383 len = Math.min(a.length, b.length); 2384 res = []; 2385 2386 for (i = 0; i < len; i++) { 2387 res[i] = a[i] - b[i]; 2388 } 2389 } else if (Type.isNumber(a) && Type.isNumber(b)) { 2390 res = a - b; 2391 } else { 2392 this._error('Operation - not defined on operands ' + typeof a + ' and ' + typeof b); 2393 } 2394 2395 return res; 2396 }, 2397 2398 /** 2399 * unary - operator implementation 2400 * @param {Number|Array|JXG.Point} a 2401 * @returns {Number|Array} 2402 */ 2403 neg: function (a) { 2404 var i, len, res; 2405 2406 a = Type.evalSlider(a); 2407 2408 if (Interval.isInterval(a)) { 2409 res = Interval.negative(a); 2410 } else if (Type.isArray(a)) { 2411 len = a.length; 2412 res = []; 2413 2414 for (i = 0; i < len; i++) { 2415 res[i] = -a[i]; 2416 } 2417 } else if (Type.isNumber(a)) { 2418 res = -a; 2419 } else { 2420 this._error('Unary operation - not defined on operand ' + typeof a); 2421 } 2422 2423 return res; 2424 }, 2425 2426 /** 2427 * Multiplication of vectors and numbers 2428 * @param {Number|Array} a 2429 * @param {Number|Array} b 2430 * @returns {Number|Array} (Inner) product of the given input values. 2431 */ 2432 mul: function (a, b) { 2433 var i, len, res; 2434 2435 a = Type.evalSlider(a); 2436 b = Type.evalSlider(b); 2437 2438 if (Type.isArray(a) && Type.isNumber(b)) { 2439 // swap b and a 2440 i = a; 2441 a = b; 2442 b = a; 2443 } 2444 2445 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2446 res = Interval.mul(a, b); 2447 } else if (Type.isArray(a) && Type.isArray(b)) { 2448 len = Math.min(a.length, b.length); 2449 res = Mat.innerProduct(a, b, len); 2450 } else if (Type.isNumber(a) && Type.isArray(b)) { 2451 len = b.length; 2452 res = []; 2453 2454 for (i = 0; i < len; i++) { 2455 res[i] = a * b[i]; 2456 } 2457 } else if (Type.isNumber(a) && Type.isNumber(b)) { 2458 res = a * b; 2459 } else { 2460 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b); 2461 } 2462 2463 return res; 2464 }, 2465 2466 /** 2467 * Implementation of the / operator. 2468 * @param {Number|Array} a 2469 * @param {Number} b 2470 * @returns {Number|Array} 2471 */ 2472 div: function (a, b) { 2473 var i, len, res; 2474 2475 a = Type.evalSlider(a); 2476 b = Type.evalSlider(b); 2477 2478 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2479 res = Interval.div(a, b); 2480 } else if (Type.isArray(a) && Type.isNumber(b)) { 2481 len = a.length; 2482 res = []; 2483 2484 for (i = 0; i < len; i++) { 2485 res[i] = a[i] / b; 2486 } 2487 } else if (Type.isNumber(a) && Type.isNumber(b)) { 2488 res = a / b; 2489 } else { 2490 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b); 2491 } 2492 2493 return res; 2494 }, 2495 2496 /** 2497 * Implementation of the % operator. 2498 * @param {Number|Array} a 2499 * @param {Number} b 2500 * @returns {Number|Array} 2501 */ 2502 mod: function (a, b) { 2503 var i, len, res; 2504 2505 a = Type.evalSlider(a); 2506 b = Type.evalSlider(b); 2507 2508 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2509 return Interval.fmod(a, b); 2510 } else if (Type.isArray(a) && Type.isNumber(b)) { 2511 len = a.length; 2512 res = []; 2513 2514 for (i = 0; i < len; i++) { 2515 res[i] = Mat.mod(a[i], b, true); 2516 } 2517 } else if (Type.isNumber(a) && Type.isNumber(b)) { 2518 res = Mat.mod(a, b, true); 2519 } else { 2520 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b); 2521 } 2522 2523 return res; 2524 }, 2525 2526 /** 2527 * Pow function wrapper to allow direct usage of sliders. 2528 * @param {Number|Slider} a 2529 * @param {Number|Slider} b 2530 * @returns {Number} 2531 */ 2532 pow: function (a, b) { 2533 a = Type.evalSlider(a); 2534 b = Type.evalSlider(b); 2535 2536 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2537 return Interval.pow(a, b); 2538 } 2539 return Mat.pow(a, b); 2540 }, 2541 2542 lt: function (a, b) { 2543 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2544 return Interval.lt(a, b); 2545 } 2546 return a < b; 2547 }, 2548 leq: function (a, b) { 2549 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2550 return Interval.leq(a, b); 2551 } 2552 return a <= b; 2553 }, 2554 gt: function (a, b) { 2555 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2556 return Interval.gt(a, b); 2557 } 2558 return a > b; 2559 }, 2560 geq: function (a, b) { 2561 if (Interval.isInterval(a) || Interval.isInterval(b)) { 2562 return Interval.geq(a, b); 2563 } 2564 return a >= b; 2565 }, 2566 2567 randint: function (min, max, step) { 2568 if (!Type.exists(step)) { 2569 step = 1; 2570 } 2571 return Math.round(Math.random() * (max - min) / step) * step + min; 2572 }, 2573 2574 DDD: function (f) { 2575 console.log('Dummy derivative function. This should never appear!'); 2576 }, 2577 2578 /** 2579 * Implementation of the ?: operator 2580 * @param {Boolean} cond Condition 2581 * @param {*} v1 2582 * @param {*} v2 2583 * @returns {*} Either v1 or v2. 2584 */ 2585 ifthen: function (cond, v1, v2) { 2586 if (cond) { 2587 return v1; 2588 } 2589 2590 return v2; 2591 }, 2592 2593 /** 2594 * Implementation of the delete() builtin function 2595 * @param {JXG.GeometryElement} element 2596 */ 2597 del: function (element) { 2598 if (typeof element === 'object' && JXG.exists(element.type) && JXG.exists(element.elementClass)) { 2599 this.board.removeObject(element); 2600 } 2601 }, 2602 2603 /** 2604 * Implementation of the eval() builtin function. Calls JXG.evaluate(). 2605 * @param {String|Number|Function} v 2606 */ 2607 eval: function (v) { 2608 return JXG.evaluate(v); 2609 }, 2610 2611 /** 2612 * Implementation of the use() builtin function 2613 * @param {String} board 2614 */ 2615 use: function (board) { 2616 var b, ref, 2617 found = false; 2618 2619 if (typeof board === 'string') { 2620 // search all the boards for the one with the appropriate container div 2621 for (b in JXG.boards) { 2622 if (JXG.boards.hasOwnProperty(b) && JXG.boards[b].container === board) { 2623 ref = JXG.boards[b]; 2624 found = true; 2625 break; 2626 } 2627 } 2628 } else { 2629 ref = board; 2630 found = true; 2631 } 2632 2633 if (found) { 2634 this.board = ref; 2635 this.builtIn.$board = ref; 2636 this.builtIn.$board.src = '$jc$.board'; 2637 } else { 2638 this._error('Board \'' + board + '\' not found!'); 2639 } 2640 }, 2641 2642 /** 2643 * Find the first symbol to the given value from the given scope upwards. 2644 * @param v Value 2645 * @param {Number} [scope=-1] The scope, default is to start with current scope (-1). 2646 * @returns {Array} An array containing the symbol and the scope if a symbol could be found, 2647 * an empty array otherwise; 2648 */ 2649 findSymbol: function (v, scope) { 2650 var i, s; 2651 2652 scope = Type.def(scope, -1); 2653 2654 if (scope === -1) { 2655 s = this.scope; 2656 } else { 2657 s = this.scopes[scope]; 2658 } 2659 2660 while (s !== null) { 2661 for (i in s.locals) { 2662 if (s.locals.hasOwnProperty(i) && s.locals[i] === v) { 2663 return [i, s]; 2664 } 2665 } 2666 2667 s = s.previous; 2668 } 2669 2670 return []; 2671 }, 2672 2673 /** 2674 * Import modules into a JessieCode script. 2675 * @param {String} module 2676 */ 2677 importModule: function (module) { 2678 return priv.modules[module.toLowerCase()]; 2679 }, 2680 2681 /** 2682 * Defines built in methods and constants. 2683 * @returns {Object} BuiltIn control object 2684 */ 2685 defineBuiltIn: function () { 2686 var that = this, 2687 builtIn = { 2688 PI: Math.PI, 2689 EULER: Math.E, 2690 D: that.DDD, 2691 X: that.X, 2692 Y: that.Y, 2693 V: that.V, 2694 Value: that.V, 2695 L: that.L, 2696 Length: that.L, 2697 2698 acosh: Mat.acosh, 2699 acot: Mat.acot, 2700 asinh: Mat.asinh, 2701 binomial: Mat.binomial, 2702 cbrt: Mat.cbrt, 2703 cosh: Mat.cosh, 2704 cot: Mat.cot, 2705 deg: Geometry.trueAngle, 2706 A: that.area, 2707 area: that.area, 2708 Area: that.area, 2709 perimeter: that.perimeter, 2710 Perimeter: that.perimeter, 2711 dist: that.dist, 2712 Dist: that.dist, 2713 R: that.radius, 2714 radius: that.radius, 2715 Radius: that.radius, 2716 erf: Mat.erf, 2717 erfc: Mat.erfc, 2718 erfi: Mat.erfi, 2719 factorial: Mat.factorial, 2720 gcd: Mat.gcd, 2721 lb: Mat.log2, 2722 lcm: Mat.lcm, 2723 ld: Mat.log2, 2724 lg: Mat.log10, 2725 ln: Math.log, 2726 log: Mat.log, 2727 log10: Mat.log10, 2728 log2: Mat.log2, 2729 ndtr: Mat.ndtr, 2730 ndtri: Mat.ndtri, 2731 nthroot: Mat.nthroot, 2732 pow: Mat.pow, 2733 rad: Geometry.rad, 2734 ratpow: Mat.ratpow, 2735 trunc: Type.trunc, 2736 sinh: Mat.sinh, 2737 slope: that.slope, 2738 Slope: that.slope, 2739 2740 randint: that.randint, 2741 2742 IfThen: that.ifthen, 2743 'import': that.importModule, 2744 'eval': that.eval, 2745 'use': that.use, 2746 'remove': that.del, 2747 '$': that.getElementById, 2748 '$value': function(e) {return that.getElementById(e).Value(); }, 2749 getName: that.getName, 2750 name: that.getName, 2751 '$board': that.board, 2752 '$log': that.log 2753 }; 2754 2755 // special scopes for factorial, deg, and rad 2756 builtIn.rad.sc = Geometry; 2757 builtIn.deg.sc = Geometry; 2758 builtIn.factorial.sc = Mat; 2759 2760 // set the javascript equivalent for the builtIns 2761 // some of the anonymous functions should be replaced by global methods later on 2762 // EULER and PI don't get a source attribute - they will be lost anyways and apparently 2763 // some browser will throw an exception when a property is assigned to a primitive value. 2764 builtIn.X.src = '$jc$.X'; 2765 builtIn.Y.src = '$jc$.Y'; 2766 builtIn.V.src = '$jc$.V'; 2767 builtIn.Value.src = '$jc$.V'; 2768 builtIn.L.src = '$jc$.L'; 2769 builtIn.Length.src = '$jc$.L'; 2770 2771 builtIn.acosh.src = 'JXG.Math.acosh'; 2772 builtIn.acot.src = 'JXG.Math.acot'; 2773 builtIn.asinh.src = 'JXG.Math.asinh'; 2774 builtIn.binomial.src = 'JXG.Math.binomial'; 2775 builtIn.cbrt.src = 'JXG.Math.cbrt'; 2776 builtIn.cot.src = 'JXG.Math.cot'; 2777 builtIn.cosh.src = 'JXG.Math.cosh'; 2778 builtIn.deg.src = 'JXG.Math.Geometry.trueAngle'; 2779 builtIn.erf.src = 'JXG.Math.erf'; 2780 builtIn.erfc.src = 'JXG.Math.erfc'; 2781 builtIn.erfi.src = 'JXG.Math.erfi'; 2782 builtIn.A.src = '$jc$.area'; 2783 builtIn.area.src = '$jc$.area'; 2784 builtIn.Area.src = '$jc$.area'; 2785 builtIn.perimeter.src = '$jc$.perimeter'; 2786 builtIn.Perimeter.src = '$jc$.perimeter'; 2787 builtIn.dist.src = '$jc$.dist'; 2788 builtIn.Dist.src = '$jc$.dist'; 2789 builtIn.R.src = '$jc$.radius'; 2790 builtIn.radius.src = '$jc$.radius'; 2791 builtIn.Radius.src = '$jc$.radius'; 2792 builtIn.factorial.src = 'JXG.Math.factorial'; 2793 builtIn.gcd.src = 'JXG.Math.gcd'; 2794 builtIn.lb.src = 'JXG.Math.log2'; 2795 builtIn.lcm.src = 'JXG.Math.lcm'; 2796 builtIn.ld.src = 'JXG.Math.log2'; 2797 builtIn.lg.src = 'JXG.Math.log10'; 2798 builtIn.ln.src = 'Math.log'; 2799 builtIn.log.src = 'JXG.Math.log'; 2800 builtIn.log10.src = 'JXG.Math.log10'; 2801 builtIn.log2.src = 'JXG.Math.log2'; 2802 builtIn.ndtr.src = 'JXG.Math.ndtr'; 2803 builtIn.ndtri.src = 'JXG.Math.ndtri'; 2804 builtIn.nthroot.src = 'JXG.Math.nthroot'; 2805 builtIn.pow.src = 'JXG.Math.pow'; 2806 builtIn.rad.src = 'JXG.Math.Geometry.rad'; 2807 builtIn.ratpow.src = 'JXG.Math.ratpow'; 2808 builtIn.trunc.src = 'JXG.trunc'; 2809 builtIn.sinh.src = 'JXG.Math.sinh'; 2810 builtIn.slope.src = '$jc$.slope'; 2811 builtIn.Slope.src = '$jc$.slope'; 2812 2813 builtIn.randint.src = '$jc$.randint'; 2814 2815 builtIn['import'].src = '$jc$.importModule'; 2816 builtIn.eval.src = '$jc$.eval'; 2817 builtIn.use.src = '$jc$.use'; 2818 builtIn.remove.src = '$jc$.del'; 2819 builtIn.IfThen.src = '$jc$.ifthen'; 2820 // usually unused, see node_op > op_execfun 2821 builtIn.$.src = '(function (n) { return $jc$.board.select(n); })'; 2822 builtIn.$value.src = '(function (n) { return $jc$.board.select(n).Value(); })'; 2823 builtIn.getName.src = '$jc$.getName'; 2824 builtIn.name.src = '$jc$.getName'; 2825 if (builtIn.$board) { 2826 builtIn.$board.src = '$jc$.board'; 2827 } 2828 builtIn.$log.src = '$jc$.log'; 2829 2830 builtIn = JXG.merge(builtIn, that._addedBuiltIn); 2831 2832 return builtIn; 2833 }, 2834 2835 _addedBuiltIn: {}, 2836 2837 addBuiltIn: function (name, func) { 2838 if (Type.exists(this.builtIn)) { 2839 if (Type.exists(this.builtIn[name])) { 2840 return; 2841 } 2842 this.builtIn[name] = func; 2843 this.builtIn[name].src = '$jc$.' + name; 2844 } 2845 2846 if (Type.exists(this._addedBuiltIn[name])) { 2847 return; 2848 } 2849 this._addedBuiltIn[name] = func; 2850 this._addedBuiltIn[name].src = '$jc$.' + name; 2851 2852 JXG.JessieCode.prototype[name] = func; 2853 }, 2854 2855 /** 2856 * Returns information about the possible functions and constants. 2857 * @returns {Object} 2858 */ 2859 getPossibleOperands: function () { 2860 var FORBIDDEN = ['E'], 2861 jessiecode = this.builtIn || this.defineBuiltIn(), 2862 math = Math, 2863 jc, ma, merge, 2864 i, j, p, len, e, 2865 funcs, funcsJC, consts, operands, 2866 sort, pack; 2867 2868 sort = function (a, b) { 2869 return a.toLowerCase().localeCompare(b.toLowerCase()); 2870 }; 2871 2872 pack = function (name, origin) { 2873 var that = null; 2874 2875 if (origin === 'jc') that = jessiecode[name]; 2876 else if (origin === 'Math') that = math[name]; 2877 else return; 2878 2879 if (FORBIDDEN.indexOf(name) >= 0) { 2880 return; 2881 } else if (JXG.isFunction(that)) { 2882 return { 2883 name: name, 2884 type: 'function', 2885 numParams: that.length, 2886 origin: origin, 2887 }; 2888 } else if (JXG.isNumber(that)) { 2889 return { 2890 name: name, 2891 type: 'constant', 2892 value: that, 2893 origin: origin, 2894 }; 2895 } else if (name.startsWith('$')) { 2896 // do nothing 2897 } else if (that !== undefined) { 2898 console.error('undefined type', that); 2899 } 2900 }; 2901 2902 jc = Object.getOwnPropertyNames(jessiecode).sort(sort); 2903 ma = Object.getOwnPropertyNames(math).sort(sort); 2904 merge = []; 2905 i = 0; 2906 j = 0; 2907 2908 while (i < jc.length || j < ma.length) { 2909 if (jc[i] === ma[j]) { 2910 p = pack(ma[j], 'Math'); 2911 if (JXG.exists(p)) merge.push(p); 2912 i++; 2913 j++; 2914 } else if (!JXG.exists(ma[j]) || jc[i].toLowerCase().localeCompare(ma[j].toLowerCase()) < 0) { 2915 p = pack(jc[i], 'jc'); 2916 if (JXG.exists(p)) merge.push(p); 2917 i++; 2918 } else { 2919 p = pack(ma[j], 'Math'); 2920 if (JXG.exists(p)) merge.push(p); 2921 j++; 2922 } 2923 } 2924 2925 funcs = []; 2926 funcsJC = []; 2927 consts = []; 2928 operands = {}; 2929 len = merge.length; 2930 for (i = 0; i < len; i++) { 2931 e = merge[i]; 2932 switch (e.type) { 2933 case 'function': 2934 funcs.push(e.name); 2935 if (e.origin === 'jc') 2936 funcsJC.push(e.name); 2937 break; 2938 case 'constant': 2939 consts.push(e.name); 2940 break; 2941 } 2942 operands[e.name] = e; 2943 } 2944 2945 return { 2946 all: operands, 2947 list: merge, 2948 functions: funcs, 2949 functions_jessiecode: funcsJC, 2950 constants: consts, 2951 }; 2952 }, 2953 2954 /** 2955 * Output a debugging message. Uses debug console, if available. Otherwise an HTML element with the 2956 * id "debug" and an innerText property is used. 2957 * @param {String} log 2958 * @private 2959 */ 2960 _debug: function (log) { 2961 if (typeof console === 'object' && console.log) { 2962 console.log(log); 2963 } else if (Env.isBrowser && document && document.getElementById('debug') !== null) { 2964 document.getElementById('debug').innerText += log + '\n'; 2965 } 2966 }, 2967 2968 /** 2969 * Throws an exception with the given error message. 2970 * @param {String} msg Error message 2971 */ 2972 _error: function (msg) { 2973 var e = new Error('Error(' + this.line + '): ' + msg); 2974 e.line = this.line; 2975 throw e; 2976 }, 2977 2978 /** 2979 * Output a warning message using {@link JXG#debug} and precedes the message with "Warning: ". 2980 * @param {String} msg 2981 */ 2982 _warn: function (msg) { 2983 if (typeof console === 'object' && console.log) { 2984 console.log('Warning(' + this.line + '): ' + msg); 2985 } else if (Env.isBrowser && document && document.getElementById(this.warnLog) !== null) { 2986 document.getElementById(this.warnLog).innerText += 'Warning(' + this.line + '): ' + msg + '\n'; 2987 } 2988 }, 2989 2990 _log: function (msg) { 2991 if (typeof window !== 'object' && typeof self === 'object' && self.postMessage) { 2992 self.postMessage({ type: 'log', msg: 'Log: ' + msg.toString() }); 2993 } else { 2994 console.log('Log: ', arguments); 2995 } 2996 } 2997 2998 }); 2999 3000 /* parser generated by jison 0.4.18 */ 3001 /* 3002 Returns a Parser object of the following structure: 3003 3004 Parser: { 3005 yy: {} 3006 } 3007 3008 Parser.prototype: { 3009 yy: {}, 3010 trace: function(), 3011 symbols_: {associative list: name ==> number}, 3012 terminals_: {associative list: number ==> name}, 3013 productions_: [...], 3014 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), 3015 table: [...], 3016 defaultActions: {...}, 3017 parseError: function(str, hash), 3018 parse: function(input), 3019 3020 lexer: { 3021 EOF: 1, 3022 parseError: function(str, hash), 3023 setInput: function(input), 3024 input: function(), 3025 unput: function(str), 3026 more: function(), 3027 less: function(n), 3028 pastInput: function(), 3029 upcomingInput: function(), 3030 showPosition: function(), 3031 test_match: function(regex_match_array, rule_index), 3032 next: function(), 3033 lex: function(), 3034 begin: function(condition), 3035 popState: function(), 3036 _currentRules: function(), 3037 topState: function(), 3038 pushState: function(condition), 3039 3040 options: { 3041 ranges: boolean (optional: true ==> token location info will include a .range[] member) 3042 flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) 3043 backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) 3044 }, 3045 3046 performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), 3047 rules: [...], 3048 conditions: {associative list: name ==> set}, 3049 } 3050 } 3051 3052 3053 token location info (@$, _$, etc.): { 3054 first_line: n, 3055 last_line: n, 3056 first_column: n, 3057 last_column: n, 3058 range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) 3059 } 3060 3061 3062 the parseError function receives a 'hash' object with these members for lexer and parser errors: { 3063 text: (matched text) 3064 token: (the produced terminal token, if any) 3065 line: (yylineno) 3066 } 3067 while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { 3068 loc: (yylloc) 3069 expected: (string describing the set of expected tokens) 3070 recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) 3071 } 3072 */ 3073 /** 3074 * @class 3075 * @ignore 3076 */ 3077 var parser = (function(){ 3078 var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[2,14],$V1=[1,13],$V2=[1,37],$V3=[1,14],$V4=[1,15],$V5=[1,21],$V6=[1,16],$V7=[1,17],$V8=[1,33],$V9=[1,18],$Va=[1,19],$Vb=[1,12],$Vc=[1,59],$Vd=[1,60],$Ve=[1,58],$Vf=[1,46],$Vg=[1,48],$Vh=[1,49],$Vi=[1,50],$Vj=[1,51],$Vk=[1,52],$Vl=[1,53],$Vm=[1,54],$Vn=[1,45],$Vo=[1,38],$Vp=[1,39],$Vq=[5,7,8,14,15,16,17,19,20,21,23,26,27,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$Vr=[5,7,8,12,14,15,16,17,19,20,21,23,26,27,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$Vs=[8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],$Vt=[2,48],$Vu=[1,72],$Vv=[10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,66,83,86],$Vw=[1,78],$Vx=[8,10,16,32,34,35,37,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],$Vy=[1,82],$Vz=[8,10,16,32,34,35,37,39,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],$VA=[1,83],$VB=[1,84],$VC=[1,85],$VD=[8,10,16,32,34,35,37,39,41,42,43,50,51,53,54,55,57,64,65,66,83,86],$VE=[1,89],$VF=[1,90],$VG=[1,91],$VH=[1,92],$VI=[1,97],$VJ=[8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,53,54,55,57,64,65,66,83,86],$VK=[1,103],$VL=[1,104],$VM=[8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,57,64,65,66,83,86],$VN=[1,105],$VO=[1,106],$VP=[1,107],$VQ=[1,126],$VR=[1,139],$VS=[83,86],$VT=[1,150],$VU=[10,66,86],$VV=[8,10,16,20,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,82,83,86],$VW=[1,167],$VX=[10,86]; 3079 /** 3080 * @class 3081 * @ignore 3082 */ 3083 var parser = {trace: function trace () { }, 3084 yy: {}, 3085 symbols_: {"error":2,"Program":3,"StatementList":4,"EOF":5,"IfStatement":6,"IF":7,"(":8,"Expression":9,")":10,"Statement":11,"ELSE":12,"LoopStatement":13,"WHILE":14,"FOR":15,";":16,"DO":17,"UnaryStatement":18,"USE":19,"IDENTIFIER":20,"DELETE":21,"ReturnStatement":22,"RETURN":23,"EmptyStatement":24,"StatementBlock":25,"{":26,"}":27,"ExpressionStatement":28,"AssignmentExpression":29,"ConditionalExpression":30,"LeftHandSideExpression":31,"=":32,"LogicalORExpression":33,"?":34,":":35,"LogicalANDExpression":36,"||":37,"EqualityExpression":38,"&&":39,"RelationalExpression":40,"==":41,"!=":42,"~=":43,"AdditiveExpression":44,"<":45,">":46,"<=":47,">=":48,"MultiplicativeExpression":49,"+":50,"-":51,"UnaryExpression":52,"*":53,"/":54,"%":55,"ExponentExpression":56,"^":57,"!":58,"MemberExpression":59,"CallExpression":60,"PrimaryExpression":61,"FunctionExpression":62,"MapExpression":63,".":64,"[":65,"]":66,"BasicLiteral":67,"ObjectLiteral":68,"ArrayLiteral":69,"NullLiteral":70,"BooleanLiteral":71,"StringLiteral":72,"NumberLiteral":73,"NULL":74,"TRUE":75,"FALSE":76,"STRING":77,"NUMBER":78,"NAN":79,"INFINITY":80,"ElementList":81,"<<":82,">>":83,"PropertyList":84,"Property":85,",":86,"PropertyName":87,"Arguments":88,"AttributeList":89,"Attribute":90,"FUNCTION":91,"ParameterDefinitionList":92,"MAP":93,"->":94,"$accept":0,"$end":1}, 3086 terminals_: {2:"error",5:"EOF",7:"IF",8:"(",10:")",12:"ELSE",14:"WHILE",15:"FOR",16:";",17:"DO",19:"USE",20:"IDENTIFIER",21:"DELETE",23:"RETURN",26:"{",27:"}",32:"=",34:"?",35:":",37:"||",39:"&&",41:"==",42:"!=",43:"~=",45:"<",46:">",47:"<=",48:">=",50:"+",51:"-",53:"*",54:"/",55:"%",57:"^",58:"!",64:".",65:"[",66:"]",74:"NULL",75:"TRUE",76:"FALSE",77:"STRING",78:"NUMBER",79:"NAN",80:"INFINITY",82:"<<",83:">>",86:",",91:"FUNCTION",93:"MAP",94:"->"}, 3087 productions_: [0,[3,2],[6,5],[6,7],[13,5],[13,9],[13,7],[18,2],[18,2],[22,2],[22,3],[24,1],[25,3],[4,2],[4,0],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[28,2],[9,1],[29,1],[29,3],[30,1],[30,5],[33,1],[33,3],[36,1],[36,3],[38,1],[38,3],[38,3],[38,3],[40,1],[40,3],[40,3],[40,3],[40,3],[44,1],[44,3],[44,3],[49,1],[49,3],[49,3],[49,3],[56,1],[56,3],[52,1],[52,2],[52,2],[52,2],[31,1],[31,1],[59,1],[59,1],[59,1],[59,3],[59,4],[61,1],[61,1],[61,1],[61,1],[61,3],[67,1],[67,1],[67,1],[67,1],[70,1],[71,1],[71,1],[72,1],[73,1],[73,1],[73,1],[69,2],[69,3],[68,2],[68,3],[84,1],[84,3],[85,3],[87,1],[87,1],[87,1],[60,2],[60,3],[60,2],[60,4],[60,3],[88,2],[88,3],[89,1],[89,3],[90,1],[90,1],[81,1],[81,3],[62,4],[62,5],[63,5],[63,6],[92,1],[92,3]], 3088 /** 3089 * @class 3090 * @ignore 3091 */ 3092 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { 3093 /* this == yyval */ 3094 3095 var $0 = $$.length - 1; 3096 switch (yystate) { 3097 case 1: 3098 return $$[$0-1]; 3099 break; 3100 case 2: 3101 this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_if', $$[$0-2], $$[$0]); 3102 break; 3103 case 3: 3104 this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_if_else', $$[$0-4], $$[$0-2], $$[$0]); 3105 break; 3106 case 4: 3107 this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_while', $$[$0-2], $$[$0]); 3108 break; 3109 case 5: 3110 this.$ = AST.createNode(lc(_$[$0-8]), 'node_op', 'op_for', $$[$0-6], $$[$0-4], $$[$0-2], $$[$0]); 3111 break; 3112 case 6: 3113 this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_do', $$[$0-5], $$[$0-2]); 3114 break; 3115 case 7: 3116 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_use', $$[$0]); 3117 break; 3118 case 8: 3119 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_delete', $$[$0]); 3120 break; 3121 case 9: 3122 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_return', undefined); 3123 break; 3124 case 10: 3125 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_return', $$[$0-1]); 3126 break; 3127 case 11: case 14: 3128 this.$ = AST.createNode(lc(_$[$0]), 'node_op', 'op_none'); 3129 break; 3130 case 12: 3131 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_block', $$[$0-1]); 3132 break; 3133 case 13: 3134 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_none', $$[$0-1], $$[$0]); 3135 break; 3136 case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 23: case 24: case 26: case 28: case 30: case 32: case 36: case 41: case 44: case 48: case 50: case 52: case 54: case 55: case 56: case 58: case 62: case 81: case 84: case 85: case 86: 3137 this.$ = $$[$0]; 3138 break; 3139 case 22: case 65: case 93: 3140 this.$ = $$[$0-1]; 3141 break; 3142 case 25: 3143 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_assign', $$[$0-2], $$[$0]); this.$.isMath = false; 3144 break; 3145 case 27: 3146 this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_conditional', $$[$0-4], $$[$0-2], $$[$0]); this.$.isMath = false; 3147 break; 3148 case 29: 3149 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_or', $$[$0-2], $$[$0]); this.$.isMath = false; 3150 break; 3151 case 31: 3152 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_and', $$[$0-2], $$[$0]); this.$.isMath = false; 3153 break; 3154 case 33: 3155 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_eq', $$[$0-2], $$[$0]); this.$.isMath = false; 3156 break; 3157 case 34: 3158 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_neq', $$[$0-2], $$[$0]); this.$.isMath = false; 3159 break; 3160 case 35: 3161 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_approx', $$[$0-2], $$[$0]); this.$.isMath = false; 3162 break; 3163 case 37: 3164 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_lt', $$[$0-2], $$[$0]); this.$.isMath = false; 3165 break; 3166 case 38: 3167 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_gt', $$[$0-2], $$[$0]); this.$.isMath = false; 3168 break; 3169 case 39: 3170 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_leq', $$[$0-2], $$[$0]); this.$.isMath = false; 3171 break; 3172 case 40: 3173 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_geq', $$[$0-2], $$[$0]); this.$.isMath = false; 3174 break; 3175 case 42: 3176 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_add', $$[$0-2], $$[$0]); this.$.isMath = true; 3177 break; 3178 case 43: 3179 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_sub', $$[$0-2], $$[$0]); this.$.isMath = true; 3180 break; 3181 case 45: 3182 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mul', $$[$0-2], $$[$0]); this.$.isMath = true; 3183 break; 3184 case 46: 3185 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_div', $$[$0-2], $$[$0]); this.$.isMath = true; 3186 break; 3187 case 47: 3188 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mod', $$[$0-2], $$[$0]); this.$.isMath = true; 3189 break; 3190 case 49: 3191 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_exp', $$[$0-2], $$[$0]); this.$.isMath = true; 3192 break; 3193 case 51: 3194 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_not', $$[$0]); this.$.isMath = false; 3195 break; 3196 case 53: 3197 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_neg', $$[$0]); this.$.isMath = true; 3198 break; 3199 case 57: case 63: case 64: case 66: case 67: case 68: case 97: 3200 this.$ = $$[$0]; this.$.isMath = false; 3201 break; 3202 case 59: case 91: 3203 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_property', $$[$0-2], $$[$0]); this.$.isMath = true; 3204 break; 3205 case 60: case 90: 3206 this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_extvalue', $$[$0-3], $$[$0-1]); this.$.isMath = true; 3207 break; 3208 case 61: 3209 this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); 3210 break; 3211 case 69: 3212 this.$ = $$[$0]; this.$.isMath = true; 3213 break; 3214 case 70: 3215 this.$ = AST.createNode(lc(_$[$0]), 'node_const', null); 3216 break; 3217 case 71: 3218 this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', true); 3219 break; 3220 case 72: 3221 this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', false); 3222 break; 3223 case 73: 3224 this.$ = AST.createNode(lc(_$[$0]), 'node_str', $$[$0].substring(1, $$[$0].length - 1)); 3225 break; 3226 case 74: 3227 this.$ = AST.createNode(lc(_$[$0]), 'node_const', parseFloat($$[$0])); 3228 break; 3229 case 75: 3230 this.$ = AST.createNode(lc(_$[$0]), 'node_const', NaN); 3231 break; 3232 case 76: 3233 this.$ = AST.createNode(lc(_$[$0]), 'node_const', Infinity); 3234 break; 3235 case 77: 3236 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_array', []); 3237 break; 3238 case 78: 3239 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_array', $$[$0-1]); 3240 break; 3241 case 79: 3242 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_emptyobject', {}); this.$.needsAngleBrackets = true; 3243 break; 3244 case 80: 3245 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst_val', $$[$0-1]); this.$.needsAngleBrackets = true; 3246 break; 3247 case 82: 3248 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst', $$[$0-2], $$[$0]); 3249 break; 3250 case 83: 3251 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_prop', $$[$0-2], $$[$0]); 3252 break; 3253 case 87: case 89: 3254 this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_execfun', $$[$0-1], $$[$0]); this.$.isMath = true; 3255 break; 3256 case 88: 3257 this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_execfun', $$[$0-2], $$[$0-1], $$[$0], true); this.$.isMath = false; 3258 break; 3259 case 92: 3260 this.$ = []; 3261 break; 3262 case 94: case 98: case 104: 3263 this.$ = [$$[$0]]; 3264 break; 3265 case 95: case 99: case 105: 3266 this.$ = $$[$0-2].concat($$[$0]); 3267 break; 3268 case 96: 3269 this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); this.$.isMath = true; 3270 break; 3271 case 100: 3272 this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_function', [], $$[$0]); this.$.isMath = false; 3273 break; 3274 case 101: 3275 this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_function', $$[$0-2], $$[$0]); this.$.isMath = false; 3276 break; 3277 case 102: 3278 this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_map', [], $$[$0]); 3279 break; 3280 case 103: 3281 this.$ = AST.createNode(lc(_$[$0-5]), 'node_op', 'op_map', $$[$0-3], $$[$0]); 3282 break; 3283 } 3284 }, 3285 table: [o([5,7,8,14,15,16,17,19,20,21,23,26,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$V0,{3:1,4:2}),{1:[3]},{5:[1,3],6:6,7:$V1,8:$V2,9:20,11:4,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{1:[2,1]},o($Vq,[2,13]),o($Vr,[2,15]),o($Vr,[2,16]),o($Vr,[2,17]),o($Vr,[2,18]),o($Vr,[2,19]),o($Vr,[2,20]),o($Vr,[2,21]),o([7,8,14,15,16,17,19,20,21,23,26,27,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$V0,{4:61}),{8:[1,62]},{8:[1,63]},{8:[1,64]},{6:6,7:$V1,8:$V2,9:20,11:65,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{20:[1,66]},{20:[1,67]},{8:$V2,9:69,16:[1,68],20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{16:[1,70]},o($Vr,[2,11]),o($Vs,[2,23]),o($Vs,[2,24]),o([8,10,16,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,64,65,66,83,86],$Vt,{32:[1,71],57:$Vu}),o([8,10,16,32,35,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],[2,26],{34:[1,73],37:[1,74]}),o($Vv,[2,54],{88:77,8:$Vw,64:[1,75],65:[1,76]}),o($Vv,[2,55],{88:79,8:$Vw,64:[1,81],65:[1,80]}),o($Vx,[2,28],{39:$Vy}),o($Vs,[2,56]),o($Vs,[2,57]),o($Vs,[2,58]),o($Vz,[2,30],{41:$VA,42:$VB,43:$VC}),o($Vs,[2,61]),o($Vs,[2,62]),o($Vs,[2,63]),o($Vs,[2,64]),{8:$V2,9:86,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:[1,87]},{8:[1,88]},o($VD,[2,32],{45:$VE,46:$VF,47:$VG,48:$VH}),o($Vs,[2,66]),o($Vs,[2,67]),o($Vs,[2,68]),o($Vs,[2,69]),{20:$VI,72:98,73:99,77:$Vj,78:$Vk,79:$Vl,80:$Vm,83:[1,93],84:94,85:95,87:96},{8:$V2,20:$V8,29:102,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,66:[1,100],67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,81:101,82:$Vn,91:$Vo,93:$Vp},o($VJ,[2,36],{50:$VK,51:$VL}),o($Vs,[2,70]),o($Vs,[2,71]),o($Vs,[2,72]),o($Vs,[2,73]),o($Vs,[2,74]),o($Vs,[2,75]),o($Vs,[2,76]),o($VM,[2,41],{53:$VN,54:$VO,55:$VP}),o($Vs,[2,44]),o($Vs,[2,50]),{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:108,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:110,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:111,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{6:6,7:$V1,8:$V2,9:20,11:4,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,27:[1,112],28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:113,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:114,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:115,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{14:[1,116]},o($Vr,[2,7]),o($Vr,[2,8]),o($Vr,[2,9]),{16:[1,117]},o($Vr,[2,22]),{8:$V2,20:$V8,29:118,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:119,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,29:120,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,36:121,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{20:[1,122]},{8:$V2,9:123,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,87],{89:124,90:125,68:127,20:$VQ,82:$Vn}),{8:$V2,10:[1,128],20:$V8,29:102,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,81:129,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,89]),{8:$V2,9:130,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{20:[1,131]},{8:$V2,20:$V8,31:109,38:132,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,40:133,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,40:134,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,40:135,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{10:[1,136]},{10:[1,137],20:$VR,92:138},{10:[1,140],20:$VR,92:141},{8:$V2,20:$V8,31:109,44:142,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,44:143,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,44:144,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,44:145,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,79]),{83:[1,146],86:[1,147]},o($VS,[2,81]),{35:[1,148]},{35:[2,84]},{35:[2,85]},{35:[2,86]},o($Vs,[2,77]),{66:[1,149],86:$VT},o($VU,[2,98]),{8:$V2,20:$V8,31:109,49:151,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,49:152,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:153,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:154,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:155,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,51]),o([8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,64,65,66,83,86],$Vt,{57:$Vu}),o($Vs,[2,52]),o($Vs,[2,53]),o([5,7,8,10,12,14,15,16,17,19,20,21,23,26,27,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,58,64,65,66,74,75,76,77,78,79,80,82,83,86,91,93],[2,12]),{10:[1,156]},{10:[1,157]},{16:[1,158]},{8:[1,159]},o($Vr,[2,10]),o($Vs,[2,25]),o($Vs,[2,49]),{35:[1,160]},o($Vx,[2,29],{39:$Vy}),o($Vs,[2,59]),{66:[1,161]},o([8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83],[2,88],{86:[1,162]}),o($Vs,[2,94]),o($Vs,[2,96]),o($Vs,[2,97]),o($VV,[2,92]),{10:[1,163],86:$VT},{66:[1,164]},o($Vs,[2,91]),o($Vz,[2,31],{41:$VA,42:$VB,43:$VC}),o($VD,[2,33],{45:$VE,46:$VF,47:$VG,48:$VH}),o($VD,[2,34],{45:$VE,46:$VF,47:$VG,48:$VH}),o($VD,[2,35],{45:$VE,46:$VF,47:$VG,48:$VH}),o($Vs,[2,65]),{25:165,26:$Vb},{10:[1,166],86:$VW},o($VX,[2,104]),{94:[1,168]},{10:[1,169],86:$VW},o($VJ,[2,37],{50:$VK,51:$VL}),o($VJ,[2,38],{50:$VK,51:$VL}),o($VJ,[2,39],{50:$VK,51:$VL}),o($VJ,[2,40],{50:$VK,51:$VL}),o($Vs,[2,80]),{20:$VI,72:98,73:99,77:$Vj,78:$Vk,79:$Vl,80:$Vm,85:170,87:96},{8:$V2,20:$V8,29:171,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,78]),{8:$V2,20:$V8,29:172,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($VM,[2,42],{53:$VN,54:$VO,55:$VP}),o($VM,[2,43],{53:$VN,54:$VO,55:$VP}),o($Vs,[2,45]),o($Vs,[2,46]),o($Vs,[2,47]),{6:6,7:$V1,8:$V2,9:20,11:173,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{6:6,7:$V1,8:$V2,9:20,11:174,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:175,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:176,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,29:177,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,60]),{20:$VQ,68:127,82:$Vn,90:178},o($VV,[2,93]),o($Vs,[2,90]),o($Vs,[2,100]),{25:179,26:$Vb},{20:[1,180]},{8:$V2,9:181,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{94:[1,182]},o($VS,[2,82]),o($VS,[2,83]),o($VU,[2,99]),o($Vq,[2,2],{12:[1,183]}),o($Vr,[2,4]),{16:[1,184]},{10:[1,185]},o($Vs,[2,27]),o($Vs,[2,95]),o($Vs,[2,101]),o($VX,[2,105]),o($Vs,[2,102]),{8:$V2,9:186,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{6:6,7:$V1,8:$V2,9:20,11:187,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:188,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{16:[1,189]},o($Vs,[2,103]),o($Vr,[2,3]),{10:[1,190]},o($Vr,[2,6]),{6:6,7:$V1,8:$V2,9:20,11:191,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vr,[2,5])], 3286 defaultActions: {3:[2,1],97:[2,84],98:[2,85],99:[2,86]}, 3287 parseError: function parseError (str, hash) { 3288 if (hash.recoverable) { 3289 this.trace(str); 3290 } else { 3291 var error = new Error(str); 3292 error.hash = hash; 3293 throw error; 3294 } 3295 }, 3296 /** 3297 * @class 3298 * @ignore 3299 */ 3300 parse: function parse(input) { 3301 var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; 3302 var args = lstack.slice.call(arguments, 1); 3303 var lexer = Object.create(this.lexer); 3304 var sharedState = { yy: {} }; 3305 for (var k in this.yy) { 3306 if (Object.prototype.hasOwnProperty.call(this.yy, k)) { 3307 sharedState.yy[k] = this.yy[k]; 3308 } 3309 } 3310 lexer.setInput(input, sharedState.yy); 3311 sharedState.yy.lexer = lexer; 3312 sharedState.yy.parser = this; 3313 if (typeof lexer.yylloc == 'undefined') { 3314 lexer.yylloc = {}; 3315 } 3316 var yyloc = lexer.yylloc; 3317 lstack.push(yyloc); 3318 var ranges = lexer.options && lexer.options.ranges; 3319 if (typeof sharedState.yy.parseError === 'function') { 3320 this.parseError = sharedState.yy.parseError; 3321 } else { 3322 this.parseError = Object.getPrototypeOf(this).parseError; 3323 } 3324 function popStack(n) { 3325 stack.length = stack.length - 2 * n; 3326 vstack.length = vstack.length - n; 3327 lstack.length = lstack.length - n; 3328 } 3329 _token_stack: 3330 var lex = function () { 3331 var token; 3332 token = lexer.lex() || EOF; 3333 if (typeof token !== 'number') { 3334 token = self.symbols_[token] || token; 3335 } 3336 return token; 3337 }; 3338 var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; 3339 while (true) { 3340 state = stack[stack.length - 1]; 3341 if (this.defaultActions[state]) { 3342 action = this.defaultActions[state]; 3343 } else { 3344 if (symbol === null || typeof symbol == 'undefined') { 3345 symbol = lex(); 3346 } 3347 action = table[state] && table[state][symbol]; 3348 } 3349 if (typeof action === 'undefined' || !action.length || !action[0]) { 3350 var errStr = ''; 3351 expected = []; 3352 for (p in table[state]) { 3353 if (this.terminals_[p] && p > TERROR) { 3354 expected.push('\'' + this.terminals_[p] + '\''); 3355 } 3356 } 3357 if (lexer.showPosition) { 3358 errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; 3359 } else { 3360 errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); 3361 } 3362 this.parseError(errStr, { 3363 text: lexer.match, 3364 token: this.terminals_[symbol] || symbol, 3365 line: lexer.yylineno, 3366 loc: yyloc, 3367 expected: expected 3368 }); 3369 } 3370 if (action[0] instanceof Array && action.length > 1) { 3371 throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); 3372 } 3373 switch (action[0]) { 3374 case 1: 3375 stack.push(symbol); 3376 vstack.push(lexer.yytext); 3377 lstack.push(lexer.yylloc); 3378 stack.push(action[1]); 3379 symbol = null; 3380 if (!preErrorSymbol) { 3381 yyleng = lexer.yyleng; 3382 yytext = lexer.yytext; 3383 yylineno = lexer.yylineno; 3384 yyloc = lexer.yylloc; 3385 if (recovering > 0) { 3386 recovering--; 3387 } 3388 } else { 3389 symbol = preErrorSymbol; 3390 preErrorSymbol = null; 3391 } 3392 break; 3393 case 2: 3394 len = this.productions_[action[1]][1]; 3395 yyval.$ = vstack[vstack.length - len]; 3396 yyval._$ = { 3397 first_line: lstack[lstack.length - (len || 1)].first_line, 3398 last_line: lstack[lstack.length - 1].last_line, 3399 first_column: lstack[lstack.length - (len || 1)].first_column, 3400 last_column: lstack[lstack.length - 1].last_column 3401 }; 3402 if (ranges) { 3403 yyval._$.range = [ 3404 lstack[lstack.length - (len || 1)].range[0], 3405 lstack[lstack.length - 1].range[1] 3406 ]; 3407 } 3408 r = this.performAction.apply(yyval, [ 3409 yytext, 3410 yyleng, 3411 yylineno, 3412 sharedState.yy, 3413 action[1], 3414 vstack, 3415 lstack 3416 ].concat(args)); 3417 if (typeof r !== 'undefined') { 3418 return r; 3419 } 3420 if (len) { 3421 stack = stack.slice(0, -1 * len * 2); 3422 vstack = vstack.slice(0, -1 * len); 3423 lstack = lstack.slice(0, -1 * len); 3424 } 3425 stack.push(this.productions_[action[1]][0]); 3426 vstack.push(yyval.$); 3427 lstack.push(yyval._$); 3428 newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; 3429 stack.push(newState); 3430 break; 3431 case 3: 3432 return true; 3433 } 3434 } 3435 return true; 3436 }}; 3437 3438 3439 var AST = { 3440 node: function (type, value, children) { 3441 return { 3442 type: type, 3443 value: value, 3444 children: children 3445 }; 3446 }, 3447 3448 createNode: function (pos, type, value, children) { 3449 var i, 3450 n = this.node(type, value, []); 3451 3452 for (i = 3; i < arguments.length; i++) { 3453 n.children.push(arguments[i]); 3454 } 3455 3456 n.line = pos[0]; 3457 n.col = pos[1]; 3458 n.eline = pos[2]; 3459 n.ecol = pos[3]; 3460 3461 return n; 3462 } 3463 }; 3464 3465 var lc = function (lc1) { 3466 return [lc1.first_line, lc1.first_column, lc1.last_line, lc1.last_column]; 3467 }; 3468 3469 /* generated by jison-lex 0.3.4 */ 3470 var lexer = (function(){ 3471 var lexer = ({ 3472 3473 EOF:1, 3474 3475 parseError:function parseError(str, hash) { 3476 if (this.yy.parser) { 3477 this.yy.parser.parseError(str, hash); 3478 } else { 3479 throw new Error(str); 3480 } 3481 }, 3482 3483 // resets the lexer, sets new input 3484 setInput:function (input, yy) { 3485 this.yy = yy || this.yy || {}; 3486 this._input = input; 3487 this._more = this._backtrack = this.done = false; 3488 this.yylineno = this.yyleng = 0; 3489 this.yytext = this.matched = this.match = ''; 3490 this.conditionStack = ['INITIAL']; 3491 this.yylloc = { 3492 first_line: 1, 3493 first_column: 0, 3494 last_line: 1, 3495 last_column: 0 3496 }; 3497 if (this.options.ranges) { 3498 this.yylloc.range = [0,0]; 3499 } 3500 this.offset = 0; 3501 return this; 3502 }, 3503 3504 // consumes and returns one char from the input 3505 input:function () { 3506 var ch = this._input[0]; 3507 this.yytext += ch; 3508 this.yyleng++; 3509 this.offset++; 3510 this.match += ch; 3511 this.matched += ch; 3512 var lines = ch.match(/(?:\r\n?|\n).*/g); 3513 if (lines) { 3514 this.yylineno++; 3515 this.yylloc.last_line++; 3516 } else { 3517 this.yylloc.last_column++; 3518 } 3519 if (this.options.ranges) { 3520 this.yylloc.range[1]++; 3521 } 3522 3523 this._input = this._input.slice(1); 3524 return ch; 3525 }, 3526 3527 // unshifts one char (or a string) into the input 3528 unput:function (ch) { 3529 var len = ch.length; 3530 var lines = ch.split(/(?:\r\n?|\n)/g); 3531 3532 this._input = ch + this._input; 3533 this.yytext = this.yytext.substr(0, this.yytext.length - len); 3534 //this.yyleng -= len; 3535 this.offset -= len; 3536 var oldLines = this.match.split(/(?:\r\n?|\n)/g); 3537 this.match = this.match.substr(0, this.match.length - 1); 3538 this.matched = this.matched.substr(0, this.matched.length - 1); 3539 3540 if (lines.length - 1) { 3541 this.yylineno -= lines.length - 1; 3542 } 3543 var r = this.yylloc.range; 3544 3545 this.yylloc = { 3546 first_line: this.yylloc.first_line, 3547 last_line: this.yylineno + 1, 3548 first_column: this.yylloc.first_column, 3549 last_column: lines ? 3550 (lines.length === oldLines.length ? this.yylloc.first_column : 0) 3551 + oldLines[oldLines.length - lines.length].length - lines[0].length : 3552 this.yylloc.first_column - len 3553 }; 3554 3555 if (this.options.ranges) { 3556 this.yylloc.range = [r[0], r[0] + this.yyleng - len]; 3557 } 3558 this.yyleng = this.yytext.length; 3559 return this; 3560 }, 3561 3562 // When called from action, caches matched text and appends it on next action 3563 more:function () { 3564 this._more = true; 3565 return this; 3566 }, 3567 3568 // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. 3569 reject:function () { 3570 if (this.options.backtrack_lexer) { 3571 this._backtrack = true; 3572 } else { 3573 return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { 3574 text: "", 3575 token: null, 3576 line: this.yylineno 3577 }); 3578 3579 } 3580 return this; 3581 }, 3582 3583 // retain first n characters of the match 3584 less:function (n) { 3585 this.unput(this.match.slice(n)); 3586 }, 3587 3588 // displays already matched input, i.e. for error messages 3589 pastInput:function () { 3590 var past = this.matched.substr(0, this.matched.length - this.match.length); 3591 return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "").replace(/[&<>]/g, function (c) { 3592 return c === '&' ? '&' : (c === '<' ? '<' : '>'); 3593 }); 3594 }, 3595 3596 // displays upcoming input, i.e. for error messages 3597 upcomingInput:function () { 3598 var next = this.match; 3599 if (next.length < 20) { 3600 next += this._input.substr(0, 20-next.length); 3601 } 3602 return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "").replace(/[&<>]/g, function (c) { 3603 return c === '&' ? '&' : (c === '<' ? '<' : '>'); 3604 }); 3605 }, 3606 3607 // displays the character position where the lexing error occurred, i.e. for error messages 3608 showPosition:function () { 3609 var pre = this.pastInput(); 3610 var c = new Array(pre.length + 1).join("-"); 3611 return pre + this.upcomingInput() + "\n" + c + "^"; 3612 }, 3613 3614 // test the lexed token: return FALSE when not a match, otherwise return token 3615 test_match:function(match, indexed_rule) { 3616 var token, 3617 lines, 3618 backup; 3619 3620 if (this.options.backtrack_lexer) { 3621 // save context 3622 backup = { 3623 yylineno: this.yylineno, 3624 yylloc: { 3625 first_line: this.yylloc.first_line, 3626 last_line: this.last_line, 3627 first_column: this.yylloc.first_column, 3628 last_column: this.yylloc.last_column 3629 }, 3630 yytext: this.yytext, 3631 match: this.match, 3632 matches: this.matches, 3633 matched: this.matched, 3634 yyleng: this.yyleng, 3635 offset: this.offset, 3636 _more: this._more, 3637 _input: this._input, 3638 yy: this.yy, 3639 conditionStack: this.conditionStack.slice(0), 3640 done: this.done 3641 }; 3642 if (this.options.ranges) { 3643 backup.yylloc.range = this.yylloc.range.slice(0); 3644 } 3645 } 3646 3647 lines = match[0].match(/(?:\r\n?|\n).*/g); 3648 if (lines) { 3649 this.yylineno += lines.length; 3650 } 3651 this.yylloc = { 3652 first_line: this.yylloc.last_line, 3653 last_line: this.yylineno + 1, 3654 first_column: this.yylloc.last_column, 3655 last_column: lines ? 3656 lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : 3657 this.yylloc.last_column + match[0].length 3658 }; 3659 this.yytext += match[0]; 3660 this.match += match[0]; 3661 this.matches = match; 3662 this.yyleng = this.yytext.length; 3663 if (this.options.ranges) { 3664 this.yylloc.range = [this.offset, this.offset += this.yyleng]; 3665 } 3666 this._more = false; 3667 this._backtrack = false; 3668 this._input = this._input.slice(match[0].length); 3669 this.matched += match[0]; 3670 token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); 3671 if (this.done && this._input) { 3672 this.done = false; 3673 } 3674 if (token) { 3675 return token; 3676 } else if (this._backtrack) { 3677 // recover context 3678 for (var k in backup) { 3679 this[k] = backup[k]; 3680 } 3681 return false; // rule action called reject() implying the next rule should be tested instead. 3682 } 3683 return false; 3684 }, 3685 3686 // return next match in input 3687 next:function () { 3688 if (this.done) { 3689 return this.EOF; 3690 } 3691 if (!this._input) { 3692 this.done = true; 3693 } 3694 3695 var token, 3696 match, 3697 tempMatch, 3698 index; 3699 if (!this._more) { 3700 this.yytext = ''; 3701 this.match = ''; 3702 } 3703 var rules = this._currentRules(); 3704 for (var i = 0; i < rules.length; i++) { 3705 tempMatch = this._input.match(this.rules[rules[i]]); 3706 if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { 3707 match = tempMatch; 3708 index = i; 3709 if (this.options.backtrack_lexer) { 3710 token = this.test_match(tempMatch, rules[i]); 3711 if (token !== false) { 3712 return token; 3713 } else if (this._backtrack) { 3714 match = false; 3715 continue; // rule action called reject() implying a rule MISmatch. 3716 } else { 3717 // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) 3718 return false; 3719 } 3720 } else if (!this.options.flex) { 3721 break; 3722 } 3723 } 3724 } 3725 if (match) { 3726 token = this.test_match(match, rules[index]); 3727 if (token !== false) { 3728 return token; 3729 } 3730 // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) 3731 return false; 3732 } 3733 if (this._input === "") { 3734 return this.EOF; 3735 } else { 3736 return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { 3737 text: "", 3738 token: null, 3739 line: this.yylineno 3740 }); 3741 } 3742 }, 3743 3744 // return next match that has a token 3745 lex:function lex () { 3746 var r = this.next(); 3747 if (r) { 3748 return r; 3749 } else { 3750 return this.lex(); 3751 } 3752 }, 3753 3754 // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) 3755 begin:function begin (condition) { 3756 this.conditionStack.push(condition); 3757 }, 3758 3759 // pop the previously active lexer condition state off the condition stack 3760 popState:function popState () { 3761 var n = this.conditionStack.length - 1; 3762 if (n > 0) { 3763 return this.conditionStack.pop(); 3764 } else { 3765 return this.conditionStack[0]; 3766 } 3767 }, 3768 3769 // produce the lexer rule set which is active for the currently active lexer condition state 3770 _currentRules:function _currentRules () { 3771 if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { 3772 return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; 3773 } else { 3774 return this.conditions["INITIAL"].rules; 3775 } 3776 }, 3777 3778 // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available 3779 topState:function topState (n) { 3780 n = this.conditionStack.length - 1 - Math.abs(n || 0); 3781 if (n >= 0) { 3782 return this.conditionStack[n]; 3783 } else { 3784 return "INITIAL"; 3785 } 3786 }, 3787 3788 // alias for begin(condition) 3789 pushState:function pushState (condition) { 3790 this.begin(condition); 3791 }, 3792 3793 // return the number of states currently on the stack 3794 stateStackSize:function stateStackSize() { 3795 return this.conditionStack.length; 3796 }, 3797 options: {}, 3798 /** 3799 * @class 3800 * @ignore 3801 */ 3802 performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { 3803 var YYSTATE=YY_START; 3804 switch($avoiding_name_collisions) { 3805 case 0:/* ignore */ 3806 break; 3807 case 1:return 78 /* New 123.1234e+-12 */ 3808 break; 3809 case 2:return 78 /* Old 123.1234 or .1234 */ 3810 break; 3811 case 3:return 78 /* Old 123 */ 3812 break; 3813 case 4: return 77; 3814 break; 3815 case 5: return 77; 3816 break; 3817 case 6:/* ignore comment */ 3818 break; 3819 case 7:/* ignore multiline comment */ 3820 break; 3821 case 8:return 7 3822 break; 3823 case 9:return 12 3824 break; 3825 case 10:return 14 3826 break; 3827 case 11:return 17 3828 break; 3829 case 12:return 15 3830 break; 3831 case 13:return 91 3832 break; 3833 case 14:return 93 3834 break; 3835 case 15:return 19 3836 break; 3837 case 16:return 23 3838 break; 3839 case 17:return 21 3840 break; 3841 case 18:return 75 3842 break; 3843 case 19:return 76 3844 break; 3845 case 20:return 74 3846 break; 3847 case 21:return 80 3848 break; 3849 case 22:return 94 3850 break; 3851 case 23:return 94 3852 break; 3853 case 24:return 82 3854 break; 3855 case 25:return 83 3856 break; 3857 case 26:return 26 3858 break; 3859 case 27:return 27 3860 break; 3861 case 28:return 16 3862 break; 3863 case 29:return '#' 3864 break; 3865 case 30:return 34 3866 break; 3867 case 31:return 35 3868 break; 3869 case 32:return 79 3870 break; 3871 case 33:return 64 3872 break; 3873 case 34:return 65 3874 break; 3875 case 35:return 66 3876 break; 3877 case 36:return 8 3878 break; 3879 case 37:return 10 3880 break; 3881 case 38:return 58 3882 break; 3883 case 39:return 57 3884 break; 3885 case 40:return 57 3886 break; 3887 case 41:return 53 3888 break; 3889 case 42:return 54 3890 break; 3891 case 43:return 55 3892 break; 3893 case 44:return 50 3894 break; 3895 case 45:return 51 3896 break; 3897 case 46:return 47 3898 break; 3899 case 47:return 45 3900 break; 3901 case 48:return 48 3902 break; 3903 case 49:return 46 3904 break; 3905 case 50:return 41 3906 break; 3907 case 51:return 43 3908 break; 3909 case 52:return 42 3910 break; 3911 case 53:return 39 3912 break; 3913 case 54:return 37 3914 break; 3915 case 55:return 32 3916 break; 3917 case 56:return 86 3918 break; 3919 case 57:return 5 3920 break; 3921 case 58:return 20 3922 break; 3923 case 59:return 'INVALID' 3924 break; 3925 } 3926 }, 3927 rules: [/^(?:\s+)/,/^(?:[0-9]*\.?[0-9]+([eE][-+]?[0-9]+))/,/^(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+\b)/,/^(?:[0-9]+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:\/\/.*)/,/^(?:\/\*(.|\n|\r)*?\*\/)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:while\b)/,/^(?:do\b)/,/^(?:for\b)/,/^(?:function\b)/,/^(?:map\b)/,/^(?:use\b)/,/^(?:return\b)/,/^(?:delete\b)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:Infinity\b)/,/^(?:->)/,/^(?:=>)/,/^(?:<<)/,/^(?:>>)/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:#)/,/^(?:\?)/,/^(?::)/,/^(?:NaN\b)/,/^(?:\.)/,/^(?:\[)/,/^(?:\])/,/^(?:\()/,/^(?:\))/,/^(?:!)/,/^(?:\^)/,/^(?:\*\*)/,/^(?:\*)/,/^(?:\/)/,/^(?:%)/,/^(?:\+)/,/^(?:-)/,/^(?:<=)/,/^(?:<)/,/^(?:>=)/,/^(?:>)/,/^(?:==)/,/^(?:~=)/,/^(?:!=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:=)/,/^(?:,)/,/^(?:$)/,/^(?:[A-Za-z_\$][A-Za-z0-9_]*)/,/^(?:.)/], 3928 conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59],"inclusive":true}} 3929 }); 3930 return lexer; 3931 })(); 3932 parser.lexer = lexer; 3933 /** 3934 * @class 3935 * @ignore 3936 */ 3937 function Parser () { 3938 this.yy = {}; 3939 } 3940 Parser.prototype = parser;parser.Parser = Parser; 3941 return new Parser; 3942 })(); 3943 // Work around an issue with browsers that don't support Object.getPrototypeOf() 3944 parser.yy.parseError = parser.parseError; 3945 3946 export default JXG.JessieCode; 3947