{"LICENSE": "Most of the software in this directory is Copyright (C) Scott\nFortmann-Roe.\n\nUnless otherwise stated in particular files or directories, this\nsoftware is free software; you can redistribute it and/or modify it\nunder the terms of the GNU Affero General Public License as published\nby the Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nInformation about the GNU Affero GPL is available here:\nhttp://www.fsf.org/licensing/licenses/agpl-3.0.html\n\nA copy of the GNU Affero General Public License follows.\n\n-----------------------------------------------------------------------\n\n                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n", "vite.config.js": "import { configDefaults, defineConfig } from \"vitest/config\";\n\nexport default defineConfig(({ command }) => ({\n  test: {\n    globals: true,\n    testTimeout: 60000,\n    exclude: [...configDefaults.exclude, \"types/**\"]\n  }\n}));\n", "package.json": "{\n  \"name\": \"simulation\",\n  \"version\": \"9.0.0\",\n  \"author\": \"Scott Fortmann-Roe\",\n  \"license\": \"AGPL\",\n  \"description\": \"simulation is a multi-method simulation package for physical or social systems. Use it to create models for the environment, business, or other domains.\",\n  \"keywords\": [\n    \"simulation\",\n    \"modeling\",\n    \"differential equations\",\n    \"system dynamics\",\n    \"agent based modeling\",\n    \"ABM\"\n  ],\n  \"homepage\": \"https://github.com/scottfr/simulation\",\n  \"type\": \"module\",\n  \"main\": \"src/api/Model.js\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./types/api/Model.d.ts\",\n      \"import\": \"./src/api/Model.js\",\n      \"default\": \"./src/api/Model.js\"\n    }\n  },\n  \"scripts\": {\n    \"test\": \"vitest run\",\n    \"build-d-ts\": \"( test ! -d types || rm -r types ) && npx -p typescript tsc -p tsconfig.types.json\"\n  }\n}", "vendor/graph.js": "// @ts-nocheck\n/* eslint-disable */\n/**\n * Springy v1.0.1\n *\n * Copyright (c) 2010 Dennis Hotson\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nexport let Graph = function() {\n\tthis.nodeSet = {};\n\tthis.nodes = [];\n\tthis.edges = [];\n\tthis.adjacency = {};\n\n\tthis.nextNodeId = 0;\n\tthis.nextEdgeId = 0;\n\tthis.eventListeners = [];\n};\n\nvar Node = function(id, data) {\n\tthis.id = id;\n\tthis.data = typeof(data) !== 'undefined' ? data : {};\n};\n\nvar Edge = function(id, source, target, data) {\n\tthis.id = id;\n\tthis.source = source;\n\tthis.target = target;\n\tthis.data = typeof(data) !== 'undefined' ? data : {};\n};\n\nGraph.prototype.addNode = function(node) {\n\tif (typeof(this.nodeSet[node.id]) === 'undefined') {\n\t\tthis.nodes.push(node);\n\t}\n\n\tthis.nodeSet[node.id] = node;\n\n\tthis.notify();\n\treturn node;\n};\n\nGraph.prototype.addEdge = function(edge) {\n\tvar exists = false;\n\tthis.edges.forEach(function(e) {\n\t\tif (edge.id === e.id) { exists = true; }\n\t});\n\n\tif (!exists) {\n\t\tthis.edges.push(edge);\n\t}\n\n\tif (typeof(this.adjacency[edge.source.id]) === 'undefined') {\n\t\tthis.adjacency[edge.source.id] = {};\n\t}\n\tif (typeof(this.adjacency[edge.source.id][edge.target.id]) === 'undefined') {\n\t\tthis.adjacency[edge.source.id][edge.target.id] = [];\n\t}\n\n\texists = false;\n\tthis.adjacency[edge.source.id][edge.target.id].forEach(function(e) {\n\t\t\tif (edge.id === e.id) { exists = true; }\n\t});\n\n\tif (!exists) {\n\t\tthis.adjacency[edge.source.id][edge.target.id].push(edge);\n\t}\n\n\tthis.notify();\n\treturn edge;\n};\n\nGraph.prototype.newNode = function(data) {\n\tvar node = new Node(this.nextNodeId++, data);\n\tthis.addNode(node);\n\treturn node;\n};\n\nGraph.prototype.newEdge = function(source, target, data) {\n\tvar edge = new Edge(this.nextEdgeId++, source, target, data);\n\tthis.addEdge(edge);\n\treturn edge;\n};\n\n// find the edges from node1 to node2\nGraph.prototype.getEdges = function(node1, node2) {\n\tif (typeof(this.adjacency[node1.id]) !== 'undefined'\n\t\t&& typeof(this.adjacency[node1.id][node2.id]) !== 'undefined') {\n\t\treturn this.adjacency[node1.id][node2.id];\n\t}\n\n\treturn [];\n};\n\n// remove a node and it's associated edges from the graph\nGraph.prototype.removeNode = function(node) {\n\tif (typeof(this.nodeSet[node.id]) !== 'undefined') {\n\t\tdelete this.nodeSet[node.id];\n\t}\n\n\tfor (var i = this.nodes.length - 1; i >= 0; i--) {\n\t\tif (this.nodes[i].id === node.id) {\n\t\t\tthis.nodes.splice(i, 1);\n\t\t}\n\t}\n\n\tthis.detachNode(node);\n\n};\n\n// removes edges associated with a given node\nGraph.prototype.detachNode = function(node) {\n\tvar tmpEdges = this.edges.slice();\n\ttmpEdges.forEach(function(e) {\n\t\tif (e.source.id === node.id || e.target.id === node.id) {\n\t\t\tthis.removeEdge(e);\n\t\t}\n\t}, this);\n\n\tthis.notify();\n};\n\n// remove a node and it's associated edges from the graph\nGraph.prototype.removeEdge = function(edge) {\n\tfor (var i = this.edges.length - 1; i >= 0; i--) {\n\t\tif (this.edges[i].id === edge.id) {\n\t\t\tthis.edges.splice(i, 1);\n\t\t}\n\t}\n\n\tfor (var x in this.adjacency) {\n\t\tfor (var y in this.adjacency[x]) {\n\t\t\tvar edges = this.adjacency[x][y];\n\n\t\t\tfor (var j=edges.length - 1; j>=0; j--) {\n\t\t\t\tif (this.adjacency[x][y][j].id === edge.id) {\n\t\t\t\t\tthis.adjacency[x][y].splice(j, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tthis.notify();\n};\n\n/* Merge a list of nodes and edges into the current graph. eg.\nvar o = {\n\tnodes: [\n\t\t{id: 123, data: {type: 'user', userid: 123, displayname: 'aaa'}},\n\t\t{id: 234, data: {type: 'user', userid: 234, displayname: 'bbb'}}\n\t],\n\tedges: [\n\t\t{from: 0, to: 1, type: 'submitted_design', directed: true, data: {weight: }}\n\t]\n}\n*/\nGraph.prototype.merge = function(data) {\n\tvar nodes = [];\n\tdata.nodes.forEach(function(n) {\n\t\tnodes.push(this.addNode(new Node(n.id, n.data)));\n\t}, this);\n\n\tdata.edges.forEach(function(e) {\n\t\tvar from = nodes[e.from];\n\t\tvar to = nodes[e.to];\n\n\t\tvar id = (e.directed)\n\t\t\t? (id = e.type + \"-\" + from.id + \"-\" + to.id)\n\t\t\t: (from.id < to.id) // normalise id for non-directed edges\n\t\t\t\t? e.type + \"-\" + from.id + \"-\" + to.id\n\t\t\t\t: e.type + \"-\" + to.id + \"-\" + from.id;\n\n\t\tvar edge = this.addEdge(new Edge(id, from, to, e.data));\n\t\tedge.data.type = e.type;\n\t}, this);\n};\n\nGraph.prototype.filterNodes = function(fn) {\n\tvar tmpNodes = this.nodes.slice();\n\ttmpNodes.forEach(function(n) {\n\t\tif (!fn(n)) {\n\t\t\tthis.removeNode(n);\n\t\t}\n\t}, this);\n};\n\nGraph.prototype.filterEdges = function(fn) {\n\tvar tmpEdges = this.edges.slice();\n\ttmpEdges.forEach(function(e) {\n\t\tif (!fn(e)) {\n\t\t\tthis.removeEdge(e);\n\t\t}\n\t}, this);\n};\n\n\nGraph.prototype.addGraphListener = function(obj) {\n\tthis.eventListeners.push(obj);\n};\n\nGraph.prototype.notify = function() {\n\tthis.eventListeners.forEach(function(obj){\n\t\tobj.graphChanged();\n\t});\n};\n\n// -----------\nexport let Layout = {};\nLayout.ForceDirected = function(graph, stiffness, repulsion, damping) {\n\tthis.graph = graph;\n\tthis.stiffness = stiffness; // spring stiffness constant\n\tthis.repulsion = repulsion; // repulsion constant\n\tthis.damping = damping; // velocity damping factor\n\n\tthis.nodePoints = {}; // keep track of points associated with nodes\n\tthis.edgeSprings = {}; // keep track of springs associated with edges\n\tthis.getRandom = () => Math.random();\n};\n\nLayout.ForceDirected.prototype.point = function(node) {\n\tif (typeof(this.nodePoints[node.id]) === 'undefined') {\n\t\tvar mass = typeof(node.data.mass) !== 'undefined' ? node.data.mass : 1.0;\n\t\tthis.nodePoints[node.id] = new Layout.ForceDirected.Point(gVector.random(this.getRandom), mass);\n\t}\n\n\treturn this.nodePoints[node.id];\n};\n\nLayout.ForceDirected.prototype.spring = function(edge) {\n\tif (typeof(this.edgeSprings[edge.id]) === 'undefined') {\n\t\tvar length = typeof(edge.data.length) !== 'undefined' ? edge.data.length : 1.0;\n\n\t\tvar existingSpring = false;\n\n\t\tvar from = this.graph.getEdges(edge.source, edge.target);\n\t\tfrom.forEach(function(e) {\n\t\t\tif (existingSpring === false && typeof(this.edgeSprings[e.id]) !== 'undefined') {\n\t\t\t\texistingSpring = this.edgeSprings[e.id];\n\t\t\t}\n\t\t}, this);\n\n\t\tif (existingSpring !== false) {\n\t\t\treturn new Layout.ForceDirected.Spring(existingSpring.point1, existingSpring.point2, 0.0, 0.0);\n\t\t}\n\n\t\tvar to = this.graph.getEdges(edge.target, edge.source);\n\t\tfrom.forEach(function(e){\n\t\t\tif (existingSpring === false && typeof(this.edgeSprings[e.id]) !== 'undefined') {\n\t\t\t\texistingSpring = this.edgeSprings[e.id];\n\t\t\t}\n\t\t}, this);\n\n\t\tif (existingSpring !== false) {\n\t\t\treturn new Layout.ForceDirected.Spring(existingSpring.point2, existingSpring.point1, 0.0, 0.0);\n\t\t}\n\n\t\tthis.edgeSprings[edge.id] = new Layout.ForceDirected.Spring(\n\t\t\tthis.point(edge.source), this.point(edge.target), length, this.stiffness\n\t\t);\n\t}\n\n\treturn this.edgeSprings[edge.id];\n};\n\n// callback should accept two arguments: Node, Point\nLayout.ForceDirected.prototype.eachNode = function(callback) {\n\tvar t = this;\n\tthis.graph.nodes.forEach(function(n){\n\t\tcallback.call(t, n, t.point(n));\n\t});\n};\n\n// callback should accept two arguments: Edge, Spring\nLayout.ForceDirected.prototype.eachEdge = function(callback) {\n\tvar t = this;\n\tthis.graph.edges.forEach(function(e){\n\t\tcallback.call(t, e, t.spring(e));\n\t});\n};\n\n// callback should accept one argument: Spring\nLayout.ForceDirected.prototype.eachSpring = function(callback) {\n\tvar t = this;\n\tthis.graph.edges.forEach(function(e){\n\t\tcallback.call(t, t.spring(e));\n\t});\n};\n\n\n// Physics stuff\nLayout.ForceDirected.prototype.applyCoulombsLaw = function() {\n\tthis.eachNode(function(n1, point1) {\n\t\tthis.eachNode(function(n2, point2) {\n\t\t\tif (point1 !== point2)\n\t\t\t{\n\t\t\t\tvar d = point1.p.subtract(point2.p);\n\t\t\t\tvar distance = d.magnitude() + 0.1; // avoid massive forces at small distances (and divide by zero)\n\t\t\t\tvar direction = d.normalise();\n\n\t\t\t\t// apply force to each end point\n\t\t\t\tpoint1.applyForce(direction.multiply(this.repulsion).divide(distance * distance * 0.5));\n\t\t\t\tpoint2.applyForce(direction.multiply(this.repulsion).divide(distance * distance * -0.5));\n\t\t\t}\n\t\t});\n\t});\n};\n\nLayout.ForceDirected.prototype.applyHookesLaw = function() {\n\tthis.eachSpring(function(spring){\n\t\tvar d = spring.point2.p.subtract(spring.point1.p); // the direction of the spring\n\t\tvar displacement = spring.length - d.magnitude();\n\t\tvar direction = d.normalise();\n\n\t\t// apply force to each end point\n\t\tspring.point1.applyForce(direction.multiply(spring.k * displacement * -0.5));\n\t\tspring.point2.applyForce(direction.multiply(spring.k * displacement * 0.5));\n\t});\n};\n\nLayout.ForceDirected.prototype.attractToCentre = function() {\n\tthis.eachNode(function(node, point) {\n\t\tvar direction = point.p.multiply(-1.0);\n\t\tpoint.applyForce(direction.multiply(this.repulsion / 50.0));\n\t});\n};\n\n\nLayout.ForceDirected.prototype.updateVelocity = function(timestep) {\n\tthis.eachNode(function(node, point) {\n\t\t// Is this, along with updatePosition below, the only places that your\n\t\t// integration code exist?\n\t\tpoint.v = point.v.add(point.a.multiply(timestep)).multiply(this.damping);\n\t\tpoint.a = new gVector(0,0);\n\t});\n};\n\nLayout.ForceDirected.prototype.updatePosition = function(timestep) {\n\tthis.eachNode(function(node, point) {\n\t\t// Same question as above; along with updateVelocity, is this all of\n\t\t// your integration code?\n\t\tpoint.p = point.p.add(point.v.multiply(timestep));\n\t});\n};\n\n// Calculate the total kinetic energy of the system\nLayout.ForceDirected.prototype.totalEnergy = function(timestep) {\n\tvar energy = 0.0;\n\tthis.eachNode(function(node, point) {\n\t\tvar speed = point.v.magnitude();\n\t\tenergy += 0.5 * point.m * speed * speed;\n\t});\n\n\treturn energy;\n};\n\n\n// Find the nearest point to a particular position\nLayout.ForceDirected.prototype.nearest = function(pos) {\n\tvar min = {node: null, point: null, distance: null};\n\tvar t = this;\n\tthis.graph.nodes.forEach(function(n){\n\t\tvar point = t.point(n);\n\t\tvar distance = point.p.subtract(pos).magnitude();\n\n\t\tif (min.distance === null || distance < min.distance) {\n\t\t\tmin = {node: n, point: point, distance: distance};\n\t\t}\n\t});\n\n\treturn min;\n};\n\n// returns [bottomleft, topright]\nLayout.ForceDirected.prototype.getBoundingBox = function() {\n\tvar bottomleft = new gVector(-2,-2);\n\tvar topright = new gVector(2,2);\n\n\tthis.eachNode(function(n, point) {\n\t\tif (point.p.x < bottomleft.x) {\n\t\t\tbottomleft.x = point.p.x;\n\t\t}\n\t\tif (point.p.y < bottomleft.y) {\n\t\t\tbottomleft.y = point.p.y;\n\t\t}\n\t\tif (point.p.x > topright.x) {\n\t\t\ttopright.x = point.p.x;\n\t\t}\n\t\tif (point.p.y > topright.y) {\n\t\t\ttopright.y = point.p.y;\n\t\t}\n\t});\n\n\tvar padding = topright.subtract(bottomleft).multiply(0.07); // ~5% padding\n\n\treturn {bottomleft: bottomleft.subtract(padding), topright: topright.add(padding)};\n};\n\n\n// gVector\nvar gVector = function(x, y) {\n\tthis.x = x;\n\tthis.y = y;\n};\n\ngVector.random = function(fn) {\n\treturn new gVector(10.0 * (fn() - 0.5), 10.0 * (fn() - 0.5));\n};\n\ngVector.prototype.add = function(v2) {\n\treturn new gVector(this.x + v2.x, this.y + v2.y);\n};\n\ngVector.prototype.subtract = function(v2) {\n\treturn new gVector(this.x - v2.x, this.y - v2.y);\n};\n\ngVector.prototype.multiply = function(n) {\n\treturn new gVector(this.x * n, this.y * n);\n};\n\ngVector.prototype.divide = function(n) {\n\treturn new gVector((this.x / n) || 0, (this.y / n) || 0); // Avoid divide by zero errors..\n};\n\ngVector.prototype.magnitude = function() {\n\treturn Math.sqrt(this.x*this.x + this.y*this.y);\n};\n\ngVector.prototype.normal = function() {\n\treturn new gVector(-this.y, this.x);\n};\n\ngVector.prototype.normalise = function() {\n\treturn this.divide(this.magnitude());\n};\n\n// Point\nLayout.ForceDirected.Point = function(position, mass) {\n\tthis.p = position; // position\n\tthis.m = mass; // mass\n\tthis.v = new gVector(0, 0); // velocity\n\tthis.a = new gVector(0, 0); // acceleration\n};\n\nLayout.ForceDirected.Point.prototype.applyForce = function(force) {\n\tthis.a = this.a.add(force.divide(this.m));\n};\n\n// Spring\nLayout.ForceDirected.Spring = function(point1, point2, length, k) {\n\tthis.point1 = point1;\n\tthis.point2 = point2;\n\tthis.length = length; // spring length at rest\n\tthis.k = k; // spring constant (See Hooke's law) .. how stiff the spring is\n};\n\n", "vendor/random.js": "// @ts-nocheck\n/* eslint-disable */\n/*\nCopyright 2019 David Bau.\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\nexport let SeedRandom = {};\n\n(function (global, pool, math) {\n  //\n  // The following constants are related to IEEE 754 limits.\n  //\n  \n  var width = 256,        // each RC4 output is 0 <= x < 256\n      chunks = 6,         // at least six RC4 outputs for each double\n      digits = 52,        // there are 52 significant digits in a double\n      rngname = 'random', // rngname: name for Math.random and Math.seedrandom\n      startdenom = math.pow(width, chunks),\n      significance = math.pow(2, digits),\n      overflow = significance * 2,\n      mask = width - 1,\n      nodecrypto;         // node.js crypto module, initialized at the bottom.\n  \n  //\n  // seedrandom()\n  // This is the seedrandom function described above.\n  //\n  function seedrandom(seed, options, callback) {\n    var key = [];\n    options = (options == true) ? { entropy: true } : (options || {});\n  \n    // Flatten the seed string or build one from local entropy if needed.\n    var shortseed = mixkey(flatten(\n      options.entropy ? [seed, tostring(pool)] :\n      (seed == null) ? autoseed() : seed, 3), key);\n  \n    // Use the seed to initialize an ARC4 generator.\n    var arc4 = new ARC4(key);\n  \n    // This function returns a random double in [0, 1) that contains\n    // randomness in every bit of the mantissa of the IEEE 754 value.\n    var prng = function() {\n      var n = arc4.g(chunks),             // Start with a numerator n < 2 ^ 48\n          d = startdenom,                 //   and denominator d = 2 ^ 48.\n          x = 0;                          //   and no 'extra last byte'.\n      while (n < significance) {          // Fill up all significant digits by\n        n = (n + x) * width;              //   shifting numerator and\n        d *= width;                       //   denominator and generating a\n        x = arc4.g(1);                    //   new least-significant-byte.\n      }\n      while (n >= overflow) {             // To avoid rounding up, before adding\n        n /= 2;                           //   last byte, shift everything\n        d /= 2;                           //   right using integer math until\n        x >>>= 1;                         //   we have exactly the desired bits.\n      }\n      return (n + x) / d;                 // Form the number within [0, 1).\n    };\n  \n    prng.int32 = function() { return arc4.g(4) | 0; }\n    prng.quick = function() { return arc4.g(4) / 0x100000000; }\n    prng.double = prng;\n  \n    // Mix the randomness into accumulated entropy.\n    mixkey(tostring(arc4.S), pool);\n  \n    // Calling convention: what to return as a function of prng, seed, is_math.\n    return (options.pass || callback ||\n        function(prng, seed, is_math_call, state) {\n          if (state) {\n            // Load the arc4 state from the given state if it has an S array.\n            if (state.S) { copy(state, arc4); }\n            // Only provide the .state method if requested via options.state.\n            prng.state = function() { return copy(arc4, {}); }\n          }\n  \n          // If called as a method of Math (Math.seedrandom()), mutate\n          // Math.random because that is how seedrandom.js has worked since v1.0.\n          if (is_math_call) { math[rngname] = prng; return seed; }\n  \n          // Otherwise, it is a newer calling convention, so return the\n          // prng directly.\n          else return prng;\n        })(\n    prng,\n    shortseed,\n    'global' in options ? options.global : (this == math),\n    options.state);\n  }\n  \n  //\n  // ARC4\n  //\n  // An ARC4 implementation.  The constructor takes a key in the form of\n  // an array of at most (width) integers that should be 0 <= x < (width).\n  //\n  // The g(count) method returns a pseudorandom integer that concatenates\n  // the next (count) outputs from ARC4.  Its return value is a number x\n  // that is in the range 0 <= x < (width ^ count).\n  //\n  function ARC4(key) {\n    var t, keylen = key.length,\n        me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];\n  \n    // The empty key [] is treated as [0].\n    if (!keylen) { key = [keylen++]; }\n  \n    // Set up S using the standard key scheduling algorithm.\n    while (i < width) {\n      s[i] = i++;\n    }\n    for (i = 0; i < width; i++) {\n      s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))];\n      s[j] = t;\n    }\n  \n    // The \"g\" method returns the next (count) outputs as one number.\n    (me.g = function(count) {\n      // Using instance members instead of closure state nearly doubles speed.\n      var t, r = 0,\n          i = me.i, j = me.j, s = me.S;\n      while (count--) {\n        t = s[i = mask & (i + 1)];\n        r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))];\n      }\n      me.i = i; me.j = j;\n      return r;\n      // For robust unpredictability, the function call below automatically\n      // discards an initial batch of values.  This is called RC4-drop[256].\n      // See http://google.com/search?q=rsa+fluhrer+response&btnI\n    })(width);\n  }\n  \n  //\n  // copy()\n  // Copies internal state of ARC4 to or from a plain object.\n  //\n  function copy(f, t) {\n    t.i = f.i;\n    t.j = f.j;\n    t.S = f.S.slice();\n    return t;\n  };\n  \n  //\n  // flatten()\n  // Converts an object tree to nested arrays of strings.\n  //\n  function flatten(obj, depth) {\n    var result = [], typ = (typeof obj), prop;\n    if (depth && typ == 'object') {\n      for (prop in obj) {\n        try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}\n      }\n    }\n    return (result.length ? result : typ == 'string' ? obj : obj + '\\0');\n  }\n  \n  //\n  // mixkey()\n  // Mixes a string seed into a key that is an array of integers, and\n  // returns a shortened string seed that is equivalent to the result key.\n  //\n  function mixkey(seed, key) {\n    var stringseed = seed + '', smear, j = 0;\n    while (j < stringseed.length) {\n      key[mask & j] =\n        mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++));\n    }\n    return tostring(key);\n  }\n  \n  //\n  // autoseed()\n  // Returns an object for autoseeding, using window.crypto and Node crypto\n  // module if available.\n  //\n  function autoseed() {\n    try {\n      var out;\n      if (nodecrypto && (out = nodecrypto.randomBytes)) {\n        // The use of 'out' to remember randomBytes makes tight minified code.\n        out = out(width);\n      } else {\n        out = new Uint8Array(width);\n        (global.crypto || global.msCrypto).getRandomValues(out);\n      }\n      return tostring(out);\n    } catch (e) {\n      var browser = global.navigator,\n          plugins = browser && browser.plugins;\n      return [+new Date, global, plugins, global.screen, tostring(pool)];\n    }\n  }\n  \n  //\n  // tostring()\n  // Converts an array of charcodes to a string\n  //\n  function tostring(a) {\n    return String.fromCharCode.apply(0, a);\n  }\n  \n  //\n  // When seedrandom.js is loaded, we immediately mix a few bits\n  // from the built-in RNG into the entropy pool.  Because we do\n  // not want to interfere with deterministic PRNG state later,\n  // seedrandom will not call math.random on its own again after\n  // initialization.\n  //\n  mixkey(math.random(), pool);\n  \n  SeedRandom.seedrandom = seedrandom;\n \n  \n  // End anonymous scope, and pass initial values.\n  })(\n    // global: `self` in browsers (including strict mode and web workers),\n    // otherwise `this` in Node and other environments\n    (typeof self !== 'undefined') ? self : this,\n    [],     // pool: entropy pool starts empty\n    Math    // math: package containing random, pow, and seedrandom\n  );", "vendor/toposort.js": "// @ts-ignore\n/* eslint-disable */\n\n/**\n * Toposort - Topological sorting for node.js\nCopyright (c) 2012 by Marcel Klehr <mklehr@gmx.net>\nMIT LICENSE\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n */\n\n\n\n/**\n * Topological sorting function\n *\n * @param {Array} edges\n * @returns {Array}\n */\n\nexport default function(edges) {\n  return toposort(uniqueNodes(edges), edges);\n}\n\n\nfunction toposort(nodes, edges) {\n  let cursor = nodes.length\n    , sorted = new Array(cursor)\n    , visited = {}\n    , i = cursor\n    // Better data structures make algorithm much faster.\n    , outgoingEdges = makeOutgoingEdges(edges)\n    , nodesHash = makeNodesHash(nodes);\n\n  // check for unknown nodes\n  edges.forEach((edge) => {\n    if (!nodesHash.has(edge[0]) || !nodesHash.has(edge[1])) {\n      throw new Error(\"Unknown node. There is an unknown node in the supplied edges.\");\n    }\n  });\n\n  while (i--) {\n    if (!visited[i]) visit(nodes[i], i, new Set());\n  }\n\n  return sorted;\n\n  function visit(node, i, predecessors) {\n    if(predecessors.has(node)) {\n      let nodeRep;\n      try {\n        nodeRep = \", node was:\" + JSON.stringify(node);\n      } catch(e) {\n        nodeRep = \"\";\n      }\n      throw new Error(\"Cyclic dependency\" + nodeRep);\n    }\n\n    if (!nodesHash.has(node)) {\n      throw new Error(\"Found unknown node. Make sure to provided all involved nodes. Unknown node: \"+JSON.stringify(node));\n    }\n\n    if (visited[i]) return;\n    visited[i] = true;\n\n    let outgoing = outgoingEdges.get(node) || new Set();\n    outgoing = Array.from(outgoing);\n\n    if (i = outgoing.length) {\n      predecessors.add(node);\n      do {\n        let child = outgoing[--i];\n        visit(child, nodesHash.get(child), predecessors);\n      } while (i);\n      predecessors.delete(node);\n    }\n\n    sorted[--cursor] = node;\n  }\n}\n\nfunction uniqueNodes(arr){\n  let res = new Set();\n  for (let i = 0, len = arr.length; i < len; i++) {\n    let edge = arr[i];\n    res.add(edge[0]);\n    res.add(edge[1]);\n  }\n  return Array.from(res);\n}\n\nfunction makeOutgoingEdges(arr){\n  let edges = new Map();\n  for (let i = 0, len = arr.length; i < len; i++) {\n    let edge = arr[i];\n    if (!edges.has(edge[0])) edges.set(edge[0], new Set());\n    if (!edges.has(edge[1])) edges.set(edge[1], new Set());\n    edges.get(edge[0]).add(edge[1]);\n  }\n  return edges;\n}\n\nfunction makeNodesHash(arr){\n  let res = new Map();\n  for (let i = 0, len = arr.length; i < len; i++) {\n    res.set(arr[i], i);\n  }\n  return res;\n}", "vendor/antlr4ng-all.js": "// @ts-nocheck\n//#region node_modules/antlr4ng/dist/index.mjs\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", {\n\tvalue,\n\tconfigurable: true\n});\nvar IntStream;\n((IntStream2) => {\n\tIntStream2.EOF = -1;\n\tIntStream2.UNKNOWN_SOURCE_NAME = \"<unknown>\";\n})(IntStream || (IntStream = {}));\nvar Token;\n((Token2) => {\n\tToken2.INVALID_TYPE = 0;\n\tToken2.EPSILON = -2;\n\tToken2.MIN_USER_TOKEN_TYPE = 1;\n\tToken2.EOF = IntStream.EOF;\n\tToken2.DEFAULT_CHANNEL = 0;\n\tToken2.HIDDEN_CHANNEL = 1;\n\tToken2.MIN_USER_CHANNEL_VALUE = 2;\n})(Token || (Token = {}));\nvar isToken = /* @__PURE__ */ __name((candidate) => {\n\tconst token = candidate;\n\treturn token.tokenSource !== void 0 && token.channel !== void 0;\n}, \"isToken\");\nvar BitSet = class {\n\tstatic {\n\t\t__name(this, \"BitSet\");\n\t}\n\tdata;\n\t/**\n\t* Creates a new bit set. All bits are initially `false`.\n\t*\n\t* @param data Optional initial data.\n\t*/\n\tconstructor(data) {\n\t\tif (data) this.data = new Uint32Array(data.map((value) => {\n\t\t\treturn value >>> 0;\n\t\t}));\n\t\telse this.data = new Uint32Array(1);\n\t}\n\t/**\n\t* @returns an iterator over all set bits.\n\t*/\n\t[Symbol.iterator]() {\n\t\tconst length = this.data.length;\n\t\tlet currentIndex = 0;\n\t\tlet currentWord = this.data[currentIndex];\n\t\tconst words = this.data;\n\t\treturn {\n\t\t\t[Symbol.iterator]() {\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tnext: /* @__PURE__ */ __name(() => {\n\t\t\t\twhile (currentIndex < length) if (currentWord !== 0) {\n\t\t\t\t\tconst t = currentWord & -currentWord;\n\t\t\t\t\tconst value = (currentIndex << 5) + this.bitCount(t - 1);\n\t\t\t\t\tcurrentWord ^= t;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdone: false,\n\t\t\t\t\t\tvalue\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcurrentIndex++;\n\t\t\t\t\tif (currentIndex < length) currentWord = words[currentIndex];\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tdone: true,\n\t\t\t\t\tvalue: void 0\n\t\t\t\t};\n\t\t\t}, \"next\")\n\t\t};\n\t}\n\t/**\n\t* Sets a single bit or all of the bits in this `BitSet` to `false`.\n\t*\n\t* @param index the index of the bit to be cleared, or undefined to clear all bits.\n\t*/\n\tclear(index) {\n\t\tif (index === void 0) this.data = new Uint32Array();\n\t\telse {\n\t\t\tthis.resize(index);\n\t\t\tthis.data[index >>> 5] &= ~(1 << index);\n\t\t}\n\t}\n\t/**\n\t* Performs a logical **OR** of this bit set with the bit set argument. This bit set is modified so that a bit in it\n\t* has the value `true` if and only if it either already had the value `true` or the corresponding bit in the bit\n\t* set argument has the value `true`.\n\t*\n\t* @param set the bit set to be ORed with.\n\t*/\n\tor(set) {\n\t\tconst minCount = Math.min(this.data.length, set.data.length);\n\t\tfor (let k = 0; k < minCount; ++k) this.data[k] |= set.data[k];\n\t\tif (this.data.length < set.data.length) {\n\t\t\tthis.resize((set.data.length << 5) - 1);\n\t\t\tconst c = set.data.length;\n\t\t\tfor (let k = minCount; k < c; ++k) this.data[k] = set.data[k];\n\t\t}\n\t}\n\t/**\n\t* Returns the value of the bit with the specified index. The value is `true` if the bit with the index `bitIndex`\n\t* is currently set in this `BitSet`; otherwise, the result is `false`.\n\t*\n\t* @param index the bit index\n\t*\n\t* @returns the value of the bit with the specified index.\n\t*/\n\tget(index) {\n\t\tif (index < 0) throw new RangeError(\"index cannot be negative\");\n\t\tconst slot = index >>> 5;\n\t\tif (slot >= this.data.length) return false;\n\t\treturn (this.data[slot] & 1 << index % 32) !== 0;\n\t}\n\t/**\n\t* @returns the number of set bits.\n\t*/\n\tget length() {\n\t\tlet result = 0;\n\t\tconst c = this.data.length;\n\t\tconst w = this.data;\n\t\tfor (let i = 0; i < c; i++) result += this.bitCount(w[i]);\n\t\treturn result;\n\t}\n\t/**\n\t* @returns an array with indices of set bits.\n\t*/\n\tvalues() {\n\t\tconst result = new Array(this.length);\n\t\tlet pos = 0;\n\t\tconst length = this.data.length;\n\t\tfor (let k = 0; k < length; ++k) {\n\t\t\tlet w = this.data[k];\n\t\t\twhile (w !== 0) {\n\t\t\t\tconst t = w & -w;\n\t\t\t\tresult[pos++] = (k << 5) + this.bitCount(t - 1);\n\t\t\t\tw ^= t;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* @returns the index of the first bit that is set to `true` that occurs on or after the specified starting index.\n\t* If no such bit exists then undefined is returned.\n\t*\n\t* @param fromIndex the index to start checking from (inclusive)\n\t*/\n\tnextSetBit(fromIndex) {\n\t\tif (fromIndex < 0) throw new RangeError(\"index cannot be negative\");\n\t\tfor (const index of this) if (index >= fromIndex) return index;\n\t}\n\t/**\n\t* Sets the bit at the specified index to `true`.\n\t*\n\t* @param index a bit index\n\t*/\n\tset(index) {\n\t\tif (index < 0) throw new RangeError(\"index cannot be negative\");\n\t\tthis.resize(index);\n\t\tthis.data[index >>> 5] |= 1 << index % 32;\n\t}\n\t/**\n\t* @returns a string representation of this bit set.\n\t*/\n\ttoString() {\n\t\treturn \"{\" + this.values().join(\", \") + \"}\";\n\t}\n\tresize(index) {\n\t\tconst count = index + 32 >>> 5;\n\t\tif (count <= this.data.length) return;\n\t\tconst data = new Uint32Array(count);\n\t\tdata.set(this.data);\n\t\tdata.fill(0, this.data.length);\n\t\tthis.data = data;\n\t}\n\tbitCount(v) {\n\t\tv = v - (v >> 1 & 1431655765);\n\t\tv = (v & 858993459) + (v >> 2 & 858993459);\n\t\tv = v + (v >> 4) & 252645135;\n\t\tv = v + (v >> 8);\n\t\tv = v + (v >> 16);\n\t\treturn v & 63;\n\t}\n};\nvar c1 = 3432918353;\nvar c2 = 461845907;\nvar r1 = 15;\nvar r2 = 13;\nvar m = 5;\nvar n = 3864292196;\nvar MurmurHash = class _MurmurHash {\n\tstatic {\n\t\t__name(this, \"MurmurHash\");\n\t}\n\tstatic defaultSeed = 701;\n\tconstructor() {}\n\t/**\n\t* Initialize the hash using the specified {@code seed}.\n\t*\n\t* @param seed the seed\n\t*\n\t* @returns the intermediate hash value\n\t*/\n\tstatic initialize(seed = _MurmurHash.defaultSeed) {\n\t\treturn seed;\n\t}\n\tstatic updateFromComparable(hash, value) {\n\t\treturn this.update(hash, value?.hashCode() ?? 0);\n\t}\n\t/**\n\t* Update the intermediate hash value for the next input {@code value}.\n\t*\n\t* @param hash The intermediate hash value.\n\t* @param value the value to add to the current hash.\n\t*\n\t* @returns the updated intermediate hash value\n\t*/\n\tstatic update(hash, value) {\n\t\tvalue = Math.imul(value, c1);\n\t\tvalue = value << r1 | value >>> 32 - r1;\n\t\tvalue = Math.imul(value, c2);\n\t\thash = hash ^ value;\n\t\thash = hash << r2 | hash >>> 32 - r2;\n\t\thash = Math.imul(hash, m) + n;\n\t\treturn hash;\n\t}\n\t/**\n\t* Apply the final computation steps to the intermediate value {@code hash}\n\t* to form the final result of the MurmurHash 3 hash function.\n\t*\n\t* @param hash The intermediate hash value.\n\t* @param entryCount The number of values added to the hash.\n\t*\n\t* @returns the final hash result\n\t*/\n\tstatic finish(hash, entryCount) {\n\t\thash ^= entryCount * 4;\n\t\thash ^= hash >>> 16;\n\t\thash = Math.imul(hash, 2246822507);\n\t\thash ^= hash >>> 13;\n\t\thash = Math.imul(hash, 3266489909);\n\t\thash ^= hash >>> 16;\n\t\treturn hash;\n\t}\n\t/**\n\t* An all-in-one convenience method to compute a hash for a single value.\n\t*\n\t* @param value The value to hash.\n\t* @param seed The seed for the hash value.\n\t*\n\t* @returns The computed hash.\n\t*/\n\tstatic hashCode(value, seed) {\n\t\treturn _MurmurHash.finish(_MurmurHash.update(seed ?? _MurmurHash.defaultSeed, value), 1);\n\t}\n};\nvar ObjectEqualityComparator = class _ObjectEqualityComparator {\n\tstatic {\n\t\t__name(this, \"ObjectEqualityComparator\");\n\t}\n\tstatic instance = new _ObjectEqualityComparator();\n\thashCode(obj) {\n\t\tif (obj == null) return 0;\n\t\treturn obj.hashCode();\n\t}\n\tequals(a, b) {\n\t\tif (a == null) return b == null;\n\t\treturn a.equals(b);\n\t}\n};\nvar DefaultEqualityComparator = class _DefaultEqualityComparator {\n\tstatic {\n\t\t__name(this, \"DefaultEqualityComparator\");\n\t}\n\tstatic instance = new _DefaultEqualityComparator();\n\thashCode(obj) {\n\t\tif (obj == null) return 0;\n\t\treturn ObjectEqualityComparator.instance.hashCode(obj);\n\t}\n\tequals(a, b) {\n\t\tif (a == null) return b == null;\n\t\tif (typeof a === \"string\" || typeof a === \"number\") return a === b;\n\t\treturn ObjectEqualityComparator.instance.equals(a, b);\n\t}\n};\nvar HashSet = class _HashSet {\n\tstatic {\n\t\t__name(this, \"HashSet\");\n\t}\n\tstatic defaultLoadFactor = .75;\n\tstatic initialCapacity = 16;\n\tcomparator;\n\tbuckets;\n\tthreshold;\n\t/** How many elements in set */\n\titemCount = 0;\n\tconstructor(comparatorOrSet, initialCapacity = _HashSet.initialCapacity) {\n\t\tif (comparatorOrSet instanceof _HashSet) {\n\t\t\tthis.comparator = comparatorOrSet.comparator;\n\t\t\tthis.buckets = comparatorOrSet.buckets.slice(0);\n\t\t\tfor (let i = 0; i < this.buckets.length; i++) {\n\t\t\t\tconst bucket = this.buckets[i];\n\t\t\t\tif (bucket) this.buckets[i] = bucket.slice(0);\n\t\t\t}\n\t\t\tthis.itemCount = comparatorOrSet.itemCount;\n\t\t\tthis.threshold = comparatorOrSet.threshold;\n\t\t} else {\n\t\t\tthis.comparator = comparatorOrSet ?? DefaultEqualityComparator.instance;\n\t\t\tthis.buckets = this.createBuckets(initialCapacity);\n\t\t\tthis.threshold = Math.floor(_HashSet.initialCapacity * _HashSet.defaultLoadFactor);\n\t\t}\n\t}\n\t/**\n\t* Add `o` to set if not there; return existing value if already\n\t* there. This method performs the same operation as {@link #add} aside from\n\t* the return value.\n\t*\n\t* @param o the object to add to the set.\n\t*\n\t* @returns An existing element that equals to `o` if already in set, otherwise `o`.\n\t*/\n\tgetOrAdd(o) {\n\t\tif (this.itemCount > this.threshold) this.expand();\n\t\tconst b = this.getBucket(o);\n\t\tlet bucket = this.buckets[b];\n\t\tif (!bucket) {\n\t\t\tbucket = [o];\n\t\t\tthis.buckets[b] = bucket;\n\t\t\t++this.itemCount;\n\t\t\treturn o;\n\t\t}\n\t\tfor (const existing of bucket) if (this.comparator.equals(existing, o)) return existing;\n\t\tbucket.push(o);\n\t\t++this.itemCount;\n\t\treturn o;\n\t}\n\tget(o) {\n\t\tif (o == null) return o;\n\t\tconst b = this.getBucket(o);\n\t\tconst bucket = this.buckets[b];\n\t\tif (!bucket) return;\n\t\tfor (const e of bucket) if (this.comparator.equals(e, o)) return e;\n\t}\n\t/**\n\t* Removes the specified element from this set if it is present.\n\t*\n\t* @param o object to be removed from this set, if present.\n\t*\n\t* @returns `true` if the set contained the specified element.\n\t*/\n\tremove(o) {\n\t\tif (o == null) return false;\n\t\tconst b = this.getBucket(o);\n\t\tconst bucket = this.buckets[b];\n\t\tif (!bucket) return false;\n\t\tfor (let i = 0; i < bucket.length; i++) {\n\t\t\tconst existing = bucket[i];\n\t\t\tif (this.comparator.equals(existing, o)) {\n\t\t\t\tbucket.splice(i, 1);\n\t\t\t\t--this.itemCount;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\thashCode() {\n\t\tlet hash = MurmurHash.initialize();\n\t\tfor (const bucket of this.buckets) {\n\t\t\tif (bucket == null) continue;\n\t\t\tfor (const o of bucket) {\n\t\t\t\tif (o == null) break;\n\t\t\t\thash = MurmurHash.update(hash, this.comparator.hashCode(o));\n\t\t\t}\n\t\t}\n\t\thash = MurmurHash.finish(hash, this.size);\n\t\treturn hash;\n\t}\n\tequals(o) {\n\t\tif (o === this) return true;\n\t\tif (!(o instanceof _HashSet)) return false;\n\t\tif (o.size !== this.size) return false;\n\t\treturn this.containsAll(o);\n\t}\n\tadd(t) {\n\t\treturn this.getOrAdd(t) === t;\n\t}\n\tcontains(o) {\n\t\treturn this.containsFast(o);\n\t}\n\tcontainsFast(obj) {\n\t\tif (obj == null) return false;\n\t\treturn this.get(obj) !== void 0;\n\t}\n\t*[Symbol.iterator]() {\n\t\tyield* this.toArray();\n\t}\n\ttoArray() {\n\t\tconst a = new Array(this.size);\n\t\tlet i = 0;\n\t\tfor (const bucket of this.buckets) {\n\t\t\tif (bucket == null) continue;\n\t\t\tfor (const o of bucket) {\n\t\t\t\tif (o == null) break;\n\t\t\t\ta[i++] = o;\n\t\t\t}\n\t\t}\n\t\treturn a;\n\t}\n\tcontainsAll(collection) {\n\t\tif (collection instanceof _HashSet) for (const bucket of collection.buckets) {\n\t\t\tif (bucket == null) continue;\n\t\t\tfor (const o of bucket) {\n\t\t\t\tif (o == null) break;\n\t\t\t\tif (!this.containsFast(o)) return false;\n\t\t\t}\n\t\t}\n\t\telse for (const o of collection) if (!this.containsFast(o)) return false;\n\t\treturn true;\n\t}\n\taddAll(c) {\n\t\tlet changed = false;\n\t\tfor (const o of c) if (this.getOrAdd(o) !== o) changed = true;\n\t\treturn changed;\n\t}\n\tclear() {\n\t\tthis.buckets = this.createBuckets(_HashSet.initialCapacity);\n\t\tthis.itemCount = 0;\n\t\tthis.threshold = Math.floor(_HashSet.initialCapacity * _HashSet.defaultLoadFactor);\n\t}\n\ttoString() {\n\t\tif (this.size === 0) return \"{}\";\n\t\tlet buf = \"{\";\n\t\tlet first = true;\n\t\tfor (const bucket of this.buckets) {\n\t\t\tif (bucket == null) continue;\n\t\t\tfor (const o of bucket) {\n\t\t\t\tif (o == null) break;\n\t\t\t\tif (first) first = false;\n\t\t\t\telse buf += \", \";\n\t\t\t\tbuf += o.toString();\n\t\t\t}\n\t\t}\n\t\tbuf += \"}\";\n\t\treturn buf;\n\t}\n\ttoTableString() {\n\t\tlet buf = \"\";\n\t\tfor (const bucket of this.buckets) {\n\t\t\tif (bucket == null) {\n\t\t\t\tbuf += \"null\\n\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbuf += \"[\";\n\t\t\tlet first = true;\n\t\t\tfor (const o of bucket) {\n\t\t\t\tif (first) first = false;\n\t\t\t\telse buf += \" \";\n\t\t\t\tif (o == null) buf += \"_\";\n\t\t\t\telse buf += o.toString();\n\t\t\t}\n\t\t\tbuf += \"]\\n\";\n\t\t}\n\t\treturn buf;\n\t}\n\tgetBucket(o) {\n\t\treturn this.comparator.hashCode(o) & this.buckets.length - 1;\n\t}\n\texpand() {\n\t\tconst old = this.buckets;\n\t\tconst newCapacity = this.buckets.length * 2;\n\t\tthis.buckets = this.createBuckets(newCapacity);\n\t\tthis.threshold = Math.floor(newCapacity * _HashSet.defaultLoadFactor);\n\t\tfor (const bucket of old) {\n\t\t\tif (!bucket) continue;\n\t\t\tfor (const o of bucket) {\n\t\t\t\tconst b = this.getBucket(o);\n\t\t\t\tlet newBucket = this.buckets[b];\n\t\t\t\tif (!newBucket) {\n\t\t\t\t\tnewBucket = [];\n\t\t\t\t\tthis.buckets[b] = newBucket;\n\t\t\t\t}\n\t\t\t\tnewBucket.push(o);\n\t\t\t}\n\t\t}\n\t}\n\tget size() {\n\t\treturn this.itemCount;\n\t}\n\tget isEmpty() {\n\t\treturn this.itemCount === 0;\n\t}\n\t/**\n\t* Return an array of `T[]` with length `capacity`.\n\t*\n\t* @param capacity the length of the array to return\n\t* @returns the newly constructed array\n\t*/\n\tcreateBuckets(capacity) {\n\t\treturn new Array(capacity);\n\t}\n};\nvar Interval = class _Interval {\n\tstatic {\n\t\t__name(this, \"Interval\");\n\t}\n\tstatic INVALID_INTERVAL = new _Interval(-1, -2);\n\tstatic INTERVAL_POOL_MAX_VALUE = 1e3;\n\tstatic cache = [];\n\tstart;\n\tstop;\n\tcachedHashCode;\n\tconstructor(start, stop) {\n\t\tthis.start = start;\n\t\tthis.stop = stop;\n\t\tthis.cachedHashCode = Math.imul(651 + start, 31) + stop;\n\t}\n\t/**\n\t* Creates a new interval from the given values.\n\t*\n\t* Interval objects are used readonly so share all with the\n\t* same single value a==b up to some max size. Use an array as a perfect hash.\n\t* Return shared object for 0..INTERVAL_POOL_MAX_VALUE or a new\n\t* Interval object with a..a in it.  On Java.g4, 218623 IntervalSets\n\t* have a..a (set with 1 element).\n\t*\n\t* @param a The start of the interval.\n\t* @param b The end of the interval (inclusive).\n\t*\n\t* @returns A cached or new interval.\n\t*/\n\tstatic of(a, b) {\n\t\tif (a !== b || a < 0 || a > _Interval.INTERVAL_POOL_MAX_VALUE) return new _Interval(a, b);\n\t\tif (!_Interval.cache[a]) _Interval.cache[a] = new _Interval(a, a);\n\t\treturn _Interval.cache[a];\n\t}\n\tequals(o) {\n\t\treturn this.start === o.start && this.stop === o.stop;\n\t}\n\thashCode() {\n\t\treturn this.cachedHashCode;\n\t}\n\t/** Does this start completely before other? Disjoint */\n\tstartsBeforeDisjoint(other) {\n\t\treturn this.start < other.start && this.stop < other.start;\n\t}\n\t/** Does this start at or before other? Nondisjoint */\n\tstartsBeforeNonDisjoint(other) {\n\t\treturn this.start <= other.start && this.stop >= other.start;\n\t}\n\t/** Does this.start start after other.stop? May or may not be disjoint */\n\tstartsAfter(other) {\n\t\treturn this.start > other.start;\n\t}\n\t/** Does this start completely after other? Disjoint */\n\tstartsAfterDisjoint(other) {\n\t\treturn this.start > other.stop;\n\t}\n\t/** Does this start after other? NonDisjoint */\n\tstartsAfterNonDisjoint(other) {\n\t\treturn this.start > other.start && this.start <= other.stop;\n\t}\n\t/** Are both ranges disjoint? I.e., no overlap? */\n\tdisjoint(other) {\n\t\treturn this.startsBeforeDisjoint(other) || this.startsAfterDisjoint(other);\n\t}\n\t/** Are two intervals adjacent such as 0..41 and 42..42? */\n\tadjacent(other) {\n\t\treturn this.start === other.stop + 1 || this.stop === other.start - 1;\n\t}\n\tproperlyContains(other) {\n\t\treturn other.start >= this.start && other.stop <= this.stop;\n\t}\n\t/** Return the interval computed from combining this and other */\n\tunion(other) {\n\t\treturn _Interval.of(Math.min(this.start, other.start), Math.max(this.stop, other.stop));\n\t}\n\t/** Return the interval in common between this and o */\n\tintersection(other) {\n\t\treturn _Interval.of(Math.max(this.start, other.start), Math.min(this.stop, other.stop));\n\t}\n\t/**\n\t* Return the interval with elements from this not in other;\n\t*  other must not be totally enclosed (properly contained)\n\t*  within this, which would result in two disjoint intervals\n\t*  instead of the single one returned by this method.\n\t*/\n\tdifferenceNotProperlyContained(other) {\n\t\tlet diff = null;\n\t\tif (other.startsBeforeNonDisjoint(this)) diff = _Interval.of(Math.max(this.start, other.stop + 1), this.stop);\n\t\telse if (other.startsAfterNonDisjoint(this)) diff = _Interval.of(this.start, other.start - 1);\n\t\treturn diff;\n\t}\n\ttoString() {\n\t\treturn `${this.start}..${this.stop}`;\n\t}\n\tget length() {\n\t\tif (this.stop < this.start) return 0;\n\t\treturn this.stop - this.start + 1;\n\t}\n};\nvar Vocabulary = class _Vocabulary {\n\tstatic {\n\t\t__name(this, \"Vocabulary\");\n\t}\n\tstatic EMPTY_NAMES = [];\n\t/**\n\t* Gets an empty {@link Vocabulary} instance.\n\t*\n\t*\n\t* No literal or symbol names are assigned to token types, so\n\t* {@link #getDisplayName(int)} returns the numeric value for all tokens\n\t* except {@link Token#EOF}.\n\t*/\n\tstatic EMPTY_VOCABULARY = new _Vocabulary(_Vocabulary.EMPTY_NAMES, _Vocabulary.EMPTY_NAMES, _Vocabulary.EMPTY_NAMES);\n\tmaxTokenType;\n\tliteralNames;\n\tsymbolicNames;\n\tdisplayNames;\n\t/**\n\t* Constructs a new instance of {@link Vocabulary} from the specified\n\t* literal, symbolic, and display token names.\n\t*\n\t* @param literalNames The literal names assigned to tokens, or `null`\n\t* if no literal names are assigned.\n\t* @param symbolicNames The symbolic names assigned to tokens, or\n\t* `null` if no symbolic names are assigned.\n\t* @param displayNames The display names assigned to tokens, or `null`\n\t* to use the values in `literalNames` and `symbolicNames` as\n\t* the source of display names, as described in\n\t* {@link #getDisplayName(int)}.\n\t*/\n\tconstructor(literalNames, symbolicNames, displayNames) {\n\t\tthis.literalNames = literalNames ?? _Vocabulary.EMPTY_NAMES;\n\t\tthis.symbolicNames = symbolicNames ?? _Vocabulary.EMPTY_NAMES;\n\t\tthis.displayNames = displayNames ?? _Vocabulary.EMPTY_NAMES;\n\t\tthis.maxTokenType = Math.max(this.displayNames.length, Math.max(this.literalNames.length, this.symbolicNames.length)) - 1;\n\t}\n\t/**\n\t* Returns a {@link Vocabulary} instance from the specified set of token\n\t* names. This method acts as a compatibility layer for the single\n\t* `tokenNames` array generated by previous releases of ANTLR.\n\t*\n\t* The resulting vocabulary instance returns `null` for\n\t* {@link getLiteralName getLiteralName(int)} and {@link getSymbolicName getSymbolicName(int)}, and the\n\t* value from `tokenNames` for the display names.\n\t*\n\t* @param tokenNames The token names, or `null` if no token names are\n\t* available.\n\t* @returns A {@link Vocabulary} instance which uses `tokenNames` for\n\t* the display names of tokens.\n\t*/\n\tstatic fromTokenNames(tokenNames) {\n\t\tif (tokenNames == null || tokenNames.length === 0) return _Vocabulary.EMPTY_VOCABULARY;\n\t\tconst literalNames = [...tokenNames];\n\t\tconst symbolicNames = [...tokenNames];\n\t\tfor (let i = 0; i < tokenNames.length; i++) {\n\t\t\tconst tokenName = tokenNames[i];\n\t\t\tif (tokenName == null) continue;\n\t\t\tif (tokenName.length > 0) {\n\t\t\t\tconst firstChar = tokenName.codePointAt(0);\n\t\t\t\tif (firstChar === 39) {\n\t\t\t\t\tsymbolicNames[i] = null;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (firstChar >= 65 && firstChar <= 90) {\n\t\t\t\t\tliteralNames[i] = null;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tliteralNames[i] = null;\n\t\t\tsymbolicNames[i] = null;\n\t\t}\n\t\treturn new _Vocabulary(literalNames, symbolicNames, tokenNames);\n\t}\n\tgetMaxTokenType() {\n\t\treturn this.maxTokenType;\n\t}\n\tgetLiteralName(tokenType) {\n\t\tif (tokenType >= 0 && tokenType < this.literalNames.length) return this.literalNames[tokenType];\n\t\treturn null;\n\t}\n\tgetSymbolicName(tokenType) {\n\t\tif (tokenType >= 0 && tokenType < this.symbolicNames.length) return this.symbolicNames[tokenType];\n\t\tif (tokenType === Token.EOF) return \"EOF\";\n\t\treturn null;\n\t}\n\tgetDisplayName(tokenType) {\n\t\tif (tokenType >= 0 && tokenType < this.displayNames.length) {\n\t\t\tconst displayName = this.displayNames[tokenType];\n\t\t\tif (displayName != null) return displayName;\n\t\t}\n\t\tconst literalName = this.getLiteralName(tokenType);\n\t\tif (literalName != null) return literalName;\n\t\tconst symbolicName = this.getSymbolicName(tokenType);\n\t\tif (symbolicName != null) return symbolicName;\n\t\treturn `${tokenType}`;\n\t}\n\tgetLiteralNames() {\n\t\treturn this.literalNames;\n\t}\n\tgetSymbolicNames() {\n\t\treturn this.symbolicNames;\n\t}\n\tgetDisplayNames() {\n\t\treturn this.displayNames;\n\t}\n};\nvar IntervalSet = class _IntervalSet {\n\tstatic {\n\t\t__name(this, \"IntervalSet\");\n\t}\n\t/** The list of sorted, disjoint intervals. */\n\tintervals = [];\n\tcachedHashCode;\n\tconstructor(set) {\n\t\tif (set) if (Array.isArray(set)) for (const el of set) this.addOne(el);\n\t\telse this.addSet(set);\n\t}\n\t/** Create a set with all ints within range [a..b] (inclusive) */\n\tstatic of(a, b) {\n\t\tconst s = new _IntervalSet();\n\t\ts.addRange(a, b);\n\t\treturn s;\n\t}\n\t/** Combine all sets in the array and return the union of them */\n\tstatic or(sets) {\n\t\tconst result = new _IntervalSet();\n\t\tfor (const set of sets) result.addSet(set);\n\t\treturn result;\n\t}\n\t[Symbol.iterator]() {\n\t\treturn this.intervals[Symbol.iterator]();\n\t}\n\tget(index) {\n\t\treturn this.intervals[index];\n\t}\n\t/**\n\t* Returns the minimum value contained in the set if not isNil().\n\t*\n\t* @returns the minimum value contained in the set.\n\t*/\n\tget minElement() {\n\t\tif (this.intervals.length === 0) return Token.INVALID_TYPE;\n\t\treturn this.intervals[0].start;\n\t}\n\t/**\n\t* Returns the maximum value contained in the set if not isNil().\n\t*\n\t* @returns the maximum value contained in the set.\n\t*/\n\tget maxElement() {\n\t\tif (this.intervals.length === 0) return Token.INVALID_TYPE;\n\t\treturn this.intervals[this.intervals.length - 1].stop;\n\t}\n\tclear() {\n\t\tthis.cachedHashCode = void 0;\n\t\tthis.intervals = [];\n\t}\n\t/**\n\t* Add a single element to the set.  An isolated element is stored\n\t*  as a range el..el.\n\t*/\n\taddOne(v) {\n\t\tthis.addInterval(new Interval(v, v));\n\t}\n\t/**\n\t* Add interval; i.e., add all integers from a to b to set.\n\t*  If b < a, do nothing.\n\t*  Keep list in sorted order (by left range value).\n\t*  If overlap, combine ranges. For example,\n\t*  If this is {1..5, 10..20}, adding 6..7 yields\n\t*  {1..5, 6..7, 10..20}. Adding 4..8 yields {1..8, 10..20}.\n\t*/\n\taddRange(l, h) {\n\t\tthis.addInterval(new Interval(l, h));\n\t}\n\taddInterval(addition) {\n\t\tthis.cachedHashCode = void 0;\n\t\tif (this.intervals.length === 0) this.intervals.push(addition);\n\t\telse {\n\t\t\tfor (let pos = 0; pos < this.intervals.length; pos++) {\n\t\t\t\tconst existing = this.intervals[pos];\n\t\t\t\tif (addition.equals(existing)) return;\n\t\t\t\tif (addition.adjacent(existing) || !addition.disjoint(existing)) {\n\t\t\t\t\tconst bigger = addition.union(existing);\n\t\t\t\t\tthis.intervals[pos] = bigger;\n\t\t\t\t\tfor (let sub = pos + 1; sub < this.intervals.length;) {\n\t\t\t\t\t\tconst next = this.intervals[sub];\n\t\t\t\t\t\tif (!bigger.adjacent(next) && bigger.disjoint(next)) break;\n\t\t\t\t\t\tthis.intervals.splice(sub, 1);\n\t\t\t\t\t\tthis.intervals[pos] = bigger.union(next);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (addition.startsBeforeDisjoint(existing)) {\n\t\t\t\t\tthis.intervals.splice(pos, 0, addition);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.intervals.push(addition);\n\t\t}\n\t}\n\taddSet(other) {\n\t\tother.intervals.forEach((toAdd) => {\n\t\t\treturn this.addInterval(toAdd);\n\t\t}, this);\n\t\treturn this;\n\t}\n\tcomplementWithVocabulary(vocabulary) {\n\t\tconst result = new _IntervalSet();\n\t\tif (!vocabulary) return result;\n\t\tif (vocabulary.length === 0) return result;\n\t\tresult.addSet(vocabulary);\n\t\treturn result.subtract(this);\n\t}\n\tcomplement(minElement, maxElement) {\n\t\tconst result = new _IntervalSet();\n\t\tresult.addInterval(new Interval(minElement, maxElement));\n\t\treturn result.subtract(this);\n\t}\n\t/** combine all sets in the array returned the or'd value */\n\tor(sets) {\n\t\tconst result = new _IntervalSet();\n\t\tresult.addSet(this);\n\t\tsets.forEach((set) => {\n\t\t\treturn result.addSet(set);\n\t\t});\n\t\treturn result;\n\t}\n\tand(other) {\n\t\tif (other.length === 0) return new _IntervalSet();\n\t\tconst myIntervals = this.intervals;\n\t\tconst theirIntervals = other.intervals;\n\t\tlet intersection;\n\t\tconst mySize = myIntervals.length;\n\t\tconst theirSize = theirIntervals.length;\n\t\tlet i = 0;\n\t\tlet j = 0;\n\t\twhile (i < mySize && j < theirSize) {\n\t\t\tconst mine = myIntervals[i];\n\t\t\tconst theirs = theirIntervals[j];\n\t\t\tif (mine.startsBeforeDisjoint(theirs)) i++;\n\t\t\telse if (theirs.startsBeforeDisjoint(mine)) j++;\n\t\t\telse if (mine.properlyContains(theirs)) {\n\t\t\t\tif (!intersection) intersection = new _IntervalSet();\n\t\t\t\tintersection.addInterval(mine.intersection(theirs));\n\t\t\t\tj++;\n\t\t\t} else if (theirs.properlyContains(mine)) {\n\t\t\t\tif (!intersection) intersection = new _IntervalSet();\n\t\t\t\tintersection.addInterval(mine.intersection(theirs));\n\t\t\t\ti++;\n\t\t\t} else if (!mine.disjoint(theirs)) {\n\t\t\t\tif (!intersection) intersection = new _IntervalSet();\n\t\t\t\tintersection.addInterval(mine.intersection(theirs));\n\t\t\t\tif (mine.startsAfterNonDisjoint(theirs)) j++;\n\t\t\t\telse if (theirs.startsAfterNonDisjoint(mine)) i++;\n\t\t\t}\n\t\t}\n\t\tif (!intersection) return new _IntervalSet();\n\t\treturn intersection;\n\t}\n\t/**\n\t* Compute the set difference between two interval sets. The specific\n\t* operation is `left - right`. If either of the input sets is\n\t* `null`, it is treated as though it was an empty set.\n\t*/\n\tsubtract(other) {\n\t\tif (this.length === 0) return new _IntervalSet();\n\t\tconst result = new _IntervalSet(this);\n\t\tif (other.length === 0) return result;\n\t\tlet resultI = 0;\n\t\tlet rightI = 0;\n\t\twhile (resultI < result.intervals.length && rightI < other.intervals.length) {\n\t\t\tconst resultInterval = result.intervals[resultI];\n\t\t\tconst rightInterval = other.intervals[rightI];\n\t\t\tif (rightInterval.stop < resultInterval.start) {\n\t\t\t\trightI++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (rightInterval.start > resultInterval.stop) {\n\t\t\t\tresultI++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet beforeCurrent;\n\t\t\tlet afterCurrent;\n\t\t\tif (rightInterval.start > resultInterval.start) beforeCurrent = new Interval(resultInterval.start, rightInterval.start - 1);\n\t\t\tif (rightInterval.stop < resultInterval.stop) afterCurrent = new Interval(rightInterval.stop + 1, resultInterval.stop);\n\t\t\tif (beforeCurrent) if (afterCurrent) {\n\t\t\t\tresult.intervals[resultI] = beforeCurrent;\n\t\t\t\tresult.intervals.splice(resultI + 1, 0, afterCurrent);\n\t\t\t\tresultI++;\n\t\t\t\trightI++;\n\t\t\t} else {\n\t\t\t\tresult.intervals[resultI] = beforeCurrent;\n\t\t\t\tresultI++;\n\t\t\t}\n\t\t\telse if (afterCurrent) {\n\t\t\t\tresult.intervals[resultI] = afterCurrent;\n\t\t\t\trightI++;\n\t\t\t} else result.intervals.splice(resultI, 1);\n\t\t}\n\t\treturn result;\n\t}\n\tcontains(el) {\n\t\tconst n2 = this.intervals.length;\n\t\tlet l = 0;\n\t\tlet r = n2 - 1;\n\t\twhile (l <= r) {\n\t\t\tconst m2 = Math.floor((l + r) / 2);\n\t\t\tconst interval = this.intervals[m2];\n\t\t\tif (interval.stop < el) l = m2 + 1;\n\t\t\telse if (interval.start > el) r = m2 - 1;\n\t\t\telse return true;\n\t\t}\n\t\treturn false;\n\t}\n\tremoveRange(toRemove) {\n\t\tthis.cachedHashCode = void 0;\n\t\tif (toRemove.start === toRemove.stop) this.removeOne(toRemove.start);\n\t\telse if (this.intervals !== null) {\n\t\t\tlet pos = 0;\n\t\t\tfor (const existing of this.intervals) {\n\t\t\t\tif (toRemove.stop <= existing.start) return;\n\t\t\t\telse if (toRemove.start > existing.start && toRemove.stop < existing.stop) {\n\t\t\t\t\tthis.intervals[pos] = new Interval(existing.start, toRemove.start);\n\t\t\t\t\tconst x = new Interval(toRemove.stop, existing.stop);\n\t\t\t\t\tthis.intervals.splice(pos, 0, x);\n\t\t\t\t\treturn;\n\t\t\t\t} else if (toRemove.start <= existing.start && toRemove.stop >= existing.stop) {\n\t\t\t\t\tthis.intervals.splice(pos, 1);\n\t\t\t\t\tpos = pos - 1;\n\t\t\t\t} else if (toRemove.start < existing.stop) this.intervals[pos] = new Interval(existing.start, toRemove.start);\n\t\t\t\telse if (toRemove.stop < existing.stop) this.intervals[pos] = new Interval(toRemove.stop, existing.stop);\n\t\t\t\tpos += 1;\n\t\t\t}\n\t\t}\n\t}\n\tremoveOne(value) {\n\t\tthis.cachedHashCode = void 0;\n\t\tfor (let i = 0; i < this.intervals.length; i++) {\n\t\t\tconst existing = this.intervals[i];\n\t\t\tif (value < existing.start) return;\n\t\t\telse if (value === existing.start && value === existing.stop) {\n\t\t\t\tthis.intervals.splice(i, 1);\n\t\t\t\treturn;\n\t\t\t} else if (value === existing.start) {\n\t\t\t\tthis.intervals[i] = new Interval(existing.start + 1, existing.stop);\n\t\t\t\treturn;\n\t\t\t} else if (value === existing.stop) {\n\t\t\t\tthis.intervals[i] = new Interval(existing.start, existing.stop - 1);\n\t\t\t\treturn;\n\t\t\t} else if (value < existing.stop) {\n\t\t\t\tconst replace = new Interval(existing.start, value - 1);\n\t\t\t\tthis.intervals[i] = new Interval(value + 1, existing.stop);\n\t\t\t\tthis.intervals.splice(i, 0, replace);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\tfor (const interval of this.intervals) {\n\t\t\t\thash = MurmurHash.update(hash, interval.start);\n\t\t\t\thash = MurmurHash.update(hash, interval.stop);\n\t\t\t}\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, this.intervals.length * 2);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\t/**\n\t* Are two IntervalSets equal? Because all intervals are sorted and disjoint, equals is a simple linear walk over\n\t* both lists to make sure they are the same. Interval.equals() is used by the List.equals() method to check\n\t* the ranges.\n\t*/\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (this.intervals.length !== other.intervals.length) return false;\n\t\tfor (let i = 0; i < this.intervals.length; i++) if (!this.intervals[i].equals(other.intervals[i])) return false;\n\t\treturn true;\n\t}\n\ttoString(elementsAreChar) {\n\t\tif (this.intervals.length === 0) return \"{}\";\n\t\tlet result = \"\";\n\t\tif (this.length > 1) result += \"{\";\n\t\tfor (let i = 0; i < this.intervals.length; ++i) {\n\t\t\tconst interval = this.intervals[i];\n\t\t\tconst start = interval.start;\n\t\t\tconst stop = interval.stop;\n\t\t\tif (start === stop) if (start === Token.EOF) result += \"<EOF>\";\n\t\t\telse if (elementsAreChar) result += \"'\" + String.fromCodePoint(start) + \"'\";\n\t\t\telse result += start;\n\t\t\telse if (elementsAreChar) result += \"'\" + String.fromCodePoint(start) + \"'..'\" + String.fromCodePoint(stop) + \"'\";\n\t\t\telse result += start + \"..\" + stop;\n\t\t\tif (i < this.intervals.length - 1) result += \", \";\n\t\t}\n\t\tif (this.length > 1) result += \"}\";\n\t\treturn result;\n\t}\n\ttoStringWithVocabulary(vocabulary) {\n\t\tif (this.intervals.length === 0) return \"{}\";\n\t\tlet result = \"\";\n\t\tif (this.length > 1) result += \"{\";\n\t\tfor (let i = 0; i < this.intervals.length; ++i) {\n\t\t\tconst interval = this.intervals[i];\n\t\t\tconst start = interval.start;\n\t\t\tconst stop = interval.stop;\n\t\t\tif (start === stop) if (start === Token.EOF) result += \"<EOF>\";\n\t\t\telse result += this.elementName(vocabulary, start);\n\t\t\telse for (let i2 = start; i2 <= stop; ++i2) {\n\t\t\t\tif (i2 > start) result += \", \";\n\t\t\t\tresult += this.elementName(vocabulary, i2);\n\t\t\t}\n\t\t\tif (i < this.intervals.length - 1) result += \", \";\n\t\t}\n\t\tif (this.length > 1) result += \"}\";\n\t\treturn result;\n\t}\n\ttoStringWithRuleNames(ruleNames) {\n\t\tif (this.intervals.length === 0) return \"{}\";\n\t\tlet result = \"\";\n\t\tif (this.length > 1) result += \"{\";\n\t\tconst vocabulary = Vocabulary.fromTokenNames(ruleNames);\n\t\tfor (let i = 0; i < this.intervals.length; ++i) {\n\t\t\tconst interval = this.intervals[i];\n\t\t\tconst start = interval.start;\n\t\t\tconst stop = interval.stop;\n\t\t\tif (start === stop) if (start === Token.EOF) result += \"<EOF>\";\n\t\t\telse result += this.elementName(vocabulary, start);\n\t\t\telse for (let i2 = start; i2 <= stop; ++i2) {\n\t\t\t\tif (i2 > start) result += \", \";\n\t\t\t\tresult += this.elementName(vocabulary, i2);\n\t\t\t}\n\t\t\tif (i < this.intervals.length - 1) result += \", \";\n\t\t}\n\t\tif (this.length > 1) result += \"}\";\n\t\treturn result;\n\t}\n\ttoArray() {\n\t\tconst data = [];\n\t\tfor (const interval of this.intervals) for (let j = interval.start; j <= interval.stop; j++) data.push(j);\n\t\treturn data;\n\t}\n\t/** @returns the number of elements in this set. */\n\tget length() {\n\t\tlet result = 0;\n\t\tfor (const interval of this.intervals) result += interval.length;\n\t\treturn result;\n\t}\n\telementName(vocabulary, token) {\n\t\tif (token === Token.EOF) return \"<EOF>\";\n\t\tif (token === Token.EPSILON) return \"<EPSILON>\";\n\t\treturn vocabulary.getDisplayName(token);\n\t}\n};\nvar isComparable = /* @__PURE__ */ __name((candidate) => {\n\treturn typeof candidate.equals === \"function\";\n}, \"isComparable\");\nvar valueToString = /* @__PURE__ */ __name((v) => {\n\treturn v === null ? \"null\" : v;\n}, \"valueToString\");\nvar arrayToString = /* @__PURE__ */ __name((value) => {\n\treturn Array.isArray(value) ? \"[\" + value.map(valueToString).join(\", \") + \"]\" : \"null\";\n}, \"arrayToString\");\nvar equalArrays = /* @__PURE__ */ __name((a, b) => {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst left = a[i];\n\t\tconst right = b[i];\n\t\tif (left === right) continue;\n\t\tif (!left || !left.equals(right)) return false;\n\t}\n\treturn true;\n}, \"equalArrays\");\nvar equalNumberArrays = /* @__PURE__ */ __name((a, b) => {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n\treturn true;\n}, \"equalNumberArrays\");\nvar escapeWhitespace = /* @__PURE__ */ __name((s, escapeSpaces = false) => {\n\ts = s.replace(/\\t/g, \"\\\\t\").replace(/\\n/g, \"\\\\n\").replace(/\\r/g, \"\\\\r\");\n\tif (escapeSpaces) s = s.replace(/ /g, \"\u00b7\");\n\treturn s;\n}, \"escapeWhitespace\");\nvar SemanticContext = class _SemanticContext {\n\tstatic {\n\t\t__name(this, \"SemanticContext\");\n\t}\n\tcachedHashCode;\n\tstatic andContext(a, b) {\n\t\tif (a === null || a === _SemanticContext.NONE) return b;\n\t\tif (b === null || b === _SemanticContext.NONE) return a;\n\t\tconst result = new AND(a, b);\n\t\tif (result.operands.length === 1) return result.operands[0];\n\t\treturn result;\n\t}\n\tstatic orContext(a, b) {\n\t\tif (a === null) return b;\n\t\tif (b === null) return a;\n\t\tif (a === _SemanticContext.NONE || b === _SemanticContext.NONE) return _SemanticContext.NONE;\n\t\tconst result = new OR(a, b);\n\t\tif (result.operands.length === 1) return result.operands[0];\n\t\telse return result;\n\t}\n\tstatic filterPrecedencePredicates(set) {\n\t\tconst result = [];\n\t\tfor (const context of set) if (context instanceof _SemanticContext.PrecedencePredicate) result.push(context);\n\t\treturn result;\n\t}\n\t/**\n\t* Evaluate the precedence predicates for the context and reduce the result.\n\t*\n\t* @param _parser The parser instance.\n\t* @param _parserCallStack The current parser context object.\n\t* @returns The simplified semantic context after precedence predicates are\n\t* evaluated, which will be one of the following values.\n\t* - {@link NONE}: if the predicate simplifies to `true` after\n\t* precedence predicates are evaluated.\n\t* - `null`: if the predicate simplifies to `false` after\n\t* precedence predicates are evaluated.\n\t* - `this`: if the semantic context is not changed as a result of\n\t* precedence predicate evaluation.\n\t* - A non-`null` {@link SemanticContext}: the new simplified\n\t* semantic context after precedence predicates are evaluated.\n\t*/\n\tevalPrecedence(_parser, _parserCallStack) {\n\t\treturn this;\n\t}\n};\nvar AND = class _AND extends SemanticContext {\n\tstatic {\n\t\t__name(this, \"AND\");\n\t}\n\toperands;\n\t/**\n\t* A semantic context which is true whenever none of the contained contexts\n\t* is false\n\t*/\n\tconstructor(a, b) {\n\t\tsuper();\n\t\tconst operands = new HashSet();\n\t\tif (a instanceof _AND) a.operands.forEach((o) => {\n\t\t\toperands.add(o);\n\t\t});\n\t\telse operands.add(a);\n\t\tif (b instanceof _AND) b.operands.forEach((o) => {\n\t\t\toperands.add(o);\n\t\t});\n\t\telse operands.add(b);\n\t\tconst precedencePredicates = SemanticContext.filterPrecedencePredicates(operands);\n\t\tif (precedencePredicates.length > 0) {\n\t\t\tlet reduced = null;\n\t\t\tprecedencePredicates.forEach((p) => {\n\t\t\t\tif (reduced === null || p.precedence < reduced.precedence) reduced = p;\n\t\t\t});\n\t\t\tif (reduced) operands.add(reduced);\n\t\t}\n\t\tthis.operands = operands.toArray();\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _AND)) return false;\n\t\treturn equalArrays(this.operands, other.operands);\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\tfor (const operand of this.operands) hash = MurmurHash.updateFromComparable(hash, operand);\n\t\t\thash = MurmurHash.update(hash, 3813686060);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, this.operands.length + 1);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\t/**\n\t* {@inheritDoc}\n\t*\n\t*\n\t* The evaluation of predicates by this context is short-circuiting, but\n\t* unordered.\n\t*/\n\tevaluate(parser, parserCallStack) {\n\t\tfor (const operand of this.operands) if (!operand.evaluate(parser, parserCallStack)) return false;\n\t\treturn true;\n\t}\n\tevalPrecedence(parser, parserCallStack) {\n\t\tlet differs = false;\n\t\tconst operands = [];\n\t\tfor (const context of this.operands) {\n\t\t\tconst evaluated = context.evalPrecedence(parser, parserCallStack);\n\t\t\tdiffers ||= evaluated !== context;\n\t\t\tif (evaluated === null) return null;\n\t\t\telse if (evaluated !== SemanticContext.NONE) operands.push(evaluated);\n\t\t}\n\t\tif (!differs) return this;\n\t\tif (operands.length === 0) return SemanticContext.NONE;\n\t\tlet result = null;\n\t\toperands.forEach((o) => {\n\t\t\tresult = result === null ? o : SemanticContext.andContext(result, o);\n\t\t});\n\t\treturn result;\n\t}\n\ttoString() {\n\t\tconst s = this.operands.map((o) => {\n\t\t\treturn o.toString();\n\t\t});\n\t\treturn (s.length > 3 ? s.slice(3) : s).join(\"&&\");\n\t}\n};\nvar OR = class _OR extends SemanticContext {\n\tstatic {\n\t\t__name(this, \"OR\");\n\t}\n\toperands;\n\t/**\n\t* A semantic context which is true whenever at least one of the contained\n\t* contexts is true\n\t*/\n\tconstructor(a, b) {\n\t\tsuper();\n\t\tconst operands = new HashSet();\n\t\tif (a instanceof _OR) a.operands.forEach((o) => {\n\t\t\toperands.add(o);\n\t\t});\n\t\telse operands.add(a);\n\t\tif (b instanceof _OR) b.operands.forEach((o) => {\n\t\t\toperands.add(o);\n\t\t});\n\t\telse operands.add(b);\n\t\tconst precedencePredicates = SemanticContext.filterPrecedencePredicates(operands);\n\t\tif (precedencePredicates.length > 0) {\n\t\t\tconst s = precedencePredicates.sort((a2, b2) => {\n\t\t\t\treturn a2.compareTo(b2);\n\t\t\t});\n\t\t\tconst reduced = s[s.length - 1];\n\t\t\toperands.add(reduced);\n\t\t}\n\t\tthis.operands = operands.toArray();\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\telse if (!(other instanceof _OR)) return false;\n\t\telse return equalArrays(this.operands, other.operands);\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\tfor (const operand of this.operands) hash = MurmurHash.updateFromComparable(hash, operand);\n\t\t\thash = MurmurHash.update(hash, 3383313031);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, this.operands.length + 1);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\t/**\n\t* The evaluation of predicates by this context is short-circuiting, but unordered.\n\t*/\n\tevaluate(parser, parserCallStack) {\n\t\tfor (const operand of this.operands) if (operand.evaluate(parser, parserCallStack)) return true;\n\t\treturn false;\n\t}\n\tevalPrecedence(parser, parserCallStack) {\n\t\tlet differs = false;\n\t\tconst operands = [];\n\t\tfor (const context of this.operands) {\n\t\t\tconst evaluated = context.evalPrecedence(parser, parserCallStack);\n\t\t\tdiffers ||= evaluated !== context;\n\t\t\tif (evaluated === SemanticContext.NONE) return SemanticContext.NONE;\n\t\t\telse if (evaluated !== null) operands.push(evaluated);\n\t\t}\n\t\tif (!differs) return this;\n\t\tif (operands.length === 0) return null;\n\t\tlet result = null;\n\t\toperands.forEach((o) => {\n\t\t\tresult = result === null ? o : SemanticContext.orContext(result, o);\n\t\t});\n\t\treturn result;\n\t}\n\ttoString() {\n\t\tconst s = this.operands.map((o) => {\n\t\t\treturn o.toString();\n\t\t});\n\t\treturn (s.length > 3 ? s.slice(3) : s).join(\"||\");\n\t}\n};\n((SemanticContext2) => {\n\tclass Predicate extends SemanticContext2 {\n\t\tstatic {\n\t\t\t__name(this, \"Predicate\");\n\t\t}\n\t\truleIndex;\n\t\tpredIndex;\n\t\tisCtxDependent;\n\t\tconstructor(ruleIndex, predIndex, isCtxDependent) {\n\t\t\tsuper();\n\t\t\tthis.ruleIndex = ruleIndex ?? -1;\n\t\t\tthis.predIndex = predIndex ?? -1;\n\t\t\tthis.isCtxDependent = isCtxDependent ?? false;\n\t\t}\n\t\tevaluate(parser, outerContext) {\n\t\t\tconst localctx = this.isCtxDependent ? outerContext : null;\n\t\t\treturn parser.sempred(localctx, this.ruleIndex, this.predIndex);\n\t\t}\n\t\thashCode() {\n\t\t\tif (this.cachedHashCode === void 0) {\n\t\t\t\tlet hashCode = MurmurHash.initialize();\n\t\t\t\thashCode = MurmurHash.update(hashCode, this.ruleIndex);\n\t\t\t\thashCode = MurmurHash.update(hashCode, this.predIndex);\n\t\t\t\thashCode = MurmurHash.update(hashCode, this.isCtxDependent ? 1 : 0);\n\t\t\t\thashCode = MurmurHash.finish(hashCode, 3);\n\t\t\t\tthis.cachedHashCode = hashCode;\n\t\t\t}\n\t\t\treturn this.cachedHashCode;\n\t\t}\n\t\tequals(other) {\n\t\t\tif (this === other) return true;\n\t\t\treturn this.ruleIndex === other.ruleIndex && this.predIndex === other.predIndex && this.isCtxDependent === other.isCtxDependent;\n\t\t}\n\t\ttoString() {\n\t\t\treturn \"{\" + this.ruleIndex + \":\" + this.predIndex + \"}?\";\n\t\t}\n\t}\n\tSemanticContext2.Predicate = Predicate;\n\tclass PrecedencePredicate extends SemanticContext2 {\n\t\tstatic {\n\t\t\t__name(this, \"PrecedencePredicate\");\n\t\t}\n\t\tprecedence;\n\t\tconstructor(precedence) {\n\t\t\tsuper();\n\t\t\tthis.precedence = precedence ?? 0;\n\t\t}\n\t\tevaluate(parser, outerContext) {\n\t\t\treturn parser.precpred(outerContext, this.precedence);\n\t\t}\n\t\tevalPrecedence(parser, outerContext) {\n\t\t\tif (parser.precpred(outerContext ?? null, this.precedence)) return SemanticContext2.NONE;\n\t\t\treturn null;\n\t\t}\n\t\tcompareTo(other) {\n\t\t\treturn this.precedence - other.precedence;\n\t\t}\n\t\thashCode() {\n\t\t\treturn 31 + this.precedence;\n\t\t}\n\t\tequals(other) {\n\t\t\tif (this === other) return true;\n\t\t\treturn this.precedence === other.precedence;\n\t\t}\n\t\ttoString() {\n\t\t\treturn \"{\" + this.precedence + \">=prec}?\";\n\t\t}\n\t}\n\tSemanticContext2.PrecedencePredicate = PrecedencePredicate;\n\tSemanticContext2.NONE = new Predicate();\n})(SemanticContext || (SemanticContext = {}));\nvar ATNConfig = class _ATNConfig {\n\tstatic {\n\t\t__name(this, \"ATNConfig\");\n\t}\n\t/** The ATN state associated with this configuration */\n\tstate;\n\t/** What alt (or lexer rule) is predicted by this configuration */\n\talt;\n\t/**\n\t* We cannot execute predicates dependent upon local context unless\n\t* we know for sure we are in the correct context. Because there is\n\t* no way to do this efficiently, we simply cannot evaluate\n\t* dependent predicates unless we are in the rule that initially\n\t* invokes the ATN simulator.\n\t*\n\t* closure() tracks the depth of how far we dip into the outer context:\n\t* depth > 0.\n\t*/\n\treachesIntoOuterContext = false;\n\tprecedenceFilterSuppressed = false;\n\tget semanticContext() {\n\t\treturn this.#semanticContext;\n\t}\n\tcachedHashCode;\n\t/**\n\t* The syntactic context is a graph-structured stack node whose\n\t* path(s) to the root is the rule invocation(s)\n\t* chain used to arrive at the state.  The semantic context is\n\t* the tree of semantic predicates encountered before reaching\n\t* an ATN state\n\t*/\n\t#context = null;\n\t#semanticContext;\n\t/** Never create config classes directly. Use the factory methods below. */\n\tconstructor(c, state, context, semanticContext) {\n\t\tthis.state = state;\n\t\tthis.alt = c.alt;\n\t\tthis.context = context;\n\t\tthis.#semanticContext = semanticContext ?? SemanticContext.NONE;\n\t\tthis.reachesIntoOuterContext = c.reachesIntoOuterContext;\n\t\tif (c.precedenceFilterSuppressed !== void 0) this.precedenceFilterSuppressed = c.precedenceFilterSuppressed;\n\t}\n\tstatic duplicate(old, semanticContext) {\n\t\treturn new _ATNConfig(old, old.state, old.context, semanticContext ?? old.semanticContext);\n\t}\n\tstatic createWithContext(state, alt, context, semanticContext) {\n\t\treturn new _ATNConfig({ alt }, state, context, semanticContext);\n\t}\n\tstatic createWithConfig(state, config, context) {\n\t\treturn new _ATNConfig(config, state, context ?? config.context, config.semanticContext);\n\t}\n\tstatic createWithSemanticContext(state, c, semanticContext) {\n\t\treturn new _ATNConfig(c, state ?? c.state, c.context, semanticContext);\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hashCode = MurmurHash.initialize(7);\n\t\t\thashCode = MurmurHash.update(hashCode, this.state.stateNumber);\n\t\t\thashCode = MurmurHash.update(hashCode, this.alt);\n\t\t\thashCode = MurmurHash.updateFromComparable(hashCode, this.#context);\n\t\t\thashCode = MurmurHash.updateFromComparable(hashCode, this.semanticContext);\n\t\t\thashCode = MurmurHash.finish(hashCode, 4);\n\t\t\tthis.cachedHashCode = hashCode;\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\t/**\n\t* The stack of invoking states leading to the rule/states associated\n\t* with this config.  We track only those contexts pushed during\n\t* execution of the ATN simulator.\n\t*/\n\tget context() {\n\t\treturn this.#context;\n\t}\n\tset context(context) {\n\t\tthis.#context = context;\n\t\tthis.cachedHashCode = void 0;\n\t}\n\t/**\n\t* An ATN configuration is equal to another if both have\n\t* the same state, they predict the same alternative, and\n\t* syntactic/semantic contexts are the same.\n\t*/\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\treturn this.state.stateNumber === other.state.stateNumber && this.alt === other.alt && (this.context === null ? other.context === null : this.context.equals(other.context)) && this.semanticContext.equals(other.semanticContext) && this.precedenceFilterSuppressed === other.precedenceFilterSuppressed;\n\t}\n\ttoString(_recog, showAlt = true) {\n\t\tlet alt = \"\";\n\t\tif (showAlt) alt = \",\" + this.alt;\n\t\treturn \"(\" + this.state + alt + (this.context !== null ? \",[\" + this.context.toString() + \"]\" : \"\") + (this.semanticContext !== SemanticContext.NONE ? \",\" + this.semanticContext.toString() : \"\") + (this.reachesIntoOuterContext ? \",up=\" + this.reachesIntoOuterContext : \"\") + \")\";\n\t}\n};\nvar ATNState = class _ATNState {\n\tstatic {\n\t\t__name(this, \"ATNState\");\n\t}\n\tstatic INVALID_STATE_NUMBER = -1;\n\tstatic INVALID_TYPE = 0;\n\tstatic BASIC = 1;\n\tstatic RULE_START = 2;\n\tstatic BLOCK_START = 3;\n\tstatic PLUS_BLOCK_START = 4;\n\tstatic STAR_BLOCK_START = 5;\n\tstatic TOKEN_START = 6;\n\tstatic RULE_STOP = 7;\n\tstatic BLOCK_END = 8;\n\tstatic STAR_LOOP_BACK = 9;\n\tstatic STAR_LOOP_ENTRY = 10;\n\tstatic PLUS_LOOP_BACK = 11;\n\tstatic LOOP_END = 12;\n\tstatic stateType = _ATNState.INVALID_STATE_NUMBER;\n\tstateNumber = 0;\n\truleIndex = 0;\n\tepsilonOnlyTransitions = false;\n\t/** Used to cache lookahead during parsing, not used during construction */\n\tnextTokenWithinRule;\n\t/** Track the transitions emanating from this ATN state. */\n\ttransitions = [];\n\thashCode() {\n\t\treturn this.stateNumber;\n\t}\n\tequals(other) {\n\t\treturn this.stateNumber === other.stateNumber;\n\t}\n\ttoString() {\n\t\treturn `${this.stateNumber}`;\n\t}\n\taddTransitionAtIndex(index, transition) {\n\t\tif (this.transitions.length === 0) this.epsilonOnlyTransitions = transition.isEpsilon;\n\t\telse if (this.epsilonOnlyTransitions !== transition.isEpsilon) this.epsilonOnlyTransitions = false;\n\t\tthis.transitions.splice(index, 0, transition);\n\t}\n\taddTransition(transition) {\n\t\tif (this.transitions.length === 0) this.epsilonOnlyTransitions = transition.isEpsilon;\n\t\telse if (this.epsilonOnlyTransitions !== transition.isEpsilon) this.epsilonOnlyTransitions = false;\n\t\tthis.transitions.push(transition);\n\t}\n\tsetTransition(i, e) {\n\t\tthis.transitions.splice(i, 1, e);\n\t}\n\tremoveTransition(index) {\n\t\treturn this.transitions.splice(index, 1)[0];\n\t}\n};\nvar PredictionContext = class _PredictionContext {\n\tstatic {\n\t\t__name(this, \"PredictionContext\");\n\t}\n\t/**\n\t* Represents `$` in an array in full context mode, when `$`\n\t* doesn't mean wildcard: `$ + x = [$,x]`. Here,\n\t* `$` = {@link EMPTY_RETURN_STATE}.\n\t*/\n\tstatic EMPTY_RETURN_STATE = 2147483647;\n\tstatic traceATNSimulator = false;\n\tcachedHashCode;\n\tconstructor(cachedHashCode) {\n\t\tthis.cachedHashCode = cachedHashCode;\n\t}\n\tstatic calculateEmptyHashCode() {\n\t\tlet hash = MurmurHash.initialize(31);\n\t\thash = MurmurHash.finish(hash, 0);\n\t\treturn hash;\n\t}\n\tstatic calculateHashCodeSingle(parent, returnState) {\n\t\tlet hash = MurmurHash.initialize(31);\n\t\thash = MurmurHash.updateFromComparable(hash, parent);\n\t\thash = MurmurHash.update(hash, returnState);\n\t\thash = MurmurHash.finish(hash, 2);\n\t\treturn hash;\n\t}\n\tstatic calculateHashCodeList(parents, returnStates) {\n\t\tlet hash = MurmurHash.initialize(31);\n\t\tfor (const parent of parents) hash = MurmurHash.updateFromComparable(hash, parent);\n\t\tfor (const returnState of returnStates) hash = MurmurHash.update(hash, returnState);\n\t\thash = MurmurHash.finish(hash, 2 * parents.length);\n\t\treturn hash;\n\t}\n\tisEmpty() {\n\t\treturn false;\n\t}\n\thasEmptyPath() {\n\t\treturn this.getReturnState(this.length - 1) === _PredictionContext.EMPTY_RETURN_STATE;\n\t}\n\thashCode() {\n\t\treturn this.cachedHashCode;\n\t}\n\ttoString(_recog) {\n\t\treturn \"\";\n\t}\n};\nvar SingletonPredictionContext = class _SingletonPredictionContext extends PredictionContext {\n\tstatic {\n\t\t__name(this, \"SingletonPredictionContext\");\n\t}\n\tparent;\n\treturnState;\n\tconstructor(parent, returnState) {\n\t\tsuper(parent ? PredictionContext.calculateHashCodeSingle(parent, returnState) : PredictionContext.calculateEmptyHashCode());\n\t\tthis.parent = parent ?? null;\n\t\tthis.returnState = returnState;\n\t}\n\tgetParent(_index) {\n\t\treturn this.parent;\n\t}\n\tgetReturnState(_index) {\n\t\treturn this.returnState;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _SingletonPredictionContext)) return false;\n\t\tif (this.hashCode() !== other.hashCode()) return false;\n\t\tif (this.returnState !== other.returnState) return false;\n\t\tif (this.parent == null) return other.parent == null;\n\t\treturn this.parent.equals(other.parent);\n\t}\n\ttoString() {\n\t\tconst up = this.parent === null ? \"\" : this.parent.toString();\n\t\tif (up.length === 0) {\n\t\t\tif (this.returnState === PredictionContext.EMPTY_RETURN_STATE) return \"$\";\n\t\t\treturn \"\" + this.returnState;\n\t\t} else return \"\" + this.returnState + \" \" + up;\n\t}\n\tget length() {\n\t\treturn 1;\n\t}\n};\nvar EmptyPredictionContext = class _EmptyPredictionContext extends SingletonPredictionContext {\n\tstatic {\n\t\t__name(this, \"EmptyPredictionContext\");\n\t}\n\t/**\n\t* Represents `$` in local context prediction, which means wildcard.\n\t* `*+x = *`.\n\t*/\n\tstatic instance = new _EmptyPredictionContext();\n\tconstructor() {\n\t\tsuper(void 0, PredictionContext.EMPTY_RETURN_STATE);\n\t}\n\tisEmpty() {\n\t\treturn true;\n\t}\n\tgetParent() {\n\t\treturn null;\n\t}\n\tgetReturnState() {\n\t\treturn this.returnState;\n\t}\n\tequals(other) {\n\t\treturn this === other;\n\t}\n\ttoString() {\n\t\treturn \"$\";\n\t}\n};\nvar Transition = class {\n\tstatic {\n\t\t__name(this, \"Transition\");\n\t}\n\tstatic INVALID = 0;\n\tstatic EPSILON = 1;\n\tstatic RANGE = 2;\n\tstatic RULE = 3;\n\tstatic PREDICATE = 4;\n\tstatic ATOM = 5;\n\tstatic ACTION = 6;\n\tstatic SET = 7;\n\tstatic NOT_SET = 8;\n\tstatic WILDCARD = 9;\n\tstatic PRECEDENCE = 10;\n\t/** The target of this transition. */\n\ttarget;\n\tconstructor(target) {\n\t\tthis.target = target;\n\t}\n\t/**\n\t* Determines if the transition is an \"epsilon\" transition.\n\t*\n\t* The default implementation returns `false`.\n\t*\n\t* @returns `true` if traversing this transition in the ATN does not\n\t* consume an input symbol; otherwise, `false` if traversing this\n\t* transition consumes (matches) an input symbol.\n\t*/\n\tget isEpsilon() {\n\t\treturn false;\n\t}\n\tget label() {\n\t\treturn null;\n\t}\n\ttoString() {\n\t\treturn \"\";\n\t}\n};\nvar SetTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"SetTransition\");\n\t}\n\tset;\n\tconstructor(target, set) {\n\t\tsuper(target);\n\t\tif (set) this.set = set;\n\t\telse this.set = IntervalSet.of(Token.INVALID_TYPE, Token.INVALID_TYPE);\n\t}\n\tget transitionType() {\n\t\treturn Transition.SET;\n\t}\n\tget label() {\n\t\treturn this.set;\n\t}\n\tmatches(symbol, _minVocabSymbol, _maxVocabSymbol) {\n\t\treturn this.set.contains(symbol);\n\t}\n\ttoString() {\n\t\treturn this.set.toString();\n\t}\n};\nvar NotSetTransition = class extends SetTransition {\n\tstatic {\n\t\t__name(this, \"NotSetTransition\");\n\t}\n\tget transitionType() {\n\t\treturn Transition.NOT_SET;\n\t}\n\tmatches(symbol, minVocabSymbol, maxVocabSymbol) {\n\t\treturn symbol >= minVocabSymbol && symbol <= maxVocabSymbol && !super.matches(symbol, minVocabSymbol, maxVocabSymbol);\n\t}\n\ttoString() {\n\t\treturn \"~\" + super.toString();\n\t}\n};\nvar MapKeyEqualityComparator = class {\n\tstatic {\n\t\t__name(this, \"MapKeyEqualityComparator\");\n\t}\n\tkeyComparator;\n\tconstructor(keyComparator) {\n\t\tthis.keyComparator = keyComparator;\n\t}\n\thashCode(obj) {\n\t\treturn this.keyComparator.hashCode(obj.key);\n\t}\n\tequals(a, b) {\n\t\treturn this.keyComparator.equals(a.key, b.key);\n\t}\n};\nvar HashMap = class _HashMap {\n\tstatic {\n\t\t__name(this, \"HashMap\");\n\t}\n\tbackingStore;\n\tconstructor(keyComparer) {\n\t\tif (keyComparer instanceof _HashMap) this.backingStore = new HashSet(keyComparer.backingStore);\n\t\telse {\n\t\t\tkeyComparer = keyComparer ?? DefaultEqualityComparator.instance;\n\t\t\tthis.backingStore = new HashSet(new MapKeyEqualityComparator(keyComparer));\n\t\t}\n\t}\n\tclear() {\n\t\tthis.backingStore.clear();\n\t}\n\tcontainsKey(key) {\n\t\treturn this.backingStore.contains({ key });\n\t}\n\tget(key) {\n\t\tconst bucket = this.backingStore.get({ key });\n\t\tif (!bucket) return;\n\t\treturn bucket.value;\n\t}\n\tget isEmpty() {\n\t\treturn this.backingStore.isEmpty;\n\t}\n\t/**\n\t* Sets the value for a key in the map. If the key is not present in the map, it is added.\n\t* If the key is present, the value is updated and the old value is returned.\n\t*\n\t* @param key The key to set.\n\t* @param value The value to set.\n\t*\n\t* @returns The old value for the key, if present.\n\t*/\n\tset(key, value) {\n\t\tconst element = this.backingStore.get({\n\t\t\tkey,\n\t\t\tvalue\n\t\t});\n\t\tlet result;\n\t\tif (!element) this.backingStore.add({\n\t\t\tkey,\n\t\t\tvalue\n\t\t});\n\t\telse {\n\t\t\tresult = element.value;\n\t\t\telement.value = value;\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* Sets the value for a key in the map if the key is not already present. Otherwise the value is not changed and\n\t* the old value is returned.\n\t*\n\t* @param key The key to set.\n\t* @param value The value to set.\n\t*\n\t* @returns The current value for the key, if present.\n\t*/\n\tsetIfAbsent(key, value) {\n\t\tconst element = this.backingStore.get({\n\t\t\tkey,\n\t\t\tvalue\n\t\t});\n\t\tlet result;\n\t\tif (!element) this.backingStore.add({\n\t\t\tkey,\n\t\t\tvalue\n\t\t});\n\t\telse result = element.value;\n\t\treturn result;\n\t}\n\tkeys() {\n\t\treturn this.backingStore.toArray().map((bucket) => {\n\t\t\treturn bucket.key;\n\t\t});\n\t}\n\tvalues() {\n\t\treturn this.backingStore.toArray().map((bucket) => {\n\t\t\treturn bucket.value;\n\t\t});\n\t}\n\tget size() {\n\t\treturn this.backingStore.size;\n\t}\n\thashCode() {\n\t\treturn this.backingStore.hashCode();\n\t}\n\tequals(o) {\n\t\treturn this.backingStore.equals(o.backingStore);\n\t}\n};\nvar TerminalNode = class {\n\tstatic {\n\t\t__name(this, \"TerminalNode\");\n\t}\n\tparent = null;\n\tsymbol;\n\tconstructor(symbol) {\n\t\tthis.symbol = symbol;\n\t}\n\tgetChild(_i) {\n\t\treturn null;\n\t}\n\tgetSymbol() {\n\t\treturn this.symbol;\n\t}\n\tgetPayload() {\n\t\treturn this.symbol;\n\t}\n\tgetSourceInterval() {\n\t\tif (this.symbol === null) return Interval.INVALID_INTERVAL;\n\t\tconst tokenIndex = this.symbol.tokenIndex;\n\t\treturn new Interval(tokenIndex, tokenIndex);\n\t}\n\tgetChildCount() {\n\t\treturn 0;\n\t}\n\taccept(visitor) {\n\t\treturn visitor.visitTerminal(this);\n\t}\n\tgetText() {\n\t\treturn this.symbol?.text ?? \"\";\n\t}\n\ttoString() {\n\t\tif (this.symbol?.type === Token.EOF) return \"<EOF>\";\n\t\telse return this.symbol?.text ?? \"\";\n\t}\n\ttoStringTree() {\n\t\treturn this.toString();\n\t}\n};\nvar ErrorNode = class extends TerminalNode {\n\tstatic {\n\t\t__name(this, \"ErrorNode\");\n\t}\n\taccept(visitor) {\n\t\treturn visitor.visitErrorNode(this);\n\t}\n};\nvar CommonToken = class _CommonToken {\n\tstatic {\n\t\t__name(this, \"CommonToken\");\n\t}\n\t/**\n\t* An empty tuple which is used as the default value of\n\t* {@link source} for tokens that do not have a source.\n\t*/\n\tstatic EMPTY_SOURCE = [null, null];\n\t/**\n\t* These properties share a field to reduce the memory footprint of\n\t* {@link CommonToken}. Tokens created by a {@link CommonTokenFactory} from\n\t* the same source and input stream share a reference to the same\n\t* {@link Pair} containing these values.\n\t*/\n\tsource;\n\ttokenIndex;\n\tstart;\n\tstop;\n\t/**\n\t* This is the backing field for {@link #getType} and {@link #setType}.\n\t*/\n\ttype;\n\t/**\n\t* The (one-based) line number on which the 1st character of this token was.\n\t*/\n\tline;\n\t/**\n\t* The zero-based index of the first character position in its line.\n\t*/\n\tcolumn;\n\t/**\n\t* The token's channel.\n\t*/\n\tchannel;\n\t/**\n\t* This is the backing field for {@link getText} when the token text is\n\t* explicitly set in the constructor or via {@link setText}.\n\t*/\n\t#text;\n\tconstructor(details) {\n\t\tthis.type = details.type;\n\t\tthis.source = details.source;\n\t\tthis.tokenIndex = details.tokenIndex ?? -1;\n\t\tthis.line = details.line ?? 0;\n\t\tthis.column = details.column ?? -1;\n\t\tthis.channel = details.channel ?? Token.DEFAULT_CHANNEL;\n\t\tthis.start = details.start ?? 0;\n\t\tthis.stop = details.stop ?? 0;\n\t\tthis.#text = details.text;\n\t\tif (details.line === void 0 && details.source[0] !== null) this.line = details.source[0].line;\n\t\tif (details.column === void 0 && details.source[0] !== null) this.column = details.source[0].column;\n\t}\n\t/**\n\t* Constructs a new {@link CommonToken} as a copy of another {@link Token}.\n\t*\n\t* If `token` is also a {@link CommonToken} instance, the newly\n\t* constructed token will share a reference to the {@link #text} field and\n\t* the {@link Pair} stored in {@link source}. Otherwise, {@link text} will\n\t* be assigned the result of calling {@link getText}, and {@link source}\n\t* will be constructed from the result of {@link Token.getTokenSource} and\n\t* {@link Token#getInputStream}.\n\t*\n\t* @param token The token to copy.\n\t*/\n\tstatic fromToken(token) {\n\t\tconst source = [token.tokenSource, token.inputStream];\n\t\treturn new _CommonToken({\n\t\t\ttype: token.type,\n\t\t\tline: token.line,\n\t\t\ttokenIndex: token.tokenIndex,\n\t\t\tcolumn: token.column,\n\t\t\tchannel: token.channel,\n\t\t\tstart: token.start,\n\t\t\tstop: token.stop,\n\t\t\ttext: token.text,\n\t\t\tsource\n\t\t});\n\t}\n\t/**\n\t* Constructs a new {@link CommonToken} with the specified token type and text.\n\t*\n\t* @param type The token type.\n\t* @param text The text of the token.\n\t*/\n\tstatic fromType(type, text) {\n\t\treturn new _CommonToken({\n\t\t\ttype,\n\t\t\ttext,\n\t\t\tsource: _CommonToken.EMPTY_SOURCE\n\t\t});\n\t}\n\tstatic fromSource(source, type, channel, start, stop) {\n\t\treturn new _CommonToken({\n\t\t\ttype,\n\t\t\tchannel,\n\t\t\tstart,\n\t\t\tstop,\n\t\t\tsource\n\t\t});\n\t}\n\tget tokenSource() {\n\t\treturn this.source[0];\n\t}\n\tget inputStream() {\n\t\treturn this.source[1];\n\t}\n\tset inputStream(input) {\n\t\tthis.source[1] = input;\n\t}\n\t/**\n\t* Constructs a new {@link CommonToken} as a copy of another {@link Token}.\n\t*\n\t* If `oldToken` is also a {@link CommonToken} instance, the newly\n\t* constructed token will share a reference to the {@link text} field and\n\t* the {@link Pair} stored in {@link source}. Otherwise, {@link text} will\n\t* be assigned the result of calling {@link getText}, and {@link source}\n\t* will be constructed from the result of {@link Token.getTokenSource} and\n\t* {@link Token.getInputStream}.\n\t*/\n\tclone() {\n\t\treturn new _CommonToken({\n\t\t\tsource: this.source,\n\t\t\ttype: this.type,\n\t\t\tchannel: this.channel,\n\t\t\tstart: this.start,\n\t\t\tstop: this.stop,\n\t\t\ttokenIndex: this.tokenIndex,\n\t\t\tline: this.line,\n\t\t\tcolumn: this.column,\n\t\t\ttext: this.#text\n\t\t});\n\t}\n\ttoString(recognizer) {\n\t\tlet channelStr = \"\";\n\t\tif (this.channel > 0) channelStr = \",channel=\" + this.channel;\n\t\tlet text = this.text;\n\t\tif (text) {\n\t\t\ttext = text.replace(/\\n/g, \"\\\\n\");\n\t\t\ttext = text.replace(/\\r/g, \"\\\\r\");\n\t\t\ttext = text.replace(/\\t/g, \"\\\\t\");\n\t\t} else text = \"<no text>\";\n\t\tlet typeString = String(this.type);\n\t\tif (recognizer) typeString = recognizer.vocabulary.getDisplayName(this.type) ?? \"<unknown>\";\n\t\treturn \"[@\" + this.tokenIndex + \",\" + this.start + \":\" + this.stop + \"='\" + text + \"',<\" + typeString + \">\" + channelStr + \",\" + this.line + \":\" + this.column + \"]\";\n\t}\n\tget text() {\n\t\tif (this.#text !== void 0) return this.#text;\n\t\tconst input = this.inputStream;\n\t\tif (!input) return;\n\t\tconst n2 = input.size;\n\t\tif (this.start < n2 && this.stop < n2) return input.getTextFromRange(this.start, this.stop);\n\t\treturn \"<EOF>\";\n\t}\n\tset text(text) {\n\t\tthis.#text = text;\n\t}\n\tsetText(text) {\n\t\tthis.#text = text;\n\t}\n\tsetType(ttype) {\n\t\tthis.type = ttype;\n\t}\n\tsetLine(line) {\n\t\tthis.line = line;\n\t}\n\tsetCharPositionInLine(pos) {\n\t\tthis.column = pos;\n\t}\n\tsetChannel(channel) {\n\t\tthis.channel = channel;\n\t}\n\tsetTokenIndex(index) {\n\t\tthis.tokenIndex = index;\n\t}\n};\nvar Trees = class _Trees {\n\tstatic {\n\t\t__name(this, \"Trees\");\n\t}\n\t/**\n\t* Print out a whole tree in LISP form. {@link getNodeText} is used on the\n\t* node payloads to get the text for the nodes.  Detect\n\t* parse trees and extract data appropriately.\n\t*/\n\tstatic toStringTree(tree, ruleNames, recog) {\n\t\truleNames = ruleNames ?? null;\n\t\tif (recog) ruleNames = recog.ruleNames;\n\t\tlet s = _Trees.getNodeText(tree, ruleNames);\n\t\ts = escapeWhitespace(s, false);\n\t\tconst c = tree.getChildCount();\n\t\tif (c === 0) return s;\n\t\tlet res = \"(\" + s + \" \";\n\t\tif (c > 0) {\n\t\t\ts = _Trees.toStringTree(tree.getChild(0), ruleNames);\n\t\t\tres = res.concat(s);\n\t\t}\n\t\tfor (let i = 1; i < c; i++) {\n\t\t\ts = _Trees.toStringTree(tree.getChild(i), ruleNames);\n\t\t\tres = res.concat(\" \" + s);\n\t\t}\n\t\tres = res.concat(\")\");\n\t\treturn res;\n\t}\n\tstatic getNodeText(t, ruleNames, recog) {\n\t\truleNames = ruleNames ?? null;\n\t\tif (recog) ruleNames = recog.ruleNames;\n\t\tif (ruleNames !== null) {\n\t\t\tif (t instanceof ParserRuleContext) {\n\t\t\t\tconst altNumber = t.ruleContext.getAltNumber();\n\t\t\t\tif (altNumber !== 0) return ruleNames[t.ruleIndex] + \":\" + altNumber;\n\t\t\t\treturn ruleNames[t.ruleIndex];\n\t\t\t} else if (t instanceof ErrorNode) return t.toString();\n\t\t\telse if (t instanceof TerminalNode) return t.symbol.text;\n\t\t}\n\t\tconst payload = t.getPayload();\n\t\tif (isToken(payload)) return payload.text;\n\t\treturn String(t.getPayload());\n\t}\n\t/**\n\t* Return ordered list of all children of this node\n\t*/\n\tstatic getChildren(t) {\n\t\tconst list = [];\n\t\tfor (let i = 0; i < t.getChildCount(); i++) list.push(t.getChild(i));\n\t\treturn list;\n\t}\n\t/**\n\t* Return a list of all ancestors of this node.  The first node of\n\t* list is the root and the last is the parent of this node.\n\t*/\n\tstatic getAncestors(t) {\n\t\tif (t.parent === null) return [];\n\t\tlet ancestors = [];\n\t\tlet p = t.parent;\n\t\twhile (p !== null) {\n\t\t\tancestors = [p].concat(ancestors);\n\t\t\tp = p.parent;\n\t\t}\n\t\treturn ancestors;\n\t}\n\t/**\n\t* Return true if t is u's parent or a node on path to root from u.\n\t*/\n\tstatic isAncestorOf(t, u) {\n\t\tif (t === null || u === null || t.parent === null) return false;\n\t\tlet p = u.parent;\n\t\twhile (p !== null) {\n\t\t\tif (t === p) return true;\n\t\t\tp = p.parent;\n\t\t}\n\t\treturn false;\n\t}\n\tstatic findAllTokenNodes(t, ttype) {\n\t\treturn _Trees.findAllNodes(t, ttype, true);\n\t}\n\tstatic findAllRuleNodes(t, ruleIndex) {\n\t\treturn _Trees.findAllNodes(t, ruleIndex, false);\n\t}\n\tstatic findAllNodes(t, index, findTokens) {\n\t\tconst nodes = [];\n\t\t_Trees.doFindAllNodes(t, index, findTokens, nodes);\n\t\treturn nodes;\n\t}\n\tstatic descendants(t) {\n\t\tlet nodes = [t];\n\t\tfor (let i = 0; i < t.getChildCount(); i++) nodes = nodes.concat(_Trees.descendants(t.getChild(i)));\n\t\treturn nodes;\n\t}\n\t/**\n\t* Find smallest subtree of t enclosing range startTokenIndex..stopTokenIndex\n\t* inclusively using post order traversal. Recursive depth-first-search.\n\t*/\n\tstatic getRootOfSubtreeEnclosingRegion(t, startTokenIndex, stopTokenIndex) {\n\t\tconst n2 = t.getChildCount();\n\t\tfor (let i = 0; i < n2; i++) {\n\t\t\tconst child = t.getChild(i);\n\t\t\tconst r = this.getRootOfSubtreeEnclosingRegion(child, startTokenIndex, stopTokenIndex);\n\t\t\tif (r !== null) return r;\n\t\t}\n\t\tif (t instanceof ParserRuleContext) {\n\t\t\tif (startTokenIndex >= t.start.tokenIndex && (t.stop === null || stopTokenIndex <= t.stop.tokenIndex)) return t;\n\t\t}\n\t\treturn null;\n\t}\n\t/**\n\t* Replace any subtree siblings of root that are completely to left\n\t* or right of lookahead range with a CommonToken(Token.INVALID_TYPE,\"...\")\n\t* node. The source interval for t is not altered to suit smaller range!\n\t*\n\t* WARNING: destructive to t.\n\t*/\n\tstatic stripChildrenOutOfRange(t, root, startIndex, stopIndex) {\n\t\tif (t === null) return;\n\t\tfor (let i = 0; i < t.getChildCount(); i++) {\n\t\t\tconst child = t.getChild(i);\n\t\t\tconst range = child.getSourceInterval();\n\t\t\tif (t instanceof ParserRuleContext && (range.stop < startIndex || range.start > stopIndex)) {\n\t\t\t\tif (this.isAncestorOf(child, root)) {\n\t\t\t\t\tconst abbrev = CommonToken.fromType(Token.INVALID_TYPE, \"...\");\n\t\t\t\t\tt.children[i] = new TerminalNode(abbrev);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tstatic doFindAllNodes(t, index, findTokens, nodes) {\n\t\tif (findTokens && t instanceof TerminalNode) {\n\t\t\tif (t.symbol?.type === index) nodes.push(t);\n\t\t} else if (!findTokens && t instanceof ParserRuleContext) {\n\t\t\tif (t.ruleIndex === index) nodes.push(t);\n\t\t}\n\t\tfor (let i = 0; i < t.getChildCount(); i++) _Trees.doFindAllNodes(t.getChild(i), index, findTokens, nodes);\n\t}\n};\nvar ParserRuleContext = class _ParserRuleContext {\n\tstatic {\n\t\t__name(this, \"ParserRuleContext\");\n\t}\n\tstatic empty = new _ParserRuleContext(null);\n\tstart = null;\n\tstop = null;\n\tchildren = [];\n\t/**\n\t* What state invoked the rule associated with this context?\n\t*  The \"return address\" is the followState of invokingState\n\t*  If parent is null, this should be -1 this context object represents\n\t*  the start rule.\n\t*/\n\tinvokingState;\n\tparent;\n\t/**\n\t* A rule context is a record of a single rule invocation. It knows\n\t* which context invoked it, if any. If there is no parent context, then\n\t* naturally the invoking state is not valid.  The parent link\n\t* provides a chain upwards from the current rule invocation to the root\n\t* of the invocation tree, forming a stack. We actually carry no\n\t* information about the rule associated with this context (except\n\t* when parsing). We keep only the state number of the invoking state from\n\t* the ATN submachine that invoked this. Contrast this with the s\n\t* pointer inside ParserRuleContext that tracks the current state\n\t* being \"executed\" for the current rule.\n\t*\n\t* The parent contexts are useful for computing lookahead sets and\n\t* getting error information.\n\t*\n\t* These objects are used during parsing and prediction.\n\t* For the special case of parsers, we use the subclass\n\t* ParserRuleContext.\n\t*/\n\tconstructor(parent, invokingStateNumber = -1) {\n\t\tthis.parent = parent;\n\t\tthis.invokingState = invokingStateNumber;\n\t}\n\t/** Copy a context */\n\tcopyFrom(ctx) {\n\t\tthis.parent = ctx.parent;\n\t\tthis.invokingState = ctx.invokingState;\n\t\tthis.children.slice(0, this.children.length);\n\t\tthis.start = ctx.start;\n\t\tthis.stop = ctx.stop;\n\t\tif (ctx.children) ctx.children.forEach((child) => {\n\t\t\tif (child instanceof ErrorNode) {\n\t\t\t\tthis.children.push(child);\n\t\t\t\tchild.parent = this;\n\t\t\t}\n\t\t});\n\t}\n\tenterRule(_listener) {}\n\texitRule(_listener) {}\n\taddChild(child) {\n\t\tthis.children.push(child);\n\t\treturn child;\n\t}\n\t/**\n\t* Used by enterOuterAlt to toss out a RuleContext previously added as\n\t* we entered a rule. If we have label, we will need to remove\n\t* generic ruleContext object.\n\t*/\n\tremoveLastChild() {\n\t\tthis.children.pop();\n\t}\n\taddTokenNode(token) {\n\t\tconst node = new TerminalNode(token);\n\t\tthis.children.push(node);\n\t\tnode.parent = this;\n\t\treturn node;\n\t}\n\taddErrorNode(errorNode) {\n\t\terrorNode.parent = this;\n\t\tthis.children.push(errorNode);\n\t\treturn errorNode;\n\t}\n\tgetChild(i, type) {\n\t\tif (i < 0 || i >= this.children.length) return null;\n\t\tif (!type) return this.children[i];\n\t\tfor (const child of this.children) if (child instanceof type) if (i === 0) return child;\n\t\telse i -= 1;\n\t\treturn null;\n\t}\n\tgetToken(ttype, i) {\n\t\tif (i < 0 || i >= this.children.length) return null;\n\t\tfor (const child of this.children) if (\"symbol\" in child) {\n\t\t\tif (child.symbol?.type === ttype) if (i === 0) return child;\n\t\t\telse i -= 1;\n\t\t}\n\t\treturn null;\n\t}\n\tgetTokens(ttype) {\n\t\tconst tokens = [];\n\t\tfor (const child of this.children) if (\"symbol\" in child) {\n\t\t\tif (child.symbol?.type === ttype) tokens.push(child);\n\t\t}\n\t\treturn tokens;\n\t}\n\tgetRuleContext(index, ctxType) {\n\t\treturn this.getChild(index, ctxType);\n\t}\n\tgetRuleContexts(ctxType) {\n\t\tconst contexts = [];\n\t\tfor (const child of this.children) if (child instanceof ctxType) contexts.push(child);\n\t\treturn contexts;\n\t}\n\tgetChildCount() {\n\t\treturn this.children.length;\n\t}\n\tgetSourceInterval() {\n\t\tif (this.start === null) return Interval.INVALID_INTERVAL;\n\t\tif (this.stop === null || this.stop.tokenIndex < this.start.tokenIndex) return new Interval(this.start.tokenIndex, this.start.tokenIndex - 1);\n\t\treturn new Interval(this.start.tokenIndex, this.stop.tokenIndex);\n\t}\n\tdepth() {\n\t\tlet n2 = 0;\n\t\tlet p = this;\n\t\twhile (p !== null) {\n\t\t\tp = p.parent;\n\t\t\tn2 += 1;\n\t\t}\n\t\treturn n2;\n\t}\n\t/**\n\t* A context is empty if there is no invoking state; meaning nobody call\n\t* current context.\n\t*/\n\tisEmpty() {\n\t\treturn this.invokingState === -1;\n\t}\n\tget ruleContext() {\n\t\treturn this;\n\t}\n\tget ruleIndex() {\n\t\treturn -1;\n\t}\n\tgetPayload() {\n\t\treturn this;\n\t}\n\tgetText() {\n\t\tif (this.children.length === 0) return \"\";\n\t\treturn this.children.map((child) => {\n\t\t\treturn child.getText();\n\t\t}).join(\"\");\n\t}\n\t/**\n\t* For rule associated with this parse tree internal node, return\n\t* the outer alternative number used to match the input. Default\n\t* implementation does not compute nor store this alt num. Create\n\t* a subclass of ParserRuleContext with backing field and set\n\t* option contextSuperClass.\n\t* to set it.\n\t*/\n\tgetAltNumber() {\n\t\treturn ATN.INVALID_ALT_NUMBER;\n\t}\n\t/**\n\t* Set the outer alternative number for this context node. Default\n\t* implementation does nothing to avoid backing field overhead for\n\t* trees that don't need it.  Create\n\t* a subclass of ParserRuleContext with backing field and set\n\t* option contextSuperClass.\n\t*/\n\tsetAltNumber(_altNumber) {}\n\taccept(visitor) {\n\t\treturn visitor.visitChildren(this);\n\t}\n\ttoStringTree(...args) {\n\t\tif (args.length < 2) return Trees.toStringTree(this, null, args[0]);\n\t\treturn Trees.toStringTree(this, args[0], args[1]);\n\t}\n\ttoString(ruleNames, stop) {\n\t\truleNames = ruleNames ?? null;\n\t\tstop = stop ?? null;\n\t\tlet p = this;\n\t\tlet s = \"[\";\n\t\twhile (p !== null && p !== stop) {\n\t\t\tif (ruleNames === null) {\n\t\t\t\tif (!p.isEmpty()) s += p.invokingState;\n\t\t\t} else {\n\t\t\t\tconst ri = p.ruleIndex;\n\t\t\t\tconst ruleName = ri >= 0 && ri < ruleNames.length ? ruleNames[ri] : \"\" + ri;\n\t\t\t\ts += ruleName;\n\t\t\t}\n\t\t\tif (p.parent !== null && (ruleNames !== null || !p.parent.isEmpty())) s += \" \";\n\t\t\tp = p.parent;\n\t\t}\n\t\ts += \"]\";\n\t\treturn s;\n\t}\n};\nvar ArrayPredictionContext = class _ArrayPredictionContext extends PredictionContext {\n\tstatic {\n\t\t__name(this, \"ArrayPredictionContext\");\n\t}\n\tparents = [];\n\treturnStates = [];\n\tconstructor(parents, returnStates) {\n\t\tsuper(PredictionContext.calculateHashCodeList(parents, returnStates));\n\t\tthis.parents = parents;\n\t\tthis.returnStates = returnStates;\n\t\treturn this;\n\t}\n\tisEmpty() {\n\t\treturn this.returnStates[0] === PredictionContext.EMPTY_RETURN_STATE;\n\t}\n\tget length() {\n\t\treturn this.returnStates.length;\n\t}\n\tgetParent(index) {\n\t\treturn this.parents[index];\n\t}\n\tgetReturnState(index) {\n\t\treturn this.returnStates[index];\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _ArrayPredictionContext) || this.hashCode() !== other.hashCode()) return false;\n\t\treturn equalNumberArrays(this.returnStates, other.returnStates) && equalArrays(this.parents, other.parents);\n\t}\n\ttoString() {\n\t\tif (this.isEmpty()) return \"[]\";\n\t\tconst entries = [];\n\t\tfor (let i = 0; i < this.returnStates.length; i++) {\n\t\t\tif (this.returnStates[i] === PredictionContext.EMPTY_RETURN_STATE) {\n\t\t\t\tentries.push(\"$\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tentries.push(this.returnStates[i].toString());\n\t\t\tif (this.parents[i]) entries.push(this.parents[i].toString());\n\t\t\telse entries.push(\"null\");\n\t\t}\n\t\treturn `[${entries.join(\", \")}]`;\n\t}\n};\nvar createSingletonPredictionContext = /* @__PURE__ */ __name((parent, returnState) => {\n\tif (returnState === PredictionContext.EMPTY_RETURN_STATE && parent === null) return EmptyPredictionContext.instance;\n\telse return new SingletonPredictionContext(parent, returnState);\n}, \"createSingletonPredictionContext\");\nvar predictionContextFromRuleContext = /* @__PURE__ */ __name((atn, outerContext) => {\n\tif (!outerContext) outerContext = ParserRuleContext.empty;\n\tif (!outerContext.parent || outerContext === ParserRuleContext.empty) return EmptyPredictionContext.instance;\n\tconst parent = predictionContextFromRuleContext(atn, outerContext.parent);\n\tconst transition = atn.states[outerContext.invokingState].transitions[0];\n\treturn createSingletonPredictionContext(parent, transition.followState.stateNumber);\n}, \"predictionContextFromRuleContext\");\nvar getCachedPredictionContext = /* @__PURE__ */ __name((context, contextCache, visited) => {\n\tif (context.isEmpty()) return context;\n\tlet existing = visited.get(context);\n\tif (existing) return existing;\n\texisting = contextCache.get(context);\n\tif (existing) {\n\t\tvisited.set(context, existing);\n\t\treturn existing;\n\t}\n\tlet changed = false;\n\tlet parents = [];\n\tfor (let i = 0; i < parents.length; i++) {\n\t\tconst parent = getCachedPredictionContext(context.getParent(i), contextCache, visited);\n\t\tif (changed || parent !== context.getParent(i)) {\n\t\t\tif (!changed) {\n\t\t\t\tparents = [];\n\t\t\t\tfor (let j = 0; j < context.length; j++) parents[j] = context.getParent(j);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tparents[i] = parent;\n\t\t}\n\t}\n\tif (!changed) {\n\t\tcontextCache.add(context);\n\t\tvisited.set(context, context);\n\t\treturn context;\n\t}\n\tlet updated;\n\tif (parents.length === 0) updated = EmptyPredictionContext.instance;\n\telse if (parents.length === 1) updated = createSingletonPredictionContext(parents[0] ?? void 0, context.getReturnState(0));\n\telse updated = new ArrayPredictionContext(parents, context.returnStates);\n\tcontextCache.add(updated);\n\tvisited.set(updated, updated);\n\tvisited.set(context, updated);\n\treturn updated;\n}, \"getCachedPredictionContext\");\nvar merge = /* @__PURE__ */ __name((a, b, rootIsWildcard, mergeCache) => {\n\tif (a === b || a.equals(b)) return a;\n\tif (a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) return mergeSingletons(a, b, rootIsWildcard, mergeCache);\n\tif (rootIsWildcard) {\n\t\tif (a instanceof EmptyPredictionContext) return a;\n\t\tif (b instanceof EmptyPredictionContext) return b;\n\t}\n\tif (a instanceof SingletonPredictionContext) a = new ArrayPredictionContext([a.parent], [a.returnState]);\n\tif (b instanceof SingletonPredictionContext) b = new ArrayPredictionContext([b.parent], [b.returnState]);\n\treturn mergeArrays(a, b, rootIsWildcard, mergeCache);\n}, \"merge\");\nvar mergeArrays = /* @__PURE__ */ __name((a, b, rootIsWildcard, mergeCache) => {\n\tif (mergeCache) {\n\t\tlet previous = mergeCache.get(a, b);\n\t\tif (previous) return previous;\n\t\tprevious = mergeCache.get(b, a);\n\t\tif (previous) return previous;\n\t}\n\tlet i = 0;\n\tlet j = 0;\n\tlet k = 0;\n\tlet mergedReturnStates = new Array(a.returnStates.length + b.returnStates.length).fill(0);\n\tlet mergedParents = new Array(a.returnStates.length + b.returnStates.length).fill(null);\n\twhile (i < a.returnStates.length && j < b.returnStates.length) {\n\t\tconst aParent = a.parents[i];\n\t\tconst bParent = b.parents[j];\n\t\tif (a.returnStates[i] === b.returnStates[j]) {\n\t\t\tconst payload = a.returnStates[i];\n\t\t\tif (payload === PredictionContext.EMPTY_RETURN_STATE && aParent === null && bParent === null || aParent !== null && bParent !== null && aParent === bParent) {\n\t\t\t\tmergedParents[k] = aParent;\n\t\t\t\tmergedReturnStates[k] = payload;\n\t\t\t} else {\n\t\t\t\tmergedParents[k] = merge(aParent, bParent, rootIsWildcard, mergeCache);\n\t\t\t\tmergedReturnStates[k] = payload;\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tj += 1;\n\t\t} else if (a.returnStates[i] < b.returnStates[j]) {\n\t\t\tmergedParents[k] = aParent;\n\t\t\tmergedReturnStates[k] = a.returnStates[i];\n\t\t\ti += 1;\n\t\t} else {\n\t\t\tmergedParents[k] = bParent;\n\t\t\tmergedReturnStates[k] = b.returnStates[j];\n\t\t\tj += 1;\n\t\t}\n\t\tk += 1;\n\t}\n\tif (i < a.returnStates.length) for (let p = i; p < a.returnStates.length; p++) {\n\t\tmergedParents[k] = a.parents[p];\n\t\tmergedReturnStates[k] = a.returnStates[p];\n\t\tk += 1;\n\t}\n\telse for (let p = j; p < b.returnStates.length; p++) {\n\t\tmergedParents[k] = b.parents[p];\n\t\tmergedReturnStates[k] = b.returnStates[p];\n\t\tk += 1;\n\t}\n\tif (k < mergedParents.length) {\n\t\tif (k === 1) {\n\t\t\tconst aNew = createSingletonPredictionContext(mergedParents[0] ?? void 0, mergedReturnStates[0]);\n\t\t\tif (mergeCache !== null) mergeCache.set(a, b, aNew);\n\t\t\treturn aNew;\n\t\t}\n\t\tmergedParents = mergedParents.slice(0, k);\n\t\tmergedReturnStates = mergedReturnStates.slice(0, k);\n\t}\n\tconst merged = new ArrayPredictionContext(mergedParents, mergedReturnStates);\n\tif (merged.equals(a)) {\n\t\tif (mergeCache !== null) mergeCache.set(a, b, a);\n\t\tif (PredictionContext.traceATNSimulator) console.log(\"mergeArrays a=\" + a + \",b=\" + b + \" -> a\");\n\t\treturn a;\n\t}\n\tif (merged.equals(b)) {\n\t\tif (mergeCache !== null) mergeCache.set(a, b, b);\n\t\treturn b;\n\t}\n\tcombineCommonParents(mergedParents);\n\tif (mergeCache !== null) mergeCache.set(a, b, merged);\n\tif (PredictionContext.traceATNSimulator) console.log(\"mergeArrays a=\" + a + \",b=\" + b + \" -> \" + merged);\n\treturn merged;\n}, \"mergeArrays\");\nvar combineCommonParents = /* @__PURE__ */ __name((parents) => {\n\tconst uniqueParents = new HashMap(ObjectEqualityComparator.instance);\n\tfor (const parent of parents) if (parent) {\n\t\tif (!uniqueParents.containsKey(parent)) uniqueParents.set(parent, parent);\n\t}\n\tfor (let q = 0; q < parents.length; q++) if (parents[q]) parents[q] = uniqueParents.get(parents[q]) ?? null;\n}, \"combineCommonParents\");\nvar mergeSingletons = /* @__PURE__ */ __name((a, b, rootIsWildcard, mergeCache) => {\n\tif (mergeCache !== null) {\n\t\tlet previous = mergeCache.get(a, b);\n\t\tif (previous !== null) return previous;\n\t\tprevious = mergeCache.get(b, a);\n\t\tif (previous !== null) return previous;\n\t}\n\tconst rootMerge = mergeRoot(a, b, rootIsWildcard);\n\tif (rootMerge !== null) {\n\t\tif (mergeCache !== null) mergeCache.set(a, b, rootMerge);\n\t\treturn rootMerge;\n\t}\n\tif (a.returnState === b.returnState) {\n\t\tconst parent = merge(a.parent, b.parent, rootIsWildcard, mergeCache);\n\t\tif (parent === a.parent) return a;\n\t\tif (parent === b.parent) return b;\n\t\tconst spc = createSingletonPredictionContext(parent, a.returnState);\n\t\tif (mergeCache !== null) mergeCache.set(a, b, spc);\n\t\treturn spc;\n\t} else {\n\t\tlet singleParent = null;\n\t\tif (a === b || a.parent !== null && a.parent.equals(b.parent)) singleParent = a.parent;\n\t\tif (singleParent !== null) {\n\t\t\tconst payloads2 = [a.returnState, b.returnState];\n\t\t\tif (a.returnState > b.returnState) {\n\t\t\t\tpayloads2[0] = b.returnState;\n\t\t\t\tpayloads2[1] = a.returnState;\n\t\t\t}\n\t\t\tconst apc = new ArrayPredictionContext([singleParent, singleParent], payloads2);\n\t\t\tif (mergeCache !== null) mergeCache.set(a, b, apc);\n\t\t\treturn apc;\n\t\t}\n\t\tconst payloads = [a.returnState, b.returnState];\n\t\tlet parents = [a.parent, b.parent];\n\t\tif (a.returnState > b.returnState) {\n\t\t\tpayloads[0] = b.returnState;\n\t\t\tpayloads[1] = a.returnState;\n\t\t\tparents = [b.parent, a.parent];\n\t\t}\n\t\tconst aNew = new ArrayPredictionContext(parents, payloads);\n\t\tif (mergeCache !== null) mergeCache.set(a, b, aNew);\n\t\treturn aNew;\n\t}\n}, \"mergeSingletons\");\nvar mergeRoot = /* @__PURE__ */ __name((a, b, rootIsWildcard) => {\n\tif (rootIsWildcard) {\n\t\tif (a === EmptyPredictionContext.instance || b === EmptyPredictionContext.instance) return EmptyPredictionContext.instance;\n\t} else {\n\t\tif (a === EmptyPredictionContext.instance && b === EmptyPredictionContext.instance) return EmptyPredictionContext.instance;\n\t\tif (a === EmptyPredictionContext.instance) {\n\t\t\tconst payloads = [b.returnState, PredictionContext.EMPTY_RETURN_STATE];\n\t\t\treturn new ArrayPredictionContext([b.parent, null], payloads);\n\t\t}\n\t\tif (b === EmptyPredictionContext.instance) {\n\t\t\tconst payloads = [a.returnState, PredictionContext.EMPTY_RETURN_STATE];\n\t\t\treturn new ArrayPredictionContext([a.parent, null], payloads);\n\t\t}\n\t}\n\treturn null;\n}, \"mergeRoot\");\nvar LL1Analyzer = class _LL1Analyzer {\n\tconstructor(atn) {\n\t\tthis.atn = atn;\n\t}\n\tstatic {\n\t\t__name(this, \"LL1Analyzer\");\n\t}\n\t/**\n\t* Special value added to the lookahead sets to indicate that we hit\n\t* a predicate during analysis if `seeThruPreds==false`.\n\t*/\n\tstatic hitPredicate = Token.INVALID_TYPE;\n\t/**\n\t* Calculates the SLL(1) expected lookahead set for each outgoing transition\n\t* of an {@link ATNState}. The returned array has one element for each\n\t* outgoing transition in `s`. If the closure from transition\n\t* _i_ leads to a semantic predicate before matching a symbol, the\n\t* element at index *i* of the result will be `undefined`.\n\t*\n\t* @param s the ATN state\n\t* @returns the expected symbols for each outgoing transition of `s`.\n\t*/\n\tgetDecisionLookahead(s) {\n\t\tconst count = s.transitions.length;\n\t\tconst look = new Array(count);\n\t\tfor (let alt = 0; alt < count; alt++) {\n\t\t\tconst set = new IntervalSet();\n\t\t\tconst lookBusy = new HashSet();\n\t\t\tthis.doLook(s.transitions[alt].target, void 0, EmptyPredictionContext.instance, set, lookBusy, new BitSet(), false, false);\n\t\t\tif (set.length > 0 && !set.contains(_LL1Analyzer.hitPredicate)) look[alt] = set;\n\t\t}\n\t\treturn look;\n\t}\n\t/**\n\t* Compute set of tokens that can follow `s` in the ATN in the\n\t* specified `ctx`.\n\t*\n\t* If `ctx` is `null` and the end of the rule containing\n\t* `s` is reached, {@link Token//EPSILON} is added to the result set.\n\t* If `ctx` is not `null` and the end of the outermost rule is\n\t* reached, {@link Token//EOF} is added to the result set.\n\t*\n\t* @param s the ATN state\n\t* @param stopState the ATN state to stop at. This can be a\n\t* {@link BlockEndState} to detect epsilon paths through a closure.\n\t* @param ctx the complete parser context, or `null` if the context\n\t* should be ignored\n\t*\n\t* @returns The set of tokens that can follow `s` in the ATN in the\n\t* specified `ctx`.\n\t*/\n\tlook(s, stopState, ctx) {\n\t\tconst r = new IntervalSet();\n\t\tconst lookContext = ctx ? predictionContextFromRuleContext(this.atn, ctx) : null;\n\t\tthis.doLook(s, stopState, lookContext, r, new HashSet(), new BitSet(), true, true);\n\t\treturn r;\n\t}\n\t/**\n\t* Compute set of tokens that can follow `s` in the ATN in the\n\t* specified `ctx`.\n\t*\n\t* If `ctx` is `null` and `stopState` or the end of the\n\t* rule containing `s` is reached, {@link Token//EPSILON} is added to\n\t* the result set. If `ctx` is not `null` and `addEOF` is\n\t* `true` and `stopState` or the end of the outermost rule is\n\t* reached, {@link Token//EOF} is added to the result set.\n\t*\n\t* @param s the ATN state.\n\t* @param stopState the ATN state to stop at. This can be a\n\t* {@link BlockEndState} to detect epsilon paths through a closure.\n\t* @param ctx The outer context, or `null` if the outer context should\n\t* not be used.\n\t* @param look The result lookahead set.\n\t* @param lookBusy A set used for preventing epsilon closures in the ATN\n\t* from causing a stack overflow. Outside code should pass\n\t* `new CustomizedSet<ATNConfig>` for this argument.\n\t* @param calledRuleStack A set used for preventing left recursion in the\n\t* ATN from causing a stack overflow. Outside code should pass\n\t* `new BitSet()` for this argument.\n\t* @param seeThruPreds `true` to true semantic predicates as\n\t* implicitly `true` and \"see through them\", otherwise `false`\n\t* to treat semantic predicates as opaque and add {@link hitPredicate} to the\n\t* result if one is encountered.\n\t* @param addEOF Add {@link Token//EOF} to the result if the end of the\n\t* outermost context is reached. This parameter has no effect if `ctx`\n\t* is `null`.\n\t*/\n\tdoLook(s, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF) {\n\t\tconst c = ATNConfig.createWithContext(s, 0, ctx);\n\t\tif (lookBusy.get(c)) return;\n\t\tlookBusy.add(c);\n\t\tif (s === stopState) {\n\t\t\tif (!ctx) {\n\t\t\t\tlook.addOne(Token.EPSILON);\n\t\t\t\treturn;\n\t\t\t} else if (ctx.isEmpty() && addEOF) {\n\t\t\t\tlook.addOne(Token.EOF);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (s.constructor.stateType === ATNState.RULE_STOP) {\n\t\t\tif (!ctx) {\n\t\t\t\tlook.addOne(Token.EPSILON);\n\t\t\t\treturn;\n\t\t\t} else if (ctx.isEmpty() && addEOF) {\n\t\t\t\tlook.addOne(Token.EOF);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx !== EmptyPredictionContext.instance) {\n\t\t\t\tconst removed = calledRuleStack.get(s.ruleIndex);\n\t\t\t\ttry {\n\t\t\t\t\tcalledRuleStack.clear(s.ruleIndex);\n\t\t\t\t\tfor (let i = 0; i < ctx.length; i++) {\n\t\t\t\t\t\tconst returnState = this.atn.states[ctx.getReturnState(i)];\n\t\t\t\t\t\tthis.doLook(returnState, stopState, ctx.getParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF);\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tif (removed) calledRuleStack.set(s.ruleIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tfor (const t of s.transitions) switch (t.transitionType) {\n\t\t\tcase Transition.RULE: {\n\t\t\t\tif (calledRuleStack.get(t.target.ruleIndex)) continue;\n\t\t\t\tconst newContext = createSingletonPredictionContext(ctx ?? void 0, t.followState.stateNumber);\n\t\t\t\ttry {\n\t\t\t\t\tcalledRuleStack.set(t.target.ruleIndex);\n\t\t\t\t\tthis.doLook(t.target, stopState, newContext, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);\n\t\t\t\t} finally {\n\t\t\t\t\tcalledRuleStack.clear(t.target.ruleIndex);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Transition.PREDICATE:\n\t\t\tcase Transition.PRECEDENCE:\n\t\t\t\tif (seeThruPreds) this.doLook(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);\n\t\t\t\telse look.addOne(_LL1Analyzer.hitPredicate);\n\t\t\t\tbreak;\n\t\t\tcase Transition.WILDCARD:\n\t\t\t\tlook.addRange(Token.MIN_USER_TOKEN_TYPE, this.atn.maxTokenType);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (t.isEpsilon) this.doLook(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);\n\t\t\t\telse {\n\t\t\t\t\tlet set = t.label;\n\t\t\t\t\tif (set) {\n\t\t\t\t\t\tif (t instanceof NotSetTransition) set = set.complement(Token.MIN_USER_TOKEN_TYPE, this.atn.maxTokenType);\n\t\t\t\t\t\tlook.addSet(set);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\nvar ATN = class {\n\tstatic {\n\t\t__name(this, \"ATN\");\n\t}\n\tstatic INVALID_ALT_NUMBER = 0;\n\t/** Represents the type of recognizer an ATN applies to */\n\tstatic LEXER = 0;\n\tstatic PARSER = 1;\n\t/**\n\t* Used for runtime deserialization of ATNs from strings\n\t* The type of the ATN.\n\t*/\n\tgrammarType;\n\t/** The maximum value for any symbol recognized by a transition in the ATN. */\n\tmaxTokenType;\n\tstates = [];\n\t/**\n\t* Each subrule/rule is a decision point and we must track them so we\n\t* can go back later and build DFA predictors for them.  This includes\n\t* all the rules, subrules, optional blocks, ()+, ()* etc...\n\t*/\n\tdecisionToState = [];\n\t/** Maps from rule index to starting state number. */\n\truleToStartState = [];\n\t/** Maps from rule index to stop state number. */\n\truleToStopState = [];\n\tmodeNameToStartState = /* @__PURE__ */ new Map();\n\t/**\n\t* For lexer ATNs, this maps the rule index to the resulting token type.\n\t* For parser ATNs, this maps the rule index to the generated bypass token\n\t* type if the {@link ATNDeserializationOptions//isGenerateRuleBypassTransitions}\n\t* deserialization option was specified; otherwise, this is `null`\n\t*/\n\truleToTokenType = [];\n\t/**\n\t* For lexer ATNs, this is an array of {@link LexerAction} objects which may\n\t* be referenced by action transitions in the ATN\n\t*/\n\tlexerActions = [];\n\tmodeToStartState = [];\n\tanalyzer;\n\tconstructor(grammarType, maxTokenType) {\n\t\tthis.grammarType = grammarType;\n\t\tthis.maxTokenType = maxTokenType;\n\t\tthis.analyzer = new LL1Analyzer(this);\n\t}\n\t/**\n\t* Compute the set of valid tokens that can occur starting in state `s`.\n\t* If `ctx` is null, the set of tokens will not include what can follow\n\t* the rule surrounding `s`. In other words, the set will be\n\t* restricted to tokens reachable staying within `s`'s rule.\n\t*/\n\tnextTokens(atnState, ctx) {\n\t\tif (!ctx && atnState.nextTokenWithinRule) return atnState.nextTokenWithinRule;\n\t\tconst next = this.analyzer.look(atnState, void 0, ctx);\n\t\tif (!ctx) atnState.nextTokenWithinRule = next;\n\t\treturn next;\n\t}\n\taddState(state) {\n\t\tif (state) state.stateNumber = this.states.length;\n\t\tthis.states.push(state);\n\t}\n\tremoveState(state) {\n\t\tthis.states[state.stateNumber] = null;\n\t}\n\tdefineDecisionState(s) {\n\t\tthis.decisionToState.push(s);\n\t\ts.decision = this.decisionToState.length - 1;\n\t\treturn s.decision;\n\t}\n\tgetDecisionState(decision) {\n\t\tif (this.decisionToState.length === 0) return null;\n\t\telse return this.decisionToState[decision];\n\t}\n\tgetNumberOfDecisions() {\n\t\treturn this.decisionToState.length;\n\t}\n\t/**\n\t* Computes the set of input symbols which could follow ATN state number\n\t* `stateNumber` in the specified full `context`. This method\n\t* considers the complete parser context, but does not evaluate semantic\n\t* predicates (i.e. all predicates encountered during the calculation are\n\t* assumed true). If a path in the ATN exists from the starting state to the\n\t* {@link RuleStopState} of the outermost context without matching any\n\t* symbols, {@link Token//EOF} is added to the returned set.\n\t*\n\t* If `context` is `null`, it is treated as\n\t* {@link ParserRuleContext//EMPTY}.\n\t*\n\t* @param stateNumber the ATN state number\n\t* @param context the full parse context\n\t*\n\t* @returns {IntervalSet} The set of potentially valid input symbols which could follow the\n\t* specified state in the specified context.\n\t*\n\t* @throws IllegalArgumentException if the ATN does not contain a state with\n\t* number `stateNumber`\n\t*/\n\tgetExpectedTokens(stateNumber, context) {\n\t\tif (stateNumber < 0 || stateNumber >= this.states.length) throw new Error(\"Invalid state number.\");\n\t\tconst s = this.states[stateNumber];\n\t\tlet following = this.nextTokens(s);\n\t\tif (!following.contains(Token.EPSILON)) return following;\n\t\tlet ctx = context;\n\t\tconst expected = new IntervalSet();\n\t\texpected.addSet(following);\n\t\texpected.removeOne(Token.EPSILON);\n\t\twhile (ctx !== null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {\n\t\t\tconst rt = this.states[ctx.invokingState].transitions[0];\n\t\t\tfollowing = this.nextTokens(rt.followState);\n\t\t\texpected.addSet(following);\n\t\t\texpected.removeOne(Token.EPSILON);\n\t\t\tctx = ctx.parent;\n\t\t}\n\t\tif (following.contains(Token.EPSILON)) expected.addOne(Token.EOF);\n\t\treturn expected;\n\t}\n};\nvar KeyTypeEqualityComparer = class _KeyTypeEqualityComparer {\n\tstatic {\n\t\t__name(this, \"KeyTypeEqualityComparer\");\n\t}\n\tstatic instance = new _KeyTypeEqualityComparer();\n\thashCode(config) {\n\t\tlet hashCode = 7;\n\t\thashCode = 31 * hashCode + config.state.stateNumber;\n\t\thashCode = 31 * hashCode + config.alt;\n\t\thashCode = 31 * hashCode + config.semanticContext.hashCode();\n\t\treturn hashCode;\n\t}\n\tequals(a, b) {\n\t\tif (a === b) return true;\n\t\treturn a.state.stateNumber === b.state.stateNumber && a.alt === b.alt && a.semanticContext.equals(b.semanticContext);\n\t}\n};\nvar ATNConfigSet = class {\n\tstatic {\n\t\t__name(this, \"ATNConfigSet\");\n\t}\n\t/**\n\t* The reason that we need this is because we don't want the hash map to use\n\t* the standard hash code and equals. We need all configurations with the\n\t* same\n\t* `(s,i,_,semctx)` to be equal. Unfortunately, this key effectively\n\t* doubles\n\t* the number of objects associated with ATNConfigs. The other solution is\n\t* to\n\t* use a hash table that lets us specify the equals/hashCode operation.\n\t* All configs but hashed by (s, i, _, pi) not including context. Wiped out\n\t* when we go readonly as this set becomes a DFA state\n\t*/\n\tconfigLookup = new HashSet(KeyTypeEqualityComparer.instance);\n\tconfigs = [];\n\tuniqueAlt = 0;\n\t/**\n\t* Used in parser and lexer. In lexer, it indicates we hit a pred\n\t* while computing a closure operation. Don't make a DFA state from this\n\t*/\n\thasSemanticContext = false;\n\tdipsIntoOuterContext = false;\n\t/**\n\t* Indicates that this configuration set is part of a full context\n\t* LL prediction. It will be used to determine how to merge $. With SLL\n\t* it's a wildcard whereas it is not for LL context merge\n\t*/\n\tfullCtx = false;\n\t/**\n\t* Indicates that the set of configurations is read-only. Do not\n\t* allow any code to manipulate the set; DFA states will point at\n\t* the sets and they must not change. This does not protect the other\n\t* fields; in particular, conflictingAlts is set after\n\t* we've made this readonly\n\t*/\n\treadOnly = false;\n\tconflictingAlts = null;\n\t/**\n\t* Tracks the first config that has a rule stop state. Avoids frequent linear search for that, when adding\n\t* a DFA state in the lexer ATN simulator.\n\t*/\n\tfirstStopState;\n\t#cachedHashCode = -1;\n\tconstructor(fullCtxOrOldSet) {\n\t\tif (fullCtxOrOldSet !== void 0) if (typeof fullCtxOrOldSet === \"boolean\") this.fullCtx = fullCtxOrOldSet ?? true;\n\t\telse {\n\t\t\tconst old = fullCtxOrOldSet;\n\t\t\tthis.addAll(old.configs);\n\t\t\tthis.uniqueAlt = old.uniqueAlt;\n\t\t\tthis.conflictingAlts = old.conflictingAlts;\n\t\t\tthis.hasSemanticContext = old.hasSemanticContext;\n\t\t\tthis.dipsIntoOuterContext = old.dipsIntoOuterContext;\n\t\t}\n\t}\n\t[Symbol.iterator]() {\n\t\treturn this.configs[Symbol.iterator]();\n\t}\n\t/**\n\t* Adding a new config means merging contexts with existing configs for\n\t* `(s, i, pi, _)`, where `s` is the {@link ATNConfig.state}, `i` is the {@link ATNConfig.alt}, and\n\t* `pi` is the {@link ATNConfig.semanticContext}. We use `(s,i,pi)` as key.\n\t*\n\t* This method updates {@link dipsIntoOuterContext} and\n\t* {@link hasSemanticContext} when necessary.\n\t*/\n\tadd(config, mergeCache = null) {\n\t\tif (this.readOnly) throw new Error(\"This set is readonly\");\n\t\tif (!this.firstStopState && config.state.constructor.stateType === ATNState.RULE_STOP) this.firstStopState = config;\n\t\tthis.hasSemanticContext ||= config.semanticContext !== SemanticContext.NONE;\n\t\tthis.dipsIntoOuterContext ||= config.reachesIntoOuterContext;\n\t\tconst existing = this.configLookup.getOrAdd(config);\n\t\tif (existing === config) {\n\t\t\tthis.#cachedHashCode = -1;\n\t\t\tthis.configs.push(config);\n\t\t\treturn;\n\t\t}\n\t\tconst rootIsWildcard = !this.fullCtx;\n\t\tconst merged = merge(existing.context, config.context, rootIsWildcard, mergeCache);\n\t\texisting.reachesIntoOuterContext ||= config.reachesIntoOuterContext;\n\t\texisting.precedenceFilterSuppressed ||= config.precedenceFilterSuppressed;\n\t\texisting.context = merged;\n\t}\n\t/** Return a List holding list of configs */\n\tget elements() {\n\t\treturn this.configs;\n\t}\n\t/**\n\t* Gets the complete set of represented alternatives for the configuration set.\n\t*\n\t* @returns the set of represented alternatives in this configuration set\n\t*/\n\tgetAlts() {\n\t\tconst alts = new BitSet();\n\t\tfor (const config of this.configs) alts.set(config.alt);\n\t\treturn alts;\n\t}\n\tgetPredicates() {\n\t\tconst preds = [];\n\t\tfor (const config of this.configs) if (config.semanticContext !== SemanticContext.NONE) preds.push(config.semanticContext);\n\t\treturn preds;\n\t}\n\tgetStates() {\n\t\tconst states = new HashSet();\n\t\tfor (const config of this.configs) states.add(config.state);\n\t\treturn states;\n\t}\n\toptimizeConfigs(interpreter) {\n\t\tif (this.readOnly) throw new Error(\"This set is readonly\");\n\t\tif (this.configLookup.size === 0) return;\n\t\tfor (const config of this.configs) config.context = interpreter.getCachedContext(config.context);\n\t}\n\taddAll(coll) {\n\t\tfor (const config of coll) this.add(config);\n\t\treturn false;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (this.fullCtx === other.fullCtx && this.uniqueAlt === other.uniqueAlt && this.conflictingAlts === other.conflictingAlts && this.hasSemanticContext === other.hasSemanticContext && this.dipsIntoOuterContext === other.dipsIntoOuterContext && equalArrays(this.configs, other.configs)) return true;\n\t\treturn false;\n\t}\n\thashCode() {\n\t\tif (this.#cachedHashCode === -1) this.#cachedHashCode = this.computeHashCode();\n\t\treturn this.#cachedHashCode;\n\t}\n\tget length() {\n\t\treturn this.configs.length;\n\t}\n\tisEmpty() {\n\t\treturn this.configs.length === 0;\n\t}\n\tcontains(item) {\n\t\tif (this.configLookup === null) throw new Error(\"This method is not implemented for readonly sets.\");\n\t\treturn this.configLookup.contains(item);\n\t}\n\tcontainsFast(item) {\n\t\tif (this.configLookup === null) throw new Error(\"This method is not implemented for readonly sets.\");\n\t\treturn this.configLookup.contains(item);\n\t}\n\tclear() {\n\t\tif (this.readOnly) throw new Error(\"This set is readonly\");\n\t\tthis.configs = [];\n\t\tthis.#cachedHashCode = -1;\n\t\tthis.configLookup = new HashSet(KeyTypeEqualityComparer.instance);\n\t}\n\tsetReadonly(readOnly) {\n\t\tthis.readOnly = readOnly;\n\t\tif (readOnly) this.configLookup = null;\n\t}\n\ttoString() {\n\t\treturn arrayToString(this.configs) + (this.hasSemanticContext ? \",hasSemanticContext=\" + this.hasSemanticContext : \"\") + (this.uniqueAlt !== ATN.INVALID_ALT_NUMBER ? \",uniqueAlt=\" + this.uniqueAlt : \"\") + (this.conflictingAlts !== null ? \",conflictingAlts=\" + this.conflictingAlts : \"\") + (this.dipsIntoOuterContext ? \",dipsIntoOuterContext\" : \"\");\n\t}\n\tcomputeHashCode() {\n\t\tlet hash = MurmurHash.initialize();\n\t\tthis.configs.forEach((config) => {\n\t\t\thash = MurmurHash.update(hash, config.hashCode());\n\t\t});\n\t\thash = MurmurHash.finish(hash, this.configs.length);\n\t\treturn hash;\n\t}\n};\nvar BasicState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"BasicState\");\n\t}\n\tstatic stateType = ATNState.BASIC;\n};\nvar DecisionState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"DecisionState\");\n\t}\n\tdecision = -1;\n\tnonGreedy = false;\n};\nvar BlockStartState = class extends DecisionState {\n\tstatic {\n\t\t__name(this, \"BlockStartState\");\n\t}\n\tendState;\n};\nvar BlockEndState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"BlockEndState\");\n\t}\n\tstatic stateType = ATNState.BLOCK_END;\n\tstartState;\n};\nvar LoopEndState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"LoopEndState\");\n\t}\n\tstatic stateType = ATNState.LOOP_END;\n\tloopBackState;\n};\nvar RuleStartState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"RuleStartState\");\n\t}\n\tstatic stateType = ATNState.RULE_START;\n\tstopState;\n\tisLeftRecursiveRule = false;\n};\nvar RuleStopState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"RuleStopState\");\n\t}\n\tstatic stateType = ATNState.RULE_STOP;\n};\nvar TokensStartState = class extends DecisionState {\n\tstatic {\n\t\t__name(this, \"TokensStartState\");\n\t}\n\tstatic stateType = ATNState.TOKEN_START;\n};\nvar PlusLoopbackState = class extends DecisionState {\n\tstatic {\n\t\t__name(this, \"PlusLoopbackState\");\n\t}\n\tstatic stateType = ATNState.PLUS_LOOP_BACK;\n};\nvar StarLoopbackState = class extends ATNState {\n\tstatic {\n\t\t__name(this, \"StarLoopbackState\");\n\t}\n\tstatic stateType = ATNState.STAR_LOOP_BACK;\n};\nvar StarLoopEntryState = class extends DecisionState {\n\tstatic {\n\t\t__name(this, \"StarLoopEntryState\");\n\t}\n\tstatic stateType = ATNState.STAR_LOOP_ENTRY;\n\tloopBackState;\n\t/**\n\t* Indicates whether this state can benefit from a precedence DFA during SLL\n\t* decision making.\n\t*\n\t* This is a computed property that is calculated during ATN deserialization\n\t* and stored for use in {@link ParserATNSimulator} and\n\t* {@link ParserInterpreter}.\n\t*\n\t* @see `DFA.isPrecedenceDfa`\n\t*/\n\tprecedenceRuleDecision = false;\n};\nvar PlusBlockStartState = class extends BlockStartState {\n\tstatic {\n\t\t__name(this, \"PlusBlockStartState\");\n\t}\n\tstatic stateType = ATNState.PLUS_BLOCK_START;\n\tloopBackState;\n};\nvar StarBlockStartState = class extends BlockStartState {\n\tstatic {\n\t\t__name(this, \"StarBlockStartState\");\n\t}\n\tstatic stateType = ATNState.STAR_BLOCK_START;\n};\nvar BasicBlockStartState = class extends BlockStartState {\n\tstatic {\n\t\t__name(this, \"BasicBlockStartState\");\n\t}\n\tstatic stateType = ATNState.BLOCK_START;\n};\nvar AtomTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"AtomTransition\");\n\t}\n\t/** The token type or character value; or, signifies special label. */\n\tlabelValue;\n\t#label;\n\tconstructor(target, label) {\n\t\tsuper(target);\n\t\tthis.labelValue = label;\n\t\tthis.#label = IntervalSet.of(label, label);\n\t}\n\tget label() {\n\t\treturn this.#label;\n\t}\n\tget transitionType() {\n\t\treturn Transition.ATOM;\n\t}\n\tmatches(symbol) {\n\t\treturn this.labelValue === symbol;\n\t}\n\ttoString() {\n\t\treturn this.labelValue.toString();\n\t}\n};\nvar RuleTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"RuleTransition\");\n\t}\n\truleIndex;\n\tprecedence;\n\tfollowState;\n\tconstructor(ruleStart, ruleIndex, precedence, followState) {\n\t\tsuper(ruleStart);\n\t\tthis.ruleIndex = ruleIndex;\n\t\tthis.precedence = precedence;\n\t\tthis.followState = followState;\n\t}\n\tget isEpsilon() {\n\t\treturn true;\n\t}\n\tget transitionType() {\n\t\treturn Transition.RULE;\n\t}\n\tmatches(_symbol, _minVocabSymbol, _maxVocabSymbol) {\n\t\treturn false;\n\t}\n};\nvar RangeTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"RangeTransition\");\n\t}\n\tstart;\n\tstop;\n\t#label = new IntervalSet();\n\tconstructor(target, start, stop) {\n\t\tsuper(target);\n\t\tthis.start = start;\n\t\tthis.stop = stop;\n\t\tthis.#label.addRange(start, stop);\n\t}\n\tget label() {\n\t\treturn this.#label;\n\t}\n\tget transitionType() {\n\t\treturn Transition.RANGE;\n\t}\n\tmatches(symbol, _minVocabSymbol, _maxVocabSymbol) {\n\t\treturn symbol >= this.start && symbol <= this.stop;\n\t}\n\ttoString() {\n\t\treturn \"'\" + String.fromCharCode(this.start) + \"'..'\" + String.fromCharCode(this.stop) + \"'\";\n\t}\n};\nvar ActionTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"ActionTransition\");\n\t}\n\truleIndex;\n\tactionIndex;\n\tisCtxDependent;\n\tconstructor(target, ruleIndex, actionIndex, isCtxDependent) {\n\t\tsuper(target);\n\t\tthis.ruleIndex = ruleIndex;\n\t\tthis.actionIndex = actionIndex ?? -1;\n\t\tthis.isCtxDependent = isCtxDependent ?? false;\n\t}\n\tget isEpsilon() {\n\t\treturn true;\n\t}\n\tget transitionType() {\n\t\treturn Transition.ACTION;\n\t}\n\tmatches(_symbol, _minVocabSymbol, _maxVocabSymbol) {\n\t\treturn false;\n\t}\n\ttoString() {\n\t\treturn \"action_\" + this.ruleIndex + \":\" + this.actionIndex;\n\t}\n};\nvar EpsilonTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"EpsilonTransition\");\n\t}\n\t#outermostPrecedenceReturn;\n\tconstructor(target, outermostPrecedenceReturn = -1) {\n\t\tsuper(target);\n\t\tthis.#outermostPrecedenceReturn = outermostPrecedenceReturn;\n\t}\n\t/**\n\t* @returns the rule index of a precedence rule for which this transition is\n\t* returning from, where the precedence value is 0; otherwise, -1.\n\t*\n\t* @see ATNConfig.isPrecedenceFilterSuppressed()\n\t* @see ParserATNSimulator.applyPrecedenceFilter(ATNConfigSet)\n\t* @since 4.4.1\n\t*/\n\tget outermostPrecedenceReturn() {\n\t\treturn this.#outermostPrecedenceReturn;\n\t}\n\tget isEpsilon() {\n\t\treturn true;\n\t}\n\tget transitionType() {\n\t\treturn Transition.EPSILON;\n\t}\n\tmatches() {\n\t\treturn false;\n\t}\n\ttoString() {\n\t\treturn \"epsilon\";\n\t}\n};\nvar WildcardTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"WildcardTransition\");\n\t}\n\tget transitionType() {\n\t\treturn Transition.WILDCARD;\n\t}\n\tmatches(symbol, minVocabSymbol, maxVocabSymbol) {\n\t\treturn symbol >= minVocabSymbol && symbol <= maxVocabSymbol;\n\t}\n\ttoString() {\n\t\treturn \".\";\n\t}\n};\nvar AbstractPredicateTransition = class extends Transition {\n\tstatic {\n\t\t__name(this, \"AbstractPredicateTransition\");\n\t}\n\tconstructor(target) {\n\t\tsuper(target);\n\t}\n};\nvar PredicateTransition = class extends AbstractPredicateTransition {\n\tstatic {\n\t\t__name(this, \"PredicateTransition\");\n\t}\n\truleIndex;\n\tpredIndex;\n\tisCtxDependent;\n\tconstructor(target, ruleIndex, predIndex, isCtxDependent) {\n\t\tsuper(target);\n\t\tthis.ruleIndex = ruleIndex;\n\t\tthis.predIndex = predIndex;\n\t\tthis.isCtxDependent = isCtxDependent;\n\t}\n\tget isEpsilon() {\n\t\treturn true;\n\t}\n\tmatches(_symbol, _minVocabSymbol, _maxVocabSymbol) {\n\t\treturn false;\n\t}\n\tget transitionType() {\n\t\treturn Transition.PREDICATE;\n\t}\n\tgetPredicate() {\n\t\treturn new SemanticContext.Predicate(this.ruleIndex, this.predIndex, this.isCtxDependent);\n\t}\n\ttoString() {\n\t\treturn \"pred_\" + this.ruleIndex + \":\" + this.predIndex;\n\t}\n};\nvar PrecedencePredicateTransition = class extends AbstractPredicateTransition {\n\tstatic {\n\t\t__name(this, \"PrecedencePredicateTransition\");\n\t}\n\tprecedence;\n\tconstructor(target, precedence) {\n\t\tsuper(target);\n\t\tthis.precedence = precedence;\n\t}\n\tget isEpsilon() {\n\t\treturn true;\n\t}\n\tmatches(_symbol, _minVocabSymbol, _maxVocabSymbol) {\n\t\treturn false;\n\t}\n\tgetPredicate() {\n\t\treturn new SemanticContext.PrecedencePredicate(this.precedence);\n\t}\n\tget transitionType() {\n\t\treturn Transition.PRECEDENCE;\n\t}\n\ttoString() {\n\t\treturn this.precedence + \" >= _p\";\n\t}\n};\nvar LexerActionType = {\n\tCHANNEL: 0,\n\tCUSTOM: 1,\n\tMODE: 2,\n\tMORE: 3,\n\tPOP_MODE: 4,\n\tPUSH_MODE: 5,\n\tSKIP: 6,\n\tTYPE: 7\n};\nvar LexerSkipAction = class _LexerSkipAction {\n\tstatic {\n\t\t__name(this, \"LexerSkipAction\");\n\t}\n\t/** Provides a singleton instance of this parameter-less lexer action. */\n\tstatic instance = new _LexerSkipAction();\n\tactionType;\n\tisPositionDependent = false;\n\tconstructor() {\n\t\tthis.actionType = LexerActionType.SKIP;\n\t}\n\tequals(obj) {\n\t\treturn obj === this;\n\t}\n\thashCode() {\n\t\treturn LexerActionType.SKIP;\n\t}\n\texecute(lexer) {\n\t\tlexer.skip();\n\t}\n\ttoString() {\n\t\treturn \"skip\";\n\t}\n};\nvar LexerChannelAction = class _LexerChannelAction {\n\tstatic {\n\t\t__name(this, \"LexerChannelAction\");\n\t}\n\tchannel;\n\tactionType;\n\tisPositionDependent = false;\n\tcachedHashCode;\n\tconstructor(channel) {\n\t\tthis.actionType = LexerActionType.CHANNEL;\n\t\tthis.channel = channel;\n\t}\n\t/**\n\t* This action is implemented by calling {@link Lexer.setChannel} with the\n\t* value provided by {@link getChannel}.\n\t*/\n\texecute(lexer) {\n\t\tlexer.channel = this.channel;\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\thash = MurmurHash.update(hash, this.actionType);\n\t\t\thash = MurmurHash.update(hash, this.channel);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, 2);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _LexerChannelAction)) return false;\n\t\treturn this.channel === other.channel;\n\t}\n\ttoString() {\n\t\treturn \"channel(\" + this.channel + \")\";\n\t}\n};\nvar LexerCustomAction = class _LexerCustomAction {\n\tstatic {\n\t\t__name(this, \"LexerCustomAction\");\n\t}\n\truleIndex;\n\tactionIndex;\n\tactionType;\n\tisPositionDependent = true;\n\tcachedHashCode;\n\t/**\n\t* Constructs a custom lexer action with the specified rule and action indexes.\n\t*\n\t* @param ruleIndex The rule index to use for calls to {@link Recognizer.action}.\n\t* @param actionIndex The action index to use for calls to {@link Recognizer.action}.\n\t*/\n\tconstructor(ruleIndex, actionIndex) {\n\t\tthis.actionType = LexerActionType.CUSTOM;\n\t\tthis.ruleIndex = ruleIndex;\n\t\tthis.actionIndex = actionIndex;\n\t}\n\t/**\n\t* Custom actions are implemented by calling {@link Lexer.action} with the\n\t* appropriate rule and action indexes.\n\t*/\n\texecute(lexer) {\n\t\tlexer.action(null, this.ruleIndex, this.actionIndex);\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\thash = MurmurHash.update(hash, this.actionType);\n\t\t\thash = MurmurHash.update(hash, this.ruleIndex);\n\t\t\thash = MurmurHash.update(hash, this.actionIndex);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, 3);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _LexerCustomAction)) return false;\n\t\treturn this.ruleIndex === other.ruleIndex && this.actionIndex === other.actionIndex;\n\t}\n};\nvar LexerMoreAction = class _LexerMoreAction {\n\tstatic {\n\t\t__name(this, \"LexerMoreAction\");\n\t}\n\tstatic instance = new _LexerMoreAction();\n\tactionType;\n\tisPositionDependent = false;\n\tconstructor() {\n\t\tthis.actionType = LexerActionType.MORE;\n\t}\n\tequals(obj) {\n\t\treturn obj === this;\n\t}\n\thashCode() {\n\t\treturn LexerActionType.MORE;\n\t}\n\t/**\n\t* This action is implemented by calling {@link Lexer.popMode}.\n\t*/\n\texecute(lexer) {\n\t\tlexer.more();\n\t}\n\ttoString() {\n\t\treturn \"more\";\n\t}\n};\nvar LexerTypeAction = class _LexerTypeAction {\n\tstatic {\n\t\t__name(this, \"LexerTypeAction\");\n\t}\n\ttype;\n\tactionType;\n\tisPositionDependent = false;\n\tcachedHashCode;\n\tconstructor(type) {\n\t\tthis.actionType = LexerActionType.TYPE;\n\t\tthis.type = type;\n\t}\n\texecute(lexer) {\n\t\tlexer.type = this.type;\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\thash = MurmurHash.update(hash, this.actionType);\n\t\t\thash = MurmurHash.update(hash, this.type);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, 2);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _LexerTypeAction)) return false;\n\t\treturn this.type === other.type;\n\t}\n\ttoString() {\n\t\treturn \"type(\" + this.type + \")\";\n\t}\n};\nvar LexerPushModeAction = class _LexerPushModeAction {\n\tstatic {\n\t\t__name(this, \"LexerPushModeAction\");\n\t}\n\tmode;\n\tactionType;\n\tisPositionDependent = false;\n\tcachedHashCode;\n\tconstructor(mode) {\n\t\tthis.actionType = LexerActionType.PUSH_MODE;\n\t\tthis.mode = mode;\n\t}\n\t/**\n\t* This action is implemented by calling {@link Lexer.pushMode} with the\n\t* value provided by {@link getMode}.\n\t*/\n\texecute(lexer) {\n\t\tlexer.pushMode(this.mode);\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\thash = MurmurHash.update(hash, this.actionType);\n\t\t\thash = MurmurHash.update(hash, this.mode);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, 2);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _LexerPushModeAction)) return false;\n\t\treturn this.mode === other.mode;\n\t}\n\ttoString() {\n\t\treturn \"pushMode(\" + this.mode + \")\";\n\t}\n};\nvar LexerPopModeAction = class _LexerPopModeAction {\n\tstatic {\n\t\t__name(this, \"LexerPopModeAction\");\n\t}\n\tstatic instance = new _LexerPopModeAction();\n\tactionType;\n\tisPositionDependent = false;\n\tconstructor() {\n\t\tthis.actionType = LexerActionType.POP_MODE;\n\t}\n\tequals(obj) {\n\t\treturn obj === this;\n\t}\n\thashCode() {\n\t\treturn LexerActionType.POP_MODE;\n\t}\n\t/**\n\t* This action is implemented by calling {@link Lexer//popMode}.\n\t*/\n\texecute(lexer) {\n\t\tlexer.popMode();\n\t}\n\ttoString() {\n\t\treturn \"popMode\";\n\t}\n};\nvar LexerModeAction = class _LexerModeAction {\n\tstatic {\n\t\t__name(this, \"LexerModeAction\");\n\t}\n\tmode;\n\tactionType;\n\tisPositionDependent = false;\n\tcachedHashCode;\n\tconstructor(mode) {\n\t\tthis.actionType = LexerActionType.MODE;\n\t\tthis.mode = mode;\n\t}\n\t/**\n\t* This action is implemented by calling {@link Lexer.mode} with the\n\t* value provided by {@link getMode}.\n\t*/\n\texecute(lexer) {\n\t\tlexer.mode = this.mode;\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\thash = MurmurHash.update(hash, this.actionType);\n\t\t\thash = MurmurHash.update(hash, this.mode);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, 2);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _LexerModeAction)) return false;\n\t\treturn this.mode === other.mode;\n\t}\n\ttoString() {\n\t\treturn \"mode(\" + this.mode + \")\";\n\t}\n};\nvar ATNDeserializer = class _ATNDeserializer {\n\tstatic {\n\t\t__name(this, \"ATNDeserializer\");\n\t}\n\tstatic SERIALIZED_VERSION = 4;\n\tstatic stateTypeMapper = /* @__PURE__ */ new Map([\n\t\t[ATNState.INVALID_TYPE, void 0],\n\t\t[ATNState.BASIC, BasicState],\n\t\t[ATNState.RULE_START, RuleStartState],\n\t\t[ATNState.BLOCK_START, BasicBlockStartState],\n\t\t[ATNState.PLUS_BLOCK_START, PlusBlockStartState],\n\t\t[ATNState.STAR_BLOCK_START, StarBlockStartState],\n\t\t[ATNState.TOKEN_START, TokensStartState],\n\t\t[ATNState.RULE_STOP, RuleStopState],\n\t\t[ATNState.BLOCK_END, BlockEndState],\n\t\t[ATNState.STAR_LOOP_BACK, StarLoopbackState],\n\t\t[ATNState.STAR_LOOP_ENTRY, StarLoopEntryState],\n\t\t[ATNState.PLUS_LOOP_BACK, PlusLoopbackState],\n\t\t[ATNState.LOOP_END, LoopEndState]\n\t]);\n\tstatic lexerActionFactoryMapper = /* @__PURE__ */ new Map([\n\t\t[LexerActionType.CHANNEL, (data1) => {\n\t\t\treturn new LexerChannelAction(data1);\n\t\t}],\n\t\t[LexerActionType.CUSTOM, (data1, data2) => {\n\t\t\treturn new LexerCustomAction(data1, data2);\n\t\t}],\n\t\t[LexerActionType.MODE, (data1) => {\n\t\t\treturn new LexerModeAction(data1);\n\t\t}],\n\t\t[LexerActionType.MORE, () => {\n\t\t\treturn LexerMoreAction.instance;\n\t\t}],\n\t\t[LexerActionType.POP_MODE, () => {\n\t\t\treturn LexerPopModeAction.instance;\n\t\t}],\n\t\t[LexerActionType.PUSH_MODE, (data1) => {\n\t\t\treturn new LexerPushModeAction(data1);\n\t\t}],\n\t\t[LexerActionType.SKIP, () => {\n\t\t\treturn LexerSkipAction.instance;\n\t\t}],\n\t\t[LexerActionType.TYPE, (data1) => {\n\t\t\treturn new LexerTypeAction(data1);\n\t\t}]\n\t]);\n\tdata = [];\n\tpos = 0;\n\tdeserializationOptions;\n\tactionFactories;\n\tconstructor(options) {\n\t\tif (!options) options = {\n\t\t\treadOnly: false,\n\t\t\tverifyATN: true,\n\t\t\tgenerateRuleBypassTransitions: false\n\t\t};\n\t\tthis.deserializationOptions = options;\n\t}\n\tdeserialize(data) {\n\t\tthis.data = data;\n\t\tthis.checkVersion();\n\t\tconst atn = this.readATN();\n\t\tthis.readStates(atn);\n\t\tthis.readRules(atn);\n\t\tthis.readModes(atn);\n\t\tconst sets = [];\n\t\tthis.readSets(atn, sets);\n\t\tthis.readEdges(atn, sets);\n\t\tthis.readDecisions(atn);\n\t\tthis.readLexerActions(atn);\n\t\tthis.markPrecedenceDecisions(atn);\n\t\tthis.verifyATN(atn);\n\t\tif (this.deserializationOptions.generateRuleBypassTransitions && atn.grammarType === ATN.PARSER) {\n\t\t\tthis.generateRuleBypassTransitions(atn);\n\t\t\tthis.verifyATN(atn);\n\t\t}\n\t\treturn atn;\n\t}\n\tcheckVersion() {\n\t\tconst version = this.data[this.pos++];\n\t\tif (version !== _ATNDeserializer.SERIALIZED_VERSION) throw new Error(\"Could not deserialize ATN with version \" + version + \" (expected \" + _ATNDeserializer.SERIALIZED_VERSION + \").\");\n\t}\n\treadATN() {\n\t\tconst grammarType = this.data[this.pos++];\n\t\tconst maxTokenType = this.data[this.pos++];\n\t\treturn new ATN(grammarType, maxTokenType);\n\t}\n\treadStates(atn) {\n\t\tlet j;\n\t\tlet stateNumber;\n\t\tconst loopBackStateNumbers = [];\n\t\tconst endStateNumbers = [];\n\t\tconst stateCount = this.data[this.pos++];\n\t\tfor (let i = 0; i < stateCount; i++) {\n\t\t\tconst stateType = this.data[this.pos++];\n\t\t\tif (stateType === ATNState.INVALID_TYPE) {\n\t\t\t\tatn.addState(null);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst ruleIndex = this.data[this.pos++];\n\t\t\tconst s = this.stateFactory(stateType, ruleIndex);\n\t\t\tif (stateType === ATNState.LOOP_END) {\n\t\t\t\tconst loopBackStateNumber = this.data[this.pos++];\n\t\t\t\tloopBackStateNumbers.push([s, loopBackStateNumber]);\n\t\t\t} else if (s instanceof BlockStartState) {\n\t\t\t\tconst endStateNumber = this.data[this.pos++];\n\t\t\t\tendStateNumbers.push([s, endStateNumber]);\n\t\t\t}\n\t\t\tatn.addState(s);\n\t\t}\n\t\tfor (j = 0; j < loopBackStateNumbers.length; j++) {\n\t\t\tconst pair = loopBackStateNumbers[j];\n\t\t\tpair[0].loopBackState = atn.states[pair[1]] ?? void 0;\n\t\t}\n\t\tfor (j = 0; j < endStateNumbers.length; j++) {\n\t\t\tconst pair = endStateNumbers[j];\n\t\t\tpair[0].endState = atn.states[pair[1]];\n\t\t}\n\t\tconst numNonGreedyStates = this.data[this.pos++];\n\t\tfor (j = 0; j < numNonGreedyStates; j++) {\n\t\t\tstateNumber = this.data[this.pos++];\n\t\t\tatn.states[stateNumber].nonGreedy = true;\n\t\t}\n\t\tconst numPrecedenceStates = this.data[this.pos++];\n\t\tfor (j = 0; j < numPrecedenceStates; j++) {\n\t\t\tstateNumber = this.data[this.pos++];\n\t\t\tatn.states[stateNumber].isLeftRecursiveRule = true;\n\t\t}\n\t}\n\treadRules(atn) {\n\t\tlet i;\n\t\tconst ruleCount = this.data[this.pos++];\n\t\tif (atn.grammarType === ATN.LEXER) {\n\t\t\tatn.ruleToTokenType = new Array(ruleCount);\n\t\t\tatn.ruleToTokenType.fill(0);\n\t\t}\n\t\tatn.ruleToStartState = new Array(ruleCount);\n\t\tatn.ruleToStartState.fill(null);\n\t\tfor (i = 0; i < ruleCount; i++) {\n\t\t\tconst s = this.data[this.pos++];\n\t\t\tatn.ruleToStartState[i] = atn.states[s];\n\t\t\tif (atn.grammarType === ATN.LEXER) {\n\t\t\t\tconst tokenType = this.data[this.pos++];\n\t\t\t\tatn.ruleToTokenType[i] = tokenType;\n\t\t\t}\n\t\t}\n\t\tatn.ruleToStopState = new Array(ruleCount);\n\t\tatn.ruleToStopState.fill(null);\n\t\tfor (i = 0; i < atn.states.length; i++) {\n\t\t\tconst state = atn.states[i];\n\t\t\tif (!(state instanceof RuleStopState)) continue;\n\t\t\tatn.ruleToStopState[state.ruleIndex] = state;\n\t\t\tatn.ruleToStartState[state.ruleIndex].stopState = state;\n\t\t}\n\t}\n\treadModes(atn) {\n\t\tconst modeCount = this.data[this.pos++];\n\t\tfor (let i = 0; i < modeCount; i++) {\n\t\t\tconst s = this.data[this.pos++];\n\t\t\tatn.modeToStartState.push(atn.states[s]);\n\t\t}\n\t}\n\treadSets(atn, sets) {\n\t\tconst m2 = this.data[this.pos++];\n\t\tfor (let i = 0; i < m2; i++) {\n\t\t\tconst intervalSet = new IntervalSet();\n\t\t\tsets.push(intervalSet);\n\t\t\tconst n2 = this.data[this.pos++];\n\t\t\tif (this.data[this.pos++] !== 0) intervalSet.addOne(-1);\n\t\t\tfor (let j = 0; j < n2; j++) {\n\t\t\t\tconst i1 = this.data[this.pos++];\n\t\t\t\tconst i2 = this.data[this.pos++];\n\t\t\t\tintervalSet.addRange(i1, i2);\n\t\t\t}\n\t\t}\n\t}\n\treadEdges(atn, sets) {\n\t\tlet i;\n\t\tlet j;\n\t\tlet state;\n\t\tlet trans;\n\t\tlet target;\n\t\tconst edgeCount = this.data[this.pos++];\n\t\tfor (i = 0; i < edgeCount; i++) {\n\t\t\tconst src = this.data[this.pos++];\n\t\t\tconst trg = this.data[this.pos++];\n\t\t\tconst ttype = this.data[this.pos++];\n\t\t\tconst arg1 = this.data[this.pos++];\n\t\t\tconst arg2 = this.data[this.pos++];\n\t\t\tconst arg3 = this.data[this.pos++];\n\t\t\ttrans = this.edgeFactory(atn, ttype, trg, arg1, arg2, arg3, sets);\n\t\t\tatn.states[src].addTransition(trans);\n\t\t}\n\t\tfor (i = 0; i < atn.states.length; i++) {\n\t\t\tstate = atn.states[i];\n\t\t\tfor (j = 0; j < state.transitions.length; j++) {\n\t\t\t\tconst t = state.transitions[j];\n\t\t\t\tif (!(t instanceof RuleTransition)) continue;\n\t\t\t\tlet outermostPrecedenceReturn = -1;\n\t\t\t\tif (atn.ruleToStartState[t.target.ruleIndex].isLeftRecursiveRule) {\n\t\t\t\t\tif (t.precedence === 0) outermostPrecedenceReturn = t.target.ruleIndex;\n\t\t\t\t}\n\t\t\t\ttrans = new EpsilonTransition(t.followState, outermostPrecedenceReturn);\n\t\t\t\tatn.ruleToStopState[t.target.ruleIndex].addTransition(trans);\n\t\t\t}\n\t\t}\n\t\tfor (i = 0; i < atn.states.length; i++) {\n\t\t\tstate = atn.states[i];\n\t\t\tif (state instanceof BlockStartState) {\n\t\t\t\tif (!state.endState) throw new Error(\"IllegalState\");\n\t\t\t\tif (state.endState.startState) throw new Error(\"IllegalState\");\n\t\t\t\tstate.endState.startState = state;\n\t\t\t}\n\t\t\tif (state instanceof PlusLoopbackState) for (j = 0; j < state.transitions.length; j++) {\n\t\t\t\ttarget = state.transitions[j].target;\n\t\t\t\tif (target instanceof PlusBlockStartState) target.loopBackState = state;\n\t\t\t}\n\t\t\telse if (state instanceof StarLoopbackState) for (j = 0; j < state.transitions.length; j++) {\n\t\t\t\ttarget = state.transitions[j].target;\n\t\t\t\tif (target instanceof StarLoopEntryState) target.loopBackState = state;\n\t\t\t}\n\t\t}\n\t}\n\treadDecisions(atn) {\n\t\tconst decisionCount = this.data[this.pos++];\n\t\tfor (let i = 0; i < decisionCount; i++) {\n\t\t\tconst s = this.data[this.pos++];\n\t\t\tconst decState = atn.states[s];\n\t\t\tatn.decisionToState.push(decState);\n\t\t\tdecState.decision = i;\n\t\t}\n\t}\n\treadLexerActions(atn) {\n\t\tif (atn.grammarType === ATN.LEXER) {\n\t\t\tconst count = this.data[this.pos++];\n\t\t\tatn.lexerActions = [];\n\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\tconst actionType = this.data[this.pos++];\n\t\t\t\tconst data1 = this.data[this.pos++];\n\t\t\t\tconst data2 = this.data[this.pos++];\n\t\t\t\tatn.lexerActions.push(this.lexerActionFactory(actionType, data1, data2));\n\t\t\t}\n\t\t}\n\t}\n\tgenerateRuleBypassTransitions(atn) {\n\t\tlet i;\n\t\tconst count = atn.ruleToStartState.length;\n\t\tfor (i = 0; i < count; i++) atn.ruleToTokenType[i] = atn.maxTokenType + i + 1;\n\t\tfor (i = 0; i < count; i++) this.generateRuleBypassTransition(atn, i);\n\t}\n\tgenerateRuleBypassTransition(atn, idx) {\n\t\tlet i;\n\t\tlet state;\n\t\tconst bypassStart = new BasicBlockStartState();\n\t\tbypassStart.ruleIndex = idx;\n\t\tatn.addState(bypassStart);\n\t\tconst bypassStop = new BlockEndState();\n\t\tbypassStop.ruleIndex = idx;\n\t\tatn.addState(bypassStop);\n\t\tbypassStart.endState = bypassStop;\n\t\tatn.defineDecisionState(bypassStart);\n\t\tbypassStop.startState = bypassStart;\n\t\tlet excludeTransition = null;\n\t\tlet endState = null;\n\t\tif (atn.ruleToStartState[idx].isLeftRecursiveRule) {\n\t\t\tendState = null;\n\t\t\tfor (i = 0; i < atn.states.length; i++) {\n\t\t\t\tstate = atn.states[i];\n\t\t\t\tif (this.stateIsEndStateFor(state, idx)) {\n\t\t\t\t\tendState = state;\n\t\t\t\t\texcludeTransition = state.loopBackState.transitions[0];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (excludeTransition === null) throw new Error(\"Couldn't identify final state of the precedence rule prefix section.\");\n\t\t} else endState = atn.ruleToStopState[idx];\n\t\tfor (i = 0; i < atn.states.length; i++) {\n\t\t\tstate = atn.states[i];\n\t\t\tfor (const transition of state.transitions) {\n\t\t\t\tif (transition === excludeTransition) continue;\n\t\t\t\tif (transition.target === endState) transition.target = bypassStop;\n\t\t\t}\n\t\t}\n\t\tconst ruleToStartState = atn.ruleToStartState[idx];\n\t\twhile (ruleToStartState.transitions.length > 0) {\n\t\t\tconst transition = ruleToStartState.removeTransition(ruleToStartState.transitions.length - 1);\n\t\t\tbypassStart.addTransition(transition);\n\t\t}\n\t\tatn.ruleToStartState[idx].addTransition(new EpsilonTransition(bypassStart));\n\t\tif (endState) bypassStop.addTransition(new EpsilonTransition(endState));\n\t\tconst matchState = new BasicState();\n\t\tatn.addState(matchState);\n\t\tmatchState.addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[idx]));\n\t\tbypassStart.addTransition(new EpsilonTransition(matchState));\n\t}\n\tstateIsEndStateFor(state, idx) {\n\t\tif (state.ruleIndex !== idx) return null;\n\t\tif (!(state instanceof StarLoopEntryState)) return null;\n\t\tconst maybeLoopEndState = state.transitions[state.transitions.length - 1].target;\n\t\tif (!(maybeLoopEndState instanceof LoopEndState)) return null;\n\t\tif (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transitions[0].target instanceof RuleStopState) return state;\n\t\telse return null;\n\t}\n\t/**\n\t* Analyze the {@link StarLoopEntryState} states in the specified ATN to set\n\t* the {@link StarLoopEntryState} field to the correct value.\n\t*\n\t* @param atn The ATN.\n\t*/\n\tmarkPrecedenceDecisions(atn) {\n\t\tfor (const state of atn.states) {\n\t\t\tif (!(state instanceof StarLoopEntryState)) continue;\n\t\t\tif (atn.ruleToStartState[state.ruleIndex].isLeftRecursiveRule) {\n\t\t\t\tconst maybeLoopEndState = state.transitions[state.transitions.length - 1].target;\n\t\t\t\tif (maybeLoopEndState instanceof LoopEndState) {\n\t\t\t\t\tif (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transitions[0].target instanceof RuleStopState) state.precedenceRuleDecision = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tverifyATN(atn) {\n\t\tif (!this.deserializationOptions.verifyATN) return;\n\t\tfor (const state of atn.states) {\n\t\t\tif (state === null) continue;\n\t\t\tthis.checkCondition(state.epsilonOnlyTransitions || state.transitions.length <= 1);\n\t\t\tif (state instanceof PlusBlockStartState) this.checkCondition(state.loopBackState !== null);\n\t\t\telse if (state instanceof StarLoopEntryState) {\n\t\t\t\tthis.checkCondition(state.loopBackState !== null);\n\t\t\t\tthis.checkCondition(state.transitions.length === 2);\n\t\t\t\tif (state.transitions[0].target instanceof StarBlockStartState) {\n\t\t\t\t\tthis.checkCondition(state.transitions[1].target instanceof LoopEndState);\n\t\t\t\t\tthis.checkCondition(!state.nonGreedy);\n\t\t\t\t} else if (state.transitions[0].target instanceof LoopEndState) {\n\t\t\t\t\tthis.checkCondition(state.transitions[1].target instanceof StarBlockStartState);\n\t\t\t\t\tthis.checkCondition(state.nonGreedy);\n\t\t\t\t} else throw new Error(\"IllegalState\");\n\t\t\t} else if (state instanceof StarLoopbackState) {\n\t\t\t\tthis.checkCondition(state.transitions.length === 1);\n\t\t\t\tthis.checkCondition(state.transitions[0].target instanceof StarLoopEntryState);\n\t\t\t} else if (state instanceof LoopEndState) this.checkCondition(state.loopBackState !== null);\n\t\t\telse if (state instanceof RuleStartState) this.checkCondition(state.stopState !== null);\n\t\t\telse if (state instanceof BlockStartState) this.checkCondition(state.endState !== null);\n\t\t\telse if (state instanceof BlockEndState) this.checkCondition(state.startState !== null);\n\t\t\telse if (state instanceof DecisionState) this.checkCondition(state.transitions.length <= 1 || state.decision >= 0);\n\t\t\telse this.checkCondition(state.transitions.length <= 1 || state instanceof RuleStopState);\n\t\t}\n\t}\n\tcheckCondition(condition, message) {\n\t\tif (!condition) {\n\t\t\tif (message === void 0 || message === null) message = \"IllegalState\";\n\t\t\tthrow message;\n\t\t}\n\t}\n\tedgeFactory(atn, type, trg, arg1, arg2, arg3, sets) {\n\t\tconst target = atn.states[trg];\n\t\tswitch (type) {\n\t\t\tcase Transition.EPSILON: return new EpsilonTransition(target);\n\t\t\tcase Transition.RANGE: return arg3 !== 0 ? new RangeTransition(target, Token.EOF, arg2) : new RangeTransition(target, arg1, arg2);\n\t\t\tcase Transition.RULE: return new RuleTransition(atn.states[arg1], arg2, arg3, target);\n\t\t\tcase Transition.PREDICATE: return new PredicateTransition(target, arg1, arg2, arg3 !== 0);\n\t\t\tcase Transition.PRECEDENCE: return new PrecedencePredicateTransition(target, arg1);\n\t\t\tcase Transition.ATOM: return arg3 !== 0 ? new AtomTransition(target, Token.EOF) : new AtomTransition(target, arg1);\n\t\t\tcase Transition.ACTION: return new ActionTransition(target, arg1, arg2, arg3 !== 0);\n\t\t\tcase Transition.SET: return new SetTransition(target, sets[arg1]);\n\t\t\tcase Transition.NOT_SET: return new NotSetTransition(target, sets[arg1]);\n\t\t\tcase Transition.WILDCARD: return new WildcardTransition(target);\n\t\t\tdefault: throw new Error(\"The specified transition type: \" + type + \" is not valid.\");\n\t\t}\n\t}\n\tstateFactory(type, ruleIndex) {\n\t\tconst ctor = _ATNDeserializer.stateTypeMapper.get(type);\n\t\tif (!ctor) throw new Error(\"The specified state type \" + type + \" is not valid.\");\n\t\tconst s = new ctor();\n\t\ts.ruleIndex = ruleIndex;\n\t\treturn s;\n\t}\n\tlexerActionFactory(type, data1, data2) {\n\t\tconst factory = _ATNDeserializer.lexerActionFactoryMapper.get(type);\n\t\tif (!factory) throw new Error(\"The specified lexer action type \" + type + \" is not valid.\");\n\t\treturn factory(data1, data2);\n\t}\n};\nvar OrderedHashMap = class _OrderedHashMap extends HashMap {\n\tstatic {\n\t\t__name(this, \"OrderedHashMap\");\n\t}\n\t#keys = [];\n\tclear() {\n\t\tsuper.clear();\n\t\tthis.#keys = [];\n\t}\n\tget(key) {\n\t\treturn super.get(key);\n\t}\n\tset(key, value) {\n\t\tconst result = super.set(key, value);\n\t\tif (result === void 0) this.#keys.push(key);\n\t\treturn result;\n\t}\n\tsetIfAbsent(key, value) {\n\t\tconst result = super.setIfAbsent(key, value);\n\t\tif (result === void 0) this.#keys.push(key);\n\t\treturn result;\n\t}\n\t/**\n\t* @returns an iterable of the values in the map, in the order they were inserted.\n\t*/\n\tvalues() {\n\t\treturn { [Symbol.iterator]: () => {\n\t\t\tlet index = 0;\n\t\t\treturn { next: /* @__PURE__ */ __name(() => {\n\t\t\t\tif (index < this.#keys.length) return {\n\t\t\t\t\tdone: false,\n\t\t\t\t\tvalue: super.get(this.#keys[index++])\n\t\t\t\t};\n\t\t\t\treturn {\n\t\t\t\t\tdone: true,\n\t\t\t\t\tvalue: void 0\n\t\t\t\t};\n\t\t\t}, \"next\") };\n\t\t} };\n\t}\n\t/**\n\t* @returns an iterable of the keys in the map, in the order they were inserted.\n\t*/\n\tkeys() {\n\t\treturn this.#keys[Symbol.iterator]();\n\t}\n\tequals(o) {\n\t\tif (!(o instanceof _OrderedHashMap)) return false;\n\t\treturn super.equals(o);\n\t}\n};\nvar ATNSerializer = class _ATNSerializer {\n\tstatic {\n\t\t__name(this, \"ATNSerializer\");\n\t}\n\tatn;\n\tdata = [];\n\tsets = new OrderedHashMap(ObjectEqualityComparator.instance);\n\tnonGreedyStates = [];\n\tprecedenceStates = [];\n\tconstructor(atn) {\n\t\tthis.atn = atn;\n\t}\n\tstatic getSerialized(atn) {\n\t\treturn new _ATNSerializer(atn).serialize();\n\t}\n\tstatic serializeSets(data, sets) {\n\t\tdata.push(sets.length);\n\t\tfor (const set of sets) {\n\t\t\tconst containsEof = set.contains(Token.EOF);\n\t\t\tconst intervals = [...set];\n\t\t\tif (containsEof && intervals[0].stop === Token.EOF) data.push(intervals.length - 1);\n\t\t\telse data.push(intervals.length);\n\t\t\tdata.push(containsEof ? 1 : 0);\n\t\t\tfor (const interval of intervals) {\n\t\t\t\tif (interval.start === Token.EOF) if (interval.stop === Token.EOF) continue;\n\t\t\t\telse data.push(0);\n\t\t\t\telse data.push(interval.start);\n\t\t\t\tdata.push(interval.stop);\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t* Serialize state descriptors, edge descriptors, and decision -> state map\n\t*  into list of ints.  Likely out of date, but keeping as it could be helpful:\n\t*\n\t*      SERIALIZED_VERSION\n\t*      UUID (2 longs)\n\t* \t\tgrammar-type, (ANTLRParser.LEXER, ...)\n\t*  \tmax token type,\n\t*  \tnum states,\n\t*  \tstate-0-type ruleIndex, state-1-type ruleIndex, ... state-i-type ruleIndex optional-arg ...\n\t*  \tnum rules,\n\t*  \trule-1-start-state rule-1-args, rule-2-start-state  rule-2-args, ...\n\t*  \t(args are token type,actionIndex in lexer else 0,0)\n\t*      num modes,\n\t*      mode-0-start-state, mode-1-start-state, ... (parser has 0 modes)\n\t*      num unicode-bmp-sets\n\t*      bmp-set-0-interval-count intervals, bmp-set-1-interval-count intervals, ...\n\t*      num unicode-smp-sets\n\t*      smp-set-0-interval-count intervals, smp-set-1-interval-count intervals, ...\n\t*\tnum total edges,\n\t*      src, trg, edge-type, edge arg1, optional edge arg2 (present always), ...\n\t*      num decisions,\n\t*      decision-0-start-state, decision-1-start-state, ...\n\t*\n\t*  Convenient to pack into unsigned shorts to make as Java string.\n\t*/\n\tserialize() {\n\t\tthis.addPreamble();\n\t\tconst edgeCount = this.addEdges();\n\t\tthis.addNonGreedyStates();\n\t\tthis.addPrecedenceStates();\n\t\tthis.addRuleStatesAndLexerTokenTypes();\n\t\tthis.addModeStartStates();\n\t\tconst setIndices = this.addSets();\n\t\tthis.addEdges(edgeCount, setIndices);\n\t\tthis.addDecisionStartStates();\n\t\tthis.addLexerActions();\n\t\treturn this.data;\n\t}\n\taddPreamble() {\n\t\tthis.data.push(ATNDeserializer.SERIALIZED_VERSION);\n\t\tthis.data.push(this.atn.grammarType);\n\t\tthis.data.push(this.atn.maxTokenType);\n\t}\n\taddLexerActions() {\n\t\tif (this.atn.grammarType === ATN.LEXER) {\n\t\t\tthis.data.push(this.atn.lexerActions.length);\n\t\t\tfor (const action of this.atn.lexerActions) {\n\t\t\t\tthis.data.push(action.actionType);\n\t\t\t\tswitch (action.actionType) {\n\t\t\t\t\tcase LexerActionType.CHANNEL: {\n\t\t\t\t\t\tconst channel = action.channel;\n\t\t\t\t\t\tthis.data.push(channel);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase LexerActionType.CUSTOM: {\n\t\t\t\t\t\tconst ruleIndex = action.ruleIndex;\n\t\t\t\t\t\tconst actionIndex = action.actionIndex;\n\t\t\t\t\t\tthis.data.push(ruleIndex);\n\t\t\t\t\t\tthis.data.push(actionIndex);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase LexerActionType.MODE: {\n\t\t\t\t\t\tconst mode = action.mode;\n\t\t\t\t\t\tthis.data.push(mode);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase LexerActionType.MORE:\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase LexerActionType.POP_MODE:\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase LexerActionType.PUSH_MODE: {\n\t\t\t\t\t\tconst mode = action.mode;\n\t\t\t\t\t\tthis.data.push(mode);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase LexerActionType.SKIP:\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase LexerActionType.TYPE: {\n\t\t\t\t\t\tconst type = action.type;\n\t\t\t\t\t\tthis.data.push(type);\n\t\t\t\t\t\tthis.data.push(0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: throw new Error(`The specified lexer action type ${action.actionType} is not valid.`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\taddDecisionStartStates() {\n\t\tthis.data.push(this.atn.decisionToState.length);\n\t\tfor (const decStartState of this.atn.decisionToState) this.data.push(decStartState.stateNumber);\n\t}\n\taddEdges(...args) {\n\t\tswitch (args.length) {\n\t\t\tcase 0: {\n\t\t\t\tlet edgeCount = 0;\n\t\t\t\tthis.data.push(this.atn.states.length);\n\t\t\t\tfor (const s of this.atn.states) {\n\t\t\t\t\tif (s === null) {\n\t\t\t\t\t\tthis.data.push(ATNState.INVALID_TYPE);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst stateType = s.constructor.stateType;\n\t\t\t\t\tif (s instanceof DecisionState && s.nonGreedy) this.nonGreedyStates.push(s.stateNumber);\n\t\t\t\t\tif (s instanceof RuleStartState && s.isLeftRecursiveRule) this.precedenceStates.push(s.stateNumber);\n\t\t\t\t\tthis.data.push(stateType);\n\t\t\t\t\tthis.data.push(s.ruleIndex);\n\t\t\t\t\tif (s.constructor.stateType === ATNState.LOOP_END) this.data.push(s.loopBackState.stateNumber);\n\t\t\t\t\telse if (s instanceof BlockStartState) this.data.push(s.endState.stateNumber);\n\t\t\t\t\tif (s.constructor.stateType !== ATNState.RULE_STOP) edgeCount += s.transitions.length;\n\t\t\t\t\tfor (const t of s.transitions) {\n\t\t\t\t\t\tconst edgeType = t.transitionType;\n\t\t\t\t\t\tif (edgeType === Transition.SET || edgeType === Transition.NOT_SET) {\n\t\t\t\t\t\t\tconst st = t;\n\t\t\t\t\t\t\tthis.sets.set(st.set, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn edgeCount;\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\tconst [edgeCount, setIndices] = args;\n\t\t\t\tthis.data.push(edgeCount);\n\t\t\t\tfor (const s of this.atn.states) {\n\t\t\t\t\tif (s === null) continue;\n\t\t\t\t\tif (s.constructor.stateType === ATNState.RULE_STOP) continue;\n\t\t\t\t\tfor (const t of s.transitions) {\n\t\t\t\t\t\tif (this.atn.states[t.target.stateNumber] === null) throw new Error(\"Cannot serialize a transition to a removed state.\");\n\t\t\t\t\t\tconst src = s.stateNumber;\n\t\t\t\t\t\tlet trg = t.target.stateNumber;\n\t\t\t\t\t\tconst edgeType = t.transitionType;\n\t\t\t\t\t\tlet arg1 = 0;\n\t\t\t\t\t\tlet arg2 = 0;\n\t\t\t\t\t\tlet arg3 = 0;\n\t\t\t\t\t\tswitch (edgeType) {\n\t\t\t\t\t\t\tcase Transition.RULE:\n\t\t\t\t\t\t\t\ttrg = t.followState.stateNumber;\n\t\t\t\t\t\t\t\targ1 = t.target.stateNumber;\n\t\t\t\t\t\t\t\targ2 = t.ruleIndex;\n\t\t\t\t\t\t\t\targ3 = t.precedence;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase Transition.PRECEDENCE:\n\t\t\t\t\t\t\t\targ1 = t.precedence;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase Transition.PREDICATE: {\n\t\t\t\t\t\t\t\tconst pt = t;\n\t\t\t\t\t\t\t\targ1 = pt.ruleIndex;\n\t\t\t\t\t\t\t\targ2 = pt.predIndex;\n\t\t\t\t\t\t\t\targ3 = pt.isCtxDependent ? 1 : 0;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase Transition.RANGE:\n\t\t\t\t\t\t\t\targ1 = t.start;\n\t\t\t\t\t\t\t\targ2 = t.stop;\n\t\t\t\t\t\t\t\tif (arg1 === Token.EOF) {\n\t\t\t\t\t\t\t\t\targ1 = 0;\n\t\t\t\t\t\t\t\t\targ3 = 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase Transition.ATOM:\n\t\t\t\t\t\t\t\targ1 = t.labelValue;\n\t\t\t\t\t\t\t\tif (arg1 === Token.EOF) {\n\t\t\t\t\t\t\t\t\targ1 = 0;\n\t\t\t\t\t\t\t\t\targ3 = 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase Transition.ACTION: {\n\t\t\t\t\t\t\t\tconst at = t;\n\t\t\t\t\t\t\t\targ1 = at.ruleIndex;\n\t\t\t\t\t\t\t\targ2 = at.actionIndex;\n\t\t\t\t\t\t\t\targ3 = at.isCtxDependent ? 1 : 0;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcase Transition.SET:\n\t\t\t\t\t\t\t\targ1 = setIndices.get(t.set);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase Transition.NOT_SET:\n\t\t\t\t\t\t\t\targ1 = setIndices.get(t.set);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase Transition.WILDCARD: break;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.data.push(src);\n\t\t\t\t\t\tthis.data.push(trg);\n\t\t\t\t\t\tthis.data.push(edgeType);\n\t\t\t\t\t\tthis.data.push(arg1);\n\t\t\t\t\t\tthis.data.push(arg2);\n\t\t\t\t\t\tthis.data.push(arg3);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: throw new Error(\"Invalid number of arguments\");\n\t\t}\n\t}\n\taddSets() {\n\t\t_ATNSerializer.serializeSets(this.data, [...this.sets.keys()]);\n\t\tconst setIndices = new HashMap();\n\t\tlet setIndex = 0;\n\t\tfor (const s of this.sets.keys()) setIndices.set(s, setIndex++);\n\t\treturn setIndices;\n\t}\n\taddModeStartStates() {\n\t\tconst modeCount = this.atn.modeToStartState.length;\n\t\tthis.data.push(modeCount);\n\t\tif (modeCount > 0) for (const modeStartState of this.atn.modeToStartState) this.data.push(modeStartState.stateNumber);\n\t}\n\taddRuleStatesAndLexerTokenTypes() {\n\t\tconst ruleCount = this.atn.ruleToStartState.length;\n\t\tthis.data.push(ruleCount);\n\t\tfor (let r = 0; r < ruleCount; r++) {\n\t\t\tconst ruleStartState = this.atn.ruleToStartState[r];\n\t\t\tthis.data.push(ruleStartState.stateNumber);\n\t\t\tif (this.atn.grammarType === ATN.LEXER) this.data.push(this.atn.ruleToTokenType[r]);\n\t\t}\n\t}\n\taddPrecedenceStates() {\n\t\tthis.data.push(this.precedenceStates.length);\n\t\tfor (const state of this.precedenceStates) this.data.push(state);\n\t}\n\taddNonGreedyStates() {\n\t\tthis.data.push(this.nonGreedyStates.length);\n\t\tfor (const state of this.nonGreedyStates) this.data.push(state);\n\t}\n};\nvar DFAState = class _DFAState {\n\tstatic {\n\t\t__name(this, \"DFAState\");\n\t}\n\tstateNumber = -1;\n\tconfigs;\n\t/**\n\t* `edges[symbol]` points to target of symbol. Shift up by 1 so (-1) {@link Token.EOF} maps to `edges[0]`.\n\t*/\n\tedges = [];\n\tisAcceptState = false;\n\t/**\n\t* If accept state, what ttype do we match or alt do we predict? This is set to {@link ATN.INVALID_ALT_NUMBER}\n\t* when {@link predicates} `!= null` or {@link requiresFullContext}.\n\t*/\n\tprediction = -1;\n\tlexerActionExecutor = null;\n\t/**\n\t* Indicates that this state was created during SLL prediction that discovered a conflict between the configurations\n\t* in the state. Future {@link ParserATNSimulator.execATN} invocations immediately jumped doing\n\t* full context prediction if this field is true.\n\t*/\n\trequiresFullContext = false;\n\t/**\n\t* During SLL parsing, this is a list of predicates associated with the ATN configurations of the DFA state.\n\t* When we have predicates, {@link requiresFullContext} is `false` since full context prediction evaluates\n\t* predicates on-the-fly. If this is not null, then {@link prediction} is `ATN.INVALID_ALT_NUMBER`.\n\t*\n\t* We only use these for non-{@link #requiresFullContext} but conflicting states. That\n\t* means we know from the context (it's $ or we don't dip into outer\n\t* context) that it's an ambiguity not a conflict.\n\t*\n\t* This list is computed by {@link ParserATNSimulator#predicateDFAState}.\n\t*/\n\tpredicates = null;\n\tconstructor(configs) {\n\t\tif (configs) this.configs = configs;\n\t}\n\tstatic fromState(stateNumber) {\n\t\tconst result = new _DFAState();\n\t\tresult.stateNumber = stateNumber;\n\t\treturn result;\n\t}\n\tstatic fromConfigs(configs) {\n\t\treturn new _DFAState(configs);\n\t}\n\tstatic hashCode(state) {\n\t\treturn state.configs.hashCode();\n\t}\n\t/**\n\t* Two {@link DFAState} instances are equal if their ATN configuration sets\n\t* are the same. This method is used to see if a state already exists.\n\t*\n\t* Because the number of alternatives and number of ATN configurations are\n\t* finite, there is a finite number of DFA states that can be processed.\n\t* This is necessary to show that the algorithm terminates.\n\t*\n\t* Cannot test the DFA state numbers here because in\n\t* {@link ParserATNSimulator#addDFAState} we need to know if any other state\n\t* exists that has this exact set of ATN configurations. The\n\t* {@link #stateNumber} is irrelevant.\n\t*\n\t* @param a The first {@link DFAState}.\n\t* @param b The second {@link DFAState}.\n\t*\n\t* @returns `true` if the two states are equal, otherwise `false`.\n\t*/\n\tstatic equals(a, b) {\n\t\treturn a.configs.equals(b.configs);\n\t}\n\t/**\n\t* @returns the set of all alts mentioned by all ATN configurations in this DFA state.\n\t*/\n\tgetAltSet() {\n\t\tconst alts = /* @__PURE__ */ new Set();\n\t\tfor (const config of this.configs) alts.add(config.alt);\n\t\tif (alts.size === 0) return null;\n\t\treturn alts;\n\t}\n\ttoString() {\n\t\tlet buf = \"\";\n\t\tbuf += this.stateNumber;\n\t\tbuf += \":\";\n\t\tbuf += this.configs ? this.configs.toString() : \"\";\n\t\tif (this.isAcceptState) {\n\t\t\tbuf += \"=>\";\n\t\t\tif (this.predicates) buf += arrayToString(this.predicates);\n\t\t\telse buf += this.prediction;\n\t\t}\n\t\treturn buf.toString();\n\t}\n};\nvar ATNSimulator = class {\n\tstatic {\n\t\t__name(this, \"ATNSimulator\");\n\t}\n\t/** Must distinguish between missing edge and edge we know leads nowhere */\n\tstatic ERROR = DFAState.fromState(2147483647);\n\tatn;\n\t/**\n\t* The context cache maps all PredictionContext objects that are ==\n\t* to a single cached copy. This cache is shared across all contexts\n\t* in all ATNConfigs in all DFA states.  We rebuild each ATNConfigSet\n\t* to use only cached nodes/graphs in addDFAState(). We don't want to\n\t* fill this during closure() since there are lots of contexts that\n\t* pop up but are not used ever again. It also greatly slows down closure().\n\t*\n\t* This cache makes a huge difference in memory and a little bit in speed.\n\t* For the Java grammar on java.*, it dropped the memory requirements\n\t* at the end from 25M to 16M. We don't store any of the full context\n\t* graphs in the DFA because they are limited to local context only,\n\t* but apparently there's a lot of repetition there as well. We optimize\n\t* the config contexts before storing the config set in the DFA states\n\t* by literally rebuilding them with cached subgraphs only.\n\t*\n\t* I tried a cache for use during closure operations, that was\n\t* whacked after each adaptivePredict(). It cost a little bit\n\t* more time I think and doesn't save on the overall footprint\n\t* so it's not worth the complexity.\n\t*/\n\tsharedContextCache;\n\tconstructor(atn, sharedContextCache) {\n\t\tthis.atn = atn;\n\t\tthis.sharedContextCache = sharedContextCache;\n\t\treturn this;\n\t}\n\tgetCachedContext(context) {\n\t\tif (!this.sharedContextCache) return context;\n\t\tconst visited = new HashMap(ObjectEqualityComparator.instance);\n\t\treturn getCachedPredictionContext(context, this.sharedContextCache, visited);\n\t}\n};\nvar CodePointTransitions = class _CodePointTransitions {\n\tstatic {\n\t\t__name(this, \"CodePointTransitions\");\n\t}\n\t/** @returns new {@link AtomTransition}     */\n\tstatic createWithCodePoint(target, codePoint) {\n\t\treturn _CodePointTransitions.createWithCodePointRange(target, codePoint, codePoint);\n\t}\n\t/** @returns new {@link AtomTransition} if range represents one atom else {@link SetTransition}. */\n\tstatic createWithCodePointRange(target, codePointFrom, codePointTo) {\n\t\treturn codePointFrom === codePointTo ? new AtomTransition(target, codePointFrom) : new RangeTransition(target, codePointFrom, codePointTo);\n\t}\n};\nvar DecisionInfo = class {\n\tstatic {\n\t\t__name(this, \"DecisionInfo\");\n\t}\n\t/**\n\t* The decision number, which is an index into {@link ATN.decisionToState}.\n\t*/\n\tdecision = 0;\n\t/**\n\t* The total number of times {@link ParserATNSimulator.adaptivePredict} was\n\t* invoked for this decision.\n\t*/\n\tinvocations = 0;\n\t/**\n\t* The total time spent in {@link ParserATNSimulator.adaptivePredict} for\n\t* this decision, in nanoseconds.\n\t*\n\t* The value of this field contains the sum of differential results obtained\n\t* by {@link process.hrtime()}, and is not adjusted to compensate for JIT\n\t* and/or garbage collection overhead. For best accuracy, use a modern Node.js\n\t* version that provides precise results from {@link process.hrtime()}, and\n\t* perform profiling in a separate process which is warmed up by parsing the\n\t* input prior to profiling.\n\t*/\n\ttimeInPrediction = 0;\n\t/**\n\t* The sum of the lookahead required for SLL prediction for this decision.\n\t* Note that SLL prediction is used before LL prediction for performance\n\t* reasons even when {@link PredictionMode.LL} or\n\t* {@link PredictionMode.LL_EXACT_AMBIG_DETECTION} is used.\n\t*/\n\tsllTotalLook = 0;\n\t/**\n\t* Gets the minimum lookahead required for any single SLL prediction to\n\t* complete for this decision, by reaching a unique prediction, reaching an\n\t* SLL conflict state, or encountering a syntax error.\n\t*/\n\tsllMinLook = 0;\n\t/**\n\t* Gets the maximum lookahead required for any single SLL prediction to\n\t* complete for this decision, by reaching a unique prediction, reaching an\n\t* SLL conflict state, or encountering a syntax error.\n\t*/\n\tsllMaxLook = 0;\n\t/**\n\t* Gets the {@link LookaheadEventInfo} associated with the event where the\n\t* {@link sllMaxLook} value was set.\n\t*/\n\tsllMaxLookEvent;\n\t/**\n\t* The sum of the lookahead required for LL prediction for this decision.\n\t* Note that LL prediction is only used when SLL prediction reaches a\n\t* conflict state.\n\t*/\n\tllTotalLook = 0;\n\t/**\n\t* Gets the minimum lookahead required for any single LL prediction to\n\t* complete for this decision. An LL prediction completes when the algorithm\n\t* reaches a unique prediction, a conflict state (for\n\t* {@link PredictionMode.LL}, an ambiguity state (for\n\t* {@link PredictionMode.LL_EXACT_AMBIG_DETECTION}, or a syntax error.\n\t*/\n\tllMinLook = 0;\n\t/**\n\t* Gets the maximum lookahead required for any single LL prediction to\n\t* complete for this decision. An LL prediction completes when the algorithm\n\t* reaches a unique prediction, a conflict state (for\n\t* {@link PredictionMode.LL}, an ambiguity state (for\n\t* {@link PredictionMode.LL_EXACT_AMBIG_DETECTION}, or a syntax error.\n\t*/\n\tllMaxLook = 0;\n\t/**\n\t* Gets the {@link LookaheadEventInfo} associated with the event where the\n\t* {@link llMaxLook} value was set.\n\t*/\n\tllMaxLookEvent;\n\t/**\n\t* A collection of {@link ContextSensitivityInfo} instances describing the\n\t* context sensitivities encountered during LL prediction for this decision.\n\t*/\n\tcontextSensitivities;\n\t/**\n\t* A collection of {@link DecisionEventInfo} instances describing the parse errors\n\t* identified during calls to {@link ParserATNSimulator.adaptivePredict} for\n\t* this decision.\n\t*/\n\terrors;\n\t/**\n\t* A collection of {@link AmbiguityInfo} instances describing the\n\t* ambiguities encountered during LL prediction for this decision.\n\t*/\n\tambiguities;\n\t/**\n\t* A collection of {@link PredicateEvalInfo} instances describing the\n\t* results of evaluating individual predicates during prediction for this\n\t* decision.\n\t*/\n\tpredicateEvals;\n\t/**\n\t* The total number of ATN transitions required during SLL prediction for\n\t* this decision. An ATN transition is determined by the number of times the\n\t* DFA does not contain an edge that is required for prediction, resulting\n\t* in on-the-fly computation of that edge.\n\t/**\n\t* If DFA caching of SLL transitions is employed by the implementation, ATN\n\t* computation may cache the computed edge for efficient lookup during\n\t* future parsing of this decision. Otherwise, the SLL parsing algorithm\n\t* will use ATN transitions exclusively.\n\t*\n\t* @see sllDFATransitions\n\t* @see ParserATNSimulator.computeTargetState\n\t* @see LexerATNSimulator.computeTargetState\n\t*/\n\tsllATNTransitions = 0;\n\t/**\n\t* The total number of DFA transitions required during SLL prediction for\n\t* this decision.\n\t*\n\t* If the ATN simulator implementation does not use DFA caching for SLL\n\t* transitions, this value will be 0.\n\t*\n\t* @see ParserATNSimulator.getExistingTargetState\n\t* @see LexerATNSimulator.getExistingTargetState\n\t*/\n\tsllDFATransitions = 0;\n\t/**\n\t* Gets the total number of times SLL prediction completed in a conflict\n\t* state, resulting in fallback to LL prediction.\n\t*\n\t* Note that this value is not related to whether or not\n\t* {@link PredictionMode.SLL} may be used successfully with a particular\n\t* grammar. If the ambiguity resolution algorithm applied to the SLL\n\t* conflicts for this decision produce the same result as LL prediction for\n\t* this decision, {@link PredictionMode.SLL} would produce the same overall\n\t* parsing result as {@link PredictionMode.LL}.\n\t*/\n\tllFallback = 0;\n\t/**\n\t* The total number of ATN transitions required during LL prediction for\n\t* this decision. An ATN transition is determined by the number of times the\n\t* DFA does not contain an edge that is required for prediction, resulting\n\t* in on-the-fly computation of that edge.\n\t*\n\t* If DFA caching of LL transitions is employed by the implementation, ATN\n\t* computation may cache the computed edge for efficient lookup during\n\t* future parsing of this decision. Otherwise, the LL parsing algorithm will\n\t* use ATN transitions exclusively.\n\t*\n\t* @see llDFATransitions\n\t* @see ParserATNSimulator.computeTargetState\n\t* @see LexerATNSimulator.computeTargetState\n\t*/\n\tllATNTransitions = 0;\n\t/**\n\t* The total number of DFA transitions required during LL prediction for\n\t* this decision.\n\t*\n\t* If the ATN simulator implementation does not use DFA caching for LL\n\t* transitions, this value will be 0.\n\t*\n\t* @see ParserATNSimulator.getExistingTargetState\n\t* @see LexerATNSimulator.getExistingTargetState\n\t*/\n\tllDFATransitions = 0;\n\t/**\n\t* Constructs a new instance of the {@link DecisionInfo} class to contain\n\t* statistics for a particular decision.\n\t*\n\t* @param decision The decision number\n\t*/\n\tconstructor(decision) {\n\t\tthis.decision = decision;\n\t\tthis.contextSensitivities = [];\n\t\tthis.errors = [];\n\t\tthis.ambiguities = [];\n\t\tthis.predicateEvals = [];\n\t}\n\ttoString() {\n\t\treturn \"{decision=\" + this.decision + \", contextSensitivities=\" + this.contextSensitivities.length + \", errors=\" + this.errors.length + \", ambiguities=\" + this.ambiguities.length + \", sllLookahead=\" + this.sllTotalLook + \", sllATNTransitions=\" + this.sllATNTransitions + \", sllDFATransitions=\" + this.sllDFATransitions + \", llFallback=\" + this.llFallback + \", llLookahead=\" + this.llTotalLook + \", llATNTransitions=\" + this.llATNTransitions + \"}\";\n\t}\n};\nvar LexerATNConfig = class _LexerATNConfig extends ATNConfig {\n\tstatic {\n\t\t__name(this, \"LexerATNConfig\");\n\t}\n\t/**\n\t* This is the backing field for {@link #getLexerActionExecutor}.\n\t*/\n\tlexerActionExecutor;\n\tpassedThroughNonGreedyDecision;\n\tconstructor(config, state, context, lexerActionExecutor) {\n\t\tsuper(config, state, context ?? config.context, context ? SemanticContext.NONE : config.semanticContext);\n\t\tthis.lexerActionExecutor = context ? lexerActionExecutor : config.lexerActionExecutor ?? null;\n\t\tthis.passedThroughNonGreedyDecision = _LexerATNConfig.checkNonGreedyDecision(config, this.state);\n\t\treturn this;\n\t}\n\tstatic createWithExecutor(config, state, lexerActionExecutor) {\n\t\treturn new _LexerATNConfig(config, state, config.context, lexerActionExecutor);\n\t}\n\tstatic createWithConfig(state, config, context) {\n\t\treturn new _LexerATNConfig(config, state, context ?? null, config.lexerActionExecutor);\n\t}\n\tstatic createWithContext(state, alt, context) {\n\t\treturn new _LexerATNConfig({ alt }, state, context, null);\n\t}\n\tstatic checkNonGreedyDecision(source, target) {\n\t\treturn source.passedThroughNonGreedyDecision || \"nonGreedy\" in target && target.nonGreedy;\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hashCode = MurmurHash.initialize(7);\n\t\t\thashCode = MurmurHash.update(hashCode, this.state.stateNumber);\n\t\t\thashCode = MurmurHash.update(hashCode, this.alt);\n\t\t\thashCode = MurmurHash.updateFromComparable(hashCode, this.context);\n\t\t\thashCode = MurmurHash.updateFromComparable(hashCode, this.semanticContext);\n\t\t\thashCode = MurmurHash.update(hashCode, this.passedThroughNonGreedyDecision ? 1 : 0);\n\t\t\thashCode = MurmurHash.updateFromComparable(hashCode, this.lexerActionExecutor);\n\t\t\thashCode = MurmurHash.finish(hashCode, 6);\n\t\t\tthis.cachedHashCode = hashCode;\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\treturn this.passedThroughNonGreedyDecision === other.passedThroughNonGreedyDecision && (this.lexerActionExecutor && other.lexerActionExecutor ? this.lexerActionExecutor.equals(other.lexerActionExecutor) : !other.lexerActionExecutor) && super.equals(other);\n\t}\n};\nvar BaseErrorListener = class {\n\tstatic {\n\t\t__name(this, \"BaseErrorListener\");\n\t}\n\tsyntaxError(recognizer, offendingSymbol, line, column, msg, e) {}\n\treportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) {}\n\treportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) {}\n\treportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) {}\n};\nvar ConsoleErrorListener = class _ConsoleErrorListener extends BaseErrorListener {\n\tstatic {\n\t\t__name(this, \"ConsoleErrorListener\");\n\t}\n\t/**\n\t* Provides a default instance of {@link ConsoleErrorListener}.\n\t*/\n\tstatic instance = new _ConsoleErrorListener();\n\tsyntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, _e) {\n\t\tconsole.error(\"line \" + line + \":\" + charPositionInLine + \" \" + msg);\n\t}\n};\nvar ProxyErrorListener = class extends BaseErrorListener {\n\tconstructor(delegates) {\n\t\tsuper();\n\t\tthis.delegates = delegates;\n\t\treturn this;\n\t}\n\tstatic {\n\t\t__name(this, \"ProxyErrorListener\");\n\t}\n\tsyntaxError(recognizer, offendingSymbol, line, column, msg, e) {\n\t\tthis.delegates.forEach((d) => {\n\t\t\td.syntaxError(recognizer, offendingSymbol, line, column, msg, e);\n\t\t});\n\t}\n\treportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) {\n\t\tthis.delegates.forEach((d) => {\n\t\t\td.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs);\n\t\t});\n\t}\n\treportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) {\n\t\tthis.delegates.forEach((d) => {\n\t\t\td.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs);\n\t\t});\n\t}\n\treportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) {\n\t\tthis.delegates.forEach((d) => {\n\t\t\td.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs);\n\t\t});\n\t}\n};\nvar Recognizer = class _Recognizer {\n\tstatic {\n\t\t__name(this, \"Recognizer\");\n\t}\n\tstatic EOF = -1;\n\tstatic tokenTypeMapCache = /* @__PURE__ */ new Map();\n\tstatic ruleIndexMapCache = /* @__PURE__ */ new Map();\n\tinterpreter;\n\tlisteners = [ConsoleErrorListener.instance];\n\tstateNumber = -1;\n\tcheckVersion(toolVersion) {\n\t\tconst runtimeVersion = \"4.13.1\";\n\t\tif (runtimeVersion !== toolVersion) console.error(\"ANTLR runtime and generated code versions disagree: \" + runtimeVersion + \"!=\" + toolVersion);\n\t}\n\taddErrorListener(listener) {\n\t\tthis.listeners.push(listener);\n\t}\n\tremoveErrorListeners() {\n\t\tthis.listeners = [];\n\t}\n\tremoveErrorListener(listener) {\n\t\tfor (let i = 0; i < this.listeners.length; i++) if (this.listeners[i] === listener) {\n\t\t\tthis.listeners.splice(i, 1);\n\t\t\treturn;\n\t\t}\n\t}\n\tgetErrorListeners() {\n\t\treturn this.listeners;\n\t}\n\tgetTokenTypeMap() {\n\t\tconst vocabulary = this.vocabulary;\n\t\tlet result = _Recognizer.tokenTypeMapCache.get(vocabulary);\n\t\tif (!result) {\n\t\t\tresult = /* @__PURE__ */ new Map();\n\t\t\tfor (let i = 0; i <= this.atn.maxTokenType; i++) {\n\t\t\t\tconst literalName = vocabulary.getLiteralName(i);\n\t\t\t\tif (literalName) result.set(literalName, i);\n\t\t\t\tconst symbolicName = vocabulary.getSymbolicName(i);\n\t\t\t\tif (symbolicName) result.set(symbolicName, i);\n\t\t\t}\n\t\t\tresult.set(\"EOF\", Token.EOF);\n\t\t\t_Recognizer.tokenTypeMapCache.set(vocabulary, result);\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* Get a map from rule names to rule indexes.\n\t* Used for XPath and tree pattern compilation.\n\t*/\n\tgetRuleIndexMap() {\n\t\tconst ruleNames = this.ruleNames;\n\t\tlet result = _Recognizer.ruleIndexMapCache.get(ruleNames);\n\t\tif (!result) {\n\t\t\tresult = /* @__PURE__ */ new Map();\n\t\t\truleNames.forEach((ruleName, idx) => {\n\t\t\t\treturn result.set(ruleName, idx);\n\t\t\t});\n\t\t\t_Recognizer.ruleIndexMapCache.set(ruleNames, result);\n\t\t}\n\t\treturn result;\n\t}\n\tgetTokenType(tokenName) {\n\t\tconst ttype = this.getTokenTypeMap().get(tokenName);\n\t\tif (ttype) return ttype;\n\t\treturn Token.INVALID_TYPE;\n\t}\n\t/** What is the error header, normally line/character position information? */\n\tgetErrorHeader(e) {\n\t\tconst line = e.offendingToken?.line;\n\t\tconst column = e.offendingToken?.column;\n\t\treturn \"line \" + line + \":\" + column;\n\t}\n\tget errorListenerDispatch() {\n\t\treturn new ProxyErrorListener(this.listeners);\n\t}\n\t/**\n\t* subclass needs to override these if there are semantic predicates or actions\n\t* that the ATN interp needs to execute\n\t*/\n\tsempred(_localctx, _ruleIndex, _actionIndex) {\n\t\treturn true;\n\t}\n\tprecpred(_localctx, _precedence) {\n\t\treturn true;\n\t}\n\taction(_localctx, _ruleIndex, _actionIndex) {}\n\tget atn() {\n\t\treturn this.interpreter.atn;\n\t}\n\tget state() {\n\t\treturn this.stateNumber;\n\t}\n\tset state(state) {\n\t\tthis.stateNumber = state;\n\t}\n\tgetParseInfo() {}\n};\nvar CommonTokenFactory = class _CommonTokenFactory {\n\tstatic {\n\t\t__name(this, \"CommonTokenFactory\");\n\t}\n\t/**\n\t* The default {@link CommonTokenFactory} instance.\n\t*\n\t*\n\t* This token factory does not explicitly copy token text when constructing\n\t* tokens.\n\t*/\n\tstatic DEFAULT = new _CommonTokenFactory();\n\t/**\n\t* Indicates whether {@link CommonToken.setText} should be called after\n\t* constructing tokens to explicitly set the text. This is useful for cases\n\t* where the input stream might not be able to provide arbitrary substrings\n\t* of text from the input after the lexer creates a token (e.g. the\n\t* implementation of {@link CharStream.getText} in\n\t* {@link UnbufferedCharStream} throws an\n\t* {@link UnsupportedOperationException}). Explicitly setting the token text\n\t* allows {@link Token.getText} to be called at any time regardless of the\n\t* input stream implementation.\n\t*\n\t*\n\t* The default value is `false` to avoid the performance and memory\n\t* overhead of copying text for every token unless explicitly requested.\n\t*/\n\tcopyText = false;\n\tconstructor(copyText) {\n\t\tthis.copyText = copyText ?? false;\n\t}\n\tcreate(source, type, text, channel, start, stop, line, column) {\n\t\tconst t = CommonToken.fromSource(source, type, channel, start, stop);\n\t\tt.line = line;\n\t\tt.column = column;\n\t\tif (text) t.text = text;\n\t\telse if (this.copyText && source[1] !== null) t.text = source[1].getTextFromRange(start, stop);\n\t\treturn t;\n\t}\n};\nvar RecognitionException = class _RecognitionException extends Error {\n\tstatic {\n\t\t__name(this, \"RecognitionException\");\n\t}\n\tctx;\n\t/**\n\t* The current {@link Token} when an error occurred. Since not all streams\n\t* support accessing symbols by index, we have to track the {@link Token}\n\t* instance itself\n\t*/\n\toffendingToken = null;\n\t/**\n\t* Get the ATN state number the parser was in at the time the error\n\t* occurred. For {@link NoViableAltException} and\n\t* {@link LexerNoViableAltException} exceptions, this is the\n\t* {@link DecisionState} number. For others, it is the state whose outgoing\n\t* edge we couldn't match.\n\t*/\n\toffendingState = -1;\n\trecognizer;\n\tinput;\n\tconstructor(params) {\n\t\tsuper(params.message);\n\t\tif (Error.captureStackTrace) Error.captureStackTrace(this, _RecognitionException);\n\t\tthis.message = params.message;\n\t\tthis.recognizer = params.recognizer;\n\t\tthis.input = params.input;\n\t\tthis.ctx = params.ctx;\n\t\tif (this.recognizer !== null) this.offendingState = this.recognizer.state;\n\t}\n\t/**\n\t* Gets the set of input symbols which could potentially follow the\n\t* previously matched symbol at the time this exception was thrown.\n\t*\n\t* If the set of expected tokens is not known and could not be computed,\n\t* this method returns `null`.\n\t*\n\t* @returns The set of token types that could potentially follow the current\n\t* state in the ATN, or `null` if the information is not available.\n\t*/\n\tgetExpectedTokens() {\n\t\tif (this.recognizer !== null && this.ctx !== null) return this.recognizer.atn.getExpectedTokens(this.offendingState, this.ctx);\n\t\telse return null;\n\t}\n\ttoString() {\n\t\treturn this.message;\n\t}\n};\nvar LexerNoViableAltException = class extends RecognitionException {\n\tstatic {\n\t\t__name(this, \"LexerNoViableAltException\");\n\t}\n\tstartIndex;\n\tdeadEndConfigs;\n\tconstructor(lexer, input, startIndex, deadEndConfigs) {\n\t\tsuper({\n\t\t\tmessage: \"\",\n\t\t\trecognizer: lexer,\n\t\t\tinput,\n\t\t\tctx: null\n\t\t});\n\t\tthis.startIndex = startIndex;\n\t\tthis.deadEndConfigs = deadEndConfigs;\n\t}\n\ttoString() {\n\t\tlet symbol = \"\";\n\t\tif (this.input && this.startIndex >= 0 && this.startIndex < this.input.size) symbol = this.input.getTextFromRange(this.startIndex, this.startIndex);\n\t\treturn `LexerNoViableAltException(${symbol})`;\n\t}\n};\nvar Lexer = class _Lexer extends Recognizer {\n\tstatic {\n\t\t__name(this, \"Lexer\");\n\t}\n\tstatic DEFAULT_MODE = 0;\n\tstatic MORE = -2;\n\tstatic SKIP = -3;\n\tstatic DEFAULT_TOKEN_CHANNEL = Token.DEFAULT_CHANNEL;\n\tstatic HIDDEN = Token.HIDDEN_CHANNEL;\n\toptions = {\n\t\tminDFAEdge: 0,\n\t\tmaxDFAEdge: 256,\n\t\tminCodePoint: 0,\n\t\tmaxCodePoint: 1114111\n\t};\n\t/**\n\t* What character index in the stream did the current token start at?\n\t*  Needed, for example, to get the text for current token.  Set at\n\t*  the start of nextToken.\n\t*/\n\ttokenStartCharIndex = -1;\n\t/** The channel number for the current token */\n\tchannel = 0;\n\t/** The token type for the current token */\n\ttype = 0;\n\tmode = _Lexer.DEFAULT_MODE;\n\t/** The start column of the current token (the one that was last read by `nextToken`). */\n\tcurrentTokenColumn = 0;\n\t/**\n\t* The line on which the first character of the current token (the one that was last read by `nextToken`) resides.\n\t*/\n\tcurrentTokenStartLine = 0;\n\tinput;\n\t/**\n\t* The goal of all lexer rules/methods is to create a token object.\n\t*  This is an instance variable as multiple rules may collaborate to\n\t*  create a single token.  nextToken will return this object after\n\t*  matching lexer rule(s).  If you subclass to allow multiple token\n\t*  emissions, then set this to the last token to be matched or\n\t*  something non-null so that the auto token emit mechanism will not\n\t*  emit another token.\n\t*/\n\ttoken = null;\n\t/**\n\t* Once we see EOF on char stream, next token will be EOF.\n\t* If you have DONE : EOF ; then you see DONE EOF.\n\t*/\n\thitEOF = false;\n\tfactory;\n\t#modeStack = [];\n\t/**\n\t* The text to be used for the next token. If this is not null, then the text\n\t* for the next token is fixed and is not subject to change in the normal\n\t* workflow of the lexer.\n\t*/\n\t#text;\n\tconstructor(input, options) {\n\t\tsuper();\n\t\tthis.options = {\n\t\t\t...this.options,\n\t\t\t...options\n\t\t};\n\t\tthis.input = input;\n\t\tthis.factory = CommonTokenFactory.DEFAULT;\n\t}\n\treset(seekBack = true) {\n\t\tif (seekBack) this.input.seek(0);\n\t\tthis.token = null;\n\t\tthis.type = Token.INVALID_TYPE;\n\t\tthis.channel = Token.DEFAULT_CHANNEL;\n\t\tthis.tokenStartCharIndex = -1;\n\t\tthis.currentTokenColumn = -1;\n\t\tthis.currentTokenStartLine = -1;\n\t\tthis.#text = void 0;\n\t\tthis.hitEOF = false;\n\t\tthis.mode = _Lexer.DEFAULT_MODE;\n\t\tthis.#modeStack = [];\n\t\tthis.interpreter.reset();\n\t}\n\t/** @returns a token from this source; i.e., match a token on the char stream. */\n\tnextToken() {\n\t\tif (this.input === null) throw new Error(\"nextToken requires a non-null input stream.\");\n\t\tconst tokenStartMarker = this.input.mark();\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tif (this.hitEOF) {\n\t\t\t\t\tthis.emitEOF();\n\t\t\t\t\treturn this.token;\n\t\t\t\t}\n\t\t\t\tthis.token = null;\n\t\t\t\tthis.channel = Token.DEFAULT_CHANNEL;\n\t\t\t\tthis.tokenStartCharIndex = this.input.index;\n\t\t\t\tthis.currentTokenColumn = this.interpreter.column;\n\t\t\t\tthis.currentTokenStartLine = this.interpreter.line;\n\t\t\t\tthis.#text = void 0;\n\t\t\t\tlet continueOuter = false;\n\t\t\t\twhile (true) {\n\t\t\t\t\tthis.type = Token.INVALID_TYPE;\n\t\t\t\t\tlet ttype = _Lexer.SKIP;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tttype = this.interpreter.match(this.input, this.mode);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (e instanceof LexerNoViableAltException) {\n\t\t\t\t\t\t\tthis.notifyListeners(e);\n\t\t\t\t\t\t\tthis.recover(e);\n\t\t\t\t\t\t} else throw e;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.input.LA(1) === Token.EOF) this.hitEOF = true;\n\t\t\t\t\tif (this.type === Token.INVALID_TYPE) this.type = ttype;\n\t\t\t\t\tif (this.type === _Lexer.SKIP) {\n\t\t\t\t\t\tcontinueOuter = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.type !== _Lexer.MORE) break;\n\t\t\t\t}\n\t\t\t\tif (continueOuter) continue;\n\t\t\t\tif (this.token === null) this.emit();\n\t\t\t\treturn this.token;\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.input.release(tokenStartMarker);\n\t\t}\n\t}\n\t/**\n\t* Instruct the lexer to skip creating a token for current lexer rule\n\t* and look for another token. nextToken() knows to keep looking when\n\t* a lexer rule finishes with token set to SKIP_TOKEN. Recall that\n\t* if token==null at end of any token rule, it creates one for you\n\t* and emits it.\n\t*/\n\tskip() {\n\t\tthis.type = _Lexer.SKIP;\n\t}\n\tmore() {\n\t\tthis.type = _Lexer.MORE;\n\t}\n\tpushMode(m2) {\n\t\tif (LexerATNSimulator.debug) console.log(\"pushMode \" + m2);\n\t\tthis.#modeStack.push(this.mode);\n\t\tthis.mode = m2;\n\t}\n\tpopMode() {\n\t\tif (this.#modeStack.length === 0) throw new Error(\"Empty Stack\");\n\t\tif (LexerATNSimulator.debug) console.log(\"popMode back to \" + this.#modeStack.slice(0, -1));\n\t\tthis.mode = this.#modeStack.pop();\n\t\treturn this.mode;\n\t}\n\tget modeStack() {\n\t\treturn this.#modeStack;\n\t}\n\t/**\n\t* By default does not support multiple emits per nextToken invocation\n\t* for efficiency reasons. Subclass and override this method, nextToken,\n\t* and getToken (to push tokens into a list and pull from that list\n\t* rather than a single variable as this implementation does).\n\t*/\n\temitToken(token) {\n\t\tthis.token = token;\n\t}\n\t/**\n\t* The standard method called to automatically emit a token at the\n\t* outermost lexical rule. The token object should point into the\n\t* char buffer start..stop. If there is a text override in 'text',\n\t* use that to set the token's text. Override this method to emit\n\t* custom Token objects or provide a new factory.\n\t*/\n\temit() {\n\t\tconst t = this.factory.create([this, this.input], this.type, this.#text, this.channel, this.tokenStartCharIndex, this.getCharIndex() - 1, this.currentTokenStartLine, this.currentTokenColumn);\n\t\tthis.emitToken(t);\n\t\treturn t;\n\t}\n\temitEOF() {\n\t\tconst eof = this.factory.create([this, this.input], Token.EOF, void 0, Token.DEFAULT_CHANNEL, this.input.index, this.input.index - 1, this.line, this.column);\n\t\tthis.emitToken(eof);\n\t\treturn eof;\n\t}\n\t/** What is the index of the current character of lookahead? */\n\tgetCharIndex() {\n\t\treturn this.input.index;\n\t}\n\t/**\n\t* Return a list of all Token objects in input char stream.\n\t* Forces load of all tokens. Does not include EOF token.\n\t*/\n\tgetAllTokens() {\n\t\tconst tokens = [];\n\t\tlet t = this.nextToken();\n\t\twhile (t.type !== Token.EOF) {\n\t\t\ttokens.push(t);\n\t\t\tt = this.nextToken();\n\t\t}\n\t\treturn tokens;\n\t}\n\tnotifyListeners(e) {\n\t\tconst start = this.tokenStartCharIndex;\n\t\tconst stop = this.input.index;\n\t\tconst text = this.input.getTextFromRange(start, stop);\n\t\tconst msg = \"token recognition error at: '\" + this.getErrorDisplay(text) + \"'\";\n\t\tthis.errorListenerDispatch.syntaxError(this, null, this.currentTokenStartLine, this.currentTokenColumn, msg, e);\n\t}\n\tgetErrorDisplay(s) {\n\t\treturn s;\n\t}\n\tgetErrorDisplayForChar(c) {\n\t\tif (c.charCodeAt(0) === Token.EOF) return \"<EOF>\";\n\t\tif (c === \"\\n\") return \"\\\\n\";\n\t\tif (c === \"\t\") return \"\\\\t\";\n\t\tif (c === \"\\r\") return \"\\\\r\";\n\t\treturn c;\n\t}\n\tgetCharErrorDisplay(c) {\n\t\treturn \"'\" + this.getErrorDisplayForChar(c) + \"'\";\n\t}\n\t/**\n\t* Lexers can normally match any char in it's vocabulary after matching\n\t* a token, so do the easy thing and just kill a character and hope\n\t* it all works out. You can instead use the rule invocation stack\n\t* to do sophisticated error recovery if you are in a fragment rule.\n\t*/\n\trecover(re) {\n\t\tif (this.input.LA(1) !== Token.EOF) if (re instanceof LexerNoViableAltException) this.interpreter.consume(this.input);\n\t\telse this.input.consume();\n\t}\n\tget inputStream() {\n\t\treturn this.input;\n\t}\n\tset inputStream(input) {\n\t\tthis.reset(false);\n\t\tthis.input = input;\n\t}\n\tset tokenFactory(factory) {\n\t\tthis.factory = factory;\n\t}\n\tget tokenFactory() {\n\t\treturn this.factory;\n\t}\n\tget sourceName() {\n\t\treturn this.input.getSourceName();\n\t}\n\tget line() {\n\t\treturn this.interpreter.line;\n\t}\n\tset line(line) {\n\t\tthis.interpreter.line = line;\n\t}\n\tget column() {\n\t\treturn this.interpreter.column;\n\t}\n\tset column(column) {\n\t\tthis.interpreter.column = column;\n\t}\n\tget text() {\n\t\tif (this.#text) return this.#text;\n\t\telse return this.interpreter.getText(this.input);\n\t}\n\tset text(text) {\n\t\tthis.#text = text;\n\t}\n};\nvar DFASerializer = class {\n\tstatic {\n\t\t__name(this, \"DFASerializer\");\n\t}\n\tdfa;\n\tvocabulary;\n\tconstructor(dfa, vocabulary) {\n\t\tthis.dfa = dfa;\n\t\tthis.vocabulary = vocabulary;\n\t}\n\ttoString() {\n\t\tif (!this.dfa.s0) return \"\";\n\t\tlet buf = \"\";\n\t\tconst states = this.dfa.getStates();\n\t\tfor (const s of states) {\n\t\t\tlet n2 = 0;\n\t\t\tn2 = s.edges.length;\n\t\t\tfor (let i = 0; i < n2; i++) {\n\t\t\t\tconst t = s.edges[i];\n\t\t\t\tif (t && t.stateNumber !== 2147483647) {\n\t\t\t\t\tbuf += this.getStateString(s);\n\t\t\t\t\tconst label = this.getEdgeLabel(i);\n\t\t\t\t\tbuf += \"-\";\n\t\t\t\t\tbuf += label;\n\t\t\t\t\tbuf += \"->\";\n\t\t\t\t\tbuf += this.getStateString(t);\n\t\t\t\t\tbuf += \"\\n\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn buf;\n\t}\n\tgetEdgeLabel(i) {\n\t\treturn `${this.vocabulary.getDisplayName(i - 1)}`;\n\t}\n\tgetStateString(s) {\n\t\tconst n2 = s.stateNumber;\n\t\tconst baseStateStr = (s.isAcceptState ? \":\" : \"\") + \"s\" + n2 + (s.requiresFullContext ? \"^\" : \"\");\n\t\tif (s.isAcceptState) {\n\t\t\tif (s.predicates !== null) return `${baseStateStr}=>${s.predicates.toString()}`;\n\t\t\treturn `${baseStateStr}=>${s.prediction}`;\n\t\t} else return `${baseStateStr}`;\n\t}\n};\nvar LexerDFASerializer = class extends DFASerializer {\n\tstatic {\n\t\t__name(this, \"LexerDFASerializer\");\n\t}\n\tconstructor(dfa) {\n\t\tsuper(dfa, Vocabulary.EMPTY_VOCABULARY);\n\t}\n\tgetEdgeLabel = /* @__PURE__ */ __name((i) => {\n\t\treturn \"'\" + String.fromCharCode(i) + \"'\";\n\t}, \"getEdgeLabel\");\n};\nvar DFA = class {\n\tstatic {\n\t\t__name(this, \"DFA\");\n\t}\n\ts0;\n\tdecision;\n\t/** From which ATN state did we create this DFA? */\n\tatnStartState;\n\t/**\n\t* Gets whether this DFA is a precedence DFA. Precedence DFAs use a special\n\t* start state {@link #s0} which is not stored in {@link #states}. The\n\t* {@link DFAState#edges} array for this start state contains outgoing edges\n\t* supplying individual start states corresponding to specific precedence\n\t* values.\n\t*\n\t* @returns `true` if this is a precedence DFA; otherwise, `false`.\n\t*/\n\tisPrecedenceDfa;\n\t/**\n\t* A mapping from an ATNConfigSet hash to a DFAState.\n\t* Used to quick look up the DFA state for a particular configuration set.\n\t*/\n\tstates = /* @__PURE__ */ new Map();\n\tconstructor(atnStartState, decision) {\n\t\tthis.atnStartState = atnStartState;\n\t\tthis.decision = decision ?? 0;\n\t\tlet precedenceDfa = false;\n\t\tif (atnStartState instanceof StarLoopEntryState) {\n\t\t\tif (atnStartState.precedenceRuleDecision) {\n\t\t\t\tprecedenceDfa = true;\n\t\t\t\tthis.s0 = DFAState.fromState(-1);\n\t\t\t}\n\t\t}\n\t\tthis.isPrecedenceDfa = precedenceDfa;\n\t}\n\t[Symbol.iterator] = () => {\n\t\treturn this.states.values()[Symbol.iterator]();\n\t};\n\t/**\n\t* Get the start state for a specific precedence value.\n\t*\n\t* @param precedence The current precedence.\n\t@returns The start state corresponding to the specified precedence, or\n\t* `null` if no start state exists for the specified precedence.\n\t*\n\t* @throws IllegalStateException if this is not a precedence DFA.\n\t* @see #isPrecedenceDfa\n\t*/\n\tgetPrecedenceStartState = /* @__PURE__ */ __name((precedence) => {\n\t\tif (!this.isPrecedenceDfa) throw new Error(`Only precedence DFAs may contain a precedence start state.`);\n\t\tif (!this.s0 || !this.s0.edges || precedence < 0 || precedence >= this.s0.edges.length) return;\n\t\treturn this.s0.edges[precedence];\n\t}, \"getPrecedenceStartState\");\n\t/**\n\t* Set the start state for a specific precedence value.\n\t*\n\t* @param precedence The current precedence.\n\t* @param startState The start state corresponding to the specified precedence.\n\t*/\n\tsetPrecedenceStartState = /* @__PURE__ */ __name((precedence, startState) => {\n\t\tif (!this.isPrecedenceDfa) throw new Error(`Only precedence DFAs may contain a precedence start state.`);\n\t\tif (precedence < 0 || !this.s0) return;\n\t\tthis.s0.edges[precedence] = startState;\n\t}, \"setPrecedenceStartState\");\n\t/**\n\t* @returns a list of all states in this DFA, ordered by state number.\n\t*/\n\tgetStates() {\n\t\tconst result = [...this.states.values()];\n\t\tresult.sort((o1, o2) => {\n\t\t\treturn o1.stateNumber - o2.stateNumber;\n\t\t});\n\t\treturn result;\n\t}\n\tgetState(state) {\n\t\treturn this.states.get(state.configs.hashCode()) ?? null;\n\t}\n\tgetStateForConfigs(configs) {\n\t\treturn this.states.get(configs.hashCode()) ?? null;\n\t}\n\taddState(state) {\n\t\tconst hash = state.configs.hashCode();\n\t\tif (this.states.has(hash)) return;\n\t\tthis.states.set(hash, state);\n\t\tstate.stateNumber = this.states.size - 1;\n\t}\n\ttoString(vocabulary) {\n\t\tif (!vocabulary) return this.toString(Vocabulary.EMPTY_VOCABULARY);\n\t\tif (!this.s0) return \"\";\n\t\treturn new DFASerializer(this, vocabulary).toString() ?? \"\";\n\t}\n\ttoLexerString() {\n\t\tif (!this.s0) return \"\";\n\t\treturn new LexerDFASerializer(this).toString() ?? \"\";\n\t}\n\tget length() {\n\t\treturn this.states.size;\n\t}\n};\nvar LexerIndexedCustomAction = class _LexerIndexedCustomAction {\n\tstatic {\n\t\t__name(this, \"LexerIndexedCustomAction\");\n\t}\n\toffset;\n\taction;\n\tactionType;\n\tisPositionDependent = true;\n\tcachedHashCode;\n\tconstructor(offset, action) {\n\t\tthis.actionType = action.actionType;\n\t\tthis.offset = offset;\n\t\tthis.action = action;\n\t}\n\t/**\n\t* This method calls {@link execute} on the result of {@link getAction}\n\t* using the provided `lexer`.\n\t*/\n\texecute(lexer) {\n\t\tthis.action.execute(lexer);\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hash = MurmurHash.initialize();\n\t\t\thash = MurmurHash.update(hash, this.offset);\n\t\t\thash = MurmurHash.updateFromComparable(hash, this.action);\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hash, 2);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (!(other instanceof _LexerIndexedCustomAction)) return false;\n\t\treturn this.offset === other.offset && this.action === other.action;\n\t}\n};\nvar LexerActionExecutor = class _LexerActionExecutor {\n\tstatic {\n\t\t__name(this, \"LexerActionExecutor\");\n\t}\n\tlexerActions;\n\tactionType;\n\tisPositionDependent = false;\n\tcachedHashCode;\n\t/**\n\t* Represents an executor for a sequence of lexer actions which traversed during\n\t* the matching operation of a lexer rule (token).\n\t*\n\t* The executor tracks position information for position-dependent lexer actions\n\t* efficiently, ensuring that actions appearing only at the end of the rule do\n\t* not cause bloating of the {@link DFA} created for the lexer.\n\t*/\n\tconstructor(lexerActions) {\n\t\tthis.actionType = -1;\n\t\tthis.lexerActions = lexerActions ?? [];\n\t\treturn this;\n\t}\n\t/**\n\t* Creates a {@link LexerActionExecutor} which executes the actions for\n\t* the input `lexerActionExecutor` followed by a specified\n\t* `lexerAction`.\n\t*\n\t* @param lexerActionExecutor The executor for actions already traversed by\n\t* the lexer while matching a token within a particular\n\t* {@link LexerATNConfig}. If this is `null`, the method behaves as\n\t* though it were an empty executor.\n\t* @param lexerAction The lexer action to execute after the actions\n\t* specified in `lexerActionExecutor`.\n\t*\n\t* @returns {LexerActionExecutor} A {@link LexerActionExecutor} for executing the combine actions\n\t* of `lexerActionExecutor` and `lexerAction`.\n\t*/\n\tstatic append(lexerActionExecutor, lexerAction) {\n\t\tif (lexerActionExecutor === null) return new _LexerActionExecutor([lexerAction]);\n\t\treturn new _LexerActionExecutor(lexerActionExecutor.lexerActions.concat([lexerAction]));\n\t}\n\t/**\n\t* Creates a {@link LexerActionExecutor} which encodes the current offset\n\t* for position-dependent lexer actions.\n\t*\n\t* Normally, when the executor encounters lexer actions where\n\t* {@link LexerAction//isPositionDependent} returns `true`, it calls\n\t* {@link IntStream.seek} on the input {@link CharStream} to set the input\n\t* position to the *end* of the current token. This behavior provides\n\t* for efficient DFA representation of lexer actions which appear at the end\n\t* of a lexer rule, even when the lexer rule matches a variable number of\n\t* characters.\n\t*\n\t* Prior to traversing a match transition in the ATN, the current offset\n\t* from the token start index is assigned to all position-dependent lexer\n\t* actions which have not already been assigned a fixed offset. By storing\n\t* the offsets relative to the token start index, the DFA representation of\n\t* lexer actions which appear in the middle of tokens remains efficient due\n\t* to sharing among tokens of the same length, regardless of their absolute\n\t* position in the input stream.\n\t*\n\t* If the current executor already has offsets assigned to all\n\t* position-dependent lexer actions, the method returns `this`.\n\t*\n\t* @param offset The current offset to assign to all position-dependent\n\t* lexer actions which do not already have offsets assigned.\n\t*\n\t* @returns {LexerActionExecutor} A {@link LexerActionExecutor} which stores input stream offsets\n\t* for all position-dependent lexer actions.\n\t*/\n\tfixOffsetBeforeMatch(offset) {\n\t\tlet updatedLexerActions = null;\n\t\tfor (let i = 0; i < this.lexerActions.length; i++) if (this.lexerActions[i].isPositionDependent && !(this.lexerActions[i] instanceof LexerIndexedCustomAction)) {\n\t\t\tif (updatedLexerActions === null) updatedLexerActions = this.lexerActions.concat([]);\n\t\t\tupdatedLexerActions[i] = new LexerIndexedCustomAction(offset, this.lexerActions[i]);\n\t\t}\n\t\tif (updatedLexerActions === null) return this;\n\t\telse return new _LexerActionExecutor(updatedLexerActions);\n\t}\n\t/**\n\t* Execute the actions encapsulated by this executor within the context of a\n\t* particular {@link Lexer}.\n\t*\n\t* This method calls {@link IntStream.seek} to set the position of the\n\t* `input` {@link CharStream} prior to calling\n\t* {@link LexerAction.execute} on a position-dependent action. Before the\n\t* method returns, the input position will be restored to the same position\n\t* it was in when the method was invoked.\n\t*\n\t* @param lexer The lexer instance.\n\t* @param input The input stream which is the source for the current token.\n\t* When this method is called, the current {@link IntStream.index} for\n\t* `input` should be the start of the following token, i.e. 1\n\t* character past the end of the current token.\n\t* @param startIndex The token start index. This value may be passed to\n\t* {@link IntStream.seek} to set the `input` position to the beginning\n\t* of the token.\n\t*/\n\texecute(lexer, input, startIndex) {\n\t\tif (input === void 0 || startIndex === void 0) return;\n\t\tlet requiresSeek = false;\n\t\tconst stopIndex = input.index;\n\t\ttry {\n\t\t\tfor (const lexerAction of this.lexerActions) {\n\t\t\t\tlet action = lexerAction;\n\t\t\t\tif (lexerAction instanceof LexerIndexedCustomAction) {\n\t\t\t\t\tconst offset = lexerAction.offset;\n\t\t\t\t\tinput.seek(startIndex + offset);\n\t\t\t\t\taction = lexerAction.action;\n\t\t\t\t\trequiresSeek = startIndex + offset !== stopIndex;\n\t\t\t\t} else if (lexerAction.isPositionDependent) {\n\t\t\t\t\tinput.seek(stopIndex);\n\t\t\t\t\trequiresSeek = false;\n\t\t\t\t}\n\t\t\t\taction.execute(lexer);\n\t\t\t}\n\t\t} finally {\n\t\t\tif (requiresSeek) input.seek(stopIndex);\n\t\t}\n\t}\n\thashCode() {\n\t\tif (this.cachedHashCode === void 0) {\n\t\t\tlet hashCode = MurmurHash.initialize(7);\n\t\t\tfor (const lexerAction of this.lexerActions) hashCode = MurmurHash.update(hashCode, lexerAction.hashCode());\n\t\t\tthis.cachedHashCode = MurmurHash.finish(hashCode, this.lexerActions.length);\n\t\t}\n\t\treturn this.cachedHashCode;\n\t}\n\tequals(other) {\n\t\tif (this === other) return true;\n\t\tif (this.cachedHashCode !== other.cachedHashCode) return false;\n\t\tif (this.lexerActions.length !== other.lexerActions.length) return false;\n\t\treturn this.lexerActions.every((action, index) => {\n\t\t\treturn action.equals(other.lexerActions[index]);\n\t\t});\n\t}\n};\nvar OrderedHashSet = class _OrderedHashSet extends HashSet {\n\tstatic {\n\t\t__name(this, \"OrderedHashSet\");\n\t}\n\telements = [];\n\tgetOrAdd(o) {\n\t\tconst oldSize = this.size;\n\t\tconst result = super.getOrAdd(o);\n\t\tif (this.size > oldSize) this.elements.push(o);\n\t\treturn result;\n\t}\n\tequals(o) {\n\t\tif (!(o instanceof _OrderedHashSet)) return false;\n\t\treturn super.equals(o);\n\t}\n\tclear() {\n\t\tsuper.clear();\n\t\tthis.elements = [];\n\t}\n\t*[Symbol.iterator]() {\n\t\tyield* this.elements;\n\t}\n\ttoArray() {\n\t\treturn this.elements.slice(0);\n\t}\n};\nvar OrderedATNConfigSet = class extends ATNConfigSet {\n\tstatic {\n\t\t__name(this, \"OrderedATNConfigSet\");\n\t}\n\tconstructor() {\n\t\tsuper();\n\t\tthis.configLookup = new OrderedHashSet();\n\t}\n};\nvar LexerATNSimulator = class _LexerATNSimulator extends ATNSimulator {\n\tstatic {\n\t\t__name(this, \"LexerATNSimulator\");\n\t}\n\tstatic debug = false;\n\tdecisionToDFA;\n\trecognizer = null;\n\t/**\n\t* The current token's starting index into the character stream.\n\t*  Shared across DFA to ATN simulation in case the ATN fails and the\n\t*  DFA did not have a previous accept state. In this case, we use the\n\t*  ATN-generated exception object.\n\t*/\n\tstartIndex = -1;\n\t/** line number 1..n within the input */\n\tline = 1;\n\t/** The index of the character relative to the beginning of the line 0..n-1 */\n\tcolumn = 0;\n\tmode = Lexer.DEFAULT_MODE;\n\t/** Used during DFA/ATN exec to record the most recent accept configuration info */\n\tprevAccept;\n\toptions;\n\t/** Lookup table for lexer ATN config creation. */\n\tlexerATNConfigFactory;\n\t/**\n\t* When we hit an accept state in either the DFA or the ATN, we\n\t* have to notify the character stream to start buffering characters\n\t* via {@link IntStream//mark} and record the current state. The current sim state\n\t* includes the current index into the input, the current line,\n\t* and current character position in that line. Note that the Lexer is\n\t* tracking the starting line and characterization of the token. These\n\t* variables track the \"state\" of the simulator when it hits an accept state.\n\t*\n\t* We track these variables separately for the DFA and ATN simulation\n\t* because the DFA simulation often has to fail over to the ATN\n\t* simulation. If the ATN simulation fails, we need the DFA to fall\n\t* back to its previously accepted state, if any. If the ATN succeeds,\n\t* then the ATN does the accept and the DFA simulator that invoked it\n\t* can simply return the predicted token type.\n\t*/\n\tconstructor(recog, atn, decisionToDFA, sharedContextCache) {\n\t\tsuper(atn, sharedContextCache);\n\t\tthis.decisionToDFA = decisionToDFA;\n\t\tthis.recognizer = recog;\n\t\tif (recog) this.options = recog.options;\n\t\telse this.options = {\n\t\t\tminDFAEdge: 0,\n\t\t\tmaxDFAEdge: 256,\n\t\t\tminCodePoint: 0,\n\t\t\tmaxCodePoint: 1114111\n\t\t};\n\t}\n\tmatch(input, mode) {\n\t\tthis.mode = mode;\n\t\tconst mark = input.mark();\n\t\ttry {\n\t\t\tthis.startIndex = input.index;\n\t\t\tthis.prevAccept = void 0;\n\t\t\tconst dfa = this.decisionToDFA[mode];\n\t\t\tif (!dfa.s0) return this.matchATN(input);\n\t\t\treturn this.execATN(input, dfa.s0);\n\t\t} finally {\n\t\t\tinput.release(mark);\n\t\t}\n\t}\n\treset() {\n\t\tthis.prevAccept = void 0;\n\t\tthis.startIndex = -1;\n\t\tthis.line = 1;\n\t\tthis.column = 0;\n\t\tthis.mode = Lexer.DEFAULT_MODE;\n\t}\n\tclearDFA() {\n\t\tfor (let d = 0; d < this.decisionToDFA.length; d++) this.decisionToDFA[d] = new DFA(this.atn.getDecisionState(d), d);\n\t}\n\tgetDFA(mode) {\n\t\treturn this.decisionToDFA[mode];\n\t}\n\t/** @returns the text matched so far for the current token. */\n\tgetText(input) {\n\t\treturn input.getTextFromRange(this.startIndex, input.index - 1);\n\t}\n\tconsume(input) {\n\t\tif (input.LA(1) === \"\\n\".charCodeAt(0)) {\n\t\t\tthis.line += 1;\n\t\t\tthis.column = 0;\n\t\t} else this.column += 1;\n\t\tinput.consume();\n\t}\n\tgetTokenName(tt) {\n\t\tif (tt === Token.EOF) return \"EOF\";\n\t\telse return \"'\" + String.fromCharCode(tt) + \"'\";\n\t}\n\tmatchATN(input) {\n\t\tconst startState = this.atn.modeToStartState[this.mode];\n\t\tif (_LexerATNSimulator.debug) console.log(\"matchATN mode \" + this.mode + \" start: \" + startState);\n\t\tconst oldMode = this.mode;\n\t\tconst s0Closure = this.computeStartState(input, startState);\n\t\tconst suppressEdge = s0Closure.hasSemanticContext;\n\t\ts0Closure.hasSemanticContext = false;\n\t\tconst next = this.addDFAState(s0Closure);\n\t\tif (!suppressEdge) this.decisionToDFA[this.mode].s0 = next;\n\t\tconst predict = this.execATN(input, next);\n\t\tif (_LexerATNSimulator.debug) console.log(\"DFA after matchATN: \" + this.decisionToDFA[oldMode].toLexerString());\n\t\treturn predict;\n\t}\n\texecATN(input, state) {\n\t\tif (_LexerATNSimulator.debug) console.log(\"start state closure=\" + state.configs);\n\t\tif (state.isAcceptState) this.captureSimState(input, state);\n\t\tlet t = input.LA(1);\n\t\twhile (true) {\n\t\t\tif (_LexerATNSimulator.debug) console.log(\"execATN loop starting closure: \" + state.configs);\n\t\t\tlet target = this.getExistingTargetState(state, t);\n\t\t\tif (!target) target = this.computeTargetState(input, state, t);\n\t\t\tif (target === ATNSimulator.ERROR) break;\n\t\t\tif (t !== Token.EOF) this.consume(input);\n\t\t\tif (target.isAcceptState) {\n\t\t\t\tthis.captureSimState(input, target);\n\t\t\t\tif (t === Token.EOF) break;\n\t\t\t}\n\t\t\tt = input.LA(1);\n\t\t\tstate = target;\n\t\t}\n\t\treturn this.failOrAccept(input, state.configs, t);\n\t}\n\t/**\n\t* Get an existing target state for an edge in the DFA. If the target state\n\t* for the edge has not yet been computed or is otherwise not available,\n\t* this method returns `null`.\n\t*\n\t* @param s The current DFA state.\n\t* @param t The next input symbol.\n\t*\n\t* @returns The existing target DFA state for the given input symbol\n\t* `t`, or `null` if the target state for this edge is not already cached\n\t*/\n\tgetExistingTargetState(s, t) {\n\t\tif (t >= this.options.minDFAEdge && t <= this.options.maxDFAEdge) {\n\t\t\tconst target = s.edges[t - this.options.minDFAEdge];\n\t\t\tif (_LexerATNSimulator.debug && target) console.log(\"reuse state \" + s.stateNumber + \" edge to \" + target.stateNumber);\n\t\t\treturn target;\n\t\t}\n\t}\n\t/**\n\t* Compute a target state for an edge in the DFA, and attempt to add the computed state and corresponding\n\t* edge to the DFA.\n\t*\n\t* @param input The input stream\n\t* @param s The current DFA state\n\t* @param t The next input symbol\n\t*\n\t* @returns The computed target DFA state for the given input symbol `t`.\n\t*          If `t` does not lead to a valid DFA state, this method returns `ERROR`.\n\t*/\n\tcomputeTargetState(input, s, t) {\n\t\tconst reach = new OrderedATNConfigSet();\n\t\tthis.getReachableConfigSet(input, s.configs, reach, t);\n\t\tif (reach.length === 0) {\n\t\t\tif (!reach.hasSemanticContext) this.addDFAEdge(s, t, ATNSimulator.ERROR);\n\t\t\treturn ATNSimulator.ERROR;\n\t\t}\n\t\treturn this.addDFAEdge(s, t, null, reach);\n\t}\n\tfailOrAccept(input, reach, t) {\n\t\tif (this.prevAccept?.dfaState) {\n\t\t\tconst { dfaState, index, line, column } = this.prevAccept;\n\t\t\tthis.accept(input, dfaState.lexerActionExecutor, this.startIndex, index, line, column);\n\t\t\treturn dfaState.prediction;\n\t\t}\n\t\tif (t === Token.EOF && input.index === this.startIndex) return Token.EOF;\n\t\tthrow new LexerNoViableAltException(this.recognizer, input, this.startIndex, reach);\n\t}\n\t/**\n\t* Given a starting configuration set, figure out all ATN configurations we can reach upon input `t`.\n\t* Parameter `reach` is a return parameter.\n\t*/\n\tgetReachableConfigSet(input, closure, reach, t) {\n\t\tlet skipAlt = ATN.INVALID_ALT_NUMBER;\n\t\tfor (const cfg of closure) {\n\t\t\tconst currentAltReachedAcceptState = cfg.alt === skipAlt;\n\t\t\tif (currentAltReachedAcceptState && cfg.passedThroughNonGreedyDecision) continue;\n\t\t\tif (_LexerATNSimulator.debug) console.log(\"testing %s at %s\\n\", this.getTokenName(t), cfg.toString(this.recognizer, true));\n\t\t\tfor (const trans of cfg.state.transitions) {\n\t\t\t\tconst target = this.getReachableTarget(trans, t);\n\t\t\t\tif (target) {\n\t\t\t\t\tlet lexerActionExecutor = cfg.lexerActionExecutor;\n\t\t\t\t\tif (lexerActionExecutor) lexerActionExecutor = lexerActionExecutor.fixOffsetBeforeMatch(input.index - this.startIndex);\n\t\t\t\t\tconst treatEofAsEpsilon = t === Token.EOF;\n\t\t\t\t\tconst config = LexerATNConfig.createWithExecutor(cfg, target, lexerActionExecutor);\n\t\t\t\t\tif (this.closure(input, config, reach, currentAltReachedAcceptState, true, treatEofAsEpsilon)) skipAlt = cfg.alt;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\taccept(input, lexerActionExecutor, startIndex, index, line, charPos) {\n\t\tif (_LexerATNSimulator.debug) console.log(\"ACTION %s\\n\", lexerActionExecutor);\n\t\tinput.seek(index);\n\t\tthis.line = line;\n\t\tthis.column = charPos;\n\t\tif (lexerActionExecutor && this.recognizer) lexerActionExecutor.execute(this.recognizer, input, startIndex);\n\t}\n\tgetReachableTarget(trans, t) {\n\t\tif (trans.matches(t, this.options.minCodePoint, this.options.maxCodePoint)) return trans.target;\n\t\telse return;\n\t}\n\tcomputeStartState(input, p) {\n\t\tconst initialContext = EmptyPredictionContext.instance;\n\t\tconst configs = new OrderedATNConfigSet();\n\t\tfor (let i = 0; i < p.transitions.length; i++) {\n\t\t\tconst target = p.transitions[i].target;\n\t\t\tconst cfg = LexerATNConfig.createWithContext(target, i + 1, initialContext);\n\t\t\tthis.closure(input, cfg, configs, false, false, false);\n\t\t}\n\t\treturn configs;\n\t}\n\t/**\n\t* Since the alternatives within any lexer decision are ordered by\n\t* preference, this method stops pursuing the closure as soon as an accept\n\t* state is reached. After the first accept state is reached by depth-first\n\t* search from `config`, all other (potentially reachable) states for\n\t* this rule would have a lower priority.\n\t*\n\t* @returns {boolean} `true` if an accept state is reached, otherwise `false`.\n\t*/\n\tclosure(input, config, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon) {\n\t\tlet cfg = null;\n\t\tif (_LexerATNSimulator.debug) console.log(\"closure(\" + config.toString(this.recognizer, true) + \")\");\n\t\tif (config.state.constructor.stateType === ATNState.RULE_STOP) {\n\t\t\tif (_LexerATNSimulator.debug) if (this.recognizer !== null) console.log(\"closure at %s rule stop %s\\n\", this.recognizer.ruleNames[config.state.ruleIndex], config);\n\t\t\telse console.log(\"closure at rule stop %s\\n\", config);\n\t\t\tif (!config.context || config.context.hasEmptyPath()) if (!config.context || config.context.isEmpty()) {\n\t\t\t\tconfigs.add(config);\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\tconfigs.add(LexerATNConfig.createWithConfig(config.state, config, EmptyPredictionContext.instance));\n\t\t\t\tcurrentAltReachedAcceptState = true;\n\t\t\t}\n\t\t\tif (config.context && !config.context.isEmpty()) {\n\t\t\t\tfor (let i = 0; i < config.context.length; i++) if (config.context.getReturnState(i) !== PredictionContext.EMPTY_RETURN_STATE) {\n\t\t\t\t\tconst newContext = config.context.getParent(i);\n\t\t\t\t\tconst returnState = this.atn.states[config.context.getReturnState(i)];\n\t\t\t\t\tcfg = LexerATNConfig.createWithConfig(returnState, config, newContext);\n\t\t\t\t\tcurrentAltReachedAcceptState = this.closure(input, cfg, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn currentAltReachedAcceptState;\n\t\t}\n\t\tif (!config.state.epsilonOnlyTransitions) {\n\t\t\tif (!currentAltReachedAcceptState || !config.passedThroughNonGreedyDecision) configs.add(config);\n\t\t}\n\t\tfor (const trans of config.state.transitions) {\n\t\t\tcfg = this.getEpsilonTarget(input, config, trans, configs, speculative, treatEofAsEpsilon);\n\t\t\tif (cfg) currentAltReachedAcceptState = this.closure(input, cfg, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon);\n\t\t}\n\t\treturn currentAltReachedAcceptState;\n\t}\n\tgetEpsilonTarget(input, config, trans, configs, speculative, treatEofAsEpsilon) {\n\t\tif (!this.lexerATNConfigFactory) this.setupATNFactoryLookup();\n\t\tconst factory = this.lexerATNConfigFactory[trans.transitionType];\n\t\tif (!factory) return null;\n\t\treturn factory(input, config, trans, configs, speculative, treatEofAsEpsilon);\n\t}\n\t/**\n\t* Fills the lookup table for creating lexer ATN configs. This helps to avoid frequent checks of the transition\n\t* type, which determines the configuration of the created config.\n\t*/\n\tsetupATNFactoryLookup() {\n\t\tthis.lexerATNConfigFactory = [];\n\t\tthis.lexerATNConfigFactory[Transition.RULE] = (input, config, trans) => {\n\t\t\tconst newContext = createSingletonPredictionContext(config.context ?? void 0, trans.followState.stateNumber);\n\t\t\treturn LexerATNConfig.createWithConfig(trans.target, config, newContext);\n\t\t};\n\t\tthis.lexerATNConfigFactory[Transition.PRECEDENCE] = () => {\n\t\t\tthrow new Error(\"Precedence predicates are not supported in lexers.\");\n\t\t};\n\t\tthis.lexerATNConfigFactory[Transition.PREDICATE] = (input, config, trans, configs, speculative) => {\n\t\t\tconst pt = trans;\n\t\t\tif (_LexerATNSimulator.debug) console.log(\"EVAL rule \" + pt.ruleIndex + \":\" + pt.predIndex);\n\t\t\tconfigs.hasSemanticContext = true;\n\t\t\tif (this.evaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative)) return LexerATNConfig.createWithConfig(trans.target, config);\n\t\t\treturn null;\n\t\t};\n\t\tthis.lexerATNConfigFactory[Transition.ACTION] = (input, config, trans) => {\n\t\t\tif (config.context === null || config.context.hasEmptyPath()) {\n\t\t\t\tconst lexerActionExecutor = LexerActionExecutor.append(config.lexerActionExecutor, this.atn.lexerActions[trans.actionIndex]);\n\t\t\t\treturn LexerATNConfig.createWithExecutor(config, trans.target, lexerActionExecutor);\n\t\t\t} else return LexerATNConfig.createWithConfig(trans.target, config);\n\t\t};\n\t\tthis.lexerATNConfigFactory[Transition.EPSILON] = (input, config, trans) => {\n\t\t\treturn LexerATNConfig.createWithConfig(trans.target, config);\n\t\t};\n\t\tconst simple = /* @__PURE__ */ __name((input, config, trans, configs, speculative, treatEofAsEpsilon) => {\n\t\t\tif (treatEofAsEpsilon) {\n\t\t\t\tif (trans.matches(Token.EOF, this.options.minCodePoint, this.options.maxCodePoint)) return LexerATNConfig.createWithConfig(trans.target, config);\n\t\t\t}\n\t\t\treturn null;\n\t\t}, \"simple\");\n\t\tthis.lexerATNConfigFactory[Transition.ATOM] = simple;\n\t\tthis.lexerATNConfigFactory[Transition.RANGE] = simple;\n\t\tthis.lexerATNConfigFactory[Transition.SET] = simple;\n\t}\n\t/**\n\t* Evaluate a predicate specified in the lexer.\n\t*\n\t* If `speculative` is `true`, this method was called before\n\t* {@link consume} for the matched character. This method should call\n\t* {@link consume} before evaluating the predicate to ensure position\n\t* sensitive values, including {@link Lexer//getText}, {@link Lexer//getLine},\n\t* and {@link Lexer}, properly reflect the current\n\t* lexer state. This method should restore `input` and the simulator\n\t* to the original state before returning (i.e. undo the actions made by the\n\t* call to {@link consume}.\n\t*\n\t* @param input The input stream.\n\t* @param ruleIndex The rule containing the predicate.\n\t* @param predIndex The index of the predicate within the rule.\n\t* @param speculative `true` if the current index in `input` is\n\t* one character before the predicate's location.\n\t*\n\t* @returns `true` if the specified predicate evaluates to\n\t* `true`.\n\t*/\n\tevaluatePredicate(input, ruleIndex, predIndex, speculative) {\n\t\tif (!this.recognizer) return true;\n\t\tif (!speculative) return this.recognizer.sempred(null, ruleIndex, predIndex);\n\t\tconst savedColumn = this.column;\n\t\tconst savedLine = this.line;\n\t\tconst index = input.index;\n\t\tconst marker = input.mark();\n\t\ttry {\n\t\t\tthis.consume(input);\n\t\t\treturn this.recognizer.sempred(null, ruleIndex, predIndex);\n\t\t} finally {\n\t\t\tthis.column = savedColumn;\n\t\t\tthis.line = savedLine;\n\t\t\tinput.seek(index);\n\t\t\tinput.release(marker);\n\t\t}\n\t}\n\tcaptureSimState(input, dfaState) {\n\t\tthis.prevAccept = {\n\t\t\tindex: input.index,\n\t\t\tline: this.line,\n\t\t\tcolumn: this.column,\n\t\t\tdfaState\n\t\t};\n\t}\n\taddDFAEdge(from, tk, to, configs) {\n\t\tif (!to && configs) {\n\t\t\tconst suppressEdge = configs.hasSemanticContext;\n\t\t\tconfigs.hasSemanticContext = false;\n\t\t\tto = this.addDFAState(configs);\n\t\t\tif (suppressEdge) return to;\n\t\t}\n\t\tif (tk < this.options.minDFAEdge || tk > this.options.maxDFAEdge) return to;\n\t\tif (_LexerATNSimulator.debug) console.log(\"EDGE \" + from + \" -> \" + to + \" upon \" + tk);\n\t\tfrom.edges[tk - this.options.minDFAEdge] = to;\n\t\treturn to;\n\t}\n\t/**\n\t* Add a new DFA state if there isn't one with this set of configurations already. This method also detects\n\t* the first configuration containing an ATN rule stop state. Later, when traversing the DFA, we will know\n\t* which rule to accept.\n\t*/\n\taddDFAState(configs) {\n\t\tconst dfa = this.decisionToDFA[this.mode];\n\t\tconst existing = dfa.getStateForConfigs(configs);\n\t\tif (existing) return existing;\n\t\tconst proposed = DFAState.fromConfigs(configs);\n\t\tconst firstConfigWithRuleStopState = configs.firstStopState;\n\t\tif (firstConfigWithRuleStopState) {\n\t\t\tproposed.isAcceptState = true;\n\t\t\tproposed.lexerActionExecutor = firstConfigWithRuleStopState.lexerActionExecutor;\n\t\t\tproposed.prediction = this.atn.ruleToTokenType[firstConfigWithRuleStopState.state.ruleIndex];\n\t\t}\n\t\tconfigs.setReadonly(true);\n\t\tdfa.addState(proposed);\n\t\treturn proposed;\n\t}\n};\nvar ParseInfo = class {\n\tstatic {\n\t\t__name(this, \"ParseInfo\");\n\t}\n\tatnSimulator;\n\tconstructor(atnSimulator) {\n\t\tthis.atnSimulator = atnSimulator;\n\t}\n\t/**\n\t* Gets an array of {@link DecisionInfo} instances containing the profiling\n\t* information gathered for each decision in the ATN.\n\t*\n\t* @returns An array of {@link DecisionInfo} instances, indexed by decision\n\t* number.\n\t*/\n\tgetDecisionInfo() {\n\t\treturn this.atnSimulator.getDecisionInfo();\n\t}\n\t/**\n\t* Gets the decision numbers for decisions that required one or more\n\t* full-context predictions during parsing. These are decisions for which\n\t* {@link DecisionInfo#llFallback} is non-zero.\n\t*\n\t* @returns A list of decision numbers which required one or more\n\t* full-context predictions during parsing.\n\t*/\n\tgetLLDecisions() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tconst result = new Array();\n\t\tfor (let i = 0; i < decisions.length; i++) if (decisions[i].llFallback > 0) result.push(i);\n\t\treturn result;\n\t}\n\t/**\n\t* Gets the total time spent during prediction across all decisions made\n\t* during parsing. This value is the sum of\n\t* {@link DecisionInfo#timeInPrediction} for all decisions.\n\t*/\n\tgetTotalTimeInPrediction() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tlet t = 0;\n\t\tfor (const decision of decisions) t += decision.timeInPrediction;\n\t\treturn t;\n\t}\n\t/**\n\t* Gets the total number of SLL lookahead operations across all decisions\n\t* made during parsing. This value is the sum of\n\t* {@link DecisionInfo#sllTotalLook} for all decisions.\n\t*/\n\tgetTotalSLLLookaheadOps() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tlet k = 0;\n\t\tfor (const decision of decisions) k += decision.sllTotalLook;\n\t\treturn k;\n\t}\n\t/**\n\t* Gets the total number of LL lookahead operations across all decisions\n\t* made during parsing. This value is the sum of\n\t* {@link DecisionInfo#llTotalLook} for all decisions.\n\t*/\n\tgetTotalLLLookaheadOps() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tlet k = 0;\n\t\tfor (const decision of decisions) k += decision.llTotalLook;\n\t\treturn k;\n\t}\n\t/**\n\t* Gets the total number of ATN lookahead operations for SLL prediction\n\t* across all decisions made during parsing.\n\t*/\n\tgetTotalSLLATNLookaheadOps() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tlet k = 0;\n\t\tfor (const decision of decisions) k += decision.sllATNTransitions;\n\t\treturn k;\n\t}\n\t/**\n\t* Gets the total number of ATN lookahead operations for LL prediction\n\t* across all decisions made during parsing.\n\t*/\n\tgetTotalLLATNLookaheadOps() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tlet k = 0;\n\t\tfor (const decision of decisions) k += decision.llATNTransitions;\n\t\treturn k;\n\t}\n\t/**\n\t* Gets the total number of ATN lookahead operations for SLL and LL\n\t* prediction across all decisions made during parsing.\n\t*\n\t*\n\t* This value is the sum of {@link #getTotalSLLATNLookaheadOps} and\n\t* {@link #getTotalLLATNLookaheadOps}.\n\t*/\n\tgetTotalATNLookaheadOps() {\n\t\tconst decisions = this.atnSimulator.getDecisionInfo();\n\t\tlet k = 0;\n\t\tfor (const decision of decisions) {\n\t\t\tk += decision.sllATNTransitions;\n\t\t\tk += decision.llATNTransitions;\n\t\t}\n\t\treturn k;\n\t}\n\tgetDFASize(decision) {\n\t\tif (decision === void 0) {\n\t\t\tlet n2 = 0;\n\t\t\tconst decisionToDFA = this.atnSimulator.decisionToDFA;\n\t\t\tfor (let i = 0; i < decisionToDFA.length; i++) n2 += this.getDFASize(i);\n\t\t\treturn n2;\n\t\t} else return this.atnSimulator.decisionToDFA[decision].length;\n\t}\n};\nvar NoViableAltException = class extends RecognitionException {\n\tstatic {\n\t\t__name(this, \"NoViableAltException\");\n\t}\n\t/** Which configurations did we try at input.index() that couldn't match input.LT(1)? */\n\tdeadEndConfigs = null;\n\t/**\n\t* The token object at the start index; the input stream might\n\t* \tnot be buffering tokens so get a reference to it. (At the\n\t*  time the error occurred, of course the stream needs to keep a\n\t*  buffer all of the tokens but later we might not have access to those.)\n\t*/\n\tstartToken;\n\tconstructor(recognizer, input = null, startToken = null, offendingToken = null, deadEndConfigs = null, ctx = null) {\n\t\tctx = ctx ?? recognizer.context;\n\t\toffendingToken = offendingToken ?? recognizer.getCurrentToken();\n\t\tstartToken = startToken ?? recognizer.getCurrentToken();\n\t\tinput = input ?? recognizer.inputStream;\n\t\tsuper({\n\t\t\tmessage: \"\",\n\t\t\trecognizer,\n\t\t\tinput,\n\t\t\tctx\n\t\t});\n\t\tthis.deadEndConfigs = deadEndConfigs;\n\t\tthis.startToken = startToken;\n\t\tthis.offendingToken = offendingToken;\n\t}\n};\nvar DoubleDict = class {\n\tstatic {\n\t\t__name(this, \"DoubleDict\");\n\t}\n\tcacheMap;\n\tconstructor() {\n\t\tthis.cacheMap = new HashMap();\n\t}\n\tget(a, b) {\n\t\tconst d = this.cacheMap.get(a) ?? null;\n\t\treturn d === null ? null : d.get(b) ?? null;\n\t}\n\tset(a, b, o) {\n\t\tlet d = this.cacheMap.get(a);\n\t\tif (!d) {\n\t\t\td = new HashMap();\n\t\t\tthis.cacheMap.set(a, d);\n\t\t}\n\t\td.set(b, o);\n\t}\n};\nvar SubsetEqualityComparer = class _SubsetEqualityComparer {\n\tstatic {\n\t\t__name(this, \"SubsetEqualityComparer\");\n\t}\n\tstatic instance = new _SubsetEqualityComparer();\n\thashCode(config) {\n\t\tlet hashCode = MurmurHash.initialize(7);\n\t\thashCode = MurmurHash.update(hashCode, config.state.stateNumber);\n\t\thashCode = MurmurHash.updateFromComparable(hashCode, config.context);\n\t\thashCode = MurmurHash.finish(hashCode, 2);\n\t\treturn hashCode;\n\t}\n\tequals(a, b) {\n\t\treturn a.state.stateNumber === b.state.stateNumber && (a.context?.equals(b.context) ?? true);\n\t}\n};\nvar PredictionMode = class _PredictionMode {\n\tstatic {\n\t\t__name(this, \"PredictionMode\");\n\t}\n\t/**\n\t* The SLL(*) prediction mode. This prediction mode ignores the current\n\t* parser context when making predictions. This is the fastest prediction\n\t* mode, and provides correct results for many grammars. This prediction\n\t* mode is more powerful than the prediction mode provided by ANTLR 3, but\n\t* may result in syntax errors for grammar and input combinations which are\n\t* not SLL.\n\t*\n\t*\n\t* When using this prediction mode, the parser will either return a correct\n\t* parse tree (i.e. the same parse tree that would be returned with the\n\t* {@link LL} prediction mode), or it will report a syntax error. If a\n\t* syntax error is encountered when using the {@link SLL} prediction mode,\n\t* it may be due to either an actual syntax error in the input or indicate\n\t* that the particular combination of grammar and input requires the more\n\t* powerful {@link LL} prediction abilities to complete successfully.\n\t*\n\t*\n\t* This prediction mode does not provide any guarantees for prediction\n\t* behavior for syntactically-incorrect inputs.\n\t*/\n\tstatic SLL = 0;\n\t/**\n\t* The LL(*) prediction mode. This prediction mode allows the current parser\n\t* context to be used for resolving SLL conflicts that occur during\n\t* prediction. This is the fastest prediction mode that guarantees correct\n\t* parse results for all combinations of grammars with syntactically correct\n\t* inputs.\n\t*\n\t*\n\t* When using this prediction mode, the parser will make correct decisions\n\t* for all syntactically-correct grammar and input combinations. However, in\n\t* cases where the grammar is truly ambiguous this prediction mode might not\n\t* report a precise answer for *exactly which* alternatives are\n\t* ambiguous.\n\t*\n\t*\n\t* This prediction mode does not provide any guarantees for prediction\n\t* behavior for syntactically-incorrect inputs.\n\t*/\n\tstatic LL = 1;\n\t/**\n\t*\n\t* The LL(*) prediction mode with exact ambiguity detection. In addition to\n\t* the correctness guarantees provided by the {@link LL} prediction mode,\n\t* this prediction mode instructs the prediction algorithm to determine the\n\t* complete and exact set of ambiguous alternatives for every ambiguous\n\t* decision encountered while parsing.\n\t*\n\t*\n\t* This prediction mode may be used for diagnosing ambiguities during\n\t* grammar development. Due to the performance overhead of calculating sets\n\t* of ambiguous alternatives, this prediction mode should be avoided when\n\t* the exact results are not necessary.\n\t*\n\t*\n\t* This prediction mode does not provide any guarantees for prediction\n\t* behavior for syntactically-incorrect inputs.\n\t*/\n\tstatic LL_EXACT_AMBIG_DETECTION = 2;\n\t/**\n\t*\n\t*Computes the SLL prediction termination condition.\n\t*\n\t*\n\t*This method computes the SLL prediction termination condition for both of\n\t*the following cases.\n\t*\n\t* - The usual SLL+LL fallback upon SLL conflict\n\t* - Pure SLL without LL fallback\n\t*\n\t***COMBINED SLL+LL PARSING**\n\t*\n\t*When LL-fallback is enabled upon SLL conflict, correct predictions are\n\t*ensured regardless of how the termination condition is computed by this\n\t*method. Due to the substantially higher cost of LL prediction, the\n\t*prediction should only fall back to LL when the additional lookahead\n\t*cannot lead to a unique SLL prediction.\n\t*\n\t*Assuming combined SLL+LL parsing, an SLL configuration set with only\n\t*conflicting subsets should fall back to full LL, even if the\n\t*configuration sets don't resolve to the same alternative (e.g.\n\t*`{1,2`} and `{3,4`}. If there is at least one non-conflicting\n\t*configuration, SLL could continue with the hopes that more lookahead will\n\t*resolve via one of those non-conflicting configurations.\n\t*\n\t*Here's the prediction termination rule them: SLL (for SLL+LL parsing)\n\t*stops when it sees only conflicting configuration subsets. In contrast,\n\t*full LL keeps going when there is uncertainty.\n\t*\n\t***HEURISTIC**\n\t*\n\t*As a heuristic, we stop prediction when we see any conflicting subset\n\t*unless we see a state that only has one alternative associated with it.\n\t*The single-alt-state thing lets prediction continue upon rules like\n\t*(otherwise, it would admit defeat too soon):\n\t*\n\t*`[12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) ';' ;`\n\t*\n\t*When the ATN simulation reaches the state before `';'`, it has a\n\t*DFA state that looks like: `[12|1|[], 6|2|[], 12|2|[]]`. Naturally\n\t*`12|1|[]` and `12|2|[]` conflict, but we cannot stop\n\t*processing this node because alternative to has another way to continue,\n\t*via `[6|2|[]]`.\n\t*\n\t*It also let's us continue for this rule:\n\t*\n\t*`[1|1|[], 1|2|[], 8|3|[]] a : A | A | A B ;`\n\t*\n\t*After matching input A, we reach the stop state for rule A, state 1.\n\t*State 8 is the state right before B. Clearly alternatives 1 and 2\n\t*conflict and no amount of further lookahead will separate the two.\n\t*However, alternative 3 will be able to continue and so we do not stop\n\t*working on this state. In the previous example, we're concerned with\n\t*states associated with the conflicting alternatives. Here alt 3 is not\n\t*associated with the conflicting configs, but since we can continue\n\t*looking for input reasonably, don't declare the state done.\n\t*\n\t***PURE SLL PARSING**\n\t*\n\t*To handle pure SLL parsing, all we have to do is make sure that we\n\t*combine stack contexts for configurations that differ only by semantic\n\t*predicate. From there, we can do the usual SLL termination heuristic.\n\t*\n\t***PREDICATES IN SLL+LL PARSING**\n\t*\n\t*SLL decisions don't evaluate predicates until after they reach DFA stop\n\t*states because they need to create the DFA cache that works in all\n\t*semantic situations. In contrast, full LL evaluates predicates collected\n\t*during start state computation so it can ignore predicates thereafter.\n\t*This means that SLL termination detection can totally ignore semantic\n\t*predicates.\n\t*\n\t*Implementation-wise, {@link ATNConfigSet} combines stack contexts but not\n\t*semantic predicate contexts so we might see two configurations like the\n\t*following.\n\t*\n\t*`(s, 1, x, {`), (s, 1, x', {p})}\n\t*\n\t*Before testing these configurations against others, we have to merge\n\t*`x` and `x'` (without modifying the existing configurations).\n\t*For example, we test `(x+x')==x''` when looking for conflicts in\n\t*the following configurations.\n\t*\n\t*`(s, 1, x, {`), (s, 1, x', {p}), (s, 2, x'', {})}\n\t*\n\t*If the configuration set has predicates (as indicated by\n\t*{@link ATNConfigSet//hasSemanticContext}), this algorithm makes a copy of\n\t*the configurations to strip out all of the predicates so that a standard\n\t*{@link ATNConfigSet} will merge everything ignoring predicates.\n\t*/\n\tstatic hasSLLConflictTerminatingPrediction(mode, configs) {\n\t\tif (_PredictionMode.allConfigsInRuleStopStates(configs)) return true;\n\t\tif (mode === _PredictionMode.SLL) {\n\t\t\tif (configs.hasSemanticContext) {\n\t\t\t\tconst dup = new ATNConfigSet();\n\t\t\t\tfor (let c of configs) {\n\t\t\t\t\tc = ATNConfig.duplicate(c, SemanticContext.NONE);\n\t\t\t\t\tdup.add(c);\n\t\t\t\t}\n\t\t\t\tconfigs = dup;\n\t\t\t}\n\t\t}\n\t\tconst altSets = _PredictionMode.getConflictingAltSubsets(configs);\n\t\treturn _PredictionMode.hasConflictingAltSet(altSets) && !_PredictionMode.hasStateAssociatedWithOneAlt(configs);\n\t}\n\t/**\n\t* Checks if any configuration in `configs` is in a\n\t* {@link RuleStopState}. Configurations meeting this condition have reached\n\t* the end of the decision rule (local context) or end of start rule (full\n\t* context).\n\t*\n\t* @param configs the configuration set to test\n\t* @returns `true` if any configuration in `configs` is in a\n\t* {@link RuleStopState}, otherwise `false`\n\t*/\n\tstatic hasConfigInRuleStopState(configs) {\n\t\tfor (const c of configs) if (c.state instanceof RuleStopState) return true;\n\t\treturn false;\n\t}\n\t/**\n\t* Checks if all configurations in `configs` are in a\n\t* {@link RuleStopState}. Configurations meeting this condition have reached\n\t* the end of the decision rule (local context) or end of start rule (full\n\t* context).\n\t*\n\t* @param configs the configuration set to test\n\t* @returns `true` if all configurations in `configs` are in a\n\t* {@link RuleStopState}, otherwise `false`\n\t*/\n\tstatic allConfigsInRuleStopStates(configs) {\n\t\tfor (const c of configs) if (!(c.state instanceof RuleStopState)) return false;\n\t\treturn true;\n\t}\n\t/**\n\t*\n\t* Full LL prediction termination.\n\t*\n\t* Can we stop looking ahead during ATN simulation or is there some\n\t* uncertainty as to which alternative we will ultimately pick, after\n\t* consuming more input? Even if there are partial conflicts, we might know\n\t* that everything is going to resolve to the same minimum alternative. That\n\t* means we can stop since no more lookahead will change that fact. On the\n\t* other hand, there might be multiple conflicts that resolve to different\n\t* minimums. That means we need more look ahead to decide which of those\n\t* alternatives we should predict.\n\t*\n\t* The basic idea is to split the set of configurations `C`, into\n\t* conflicting subsets `(s, _, ctx, _)` and singleton subsets with\n\t* non-conflicting configurations. Two configurations conflict if they have\n\t* identical {@link ATNConfig.state} and {@link ATNConfig.context} values\n\t* but different {@link ATNConfig.alt} value, e.g. `(s, i, ctx, _)`\n\t* and `(s, j, ctx, _)` for `i!=j`.\n\t*\n\t* Reduce these configuration subsets to the set of possible alternatives.\n\t* You can compute the alternative subsets in one pass as follows:\n\t*\n\t* `A_s,ctx = {i | (s, i, ctx, _)`} for each configuration in\n\t* `C` holding `s` and `ctx` fixed.\n\t*\n\t* Or in pseudo-code, for each configuration `c` in `C`:\n\t*\n\t* ```\n\t* map[c] U= c.{@link ATNConfig.alt alt} // map hash/equals uses s and x, not\n\t* alt and not pred\n\t* ```\n\t*\n\t* The values in `map` are the set of `A_s,ctx` sets.\n\t*\n\t* If `|A_s,ctx|=1` then there is no conflict associated with\n\t* `s` and `ctx`.\n\t*\n\t* Reduce the subsets to singletons by choosing a minimum of each subset. If\n\t* the union of these alternative subsets is a singleton, then no amount of\n\t* more lookahead will help us. We will always pick that alternative. If,\n\t* however, there is more than one alternative, then we are uncertain which\n\t* alternative to predict and must continue looking for resolution. We may\n\t* or may not discover an ambiguity in the future, even if there are no\n\t* conflicting subsets this round.\n\t*\n\t* The biggest sin is to terminate early because it means we've made a\n\t* decision but were uncertain as to the eventual outcome. We haven't used\n\t* enough lookahead. On the other hand, announcing a conflict too late is no\n\t* big deal; you will still have the conflict. It's just inefficient. It\n\t* might even look until the end of file.\n\t*\n\t* No special consideration for semantic predicates is required because\n\t* predicates are evaluated on-the-fly for full LL prediction, ensuring that\n\t* no configuration contains a semantic context during the termination\n\t* check.\n\t*\n\t* **CONFLICTING CONFIGS**\n\t*\n\t* Two configurations `(s, i, x)` and `(s, j, x')`, conflict when `i!=j` but `x=x'`. Because we merge all\n\t* `(s, i, _)` configurations together, that means that there are at most `n` configurations associated with state\n\t* `s` for `n` possible alternatives in the decision. The merged stacks complicate the comparison of configuration\n\t* contexts `x` and `x'`. Sam checks to see if one is a subset of the other by calling merge and checking to see\n\t* if the merged result is either `x` or `x'`. If the `x` associated with lowest alternative `i` is the superset,\n\t* then `i` is the only possible prediction since the others resolve to `min(i)` as well. However, if `x` is\n\t* associated with `j>i` then at least one stack configuration for `j` is not in conflict with alternative `i`.\n\t* The algorithm should keep going, looking for more lookahead due to the uncertainty.\n\t*\n\t* For simplicity, I'm doing a equality check between `x` and `x'` that lets the algorithm continue to consume\n\t* lookahead longer than necessary. The reason I like the equality is of course the simplicity but also because\n\t* that is the test you need to detect the alternatives that are actually in conflict.\n\t*\n\t* **CONTINUE/STOP RULE**\n\t*\n\t* Continue if union of resolved alternative sets from non-conflicting and conflicting alternative subsets has more\n\t* than one alternative. We are uncertain about which alternative to predict.\n\t*\n\t* The complete set of alternatives, `[i for (_,i,_)]`, tells us which alternatives are still in the running for\n\t* the amount of input we've consumed at this point. The conflicting sets let us to strip away configurations that\n\t* won't lead to more states because we resolve conflicts to the configuration with a minimum alternate for the\n\t* conflicting set.\n\t*\n\t* **CASES**\n\t*\n\t* - no conflicts and more than 1 alternative in set => continue\n\t* -  `(s, 1, x)`, `(s, 2, x)`, `(s, 3, z)`, `(s', 1, y)`, `(s', 2, y)` yields non-conflicting set `{3`} U\n\t*   conflicting sets `min({1,2`)} U `min({1,2`)} = `{1,3`} => continue\n\t* - `(s, 1, x)`, `(s, 2, x)`, `(s', 1, y)`, `(s', 2, y)`, `(s'', 1, z)` yields non-conflicting set `{1`} U\n\t*   conflicting sets `min({1,2`)} U `min({1,2`)} = `{1`} => stop and predict 1\n\t* - `(s, 1, x)`, `(s, 2, x)`, `(s', 1, y)`, `(s', 2, y)` yields conflicting, reduced sets `{1`} U\n\t*   `{1`} = `{1`} => stop and predict 1, can announce ambiguity `{1,2`}\n\t* - `(s, 1, x)`, `(s, 2, x)`, `(s', 2, y)`, `(s', 3, y)` yields conflicting, reduced sets `{1`} U\n\t*   `{2`} = `{1,2`} => continue\n\t* - `(s, 1, x)`, `(s, 2, x)`, `(s', 3, y)`, `(s', 4, y)` yields conflicting, reduced sets `{1`} U\n\t*   `{3`} = `{1,3`} => continue\n\t*\n\t* **EXACT AMBIGUITY DETECTION**\n\t*\n\t*If all states report the same conflicting set of alternatives, then we\n\t*know we have the exact ambiguity set.\n\t*\n\t* `|A_*i*|>1` and `A_*i* = A_*j*` for all *i*, *j*.\n\t*\n\t* In other words, we continue examining lookahead until all `A_i` have more than one alternative and all `A_i`\n\t* are the same. If `A={{1,2`, {1,3}}}, then regular LL prediction would terminate because the resolved set\n\t* is `{1`}. To determine what the real ambiguity is, we have to know whether the ambiguity is between one and\n\t* two or one and three so we keep going. We can only stop prediction when we need exact ambiguity detection when\n\t* the sets look like `A={{1,2`}} or `{{1,2`,{1,2}}}, etc...\n\t*/\n\tstatic resolvesToJustOneViableAlt(altSets) {\n\t\treturn _PredictionMode.getSingleViableAlt(altSets);\n\t}\n\t/**\n\t* Determines if every alternative subset in `altSets` contains more\n\t* than one alternative.\n\t*\n\t* @param altSets a collection of alternative subsets\n\t* @returns `true` if every {@link BitSet} in `altSets` has\n\t* {@link BitSet//cardinality cardinality} > 1, otherwise `false`\n\t*/\n\tstatic allSubsetsConflict(altSets) {\n\t\treturn !_PredictionMode.hasNonConflictingAltSet(altSets);\n\t}\n\t/**\n\t* Determines if any single alternative subset in `altSets` contains\n\t* exactly one alternative.\n\t*\n\t* @param altSets a collection of alternative subsets\n\t* @returns `true` if `altSets` contains a {@link BitSet} with\n\t* {@link BitSet//cardinality cardinality} 1, otherwise `false`\n\t*/\n\tstatic hasNonConflictingAltSet(altSets) {\n\t\tfor (const alts of altSets) if (alts.length === 1) return true;\n\t\treturn false;\n\t}\n\t/**\n\t* Determines if any single alternative subset in `altSets` contains\n\t* more than one alternative.\n\t*\n\t* @param altSets a collection of alternative subsets\n\t* @returns `true` if `altSets` contains a {@link BitSet} with\n\t* {@link BitSet//cardinality cardinality} > 1, otherwise `false`\n\t*/\n\tstatic hasConflictingAltSet(altSets) {\n\t\tfor (const alts of altSets) if (alts.length > 1) return true;\n\t\treturn false;\n\t}\n\t/**\n\t* Determines if every alternative subset in `altSets` is equivalent.\n\t*\n\t* @param altSets a collection of alternative subsets\n\t* @returns `true` if every member of `altSets` is equal to the\n\t* others, otherwise `false`\n\t*/\n\tstatic allSubsetsEqual(altSets) {\n\t\tlet first = null;\n\t\tfor (const alts of altSets) if (first === null) first = alts;\n\t\telse if (alts !== first) return false;\n\t\treturn true;\n\t}\n\t/**\n\t* Returns the unique alternative predicted by all alternative subsets in\n\t* `altSets`. If no such alternative exists, this method returns\n\t* {@link ATN.INVALID_ALT_NUMBER}.\n\t*\n\t* @param altSets a collection of alternative subsets\n\t*/\n\tstatic getUniqueAlt(altSets) {\n\t\tconst all = _PredictionMode.getAlts(altSets);\n\t\tif (all.length === 1) return all.nextSetBit(0);\n\t\telse return ATN.INVALID_ALT_NUMBER;\n\t}\n\t/**\n\t* Gets the complete set of represented alternatives for a collection of\n\t* alternative subsets. This method returns the union of each {@link BitSet}\n\t* in `altSets`.\n\t*\n\t* @param altSets a collection of alternative subsets\n\t* @returns the set of represented alternatives in `altSets`\n\t*/\n\tstatic getAlts(altSets) {\n\t\tconst all = new BitSet();\n\t\taltSets.forEach((alts) => {\n\t\t\tall.or(alts);\n\t\t});\n\t\treturn all;\n\t}\n\t/**\n\t* This function gets the conflicting alt subsets from a configuration set.\n\t* For each configuration `c` in `configs`:\n\t*\n\t* ```\n\t* map[c] U= c.{@link ATNConfig.alt alt} // map hash/equals uses s and x, not\n\t* alt and not pred\n\t* ```\n\t*/\n\tstatic getConflictingAltSubsets(configs) {\n\t\tconst configToAlts = new HashMap(SubsetEqualityComparer.instance);\n\t\tfor (const cfg of configs) {\n\t\t\tlet alts = configToAlts.get(cfg);\n\t\t\tif (!alts) {\n\t\t\t\talts = new BitSet();\n\t\t\t\tconfigToAlts.set(cfg, alts);\n\t\t\t}\n\t\t\talts.set(cfg.alt);\n\t\t}\n\t\treturn Array.from(configToAlts.values());\n\t}\n\t/**\n\t* Get a map from state to alt subset from a configuration set. For each configuration `c` in `configs`:\n\t*\n\t* ```\n\t* map[c.state] = c.alt\n\t* ```\n\t*/\n\tstatic getStateToAltMap(configs) {\n\t\tconst m2 = new HashMap(ObjectEqualityComparator.instance);\n\t\tfor (const c of configs) {\n\t\t\tlet alts = m2.get(c.state);\n\t\t\tif (!alts) {\n\t\t\t\talts = new BitSet();\n\t\t\t\tm2.set(c.state, alts);\n\t\t\t}\n\t\t\talts.set(c.alt);\n\t\t}\n\t\treturn m2;\n\t}\n\tstatic hasStateAssociatedWithOneAlt(configs) {\n\t\tconst counts = {};\n\t\tfor (const c of configs) {\n\t\t\tconst stateNumber = c.state.stateNumber;\n\t\t\tif (!counts[stateNumber]) counts[stateNumber] = 0;\n\t\t\tcounts[stateNumber]++;\n\t\t}\n\t\treturn Object.values(counts).some((count) => {\n\t\t\treturn count === 1;\n\t\t});\n\t}\n\tstatic getSingleViableAlt(altSets) {\n\t\tlet result = null;\n\t\tfor (const alts of altSets) {\n\t\t\tconst minAlt = alts.nextSetBit(0);\n\t\t\tif (result === null) result = minAlt;\n\t\t\telse if (result !== minAlt) return ATN.INVALID_ALT_NUMBER;\n\t\t}\n\t\treturn result ?? 0;\n\t}\n};\nvar ParserATNSimulator = class _ParserATNSimulator extends ATNSimulator {\n\tstatic {\n\t\t__name(this, \"ParserATNSimulator\");\n\t}\n\tstatic traceATNSimulator = false;\n\tstatic debug;\n\tstatic debugAdd = false;\n\tstatic debugClosure = false;\n\tstatic dfaDebug = false;\n\tstatic retryDebug = false;\n\t/** SLL, LL, or LL + exact ambig detection? */\n\tpredictionMode;\n\tdecisionToDFA;\n\tparser;\n\t/**\n\t* Each prediction operation uses a cache for merge of prediction contexts.\n\t* Don't keep around as it wastes huge amounts of memory. DoubleKeyMap\n\t* isn't synchronized but we're ok since two threads shouldn't reuse same\n\t* parser/atn sim object because it can only handle one input at a time.\n\t* This maps graphs a and b to merged result c. (a,b)->c. We can avoid\n\t* the merge if we ever see a and b again.  Note that (b,a)->c should\n\t* also be examined during cache lookup.\n\t*/\n\tmergeCache = new DoubleDict();\n\tpredictionState;\n\tconstructor(recog, atn, decisionToDFA, sharedContextCache) {\n\t\tsuper(atn, sharedContextCache);\n\t\tthis.parser = recog;\n\t\tthis.decisionToDFA = decisionToDFA;\n\t}\n\tstatic getUniqueAlt(configs) {\n\t\tlet alt = ATN.INVALID_ALT_NUMBER;\n\t\tfor (const c of configs) if (alt === ATN.INVALID_ALT_NUMBER) alt = c.alt;\n\t\telse if (c.alt !== alt) return ATN.INVALID_ALT_NUMBER;\n\t\treturn alt;\n\t}\n\treset() {}\n\tclearDFA() {\n\t\tfor (let d = 0; d < this.decisionToDFA.length; d++) this.decisionToDFA[d] = new DFA(this.atn.getDecisionState(d), d);\n\t}\n\tadaptivePredict(input, decision, outerContext) {\n\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.traceATNSimulator) console.log(\"adaptivePredict decision \" + decision + \" exec LA(1)==\" + this.getLookaheadName(input) + \" line \" + input.LT(1).line + \":\" + input.LT(1).column);\n\t\tconst dfa = this.decisionToDFA[decision];\n\t\tthis.predictionState = {\n\t\t\tinput,\n\t\t\tstartIndex: input.index,\n\t\t\touterContext: outerContext ?? void 0,\n\t\t\tdfa\n\t\t};\n\t\tconst m2 = input.mark();\n\t\tconst index = input.index;\n\t\ttry {\n\t\t\tlet s0;\n\t\t\tif (dfa.isPrecedenceDfa) s0 = dfa.getPrecedenceStartState(this.parser.getPrecedence());\n\t\t\telse s0 = dfa.s0;\n\t\t\tif (!s0) {\n\t\t\t\tif (!outerContext) outerContext = ParserRuleContext.empty;\n\t\t\t\tif (_ParserATNSimulator.debug) console.log(\"predictATN decision \" + dfa.decision + \" exec LA(1)==\" + this.getLookaheadName(input) + \", outerContext=\" + outerContext.toString(this.parser.ruleNames));\n\t\t\t\tlet s0_closure = this.computeStartState(dfa.atnStartState, ParserRuleContext.empty, false);\n\t\t\t\tif (dfa.isPrecedenceDfa) {\n\t\t\t\t\ts0_closure = this.applyPrecedenceFilter(s0_closure);\n\t\t\t\t\ts0 = this.addDFAState(dfa, DFAState.fromConfigs(s0_closure));\n\t\t\t\t\tdfa.setPrecedenceStartState(this.parser.getPrecedence(), s0);\n\t\t\t\t} else {\n\t\t\t\t\ts0 = this.addDFAState(dfa, DFAState.fromConfigs(s0_closure));\n\t\t\t\t\tdfa.s0 = s0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst alt = this.execATN(dfa, s0, input, index, outerContext);\n\t\t\tif (_ParserATNSimulator.debug) console.log(\"DFA after predictATN: \" + dfa.toString(this.parser.vocabulary));\n\t\t\treturn alt;\n\t\t} finally {\n\t\t\tthis.predictionState.dfa = void 0;\n\t\t\tthis.mergeCache = new DoubleDict();\n\t\t\tinput.seek(index);\n\t\t\tinput.release(m2);\n\t\t}\n\t}\n\t/**\n\t* Performs ATN simulation to compute a predicted alternative based\n\t*  upon the remaining input, but also updates the DFA cache to avoid\n\t*  having to traverse the ATN again for the same input sequence.\n\t*\n\t* There are some key conditions we're looking for after computing a new\n\t* set of ATN configs (proposed DFA state):\n\t*       if the set is empty, there is no viable alternative for current symbol\n\t*       does the state uniquely predict an alternative?\n\t*       does the state have a conflict that would prevent us from\n\t*         putting it on the work list?\n\t*\n\t* We also have some key operations to do:\n\t*       add an edge from previous DFA state to potentially new DFA state, D,\n\t*         upon current symbol but only if adding to work list, which means in all\n\t*         cases except no viable alternative (and possibly non-greedy decisions?)\n\t*       collecting predicates and adding semantic context to DFA accept states\n\t*       adding rule context to context-sensitive DFA accept states\n\t*       consuming an input symbol\n\t*       reporting a conflict\n\t*       reporting an ambiguity\n\t*       reporting a context sensitivity\n\t*       reporting insufficient predicates\n\t*\n\t* cover these cases:\n\t*    dead end\n\t*    single alt\n\t*    single alt + preds\n\t*    conflict\n\t*    conflict + preds\n\t*/\n\texecATN(dfa, s0, input, startIndex, outerContext) {\n\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.traceATNSimulator) console.log(\"execATN decision \" + dfa.decision + \", DFA state \" + s0 + \", LA(1)==\" + this.getLookaheadName(input) + \" line \" + input.LT(1).line + \":\" + input.LT(1).column);\n\t\tlet alt;\n\t\tlet previousState = s0;\n\t\tlet t = input.LA(1);\n\t\twhile (true) {\n\t\t\tlet nextState = this.getExistingTargetState(previousState, t);\n\t\t\tif (!nextState) nextState = this.computeTargetState(dfa, previousState, t);\n\t\t\tif (nextState === ATNSimulator.ERROR) {\n\t\t\t\tconst e = this.noViableAlt(input, outerContext, previousState.configs, startIndex);\n\t\t\t\tinput.seek(startIndex);\n\t\t\t\talt = this.getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousState.configs, outerContext);\n\t\t\t\tif (alt !== ATN.INVALID_ALT_NUMBER) return alt;\n\t\t\t\telse throw e;\n\t\t\t}\n\t\t\tif (nextState.requiresFullContext && this.predictionMode !== PredictionMode.SLL) {\n\t\t\t\tlet conflictingAlts = null;\n\t\t\t\tif (nextState.predicates !== null) {\n\t\t\t\t\tif (_ParserATNSimulator.debug) console.log(\"DFA state has preds in DFA sim LL failover\");\n\t\t\t\t\tconst conflictIndex = input.index;\n\t\t\t\t\tif (conflictIndex !== startIndex) input.seek(startIndex);\n\t\t\t\t\tconflictingAlts = this.evalSemanticContext(nextState.predicates, outerContext, true);\n\t\t\t\t\tif (conflictingAlts.length === 1) {\n\t\t\t\t\t\tif (_ParserATNSimulator.debug) console.log(\"Full LL avoided\");\n\t\t\t\t\t\treturn conflictingAlts.nextSetBit(0);\n\t\t\t\t\t}\n\t\t\t\t\tif (conflictIndex !== startIndex) input.seek(conflictIndex);\n\t\t\t\t}\n\t\t\t\tif (_ParserATNSimulator.dfaDebug) console.log(\"ctx sensitive state \" + outerContext + \" in \" + nextState);\n\t\t\t\tconst s0_closure = this.computeStartState(dfa.atnStartState, outerContext, true);\n\t\t\t\tthis.reportAttemptingFullContext(dfa, conflictingAlts, nextState.configs, startIndex, input.index);\n\t\t\t\talt = this.execATNWithFullContext(dfa, nextState, s0_closure, input, startIndex, outerContext);\n\t\t\t\treturn alt;\n\t\t\t}\n\t\t\tif (nextState.isAcceptState) {\n\t\t\t\tif (nextState.predicates === null) return nextState.prediction;\n\t\t\t\tconst stopIndex = input.index;\n\t\t\t\tinput.seek(startIndex);\n\t\t\t\tconst alts = this.evalSemanticContext(nextState.predicates, outerContext, true);\n\t\t\t\tif (alts.length === 0) throw this.noViableAlt(input, outerContext, nextState.configs, startIndex);\n\t\t\t\tif (alts.length === 1) return alts.nextSetBit(0);\n\t\t\t\tthis.reportAmbiguity(dfa, nextState, startIndex, stopIndex, false, alts, nextState.configs);\n\t\t\t\treturn alts.nextSetBit(0);\n\t\t\t}\n\t\t\tpreviousState = nextState;\n\t\t\tif (t !== Token.EOF) {\n\t\t\t\tinput.consume();\n\t\t\t\tt = input.LA(1);\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t* Get an existing target state for an edge in the DFA. If the target state\n\t* for the edge has not yet been computed or is otherwise not available,\n\t* this method returns `null`.\n\t*\n\t* @param previousD The current DFA state\n\t* @param t The next input symbol\n\t* @returns The existing target DFA state for the given input symbol\n\t* `t`, or `null` if the target state for this edge is not\n\t* already cached\n\t*/\n\tgetExistingTargetState(previousD, t) {\n\t\treturn previousD.edges[t + 1];\n\t}\n\t/**\n\t* Compute a target state for an edge in the DFA, and attempt to add the\n\t* computed state and corresponding edge to the DFA.\n\t*\n\t* @param dfa The DFA\n\t* @param previousD The current DFA state\n\t* @param t The next input symbol\n\t*\n\t* @returns The computed target DFA state for the given input symbol\n\t* `t`. If `t` does not lead to a valid DFA state, this method\n\t* returns {@link ERROR\n\t*/\n\tcomputeTargetState(dfa, previousD, t) {\n\t\tconst reach = this.computeReachSet(previousD.configs, t, false);\n\t\tif (reach === null) {\n\t\t\tthis.addDFAEdge(dfa, previousD, t, ATNSimulator.ERROR);\n\t\t\treturn ATNSimulator.ERROR;\n\t\t}\n\t\tlet D = DFAState.fromConfigs(reach);\n\t\tconst predictedAlt = _ParserATNSimulator.getUniqueAlt(reach);\n\t\tif (_ParserATNSimulator.debug) {\n\t\t\tconst altSubSets = PredictionMode.getConflictingAltSubsets(reach);\n\t\t\tconsole.log(\"SLL altSubSets=\" + arrayToString(altSubSets) + \", configs=\" + reach + \", predict=\" + predictedAlt + \", allSubsetsConflict=\" + PredictionMode.allSubsetsConflict(altSubSets) + \", conflictingAlts=\" + this.getConflictingAlts(reach));\n\t\t}\n\t\tif (predictedAlt !== ATN.INVALID_ALT_NUMBER) {\n\t\t\tD.isAcceptState = true;\n\t\t\tD.configs.uniqueAlt = predictedAlt;\n\t\t\tD.prediction = predictedAlt;\n\t\t} else if (PredictionMode.hasSLLConflictTerminatingPrediction(this.predictionMode, reach)) {\n\t\t\tD.configs.conflictingAlts = this.getConflictingAlts(reach);\n\t\t\tD.requiresFullContext = true;\n\t\t\tD.isAcceptState = true;\n\t\t\tD.prediction = D.configs.conflictingAlts.nextSetBit(0);\n\t\t}\n\t\tif (D.isAcceptState && D.configs.hasSemanticContext) {\n\t\t\tthis.predicateDFAState(D, this.atn.getDecisionState(dfa.decision));\n\t\t\tif (D.predicates !== null) D.prediction = ATN.INVALID_ALT_NUMBER;\n\t\t}\n\t\tD = this.addDFAEdge(dfa, previousD, t, D);\n\t\treturn D;\n\t}\n\tgetRuleName(index) {\n\t\tif (this.parser !== null && index >= 0) return this.parser.ruleNames[index];\n\t\telse return \"<rule \" + index + \">\";\n\t}\n\tgetTokenName(t) {\n\t\tif (t === Token.EOF) return \"EOF\";\n\t\tconst displayName = (this.parser?.vocabulary ?? Vocabulary.EMPTY_VOCABULARY).getDisplayName(t);\n\t\tif (displayName === t.toString()) return displayName;\n\t\treturn displayName + \"<\" + t + \">\";\n\t}\n\tgetLookaheadName(input) {\n\t\treturn this.getTokenName(input.LA(1));\n\t}\n\t/**\n\t* Used for debugging in adaptivePredict around execATN but I cut\n\t* it out for clarity now that alg. works well. We can leave this\n\t* \"dead\" code for a bit\n\t*/\n\tdumpDeadEndConfigs(e) {\n\t\tconsole.log(\"dead end configs: \");\n\t\tconst decs = e.deadEndConfigs;\n\t\tfor (const c of decs) {\n\t\t\tlet trans = \"no edges\";\n\t\t\tif (c.state.transitions.length > 0) {\n\t\t\t\tconst t = c.state.transitions[0];\n\t\t\t\tif (t instanceof AtomTransition) trans = \"Atom \" + this.getTokenName(t.labelValue);\n\t\t\t\telse if (t instanceof SetTransition) trans = (t instanceof NotSetTransition ? \"~\" : \"\") + \"Set \" + t.label;\n\t\t\t}\n\t\t\tconsole.error(c.toString(this.parser, true) + \":\" + trans);\n\t\t}\n\t}\n\tpredicateDFAState(dfaState, decisionState) {\n\t\tconst altCount = decisionState.transitions.length;\n\t\tconst altsToCollectPredsFrom = this.getConflictingAltsOrUniqueAlt(dfaState.configs);\n\t\tconst altToPred = this.getPredsForAmbigAlts(altsToCollectPredsFrom, dfaState.configs, altCount);\n\t\tif (altToPred !== null) {\n\t\t\tdfaState.predicates = this.getPredicatePredictions(altsToCollectPredsFrom, altToPred);\n\t\t\tdfaState.prediction = ATN.INVALID_ALT_NUMBER;\n\t\t} else dfaState.prediction = altsToCollectPredsFrom.nextSetBit(0);\n\t}\n\texecATNWithFullContext(dfa, D, s0, input, startIndex, outerContext) {\n\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.traceATNSimulator) console.log(\"execATNWithFullContext \" + s0);\n\t\tconst fullCtx = true;\n\t\tlet foundExactAmbig = false;\n\t\tlet reach;\n\t\tlet previous = s0;\n\t\tinput.seek(startIndex);\n\t\tlet t = input.LA(1);\n\t\tlet predictedAlt = -1;\n\t\tfor (;;) {\n\t\t\treach = this.computeReachSet(previous, t, fullCtx);\n\t\t\tif (reach === null) {\n\t\t\t\tconst e = this.noViableAlt(input, outerContext, previous, startIndex);\n\t\t\t\tinput.seek(startIndex);\n\t\t\t\tconst alt = this.getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext);\n\t\t\t\tif (alt !== ATN.INVALID_ALT_NUMBER) return alt;\n\t\t\t\telse throw e;\n\t\t\t}\n\t\t\tconst altSubSets = PredictionMode.getConflictingAltSubsets(reach);\n\t\t\tif (_ParserATNSimulator.debug) console.log(\"LL altSubSets=\" + altSubSets + \", predict=\" + PredictionMode.getUniqueAlt(altSubSets) + \", resolvesToJustOneViableAlt=\" + PredictionMode.resolvesToJustOneViableAlt(altSubSets));\n\t\t\treach.uniqueAlt = _ParserATNSimulator.getUniqueAlt(reach);\n\t\t\tif (reach.uniqueAlt !== ATN.INVALID_ALT_NUMBER) {\n\t\t\t\tpredictedAlt = reach.uniqueAlt;\n\t\t\t\tbreak;\n\t\t\t} else if (this.predictionMode !== PredictionMode.LL_EXACT_AMBIG_DETECTION) {\n\t\t\t\tpredictedAlt = PredictionMode.resolvesToJustOneViableAlt(altSubSets);\n\t\t\t\tif (predictedAlt !== ATN.INVALID_ALT_NUMBER) break;\n\t\t\t} else if (PredictionMode.allSubsetsConflict(altSubSets) && PredictionMode.allSubsetsEqual(altSubSets)) {\n\t\t\t\tfoundExactAmbig = true;\n\t\t\t\tpredictedAlt = PredictionMode.getSingleViableAlt(altSubSets);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprevious = reach;\n\t\t\tif (t !== Token.EOF) {\n\t\t\t\tinput.consume();\n\t\t\t\tt = input.LA(1);\n\t\t\t}\n\t\t}\n\t\tif (reach.uniqueAlt !== ATN.INVALID_ALT_NUMBER) {\n\t\t\tthis.reportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.index);\n\t\t\treturn predictedAlt;\n\t\t}\n\t\tthis.reportAmbiguity(dfa, D, startIndex, input.index, foundExactAmbig, reach.getAlts(), reach);\n\t\treturn predictedAlt;\n\t}\n\tcomputeReachSet(closure, t, fullCtx) {\n\t\tif (_ParserATNSimulator.debug) console.log(\"in computeReachSet, starting closure: \" + closure);\n\t\tconst intermediate = new ATNConfigSet(fullCtx);\n\t\tlet skippedStopStates = null;\n\t\tfor (const c of closure) {\n\t\t\tif (_ParserATNSimulator.debug) console.log(\"testing \" + this.getTokenName(t) + \" at \" + c);\n\t\t\tif (c.state instanceof RuleStopState) {\n\t\t\t\tif (fullCtx || t === Token.EOF) {\n\t\t\t\t\tif (skippedStopStates === null) skippedStopStates = [];\n\t\t\t\t\tskippedStopStates.push(c);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const trans of c.state.transitions) {\n\t\t\t\tconst target = this.getReachableTarget(trans, t);\n\t\t\t\tif (target !== null) {\n\t\t\t\t\tconst cfg = ATNConfig.createWithConfig(target, c);\n\t\t\t\t\tintermediate.add(cfg, this.mergeCache);\n\t\t\t\t\tif (_ParserATNSimulator.debugAdd) console.log(\"added \" + cfg + \" to intermediate\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlet reach = null;\n\t\tif (skippedStopStates === null && t !== Token.EOF) {\n\t\t\tif (intermediate.length === 1) reach = intermediate;\n\t\t\telse if (_ParserATNSimulator.getUniqueAlt(intermediate) !== ATN.INVALID_ALT_NUMBER) reach = intermediate;\n\t\t}\n\t\tif (reach === null) {\n\t\t\treach = new ATNConfigSet(fullCtx);\n\t\t\tconst closureBusy = new HashSet();\n\t\t\tconst treatEofAsEpsilon = t === Token.EOF;\n\t\t\tfor (const config of intermediate) this.closure(config, reach, closureBusy, false, fullCtx, treatEofAsEpsilon);\n\t\t}\n\t\tif (t === Token.EOF) reach = this.removeAllConfigsNotInRuleStopState(reach, reach === intermediate);\n\t\tif (skippedStopStates !== null && (!fullCtx || !PredictionMode.hasConfigInRuleStopState(reach))) for (const config of skippedStopStates) reach.add(config, this.mergeCache);\n\t\tif (_ParserATNSimulator.traceATNSimulator) console.log(\"computeReachSet \" + closure + \" -> \" + reach);\n\t\tif (reach.length === 0) return null;\n\t\telse return reach;\n\t}\n\t/**\n\t* Return a configuration set containing only the configurations from\n\t* `configs` which are in a {@link RuleStopState}. If all\n\t* configurations in `configs` are already in a rule stop state, this\n\t* method simply returns `configs`.\n\t*\n\t* When `lookToEndOfRule` is true, this method uses\n\t* {@link ATN.nextTokens} for each configuration in `configs` which is\n\t* not already in a rule stop state to see if a rule stop state is reachable\n\t* from the configuration via epsilon-only transitions.\n\t*\n\t* @param configs the configuration set to update\n\t* @param lookToEndOfRule when true, this method checks for rule stop states\n\t* reachable by epsilon-only transitions from each configuration in\n\t* `configs`.\n\t*\n\t* @returns `configs` if all configurations in `configs` are in a\n\t* rule stop state, otherwise return a new configuration set containing only\n\t* the configurations from `configs` which are in a rule stop state\n\t*/\n\tremoveAllConfigsNotInRuleStopState(configs, lookToEndOfRule) {\n\t\tif (PredictionMode.allConfigsInRuleStopStates(configs)) return configs;\n\t\tconst result = new ATNConfigSet(configs.fullCtx);\n\t\tfor (const config of configs) {\n\t\t\tif (config.state instanceof RuleStopState) {\n\t\t\t\tresult.add(config, this.mergeCache);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (lookToEndOfRule && config.state.epsilonOnlyTransitions) {\n\t\t\t\tif (this.atn.nextTokens(config.state).contains(Token.EPSILON)) {\n\t\t\t\t\tconst endOfRuleState = this.atn.ruleToStopState[config.state.ruleIndex];\n\t\t\t\t\tresult.add(ATNConfig.createWithConfig(endOfRuleState, config), this.mergeCache);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\tcomputeStartState(p, ctx, fullCtx) {\n\t\tconst initialContext = predictionContextFromRuleContext(this.atn, ctx);\n\t\tconst configs = new ATNConfigSet(fullCtx);\n\t\tif (_ParserATNSimulator.traceATNSimulator) console.log(\"computeStartState from ATN state \" + p + \" initialContext=\" + initialContext.toString(this.parser));\n\t\tfor (let i = 0; i < p.transitions.length; i++) {\n\t\t\tconst target = p.transitions[i].target;\n\t\t\tconst c = ATNConfig.createWithContext(target, i + 1, initialContext);\n\t\t\tconst closureBusy = new HashSet();\n\t\t\tthis.closure(c, configs, closureBusy, true, fullCtx, false);\n\t\t}\n\t\treturn configs;\n\t}\n\t/**\n\t* This method transforms the start state computed by\n\t* {@link computeStartState} to the special start state used by a\n\t* precedence DFA for a particular precedence value. The transformation\n\t* process applies the following changes to the start state's configuration\n\t* set.\n\t*\n\t* 1. Evaluate the precedence predicates for each configuration using\n\t* {@link SemanticContext//evalPrecedence}.\n\t* 2. Remove all configurations which predict an alternative greater than\n\t* 1, for which another configuration that predicts alternative 1 is in the\n\t* same ATN state with the same prediction context. This transformation is\n\t* valid for the following reasons:\n\t* 3. The closure block cannot contain any epsilon transitions which bypass\n\t* the body of the closure, so all states reachable via alternative 1 are\n\t* part of the precedence alternatives of the transformed left-recursive\n\t* rule.\n\t* 4. The \"primary\" portion of a left recursive rule cannot contain an\n\t* epsilon transition, so the only way an alternative other than 1 can exist\n\t* in a state that is also reachable via alternative 1 is by nesting calls\n\t* to the left-recursive rule, with the outer calls not being at the\n\t* preferred precedence level.\n\t*\n\t*\n\t* The prediction context must be considered by this filter to address\n\t* situations like the following.\n\t*\n\t* `\n\t* ```\n\t* grammar TA;\n\t* prog: statement* EOF;\n\t* statement: letterA | statement letterA 'b' ;\n\t* letterA: 'a';\n\t* ```\n\t* `\n\t*\n\t* If the above grammar, the ATN state immediately before the token\n\t* reference `'a'` in `letterA` is reachable from the left edge\n\t* of both the primary and closure blocks of the left-recursive rule\n\t* `statement`. The prediction context associated with each of these\n\t* configurations distinguishes between them, and prevents the alternative\n\t* which stepped out to `prog` (and then back in to `statement`\n\t* from being eliminated by the filter.\n\t*\n\t* @param configs The configuration set computed by\n\t* {@link computeStartState} as the start state for the DFA.\n\t* @returns The transformed configuration set representing the start state\n\t* for a precedence DFA at a particular precedence level (determined by\n\t* calling {@link Parser//getPrecedence})\n\t*/\n\tapplyPrecedenceFilter(configs) {\n\t\tconst statesFromAlt1 = [];\n\t\tconst configSet = new ATNConfigSet(configs.fullCtx);\n\t\tfor (const config of configs) {\n\t\t\tif (config.alt !== 1) continue;\n\t\t\tconst updatedContext = config.semanticContext.evalPrecedence(this.parser, this.predictionState.outerContext);\n\t\t\tif (updatedContext === null) continue;\n\t\t\tstatesFromAlt1[config.state.stateNumber] = config.context;\n\t\t\tif (updatedContext !== config.semanticContext) configSet.add(ATNConfig.duplicate(config, updatedContext), this.mergeCache);\n\t\t\telse configSet.add(config, this.mergeCache);\n\t\t}\n\t\tfor (const config of configs) {\n\t\t\tif (config.alt === 1) continue;\n\t\t\tif (!config.precedenceFilterSuppressed) {\n\t\t\t\tconst context = statesFromAlt1[config.state.stateNumber] || null;\n\t\t\t\tif (context !== null && context.equals(config.context)) continue;\n\t\t\t}\n\t\t\tconfigSet.add(config, this.mergeCache);\n\t\t}\n\t\treturn configSet;\n\t}\n\tgetReachableTarget(trans, ttype) {\n\t\tif (trans.matches(ttype, 0, this.atn.maxTokenType)) return trans.target;\n\t\telse return null;\n\t}\n\tgetPredsForAmbigAlts(ambigAlts, configs, altCount) {\n\t\tlet altToPred = [];\n\t\tfor (const c of configs) if (ambigAlts.get(c.alt)) altToPred[c.alt] = SemanticContext.orContext(altToPred[c.alt] ?? null, c.semanticContext);\n\t\tlet nPredAlts = 0;\n\t\tfor (let i = 1; i < altCount + 1; i++) {\n\t\t\tconst pred = altToPred[i] ?? null;\n\t\t\tif (pred === null) altToPred[i] = SemanticContext.NONE;\n\t\t\telse if (pred !== SemanticContext.NONE) nPredAlts += 1;\n\t\t}\n\t\tif (nPredAlts === 0) altToPred = null;\n\t\tif (_ParserATNSimulator.debug) console.log(\"getPredsForAmbigAlts result \" + arrayToString(altToPred));\n\t\treturn altToPred;\n\t}\n\tgetPredicatePredictions(ambigAlts, altToPred) {\n\t\tconst pairs = [];\n\t\tlet containsPredicate = false;\n\t\tfor (let i = 1; i < altToPred.length; i++) {\n\t\t\tconst pred = altToPred[i];\n\t\t\tif (ambigAlts.get(i)) pairs.push({\n\t\t\t\tpred,\n\t\t\t\talt: i\n\t\t\t});\n\t\t\tif (pred !== SemanticContext.NONE) containsPredicate = true;\n\t\t}\n\t\tif (!containsPredicate) return null;\n\t\treturn pairs;\n\t}\n\t/**\n\t* This method is used to improve the localization of error messages by\n\t* choosing an alternative rather than throwing a\n\t* {@link NoViableAltException} in particular prediction scenarios where the\n\t* {@link ERROR} state was reached during ATN simulation.\n\t*\n\t*\n\t* The default implementation of this method uses the following\n\t* algorithm to identify an ATN configuration which successfully parsed the\n\t* decision entry rule. Choosing such an alternative ensures that the\n\t* {@link ParserRuleContext} returned by the calling rule will be complete\n\t* and valid, and the syntax error will be reported later at a more\n\t* localized location.\n\t*\n\t* - If a syntactically valid path or paths reach the end of the decision rule and\n\t* they are semantically valid if predicated, return the min associated alt.\n\t* - Else, if a semantically invalid but syntactically valid path exist\n\t* or paths exist, return the minimum associated alt.\n\t*\n\t* - Otherwise, return {@link ATN//INVALID_ALT_NUMBER}.\n\t*\n\t*\n\t* In some scenarios, the algorithm described above could predict an\n\t* alternative which will result in a {@link FailedPredicateException} in\n\t* the parser. Specifically, this could occur if the *only* configuration\n\t* capable of successfully parsing to the end of the decision rule is\n\t* blocked by a semantic predicate. By choosing this alternative within\n\t* {@link adaptivePredict} instead of throwing a\n\t* {@link NoViableAltException}, the resulting\n\t* {@link FailedPredicateException} in the parser will identify the specific\n\t* predicate which is preventing the parser from successfully parsing the\n\t* decision rule, which helps developers identify and correct logic errors\n\t* in semantic predicates.\n\t*\n\t* @param configs The ATN configurations which were valid immediately before\n\t* the {@link ERROR} state was reached\n\t* @param outerContext The is the \\gamma_0 initial parser context from the paper\n\t* or the parser stack at the instant before prediction commences.\n\t*\n\t* @returns The value to return from {@link adaptivePredict}, or\n\t* {@link ATN//INVALID_ALT_NUMBER} if a suitable alternative was not\n\t* identified and {@link adaptivePredict} should report an error instead\n\t*/\n\tgetSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(configs, outerContext) {\n\t\tconst splitConfigs = this.splitAccordingToSemanticValidity(configs, outerContext);\n\t\tconst semValidConfigs = splitConfigs[0];\n\t\tconst semInvalidConfigs = splitConfigs[1];\n\t\tlet alt = this.getAltThatFinishedDecisionEntryRule(semValidConfigs);\n\t\tif (alt !== ATN.INVALID_ALT_NUMBER) return alt;\n\t\tif (semInvalidConfigs.length > 0) {\n\t\t\talt = this.getAltThatFinishedDecisionEntryRule(semInvalidConfigs);\n\t\t\tif (alt !== ATN.INVALID_ALT_NUMBER) return alt;\n\t\t}\n\t\treturn ATN.INVALID_ALT_NUMBER;\n\t}\n\tgetAltThatFinishedDecisionEntryRule(configs) {\n\t\tconst alts = [];\n\t\tfor (const c of configs) if (c.reachesIntoOuterContext || c.state instanceof RuleStopState && c.context.hasEmptyPath()) {\n\t\t\tif (alts.indexOf(c.alt) < 0) alts.push(c.alt);\n\t\t}\n\t\tif (alts.length === 0) return ATN.INVALID_ALT_NUMBER;\n\t\telse return Math.min(...alts);\n\t}\n\t/**\n\t* Walk the list of configurations and split them according to\n\t* those that have preds evaluating to true/false.  If no pred, assume\n\t* true pred and include in succeeded set.  Returns Pair of sets.\n\t*\n\t* Create a new set so as not to alter the incoming parameter.\n\t*\n\t* Assumption: the input stream has been restored to the starting point\n\t* prediction, which is where predicates need to evaluate.\n\t*/\n\tsplitAccordingToSemanticValidity(configs, outerContext) {\n\t\tconst succeeded = new ATNConfigSet(configs.fullCtx);\n\t\tconst failed = new ATNConfigSet(configs.fullCtx);\n\t\tfor (const c of configs) if (c.semanticContext !== SemanticContext.NONE) if (c.semanticContext.evaluate(this.parser, outerContext)) succeeded.add(c);\n\t\telse failed.add(c);\n\t\telse succeeded.add(c);\n\t\treturn [succeeded, failed];\n\t}\n\t/**\n\t* Look through a list of predicate/alt pairs, returning alts for the\n\t* pairs that win. A `NONE` predicate indicates an alt containing an\n\t* unpredicated config which behaves as \"always true.\" If !complete\n\t* then we stop at the first predicate that evaluates to true. This\n\t* includes pairs with null predicates.\n\t*/\n\tevalSemanticContext(predPredictions, outerContext, complete) {\n\t\tconst predictions = new BitSet();\n\t\tfor (const pair of predPredictions) {\n\t\t\tif (pair.pred === SemanticContext.NONE) {\n\t\t\t\tpredictions.set(pair.alt);\n\t\t\t\tif (!complete) break;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst predicateEvaluationResult = pair.pred.evaluate(this.parser, outerContext);\n\t\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.dfaDebug) console.log(\"eval pred \" + pair + \"=\" + predicateEvaluationResult);\n\t\t\tif (predicateEvaluationResult) {\n\t\t\t\tpredictions.set(pair.alt);\n\t\t\t\tif (!complete) break;\n\t\t\t}\n\t\t}\n\t\treturn predictions;\n\t}\n\tclosure(config, configs, closureBusy, collectPredicates, fullCtx, treatEofAsEpsilon) {\n\t\tthis.closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, 0, treatEofAsEpsilon);\n\t}\n\tclosureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon) {\n\t\tif (_ParserATNSimulator.traceATNSimulator || _ParserATNSimulator.debugClosure) console.log(\"closure(\" + config.toString(this.parser, true) + \")\");\n\t\tif (config.state instanceof RuleStopState) {\n\t\t\tif (config.context && !config.context.isEmpty()) {\n\t\t\t\tfor (let i = 0; i < config.context.length; i++) {\n\t\t\t\t\tif (config.context.getReturnState(i) === PredictionContext.EMPTY_RETURN_STATE) {\n\t\t\t\t\t\tif (fullCtx) {\n\t\t\t\t\t\t\tconfigs.add(ATNConfig.createWithConfig(config.state, config, EmptyPredictionContext.instance), this.mergeCache);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (_ParserATNSimulator.debug) console.log(\"FALLING off rule \" + this.getRuleName(config.state.ruleIndex));\n\t\t\t\t\t\t\tthis.closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst returnState = this.atn.states[config.context.getReturnState(i)];\n\t\t\t\t\tconst newContext = config.context.getParent(i);\n\t\t\t\t\tconst c = ATNConfig.createWithContext(returnState, config.alt, newContext, config.semanticContext);\n\t\t\t\t\tc.reachesIntoOuterContext = config.reachesIntoOuterContext;\n\t\t\t\t\tthis.closureCheckingStopState(c, configs, closureBusy, collectPredicates, fullCtx, depth - 1, treatEofAsEpsilon);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (fullCtx) {\n\t\t\t\tconfigs.add(config, this.mergeCache);\n\t\t\t\treturn;\n\t\t\t} else if (_ParserATNSimulator.debug) console.log(\"FALLING off rule \" + this.getRuleName(config.state.ruleIndex));\n\t\t}\n\t\tthis.closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon);\n\t}\n\tclosure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon) {\n\t\tconst p = config.state;\n\t\tif (!p.epsilonOnlyTransitions) configs.add(config, this.mergeCache);\n\t\tfor (let i = 0; i < p.transitions.length; i++) {\n\t\t\tif (i === 0 && this.canDropLoopEntryEdgeInLeftRecursiveRule(config)) continue;\n\t\t\tconst t = p.transitions[i];\n\t\t\tconst continueCollecting = collectPredicates && !(t instanceof ActionTransition);\n\t\t\tconst c = this.getEpsilonTarget(config, t, continueCollecting, depth === 0, fullCtx, treatEofAsEpsilon);\n\t\t\tif (c) {\n\t\t\t\tlet newDepth = depth;\n\t\t\t\tif (config.state.constructor.stateType === ATNState.RULE_STOP) {\n\t\t\t\t\tif (this.predictionState.dfa && this.predictionState?.dfa.isPrecedenceDfa) {\n\t\t\t\t\t\tif (t.outermostPrecedenceReturn === this.predictionState?.dfa.atnStartState?.ruleIndex) c.precedenceFilterSuppressed = true;\n\t\t\t\t\t}\n\t\t\t\t\tc.reachesIntoOuterContext = true;\n\t\t\t\t\tif (closureBusy.getOrAdd(c) !== c) continue;\n\t\t\t\t\tconfigs.dipsIntoOuterContext = true;\n\t\t\t\t\tnewDepth -= 1;\n\t\t\t\t\tif (_ParserATNSimulator.debug) console.log(\"dips into outer ctx: \" + c);\n\t\t\t\t} else {\n\t\t\t\t\tif (!t.isEpsilon && closureBusy.getOrAdd(c) !== c) continue;\n\t\t\t\t\tif (t instanceof RuleTransition) {\n\t\t\t\t\t\tif (newDepth >= 0) newDepth += 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.closureCheckingStopState(c, configs, closureBusy, continueCollecting, fullCtx, newDepth, treatEofAsEpsilon);\n\t\t\t}\n\t\t}\n\t}\n\tcanDropLoopEntryEdgeInLeftRecursiveRule(config) {\n\t\tconst p = config.state;\n\t\tif (p.constructor.stateType !== ATNState.STAR_LOOP_ENTRY || !config.context) return false;\n\t\tif (!p.precedenceRuleDecision || config.context.isEmpty() || config.context.hasEmptyPath()) return false;\n\t\tconst numCtxs = config.context.length;\n\t\tfor (let i = 0; i < numCtxs; i++) if (this.atn.states[config.context.getReturnState(i)].ruleIndex !== p.ruleIndex) return false;\n\t\tconst blockEndStateNum = p.transitions[0].target.endState.stateNumber;\n\t\tconst blockEndState = this.atn.states[blockEndStateNum];\n\t\tfor (let i = 0; i < numCtxs; i++) {\n\t\t\tconst returnStateNumber = config.context.getReturnState(i);\n\t\t\tconst returnState = this.atn.states[returnStateNumber];\n\t\t\tif (returnState.transitions.length !== 1 || !returnState.transitions[0].isEpsilon) return false;\n\t\t\tconst returnStateTarget = returnState.transitions[0].target;\n\t\t\tif (returnState.constructor.stateType === ATNState.BLOCK_END && returnStateTarget === p) continue;\n\t\t\tif (returnState === blockEndState) continue;\n\t\t\tif (returnStateTarget === blockEndState) continue;\n\t\t\tif (returnStateTarget.constructor.stateType === ATNState.BLOCK_END && returnStateTarget.transitions.length === 1 && returnStateTarget.transitions[0].isEpsilon && returnStateTarget.transitions[0].target === p) continue;\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\tgetEpsilonTarget(config, t, collectPredicates, inContext, fullCtx, treatEofAsEpsilon) {\n\t\tswitch (t.transitionType) {\n\t\t\tcase Transition.RULE: return this.ruleTransition(config, t);\n\t\t\tcase Transition.PRECEDENCE: return this.precedenceTransition(config, t, collectPredicates, inContext, fullCtx);\n\t\t\tcase Transition.PREDICATE: return this.predTransition(config, t, collectPredicates, inContext, fullCtx);\n\t\t\tcase Transition.ACTION:\n\t\t\t\tif (_ParserATNSimulator.debug) {\n\t\t\t\t\tconst at = t;\n\t\t\t\t\tconst index = at.actionIndex === -1 ? 65535 : at.actionIndex;\n\t\t\t\t\tconsole.log(\"ACTION edge \" + at.ruleIndex + \":\" + index);\n\t\t\t\t}\n\t\t\t\treturn ATNConfig.createWithConfig(t.target, config);\n\t\t\tcase Transition.EPSILON: return ATNConfig.createWithConfig(t.target, config);\n\t\t\tcase Transition.ATOM:\n\t\t\tcase Transition.RANGE:\n\t\t\tcase Transition.SET:\n\t\t\t\tif (treatEofAsEpsilon) {\n\t\t\t\t\tif (t.matches(Token.EOF, 0, 1)) return ATNConfig.createWithConfig(t.target, config);\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\tdefault: return null;\n\t\t}\n\t}\n\tprecedenceTransition(config, pt, collectPredicates, inContext, fullCtx) {\n\t\tif (_ParserATNSimulator.debug) {\n\t\t\tconsole.log(\"PRED (collectPredicates=\" + collectPredicates + \") \" + pt.precedence + \">=_p, ctx dependent=true\");\n\t\t\tif (this.parser !== null) console.log(\"context surrounding pred is \" + arrayToString(this.parser.getRuleInvocationStack()));\n\t\t}\n\t\tlet c = null;\n\t\tif (collectPredicates && inContext) if (fullCtx && this.predictionState?.input) {\n\t\t\tconst currentPosition = this.predictionState.input.index;\n\t\t\tthis.predictionState.input.seek(this.predictionState.startIndex);\n\t\t\tconst predSucceeds = pt.getPredicate().evaluate(this.parser, this.predictionState.outerContext);\n\t\t\tthis.predictionState.input.seek(currentPosition);\n\t\t\tif (predSucceeds) c = ATNConfig.createWithConfig(pt.target, config);\n\t\t} else {\n\t\t\tconst newSemCtx = SemanticContext.andContext(config.semanticContext, pt.getPredicate());\n\t\t\tc = ATNConfig.createWithSemanticContext(pt.target, config, newSemCtx);\n\t\t}\n\t\telse c = ATNConfig.createWithConfig(pt.target, config);\n\t\tif (_ParserATNSimulator.debug) console.log(\"config from pred transition=\" + c);\n\t\treturn c;\n\t}\n\tpredTransition(config, pt, collectPredicates, inContext, fullCtx) {\n\t\tif (_ParserATNSimulator.debug) {\n\t\t\tconsole.log(\"PRED (collectPredicates=\" + collectPredicates + \") \" + pt.ruleIndex + \":\" + pt.predIndex + \", ctx dependent=\" + pt.isCtxDependent);\n\t\t\tif (this.parser !== null) console.log(\"context surrounding pred is \" + arrayToString(this.parser.getRuleInvocationStack()));\n\t\t}\n\t\tlet c = null;\n\t\tif (collectPredicates && (pt.isCtxDependent && inContext || !pt.isCtxDependent)) if (fullCtx && this.predictionState?.input) {\n\t\t\tconst currentPosition = this.predictionState.input.index;\n\t\t\tthis.predictionState.input.seek(this.predictionState.startIndex);\n\t\t\tconst predSucceeds = pt.getPredicate().evaluate(this.parser, this.predictionState.outerContext);\n\t\t\tthis.predictionState.input.seek(currentPosition);\n\t\t\tif (predSucceeds) c = ATNConfig.createWithConfig(pt.target, config);\n\t\t} else {\n\t\t\tconst newSemCtx = SemanticContext.andContext(config.semanticContext, pt.getPredicate());\n\t\t\tc = ATNConfig.createWithSemanticContext(pt.target, config, newSemCtx);\n\t\t}\n\t\telse c = ATNConfig.createWithConfig(pt.target, config);\n\t\tif (_ParserATNSimulator.debug) console.log(\"config from pred transition=\" + c);\n\t\treturn c;\n\t}\n\truleTransition(config, t) {\n\t\tif (_ParserATNSimulator.debug) console.log(\"CALL rule \" + this.getRuleName(t.target.ruleIndex) + \", ctx=\" + config.context);\n\t\tconst returnState = t.followState;\n\t\tconst newContext = createSingletonPredictionContext(config.context ?? void 0, returnState.stateNumber);\n\t\treturn ATNConfig.createWithConfig(t.target, config, newContext);\n\t}\n\tgetConflictingAlts(configs) {\n\t\tconst altSets = PredictionMode.getConflictingAltSubsets(configs);\n\t\treturn PredictionMode.getAlts(altSets);\n\t}\n\t/**\n\t* Sam pointed out a problem with the previous definition, v3, of\n\t* ambiguous states. If we have another state associated with conflicting\n\t* alternatives, we should keep going. For example, the following grammar\n\t*\n\t* s : (ID | ID ID?) ';' ;\n\t*\n\t* When the ATN simulation reaches the state before ';', it has a DFA\n\t* state that looks like: [12|1|[], 6|2|[], 12|2|[]]. Naturally\n\t* 12|1|[] and 12|2|[] conflict, but we cannot stop processing this node\n\t* because alternative to has another way to continue, via [6|2|[]].\n\t* The key is that we have a single state that has config's only associated\n\t* with a single alternative, 2, and crucially the state transitions\n\t* among the configurations are all non-epsilon transitions. That means\n\t* we don't consider any conflicts that include alternative 2. So, we\n\t* ignore the conflict between alts 1 and 2. We ignore a set of\n\t* conflicting alts when there is an intersection with an alternative\n\t* associated with a single alt state in the state -> config-list map.\n\t*\n\t* It's also the case that we might have two conflicting configurations but\n\t* also a 3rd nonconflicting configuration for a different alternative:\n\t* [1|1|[], 1|2|[], 8|3|[]]. This can come about from grammar:\n\t*\n\t* a : A | A | A B ;\n\t*\n\t* After matching input A, we reach the stop state for rule A, state 1.\n\t* State 8 is the state right before B. Clearly alternatives 1 and 2\n\t* conflict and no amount of further lookahead will separate the two.\n\t* However, alternative 3 will be able to continue and so we do not\n\t* stop working on this state. In the previous example, we're concerned\n\t* with states associated with the conflicting alternatives. Here alt\n\t* 3 is not associated with the conflicting configs, but since we can continue\n\t* looking for input reasonably, I don't declare the state done. We\n\t* ignore a set of conflicting alts when we have an alternative\n\t* that we still need to pursue\n\t*/\n\tgetConflictingAltsOrUniqueAlt(configs) {\n\t\tlet conflictingAlts;\n\t\tif (configs.uniqueAlt !== ATN.INVALID_ALT_NUMBER) {\n\t\t\tconflictingAlts = new BitSet();\n\t\t\tconflictingAlts.set(configs.uniqueAlt);\n\t\t} else conflictingAlts = configs.conflictingAlts;\n\t\treturn conflictingAlts;\n\t}\n\tnoViableAlt(input, outerContext, configs, startIndex) {\n\t\treturn new NoViableAltException(this.parser, input, input.get(startIndex), input.LT(1), configs, outerContext);\n\t}\n\t/**\n\t* Add an edge to the DFA, if possible. This method calls\n\t* {@link addDFAState} to ensure the `to` state is present in the\n\t* DFA. If `from` is `null`, or if `t` is outside the\n\t* range of edges that can be represented in the DFA tables, this method\n\t* returns without adding the edge to the DFA.\n\t*\n\t* If `to` is `null`, this method returns `null`.\n\t* Otherwise, this method returns the {@link DFAState} returned by calling\n\t* {@link addDFAState} for the `to` state.\n\t*\n\t* @param dfa The DFA\n\t* @param from The source state for the edge\n\t* @param t The input symbol\n\t* @param to The target state for the edge\n\t*\n\t* @returns If `to` is `null`, this method returns `null`;\n\t* otherwise this method returns the result of calling {@link addDFAState}\n\t* on `to`\n\t*/\n\taddDFAEdge(dfa, from, t, to) {\n\t\tif (_ParserATNSimulator.debug) console.log(\"EDGE \" + from + \" -> \" + to + \" upon \" + this.getTokenName(t));\n\t\tto = this.addDFAState(dfa, to);\n\t\tif (t < -1 || t > this.atn.maxTokenType) return to;\n\t\tif (_ParserATNSimulator.debug) console.log(\"DFA=\\n\" + dfa.toString(this.parser != null ? this.parser.vocabulary : Vocabulary.EMPTY_VOCABULARY));\n\t\tfrom.edges[t + 1] = to;\n\t\treturn to;\n\t}\n\t/**\n\t* Add state `D` to the DFA if it is not already present, and return\n\t* the actual instance stored in the DFA. If a state equivalent to `D`\n\t* is already in the DFA, the existing state is returned. Otherwise this\n\t* method returns `D` after adding it to the DFA.\n\t*\n\t* If `D` is {@link ERROR}, this method returns {@link ERROR} and\n\t* does not change the DFA.\n\t*\n\t* @param dfa The dfa.\n\t* @param newState The DFA state to add.\n\t*\n\t* @returns The state stored in the DFA. This will be either the existing state if `newState` is already in\n\t*          the DFA, or `newState` itself if the state was not already present.\n\t*/\n\taddDFAState(dfa, newState) {\n\t\tif (newState === ATNSimulator.ERROR) return newState;\n\t\tconst existing = dfa.getState(newState);\n\t\tif (existing !== null) return existing;\n\t\tif (!newState.configs.readOnly) {\n\t\t\tnewState.configs.optimizeConfigs(this);\n\t\t\tnewState.configs.setReadonly(true);\n\t\t}\n\t\tif (_ParserATNSimulator.traceATNSimulator) console.log(\"addDFAState new \" + newState);\n\t\tdfa.addState(newState);\n\t\treturn newState;\n\t}\n\treportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex) {\n\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.retryDebug) {\n\t\t\tconst interval = new Interval(startIndex, stopIndex + 1);\n\t\t\tconsole.log(\"reportAttemptingFullContext decision=\" + dfa.decision + \":\" + configs + \", input=\" + this.parser.tokenStream.getTextFromInterval(interval));\n\t\t}\n\t\tthis.parser.errorListenerDispatch.reportAttemptingFullContext(this.parser, dfa, startIndex, stopIndex, conflictingAlts, configs);\n\t}\n\treportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex) {\n\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.retryDebug) {\n\t\t\tconst interval = new Interval(startIndex, stopIndex + 1);\n\t\t\tconsole.log(\"reportContextSensitivity decision=\" + dfa.decision + \":\" + configs + \", input=\" + this.parser.tokenStream.getTextFromInterval(interval));\n\t\t}\n\t\tthis.parser.errorListenerDispatch.reportContextSensitivity(this.parser, dfa, startIndex, stopIndex, prediction, configs);\n\t}\n\treportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configs) {\n\t\tif (_ParserATNSimulator.debug || _ParserATNSimulator.retryDebug) {\n\t\t\tconst interval = new Interval(startIndex, stopIndex + 1);\n\t\t\tconsole.log(\"reportAmbiguity \" + ambigAlts + \":\" + configs + \", input=\" + this.parser.tokenStream.getTextFromInterval(interval));\n\t\t}\n\t\tthis.parser.errorListenerDispatch.reportAmbiguity(this.parser, dfa, startIndex, stopIndex, exact, ambigAlts, configs);\n\t}\n};\nvar PredictionContextCache = class {\n\tstatic {\n\t\t__name(this, \"PredictionContextCache\");\n\t}\n\tcache = new HashMap(ObjectEqualityComparator.instance);\n\t/**\n\t* Add a context to the cache and return it. If the context already exists,\n\t* return that one instead and do not add a new context to the cache.\n\t* Protect shared cache from unsafe thread access.\n\t*\n\t* @param ctx tbd\n\t* @returns tbd\n\t*/\n\tadd(ctx) {\n\t\tif (ctx === EmptyPredictionContext.instance) return ctx;\n\t\tconst existing = this.cache.get(ctx);\n\t\tif (existing) return existing;\n\t\tthis.cache.set(ctx, ctx);\n\t\treturn ctx;\n\t}\n\tget(ctx) {\n\t\treturn this.cache.get(ctx);\n\t}\n\tget length() {\n\t\treturn this.cache.size;\n\t}\n};\nvar ProfilingATNSimulator = class extends ParserATNSimulator {\n\tstatic {\n\t\t__name(this, \"ProfilingATNSimulator\");\n\t}\n\tdecisions;\n\tnumDecisions = 0;\n\tcurrentDecision = 0;\n\tcurrentState;\n\t/**\n\t* At the point of LL failover, we record how SLL would resolve the conflict so that\n\t*  we can determine whether or not a decision / input pair is context-sensitive.\n\t*  If LL gives a different result than SLL's predicted alternative, we have a\n\t*  context sensitivity for sure. The converse is not necessarily true, however.\n\t*  It's possible that after conflict resolution chooses minimum alternatives,\n\t*  SLL could get the same answer as LL. Regardless of whether or not the result indicates\n\t*  an ambiguity, it is not treated as a context sensitivity because LL prediction\n\t*  was not required in order to produce a correct prediction for this decision and input sequence.\n\t*  It may in fact still be a context sensitivity but we don't know by looking at the\n\t*  minimum alternatives for the current input.\n\t*/\n\tconflictingAltResolvedBySLL;\n\tsllStopIndex = 0;\n\tllStopIndex = 0;\n\tconstructor(parser) {\n\t\tconst sharedContextCache = parser.interpreter.sharedContextCache;\n\t\tsuper(parser, parser.interpreter.atn, parser.interpreter.decisionToDFA, sharedContextCache);\n\t\tif (sharedContextCache) {\n\t\t\tthis.numDecisions = this.atn.decisionToState.length;\n\t\t\tthis.decisions = new Array(this.numDecisions);\n\t\t\tfor (let i = 0; i < this.numDecisions; i++) this.decisions[i] = new DecisionInfo(i);\n\t\t}\n\t}\n\tadaptivePredict(input, decision, outerContext) {\n\t\ttry {\n\t\t\tthis.sllStopIndex = -1;\n\t\t\tthis.llStopIndex = -1;\n\t\t\tthis.currentDecision = decision;\n\t\t\tconst start = performance.now();\n\t\t\tconst alt = super.adaptivePredict(input, decision, outerContext);\n\t\t\tconst stop = performance.now();\n\t\t\tthis.decisions[decision].timeInPrediction += stop - start;\n\t\t\tthis.decisions[decision].invocations++;\n\t\t\tconst sllLook = this.sllStopIndex - this.predictionState.startIndex + 1;\n\t\t\tthis.decisions[decision].sllTotalLook += sllLook;\n\t\t\tthis.decisions[decision].sllMinLook = this.decisions[decision].sllMinLook === 0 ? sllLook : Math.min(this.decisions[decision].sllMinLook, sllLook);\n\t\t\tif (sllLook > this.decisions[decision].sllMaxLook) {\n\t\t\t\tthis.decisions[decision].sllMaxLook = sllLook;\n\t\t\t\tthis.decisions[decision].sllMaxLookEvent = {\n\t\t\t\t\tdecision,\n\t\t\t\t\tconfigs: null,\n\t\t\t\t\tpredictedAlt: alt,\n\t\t\t\t\tinput,\n\t\t\t\t\tstartIndex: this.predictionState.startIndex,\n\t\t\t\t\tstopIndex: this.sllStopIndex,\n\t\t\t\t\tfullCtx: false\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (this.llStopIndex >= 0) {\n\t\t\t\tconst llLook = this.llStopIndex - this.predictionState.startIndex + 1;\n\t\t\t\tthis.decisions[decision].llTotalLook += llLook;\n\t\t\t\tthis.decisions[decision].llMinLook = this.decisions[decision].llMinLook === 0 ? llLook : Math.min(this.decisions[decision].llMinLook, llLook);\n\t\t\t\tif (llLook > this.decisions[decision].llMaxLook) {\n\t\t\t\t\tthis.decisions[decision].llMaxLook = llLook;\n\t\t\t\t\tthis.decisions[decision].llMaxLookEvent = {\n\t\t\t\t\t\tdecision,\n\t\t\t\t\t\tconfigs: null,\n\t\t\t\t\t\tpredictedAlt: alt,\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tstartIndex: this.predictionState.startIndex,\n\t\t\t\t\t\tstopIndex: this.llStopIndex,\n\t\t\t\t\t\tfullCtx: true\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn alt;\n\t\t} finally {\n\t\t\tthis.currentDecision = -1;\n\t\t}\n\t}\n\tgetExistingTargetState(previousD, t) {\n\t\tthis.sllStopIndex = this.predictionState.input.index;\n\t\tconst existingTargetState = super.getExistingTargetState(previousD, t);\n\t\tif (existingTargetState !== void 0) {\n\t\t\tthis.decisions[this.currentDecision].sllDFATransitions++;\n\t\t\tif (existingTargetState === ATNSimulator.ERROR) this.decisions[this.currentDecision].errors.push({\n\t\t\t\tdecision: this.currentDecision,\n\t\t\t\tconfigs: previousD.configs,\n\t\t\t\tinput: this.predictionState.input,\n\t\t\t\tstartIndex: this.predictionState.startIndex,\n\t\t\t\tstopIndex: this.sllStopIndex,\n\t\t\t\tfullCtx: false\n\t\t\t});\n\t\t}\n\t\tthis.currentState = existingTargetState;\n\t\treturn existingTargetState;\n\t}\n\tcomputeTargetState(dfa, previousD, t) {\n\t\tconst state = super.computeTargetState(dfa, previousD, t);\n\t\tthis.currentState = state;\n\t\treturn state;\n\t}\n\tcomputeReachSet(closure, t, fullCtx) {\n\t\tif (fullCtx && this.predictionState?.input) this.llStopIndex = this.predictionState.input.index;\n\t\tconst reachConfigs = super.computeReachSet(closure, t, fullCtx);\n\t\tif (this.predictionState?.input) if (fullCtx) {\n\t\t\tthis.decisions[this.currentDecision].llATNTransitions++;\n\t\t\tif (reachConfigs === null) this.decisions[this.currentDecision].errors.push({\n\t\t\t\tdecision: this.currentDecision,\n\t\t\t\tconfigs: closure,\n\t\t\t\tinput: this.predictionState.input,\n\t\t\t\tstartIndex: this.predictionState.startIndex,\n\t\t\t\tstopIndex: this.sllStopIndex,\n\t\t\t\tfullCtx: true\n\t\t\t});\n\t\t} else {\n\t\t\tthis.decisions[this.currentDecision].sllATNTransitions++;\n\t\t\tif (reachConfigs === null) this.decisions[this.currentDecision].errors.push({\n\t\t\t\tdecision: this.currentDecision,\n\t\t\t\tconfigs: closure,\n\t\t\t\tinput: this.predictionState.input,\n\t\t\t\tstartIndex: this.predictionState.startIndex,\n\t\t\t\tstopIndex: this.sllStopIndex,\n\t\t\t\tfullCtx: false\n\t\t\t});\n\t\t}\n\t\treturn reachConfigs;\n\t}\n\treportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex) {\n\t\tif (conflictingAlts !== null) this.conflictingAltResolvedBySLL = conflictingAlts.nextSetBit(0);\n\t\telse this.conflictingAltResolvedBySLL = configs.getAlts().nextSetBit(0);\n\t\tthis.decisions[this.currentDecision].llFallback++;\n\t\tif (conflictingAlts) super.reportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex);\n\t}\n\treportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex) {\n\t\tif (prediction !== this.conflictingAltResolvedBySLL && this.predictionState.input) this.decisions[this.currentDecision].contextSensitivities.push({\n\t\t\tdecision: this.currentDecision,\n\t\t\tconfigs,\n\t\t\tinput: this.predictionState.input,\n\t\t\tstartIndex,\n\t\t\tstopIndex,\n\t\t\tfullCtx: true\n\t\t});\n\t\tsuper.reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);\n\t}\n\treportAmbiguity(dfa, state, startIndex, stopIndex, exact, ambigAlts, configs) {\n\t\tlet prediction;\n\t\tif (ambigAlts) prediction = ambigAlts.nextSetBit(0);\n\t\telse prediction = configs.getAlts().nextSetBit(0);\n\t\tif (this.predictionState?.input) {\n\t\t\tif (configs.fullCtx && prediction !== this.conflictingAltResolvedBySLL) this.decisions[this.currentDecision].contextSensitivities.push({\n\t\t\t\tdecision: this.currentDecision,\n\t\t\t\tconfigs,\n\t\t\t\tinput: this.predictionState.input,\n\t\t\t\tstartIndex,\n\t\t\t\tstopIndex,\n\t\t\t\tfullCtx: true\n\t\t\t});\n\t\t\tthis.decisions[this.currentDecision].ambiguities.push({\n\t\t\t\tambigAlts,\n\t\t\t\tdecision: this.currentDecision,\n\t\t\t\tconfigs,\n\t\t\t\tinput: this.predictionState.input,\n\t\t\t\tstartIndex,\n\t\t\t\tstopIndex,\n\t\t\t\tfullCtx: configs.fullCtx\n\t\t\t});\n\t\t}\n\t\tsuper.reportAmbiguity(dfa, state, startIndex, stopIndex, exact, ambigAlts, configs);\n\t}\n\tgetDecisionInfo() {\n\t\treturn this.decisions;\n\t}\n\tgetCurrentState() {\n\t\treturn this.currentState;\n\t}\n};\nvar PredPrediction;\n((PredPrediction2) => {\n\tPredPrediction2.toString = /* @__PURE__ */ __name((prediction) => {\n\t\treturn `(${prediction.pred}, ${prediction.alt})`;\n\t}, \"toString\");\n})(PredPrediction || (PredPrediction = {}));\nvar ParseCancellationException = class extends Error {\n\tstatic {\n\t\t__name(this, \"ParseCancellationException\");\n\t}\n\tconstructor(e) {\n\t\tsuper();\n\t\tthis.cause = e;\n\t}\n};\nvar InterpreterDataReader = class {\n\tstatic {\n\t\t__name(this, \"InterpreterDataReader\");\n\t}\n\t/**\n\t* The structure of the data file is very simple. Everything is line based with empty lines\n\t* separating the different parts. For lexers the layout is:\n\t* token literal names:\n\t* ...\n\t*\n\t* token symbolic names:\n\t* ...\n\t*\n\t* rule names:\n\t* ...\n\t*\n\t* channel names:\n\t* ...\n\t*\n\t* mode names:\n\t* ...\n\t*\n\t* atn:\n\t* a single line with comma separated int values, enclosed in a pair of squared brackets.\n\t*\n\t* Data for a parser does not contain channel and mode names.\n\t*/\n\tstatic parseInterpreterData(source) {\n\t\tconst ruleNames = [];\n\t\tconst channels = [];\n\t\tconst modes = [];\n\t\tconst literalNames = [];\n\t\tconst symbolicNames = [];\n\t\tconst lines = source.split(\"\\n\");\n\t\tlet index = 0;\n\t\tlet line = lines[index++];\n\t\tif (line !== \"token literal names:\") throw new Error(\"Unexpected data entry\");\n\t\tdo {\n\t\t\tline = lines[index++];\n\t\t\tif (line.length === 0) break;\n\t\t\tliteralNames.push(line === \"null\" ? null : line);\n\t\t} while (true);\n\t\tline = lines[index++];\n\t\tif (line !== \"token symbolic names:\") throw new Error(\"Unexpected data entry\");\n\t\tdo {\n\t\t\tline = lines[index++];\n\t\t\tif (line.length === 0) break;\n\t\t\tsymbolicNames.push(line === \"null\" ? null : line);\n\t\t} while (true);\n\t\tline = lines[index++];\n\t\tif (line !== \"rule names:\") throw new Error(\"Unexpected data entry\");\n\t\tdo {\n\t\t\tline = lines[index++];\n\t\t\tif (line.length === 0) break;\n\t\t\truleNames.push(line);\n\t\t} while (true);\n\t\tline = lines[index++];\n\t\tif (line === \"channel names:\") {\n\t\t\tdo {\n\t\t\t\tline = lines[index++];\n\t\t\t\tif (line.length === 0) break;\n\t\t\t\tchannels.push(line);\n\t\t\t} while (true);\n\t\t\tline = lines[index++];\n\t\t\tif (line !== \"mode names:\") throw new Error(\"Unexpected data entry\");\n\t\t\tdo {\n\t\t\t\tline = lines[index++];\n\t\t\t\tif (line.length === 0) break;\n\t\t\t\tmodes.push(line);\n\t\t\t} while (true);\n\t\t}\n\t\tline = lines[index++];\n\t\tif (line !== \"atn:\") throw new Error(\"Unexpected data entry\");\n\t\tline = lines[index++];\n\t\tconst elements = line.split(\",\");\n\t\tlet value;\n\t\tconst serializedATN = [];\n\t\tfor (let i = 0; i < elements.length; ++i) {\n\t\t\tconst element = elements[i];\n\t\t\tif (element.startsWith(\"[\")) value = Number(element.substring(1).trim());\n\t\t\telse if (element.endsWith(\"]\")) value = Number(element.substring(0, element.length - 1).trim());\n\t\t\telse value = Number(element.trim());\n\t\t\tserializedATN[i] = value;\n\t\t}\n\t\treturn {\n\t\t\tatn: new ATNDeserializer().deserialize(serializedATN),\n\t\t\tvocabulary: new Vocabulary(literalNames, symbolicNames, []),\n\t\t\truleNames,\n\t\t\tchannels: channels.length > 0 ? channels : void 0,\n\t\t\tmodes: modes.length > 0 ? modes : void 0\n\t\t};\n\t}\n};\nvar AbstractParseTreeVisitor = class {\n\tstatic {\n\t\t__name(this, \"AbstractParseTreeVisitor\");\n\t}\n\tvisit(tree) {\n\t\treturn tree.accept(this);\n\t}\n\tvisitChildren(node) {\n\t\tlet result = this.defaultResult();\n\t\tconst n2 = node.getChildCount();\n\t\tfor (let i = 0; i < n2; i++) {\n\t\t\tif (!this.shouldVisitNextChild(node, result)) break;\n\t\t\tconst c = node.getChild(i);\n\t\t\tif (c) {\n\t\t\t\tconst childResult = c.accept(this);\n\t\t\t\tresult = this.aggregateResult(result, childResult);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\tvisitTerminal(_node) {\n\t\treturn this.defaultResult();\n\t}\n\tvisitErrorNode(_node) {\n\t\treturn this.defaultResult();\n\t}\n\tdefaultResult() {\n\t\treturn null;\n\t}\n\tshouldVisitNextChild(_node, _currentResult) {\n\t\treturn true;\n\t}\n\taggregateResult(aggregate, nextResult) {\n\t\treturn nextResult;\n\t}\n};\nvar ParseTreeWalker = class _ParseTreeWalker {\n\tstatic {\n\t\t__name(this, \"ParseTreeWalker\");\n\t}\n\tstatic DEFAULT = new _ParseTreeWalker();\n\t/**\n\t* Performs a walk on the given parse tree starting at the root and going down recursively\n\t* with depth-first search. On each node, {@link ParseTreeWalker.enterRule} is called before\n\t* recursively walking down into child nodes, then\n\t* {@link ParseTreeWalker.exitRule} is called after the recursive call to wind up.\n\t*\n\t* @param listener The listener used by the walker to process grammar rules\n\t* @param t The parse tree to be walked on\n\t*/\n\twalk(listener, t) {\n\t\tif (t instanceof ErrorNode) listener.visitErrorNode(t);\n\t\telse if (t instanceof TerminalNode) listener.visitTerminal(t);\n\t\telse {\n\t\t\tconst r = t;\n\t\t\tthis.enterRule(listener, r);\n\t\t\tfor (let i = 0; i < t.getChildCount(); i++) this.walk(listener, t.getChild(i));\n\t\t\tthis.exitRule(listener, r);\n\t\t}\n\t}\n\t/**\n\t* Enters a grammar rule by first triggering the generic event {@link ParseTreeListener.enterEveryRule}\n\t* then by triggering the event specific to the given parse tree node\n\t*\n\t* @param listener The listener responding to the trigger events\n\t* @param r The grammar rule containing the rule context\n\t*/\n\tenterRule(listener, r) {\n\t\tconst ctx = r.ruleContext;\n\t\tlistener.enterEveryRule(ctx);\n\t\tctx.enterRule(listener);\n\t}\n\t/**\n\t* Exits a grammar rule by first triggering the event specific to the given parse tree node\n\t* then by triggering the generic event {@link ParseTreeListener.exitEveryRule}\n\t*\n\t* @param listener The listener responding to the trigger events\n\t* @param r The grammar rule containing the rule context\n\t*/\n\texitRule(listener, r) {\n\t\tconst ctx = r.ruleContext;\n\t\tctx.exitRule(listener);\n\t\tlistener.exitEveryRule(ctx);\n\t}\n};\nvar CharStream;\n((CharStream2) => {\n\tCharStream2.fromString = /* @__PURE__ */ __name((str) => {\n\t\treturn new CharStreamImpl(str);\n\t}, \"fromString\");\n})(CharStream || (CharStream = {}));\nvar CharStreamImpl = class {\n\tstatic {\n\t\t__name(this, \"CharStreamImpl\");\n\t}\n\tname = \"\";\n\tindex = 0;\n\tdata;\n\tconstructor(input) {\n\t\tconst codePoints = [];\n\t\tfor (const char of input) codePoints.push(char.codePointAt(0));\n\t\tthis.data = new Uint32Array(codePoints);\n\t}\n\t/**\n\t* Reset the stream so that it's in the same state it was\n\t* when the object was created *except* the data array is not\n\t* touched.\n\t*/\n\treset() {\n\t\tthis.index = 0;\n\t}\n\tconsume() {\n\t\tif (this.index >= this.data.length) throw new Error(\"cannot consume EOF\");\n\t\tthis.index += 1;\n\t}\n\tLA(offset) {\n\t\tif (offset === 0) return 0;\n\t\tif (offset < 0) offset += 1;\n\t\tconst pos = this.index + offset - 1;\n\t\tif (pos < 0 || pos >= this.data.length) return Token.EOF;\n\t\treturn this.data[pos];\n\t}\n\tmark() {\n\t\treturn -1;\n\t}\n\trelease(_marker) {}\n\t/**\n\t* consume() ahead until p==_index; can't just set p=_index as we must\n\t* update line and column. If we seek backwards, just set p\n\t*/\n\tseek(index) {\n\t\tif (index <= this.index) {\n\t\t\tthis.index = index;\n\t\t\treturn;\n\t\t}\n\t\tthis.index = Math.min(index, this.data.length);\n\t}\n\tgetTextFromRange(start, stop) {\n\t\tstop = stop ?? this.data.length - 1;\n\t\tif (stop >= this.data.length) stop = this.data.length - 1;\n\t\tif (start >= this.data.length) return \"\";\n\t\treturn this.stringFromRange(start, stop + 1);\n\t}\n\tgetTextFromInterval(interval) {\n\t\tconst start = interval.start;\n\t\tlet stop = interval.stop;\n\t\tif (stop >= this.data.length) stop = this.data.length - 1;\n\t\tif (start >= this.data.length) return \"\";\n\t\treturn this.stringFromRange(start, stop + 1);\n\t}\n\ttoString() {\n\t\treturn this.stringFromRange(0);\n\t}\n\tget size() {\n\t\treturn this.data.length;\n\t}\n\tgetSourceName() {\n\t\tif (this.name) return this.name;\n\t\treturn IntStream.UNKNOWN_SOURCE_NAME;\n\t}\n\tstringFromRange(start, stop) {\n\t\tconst data = this.data.slice(start, stop);\n\t\tlet result = \"\";\n\t\tdata.forEach((value) => {\n\t\t\tresult += String.fromCodePoint(value);\n\t\t});\n\t\treturn result;\n\t}\n};\nvar isWritableToken = /* @__PURE__ */ __name((candidate) => {\n\treturn candidate.setText !== void 0;\n}, \"isWritableToken\");\nvar BufferedTokenStream = class {\n\tstatic {\n\t\t__name(this, \"BufferedTokenStream\");\n\t}\n\t/**\n\t* The {@link TokenSource} from which tokens for this stream are fetched.\n\t*/\n\ttokenSource;\n\t/**\n\t* A collection of all tokens fetched from the token source. The list is\n\t* considered a complete view of the input once {@link fetchedEOF} is set\n\t* to `true`.\n\t*/\n\ttokens = [];\n\t/**\n\t* The index into {@link tokens} of the current token (next token to\n\t* {@link consume}). {@link tokens}`[p]` should be\n\t* {@link LT LT(1)}.\n\t*\n\t* This field is set to -1 when the stream is first constructed or when\n\t* {@link setTokenSource} is called, indicating that the first token has\n\t* not yet been fetched from the token source. For additional information,\n\t* see the documentation of {@link IntStream} for a description of\n\t* Initializing Methods.\n\t*/\n\tp = -1;\n\t/**\n\t* Indicates whether the {@link Token.EOF} token has been fetched from\n\t* {@link tokenSource} and added to {@link tokens}. This field improves\n\t* performance for the following cases:\n\t*\n\t* - {@link consume}: The lookahead check in {@link consume} to prevent\n\t* consuming the EOF symbol is optimized by checking the values of\n\t* {@link fetchedEOF} and {@link p} instead of calling {@link LA}.\n\t* - {@link fetch}: The check to prevent adding multiple EOF symbols into\n\t* {@link tokens} is trivial with this field.\n\t*/\n\tfetchedEOF = false;\n\tconstructor(tokenSource) {\n\t\tthis.tokenSource = tokenSource;\n\t}\n\tmark() {\n\t\treturn 0;\n\t}\n\trelease(_marker) {}\n\treset() {\n\t\tthis.seek(0);\n\t}\n\tseek(index) {\n\t\tthis.lazyInit();\n\t\tthis.p = this.adjustSeekIndex(index);\n\t}\n\tget size() {\n\t\treturn this.tokens.length;\n\t}\n\tget index() {\n\t\treturn this.p;\n\t}\n\tget(index) {\n\t\tthis.lazyInit();\n\t\treturn this.tokens[index];\n\t}\n\tconsume() {\n\t\tlet skipEofCheck = false;\n\t\tif (this.p >= 0) if (this.fetchedEOF) skipEofCheck = this.p < this.tokens.length - 1;\n\t\telse skipEofCheck = this.p < this.tokens.length;\n\t\telse skipEofCheck = false;\n\t\tif (!skipEofCheck && this.LA(1) === Token.EOF) throw new Error(\"cannot consume EOF\");\n\t\tif (this.sync(this.p + 1)) this.p = this.adjustSeekIndex(this.p + 1);\n\t}\n\t/**\n\t* Make sure index `i` in tokens has a token.\n\t*\n\t* @returns {boolean} `true` if a token is located at index `i`, otherwise `false`.\n\t*/\n\tsync(i) {\n\t\tconst n2 = i - this.tokens.length + 1;\n\t\tif (n2 > 0) return this.fetch(n2) >= n2;\n\t\treturn true;\n\t}\n\t/**\n\t* Add `n` elements to buffer.\n\t*\n\t* @returns {number} The actual number of elements added to the buffer.\n\t*/\n\tfetch(n2) {\n\t\tif (this.fetchedEOF) return 0;\n\t\tfor (let i = 0; i < n2; i++) {\n\t\t\tconst t = this.tokenSource.nextToken();\n\t\t\tif (isWritableToken(t)) t.tokenIndex = this.tokens.length;\n\t\t\tthis.tokens.push(t);\n\t\t\tif (t.type === Token.EOF) {\n\t\t\t\tthis.fetchedEOF = true;\n\t\t\t\treturn i + 1;\n\t\t\t}\n\t\t}\n\t\treturn n2;\n\t}\n\t/** Get all tokens from start..stop, inclusively. */\n\tgetTokens(start, stop, types) {\n\t\tthis.lazyInit();\n\t\tif (start === void 0 && stop === void 0) return this.tokens;\n\t\tstart ??= 0;\n\t\tif (stop === void 0) stop = this.tokens.length - 1;\n\t\tif (start < 0 || stop >= this.tokens.length || stop < 0 || start >= this.tokens.length) throw new RangeError(\"start \" + start + \" or stop \" + stop + \" not in 0..\" + (this.tokens.length - 1));\n\t\tif (start > stop) return [];\n\t\tif (types === void 0) return this.tokens.slice(start, stop + 1);\n\t\tconst subset = [];\n\t\tif (stop >= this.tokens.length) stop = this.tokens.length - 1;\n\t\tfor (let i = start; i < stop; i++) {\n\t\t\tconst t = this.tokens[i];\n\t\t\tif (t.type === Token.EOF) {\n\t\t\t\tsubset.push(t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (types.has(t.type)) subset.push(t);\n\t\t}\n\t\treturn subset;\n\t}\n\tLA(k) {\n\t\treturn this.LT(k)?.type ?? Token.INVALID_TYPE;\n\t}\n\tLB(k) {\n\t\tif (this.p - k < 0) return null;\n\t\treturn this.tokens[this.p - k];\n\t}\n\tLT(k) {\n\t\tthis.lazyInit();\n\t\tif (k === 0) return null;\n\t\tif (k < 0) return this.LB(-k);\n\t\tconst i = this.p + k - 1;\n\t\tthis.sync(i);\n\t\tif (i >= this.tokens.length) return this.tokens[this.tokens.length - 1];\n\t\treturn this.tokens[i];\n\t}\n\t/**\n\t* Allowed derived classes to modify the behavior of operations which change\n\t* the current stream position by adjusting the target token index of a seek\n\t* operation. The default implementation simply returns `i`. If an\n\t* exception is thrown in this method, the current stream index should not be\n\t* changed.\n\t*\n\t* For example, {@link CommonTokenStream} overrides this method to ensure that\n\t* the seek target is always an on-channel token.\n\t*\n\t* @param  i The target token index.\n\t*\n\t* @returns The adjusted target token index.\n\t*/\n\tadjustSeekIndex(i) {\n\t\treturn i;\n\t}\n\tlazyInit() {\n\t\tif (this.p === -1) this.setup();\n\t}\n\tsetup() {\n\t\tthis.sync(0);\n\t\tthis.p = this.adjustSeekIndex(0);\n\t}\n\t/** Reset this token stream by setting its token source. */\n\tsetTokenSource(tokenSource) {\n\t\tthis.tokenSource = tokenSource;\n\t\tthis.tokens = [];\n\t\tthis.p = -1;\n\t\tthis.fetchedEOF = false;\n\t}\n\t/**\n\t* Given a starting index, return the index of the next token on channel.\n\t* Return i if tokens[i] is on channel. Return -1 if there are no tokens\n\t* on channel between i and EOF.\n\t*/\n\tnextTokenOnChannel(i, channel) {\n\t\tthis.sync(i);\n\t\tif (i >= this.tokens.length) return -1;\n\t\tlet token = this.tokens[i];\n\t\twhile (token.channel !== channel) {\n\t\t\tif (token.type === Token.EOF) return -1;\n\t\t\ti += 1;\n\t\t\tthis.sync(i);\n\t\t\ttoken = this.tokens[i];\n\t\t}\n\t\treturn i;\n\t}\n\t/**\n\t* Given a starting index, return the index of the previous token on\n\t* channel. Return `i` if `tokens[i]` is on channel. Return -1\n\t* if there are no tokens on channel between `i` and 0.\n\t*\n\t* If `i` specifies an index at or after the EOF token, the EOF token\n\t* index is returned. This is due to the fact that the EOF token is treated\n\t* as though it were on every channel.\n\t*/\n\tpreviousTokenOnChannel(i, channel) {\n\t\tif (i >= this.tokens.length) return this.tokens.length - 1;\n\t\twhile (i >= 0) {\n\t\t\tconst token = this.tokens[i];\n\t\t\tif (token.type === Token.EOF || token.channel === channel) return i;\n\t\t\t--i;\n\t\t}\n\t\treturn i;\n\t}\n\t/**\n\t* Collect all tokens on specified channel to the right of\n\t* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL or\n\t* EOF. If channel is -1, find any non default channel token.\n\t*/\n\tgetHiddenTokensToRight(tokenIndex, channel) {\n\t\tif (channel === void 0) channel = -1;\n\t\tthis.lazyInit();\n\t\tif (tokenIndex < 0 || tokenIndex >= this.tokens.length) throw new Error(`${tokenIndex} not in 0..${this.tokens.length - 1}`);\n\t\tconst nextOnChannel = this.nextTokenOnChannel(tokenIndex + 1, Lexer.DEFAULT_TOKEN_CHANNEL);\n\t\tconst from = tokenIndex + 1;\n\t\tconst to = nextOnChannel === -1 ? this.tokens.length - 1 : nextOnChannel;\n\t\treturn this.filterForChannel(from, to, channel);\n\t}\n\t/**\n\t* Collect all tokens on specified channel to the left of\n\t* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.\n\t* If channel is -1, find any non default channel token.\n\t*/\n\tgetHiddenTokensToLeft(tokenIndex, channel) {\n\t\tif (channel === void 0) channel = -1;\n\t\tthis.lazyInit();\n\t\tif (tokenIndex < 0 || tokenIndex >= this.tokens.length) throw new Error(`${tokenIndex} not in 0..${this.tokens.length - 1}`);\n\t\tconst prevOnChannel = this.previousTokenOnChannel(tokenIndex - 1, Lexer.DEFAULT_TOKEN_CHANNEL);\n\t\tif (prevOnChannel === tokenIndex - 1) return;\n\t\tconst from = prevOnChannel + 1;\n\t\tconst to = tokenIndex - 1;\n\t\treturn this.filterForChannel(from, to, channel);\n\t}\n\tfilterForChannel(left, right, channel) {\n\t\tconst hidden = [];\n\t\tfor (let i = left; i < right + 1; i++) {\n\t\t\tconst t = this.tokens[i];\n\t\t\tif (channel === -1) {\n\t\t\t\tif (t.channel !== Lexer.DEFAULT_TOKEN_CHANNEL) hidden.push(t);\n\t\t\t} else if (t.channel === channel) hidden.push(t);\n\t\t}\n\t\tif (hidden.length === 0) return;\n\t\treturn hidden;\n\t}\n\tgetSourceName() {\n\t\treturn this.tokenSource.sourceName;\n\t}\n\t/** Get the text of all tokens in this buffer. */\n\tgetText() {\n\t\treturn this.getTextFromInterval(Interval.of(0, this.size - 1));\n\t}\n\tgetTextFromInterval(interval) {\n\t\tconst start = interval.start;\n\t\tlet stop = interval.stop;\n\t\tif (start < 0 || stop < 0) return \"\";\n\t\tthis.sync(stop);\n\t\tif (stop >= this.tokens.length) stop = this.tokens.length - 1;\n\t\tlet result = \"\";\n\t\tfor (let i = start; i <= stop; ++i) {\n\t\t\tconst t = this.tokens[i];\n\t\t\tif (t.type === Token.EOF) break;\n\t\t\tresult += t.text;\n\t\t}\n\t\treturn result;\n\t}\n\tgetTextFromContext(ctx) {\n\t\treturn this.getTextFromInterval(ctx.getSourceInterval());\n\t}\n\tgetTextFromRange(start, stop) {\n\t\tif (start !== null && stop !== null) return this.getTextFromInterval(Interval.of(start.tokenIndex, stop.tokenIndex));\n\t\treturn \"\";\n\t}\n\t/** Get all tokens from lexer until EOF. */\n\tfill() {\n\t\tthis.lazyInit();\n\t\twhile (this.fetch(1e3) === 1e3);\n\t}\n\tsetLine(line) {\n\t\tthis.tokenSource.line = line;\n\t}\n\tsetColumn(column) {\n\t\tthis.tokenSource.column = column;\n\t}\n};\nvar CommonTokenStream = class extends BufferedTokenStream {\n\tstatic {\n\t\t__name(this, \"CommonTokenStream\");\n\t}\n\t/**\n\t* Specifies the channel to use for filtering tokens.\n\t*\n\t*\n\t* The default value is {@link Token.DEFAULT_CHANNEL}, which matches the\n\t* default channel assigned to tokens created by the lexer.\n\t*/\n\tchannel = Token.DEFAULT_CHANNEL;\n\tconstructor(lexer, channel) {\n\t\tsuper(lexer);\n\t\tthis.channel = channel ?? Token.DEFAULT_CHANNEL;\n\t}\n\tadjustSeekIndex(i) {\n\t\treturn this.nextTokenOnChannel(i, this.channel);\n\t}\n\tLB(k) {\n\t\tif (k === 0 || this.index - k < 0) return null;\n\t\tlet i = this.index;\n\t\tlet n2 = 1;\n\t\twhile (n2 <= k) {\n\t\t\ti = this.previousTokenOnChannel(i - 1, this.channel);\n\t\t\tn2 += 1;\n\t\t}\n\t\tif (i < 0) return null;\n\t\treturn this.tokens[i];\n\t}\n\tLT(k) {\n\t\tthis.lazyInit();\n\t\tif (k === 0) return null;\n\t\tif (k < 0) return this.LB(-k);\n\t\tlet i = this.index;\n\t\tlet n2 = 1;\n\t\twhile (n2 < k) {\n\t\t\tif (this.sync(i + 1)) i = this.nextTokenOnChannel(i + 1, this.channel);\n\t\t\tn2 += 1;\n\t\t}\n\t\treturn this.tokens[i];\n\t}\n\tgetNumberOfOnChannelTokens() {\n\t\tlet n2 = 0;\n\t\tthis.fill();\n\t\tfor (const t of this.tokens) {\n\t\t\tif (t.channel === this.channel) n2 += 1;\n\t\t\tif (t.type === Token.EOF) break;\n\t\t}\n\t\treturn n2;\n\t}\n};\nvar XPathLexer = class _XPathLexer extends Lexer {\n\tstatic {\n\t\t__name(this, \"XPathLexer\");\n\t}\n\tstatic TOKEN_REF = 1;\n\tstatic RULE_REF = 2;\n\tstatic ANYWHERE = 3;\n\tstatic ROOT = 4;\n\tstatic WILDCARD = 5;\n\tstatic BANG = 6;\n\tstatic ID = 7;\n\tstatic STRING = 8;\n\tstatic channelNames = [\"DEFAULT_TOKEN_CHANNEL\", \"HIDDEN\"];\n\tstatic literalNames = [\n\t\tnull,\n\t\tnull,\n\t\tnull,\n\t\t\"'//'\",\n\t\t\"'/'\",\n\t\t\"'*'\",\n\t\t\"'!'\"\n\t];\n\tstatic symbolicNames = [\n\t\tnull,\n\t\t\"TOKEN_REF\",\n\t\t\"RULE_REF\",\n\t\t\"ANYWHERE\",\n\t\t\"ROOT\",\n\t\t\"WILDCARD\",\n\t\t\"BANG\",\n\t\t\"ID\",\n\t\t\"STRING\"\n\t];\n\tstatic modeNames = [\"DEFAULT_MODE\"];\n\tstatic ruleNames = [\n\t\t\"ANYWHERE\",\n\t\t\"ROOT\",\n\t\t\"WILDCARD\",\n\t\t\"BANG\",\n\t\t\"ID\",\n\t\t\"NameChar\",\n\t\t\"NameStartChar\",\n\t\t\"STRING\"\n\t];\n\tconstructor(input) {\n\t\tsuper(input);\n\t\tthis.interpreter = new LexerATNSimulator(this, _XPathLexer._ATN, _XPathLexer.decisionsToDFA, new PredictionContextCache());\n\t}\n\tget grammarFileName() {\n\t\treturn \"XPathLexer.g4\";\n\t}\n\tget literalNames() {\n\t\treturn _XPathLexer.literalNames;\n\t}\n\tget symbolicNames() {\n\t\treturn _XPathLexer.symbolicNames;\n\t}\n\tget ruleNames() {\n\t\treturn _XPathLexer.ruleNames;\n\t}\n\tget serializedATN() {\n\t\treturn _XPathLexer._serializedATN;\n\t}\n\tget channelNames() {\n\t\treturn _XPathLexer.channelNames;\n\t}\n\tget modeNames() {\n\t\treturn _XPathLexer.modeNames;\n\t}\n\taction(localContext, ruleIndex, actionIndex) {\n\t\tswitch (ruleIndex) {\n\t\t\tcase 4:\n\t\t\t\tthis.ID_action(localContext, actionIndex);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tID_action(localContext, actionIndex) {\n\t\tswitch (actionIndex) {\n\t\t\tcase 0:\n\t\t\t\tconst text = this.text;\n\t\t\t\tif (text.charAt(0) === text.charAt(0).toUpperCase()) this.type = _XPathLexer.TOKEN_REF;\n\t\t\t\telse this.type = _XPathLexer.RULE_REF;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tstatic _serializedATN = [\n\t\t4,\n\t\t0,\n\t\t8,\n\t\t48,\n\t\t6,\n\t\t-1,\n\t\t2,\n\t\t0,\n\t\t7,\n\t\t0,\n\t\t2,\n\t\t1,\n\t\t7,\n\t\t1,\n\t\t2,\n\t\t2,\n\t\t7,\n\t\t2,\n\t\t2,\n\t\t3,\n\t\t7,\n\t\t3,\n\t\t2,\n\t\t4,\n\t\t7,\n\t\t4,\n\t\t2,\n\t\t5,\n\t\t7,\n\t\t5,\n\t\t2,\n\t\t6,\n\t\t7,\n\t\t6,\n\t\t2,\n\t\t7,\n\t\t7,\n\t\t7,\n\t\t1,\n\t\t0,\n\t\t1,\n\t\t0,\n\t\t1,\n\t\t0,\n\t\t1,\n\t\t1,\n\t\t1,\n\t\t1,\n\t\t1,\n\t\t2,\n\t\t1,\n\t\t2,\n\t\t1,\n\t\t3,\n\t\t1,\n\t\t3,\n\t\t1,\n\t\t4,\n\t\t1,\n\t\t4,\n\t\t5,\n\t\t4,\n\t\t29,\n\t\t8,\n\t\t4,\n\t\t10,\n\t\t4,\n\t\t12,\n\t\t4,\n\t\t32,\n\t\t9,\n\t\t4,\n\t\t1,\n\t\t4,\n\t\t1,\n\t\t4,\n\t\t1,\n\t\t5,\n\t\t1,\n\t\t5,\n\t\t1,\n\t\t6,\n\t\t1,\n\t\t6,\n\t\t1,\n\t\t7,\n\t\t1,\n\t\t7,\n\t\t5,\n\t\t7,\n\t\t42,\n\t\t8,\n\t\t7,\n\t\t10,\n\t\t7,\n\t\t12,\n\t\t7,\n\t\t45,\n\t\t9,\n\t\t7,\n\t\t1,\n\t\t7,\n\t\t1,\n\t\t7,\n\t\t1,\n\t\t43,\n\t\t0,\n\t\t8,\n\t\t1,\n\t\t3,\n\t\t3,\n\t\t4,\n\t\t5,\n\t\t5,\n\t\t7,\n\t\t6,\n\t\t9,\n\t\t7,\n\t\t11,\n\t\t0,\n\t\t13,\n\t\t0,\n\t\t15,\n\t\t8,\n\t\t1,\n\t\t0,\n\t\t2,\n\t\t784,\n\t\t0,\n\t\t0,\n\t\t8,\n\t\t14,\n\t\t27,\n\t\t48,\n\t\t57,\n\t\t65,\n\t\t90,\n\t\t95,\n\t\t95,\n\t\t97,\n\t\t122,\n\t\t127,\n\t\t159,\n\t\t170,\n\t\t170,\n\t\t173,\n\t\t173,\n\t\t181,\n\t\t181,\n\t\t186,\n\t\t186,\n\t\t192,\n\t\t214,\n\t\t216,\n\t\t246,\n\t\t248,\n\t\t705,\n\t\t710,\n\t\t721,\n\t\t736,\n\t\t740,\n\t\t748,\n\t\t748,\n\t\t750,\n\t\t750,\n\t\t768,\n\t\t884,\n\t\t886,\n\t\t887,\n\t\t890,\n\t\t893,\n\t\t895,\n\t\t895,\n\t\t902,\n\t\t902,\n\t\t904,\n\t\t906,\n\t\t908,\n\t\t908,\n\t\t910,\n\t\t929,\n\t\t931,\n\t\t1013,\n\t\t1015,\n\t\t1153,\n\t\t1155,\n\t\t1159,\n\t\t1162,\n\t\t1327,\n\t\t1329,\n\t\t1366,\n\t\t1369,\n\t\t1369,\n\t\t1376,\n\t\t1416,\n\t\t1425,\n\t\t1469,\n\t\t1471,\n\t\t1471,\n\t\t1473,\n\t\t1474,\n\t\t1476,\n\t\t1477,\n\t\t1479,\n\t\t1479,\n\t\t1488,\n\t\t1514,\n\t\t1519,\n\t\t1522,\n\t\t1536,\n\t\t1541,\n\t\t1552,\n\t\t1562,\n\t\t1564,\n\t\t1564,\n\t\t1568,\n\t\t1641,\n\t\t1646,\n\t\t1747,\n\t\t1749,\n\t\t1757,\n\t\t1759,\n\t\t1768,\n\t\t1770,\n\t\t1788,\n\t\t1791,\n\t\t1791,\n\t\t1807,\n\t\t1866,\n\t\t1869,\n\t\t1969,\n\t\t1984,\n\t\t2037,\n\t\t2042,\n\t\t2042,\n\t\t2045,\n\t\t2045,\n\t\t2048,\n\t\t2093,\n\t\t2112,\n\t\t2139,\n\t\t2144,\n\t\t2154,\n\t\t2160,\n\t\t2183,\n\t\t2185,\n\t\t2190,\n\t\t2192,\n\t\t2193,\n\t\t2200,\n\t\t2403,\n\t\t2406,\n\t\t2415,\n\t\t2417,\n\t\t2435,\n\t\t2437,\n\t\t2444,\n\t\t2447,\n\t\t2448,\n\t\t2451,\n\t\t2472,\n\t\t2474,\n\t\t2480,\n\t\t2482,\n\t\t2482,\n\t\t2486,\n\t\t2489,\n\t\t2492,\n\t\t2500,\n\t\t2503,\n\t\t2504,\n\t\t2507,\n\t\t2510,\n\t\t2519,\n\t\t2519,\n\t\t2524,\n\t\t2525,\n\t\t2527,\n\t\t2531,\n\t\t2534,\n\t\t2545,\n\t\t2556,\n\t\t2556,\n\t\t2558,\n\t\t2558,\n\t\t2561,\n\t\t2563,\n\t\t2565,\n\t\t2570,\n\t\t2575,\n\t\t2576,\n\t\t2579,\n\t\t2600,\n\t\t2602,\n\t\t2608,\n\t\t2610,\n\t\t2611,\n\t\t2613,\n\t\t2614,\n\t\t2616,\n\t\t2617,\n\t\t2620,\n\t\t2620,\n\t\t2622,\n\t\t2626,\n\t\t2631,\n\t\t2632,\n\t\t2635,\n\t\t2637,\n\t\t2641,\n\t\t2641,\n\t\t2649,\n\t\t2652,\n\t\t2654,\n\t\t2654,\n\t\t2662,\n\t\t2677,\n\t\t2689,\n\t\t2691,\n\t\t2693,\n\t\t2701,\n\t\t2703,\n\t\t2705,\n\t\t2707,\n\t\t2728,\n\t\t2730,\n\t\t2736,\n\t\t2738,\n\t\t2739,\n\t\t2741,\n\t\t2745,\n\t\t2748,\n\t\t2757,\n\t\t2759,\n\t\t2761,\n\t\t2763,\n\t\t2765,\n\t\t2768,\n\t\t2768,\n\t\t2784,\n\t\t2787,\n\t\t2790,\n\t\t2799,\n\t\t2809,\n\t\t2815,\n\t\t2817,\n\t\t2819,\n\t\t2821,\n\t\t2828,\n\t\t2831,\n\t\t2832,\n\t\t2835,\n\t\t2856,\n\t\t2858,\n\t\t2864,\n\t\t2866,\n\t\t2867,\n\t\t2869,\n\t\t2873,\n\t\t2876,\n\t\t2884,\n\t\t2887,\n\t\t2888,\n\t\t2891,\n\t\t2893,\n\t\t2901,\n\t\t2903,\n\t\t2908,\n\t\t2909,\n\t\t2911,\n\t\t2915,\n\t\t2918,\n\t\t2927,\n\t\t2929,\n\t\t2929,\n\t\t2946,\n\t\t2947,\n\t\t2949,\n\t\t2954,\n\t\t2958,\n\t\t2960,\n\t\t2962,\n\t\t2965,\n\t\t2969,\n\t\t2970,\n\t\t2972,\n\t\t2972,\n\t\t2974,\n\t\t2975,\n\t\t2979,\n\t\t2980,\n\t\t2984,\n\t\t2986,\n\t\t2990,\n\t\t3001,\n\t\t3006,\n\t\t3010,\n\t\t3014,\n\t\t3016,\n\t\t3018,\n\t\t3021,\n\t\t3024,\n\t\t3024,\n\t\t3031,\n\t\t3031,\n\t\t3046,\n\t\t3055,\n\t\t3072,\n\t\t3084,\n\t\t3086,\n\t\t3088,\n\t\t3090,\n\t\t3112,\n\t\t3114,\n\t\t3129,\n\t\t3132,\n\t\t3140,\n\t\t3142,\n\t\t3144,\n\t\t3146,\n\t\t3149,\n\t\t3157,\n\t\t3158,\n\t\t3160,\n\t\t3162,\n\t\t3165,\n\t\t3165,\n\t\t3168,\n\t\t3171,\n\t\t3174,\n\t\t3183,\n\t\t3200,\n\t\t3203,\n\t\t3205,\n\t\t3212,\n\t\t3214,\n\t\t3216,\n\t\t3218,\n\t\t3240,\n\t\t3242,\n\t\t3251,\n\t\t3253,\n\t\t3257,\n\t\t3260,\n\t\t3268,\n\t\t3270,\n\t\t3272,\n\t\t3274,\n\t\t3277,\n\t\t3285,\n\t\t3286,\n\t\t3293,\n\t\t3294,\n\t\t3296,\n\t\t3299,\n\t\t3302,\n\t\t3311,\n\t\t3313,\n\t\t3315,\n\t\t3328,\n\t\t3340,\n\t\t3342,\n\t\t3344,\n\t\t3346,\n\t\t3396,\n\t\t3398,\n\t\t3400,\n\t\t3402,\n\t\t3406,\n\t\t3412,\n\t\t3415,\n\t\t3423,\n\t\t3427,\n\t\t3430,\n\t\t3439,\n\t\t3450,\n\t\t3455,\n\t\t3457,\n\t\t3459,\n\t\t3461,\n\t\t3478,\n\t\t3482,\n\t\t3505,\n\t\t3507,\n\t\t3515,\n\t\t3517,\n\t\t3517,\n\t\t3520,\n\t\t3526,\n\t\t3530,\n\t\t3530,\n\t\t3535,\n\t\t3540,\n\t\t3542,\n\t\t3542,\n\t\t3544,\n\t\t3551,\n\t\t3558,\n\t\t3567,\n\t\t3570,\n\t\t3571,\n\t\t3585,\n\t\t3642,\n\t\t3648,\n\t\t3662,\n\t\t3664,\n\t\t3673,\n\t\t3713,\n\t\t3714,\n\t\t3716,\n\t\t3716,\n\t\t3718,\n\t\t3722,\n\t\t3724,\n\t\t3747,\n\t\t3749,\n\t\t3749,\n\t\t3751,\n\t\t3773,\n\t\t3776,\n\t\t3780,\n\t\t3782,\n\t\t3782,\n\t\t3784,\n\t\t3790,\n\t\t3792,\n\t\t3801,\n\t\t3804,\n\t\t3807,\n\t\t3840,\n\t\t3840,\n\t\t3864,\n\t\t3865,\n\t\t3872,\n\t\t3881,\n\t\t3893,\n\t\t3893,\n\t\t3895,\n\t\t3895,\n\t\t3897,\n\t\t3897,\n\t\t3902,\n\t\t3911,\n\t\t3913,\n\t\t3948,\n\t\t3953,\n\t\t3972,\n\t\t3974,\n\t\t3991,\n\t\t3993,\n\t\t4028,\n\t\t4038,\n\t\t4038,\n\t\t4096,\n\t\t4169,\n\t\t4176,\n\t\t4253,\n\t\t4256,\n\t\t4293,\n\t\t4295,\n\t\t4295,\n\t\t4301,\n\t\t4301,\n\t\t4304,\n\t\t4346,\n\t\t4348,\n\t\t4680,\n\t\t4682,\n\t\t4685,\n\t\t4688,\n\t\t4694,\n\t\t4696,\n\t\t4696,\n\t\t4698,\n\t\t4701,\n\t\t4704,\n\t\t4744,\n\t\t4746,\n\t\t4749,\n\t\t4752,\n\t\t4784,\n\t\t4786,\n\t\t4789,\n\t\t4792,\n\t\t4798,\n\t\t4800,\n\t\t4800,\n\t\t4802,\n\t\t4805,\n\t\t4808,\n\t\t4822,\n\t\t4824,\n\t\t4880,\n\t\t4882,\n\t\t4885,\n\t\t4888,\n\t\t4954,\n\t\t4957,\n\t\t4959,\n\t\t4992,\n\t\t5007,\n\t\t5024,\n\t\t5109,\n\t\t5112,\n\t\t5117,\n\t\t5121,\n\t\t5740,\n\t\t5743,\n\t\t5759,\n\t\t5761,\n\t\t5786,\n\t\t5792,\n\t\t5866,\n\t\t5870,\n\t\t5880,\n\t\t5888,\n\t\t5909,\n\t\t5919,\n\t\t5940,\n\t\t5952,\n\t\t5971,\n\t\t5984,\n\t\t5996,\n\t\t5998,\n\t\t6e3,\n\t\t6002,\n\t\t6003,\n\t\t6016,\n\t\t6099,\n\t\t6103,\n\t\t6103,\n\t\t6108,\n\t\t6109,\n\t\t6112,\n\t\t6121,\n\t\t6155,\n\t\t6169,\n\t\t6176,\n\t\t6264,\n\t\t6272,\n\t\t6314,\n\t\t6320,\n\t\t6389,\n\t\t6400,\n\t\t6430,\n\t\t6432,\n\t\t6443,\n\t\t6448,\n\t\t6459,\n\t\t6470,\n\t\t6509,\n\t\t6512,\n\t\t6516,\n\t\t6528,\n\t\t6571,\n\t\t6576,\n\t\t6601,\n\t\t6608,\n\t\t6617,\n\t\t6656,\n\t\t6683,\n\t\t6688,\n\t\t6750,\n\t\t6752,\n\t\t6780,\n\t\t6783,\n\t\t6793,\n\t\t6800,\n\t\t6809,\n\t\t6823,\n\t\t6823,\n\t\t6832,\n\t\t6845,\n\t\t6847,\n\t\t6862,\n\t\t6912,\n\t\t6988,\n\t\t6992,\n\t\t7001,\n\t\t7019,\n\t\t7027,\n\t\t7040,\n\t\t7155,\n\t\t7168,\n\t\t7223,\n\t\t7232,\n\t\t7241,\n\t\t7245,\n\t\t7293,\n\t\t7296,\n\t\t7304,\n\t\t7312,\n\t\t7354,\n\t\t7357,\n\t\t7359,\n\t\t7376,\n\t\t7378,\n\t\t7380,\n\t\t7418,\n\t\t7424,\n\t\t7957,\n\t\t7960,\n\t\t7965,\n\t\t7968,\n\t\t8005,\n\t\t8008,\n\t\t8013,\n\t\t8016,\n\t\t8023,\n\t\t8025,\n\t\t8025,\n\t\t8027,\n\t\t8027,\n\t\t8029,\n\t\t8029,\n\t\t8031,\n\t\t8061,\n\t\t8064,\n\t\t8116,\n\t\t8118,\n\t\t8124,\n\t\t8126,\n\t\t8126,\n\t\t8130,\n\t\t8132,\n\t\t8134,\n\t\t8140,\n\t\t8144,\n\t\t8147,\n\t\t8150,\n\t\t8155,\n\t\t8160,\n\t\t8172,\n\t\t8178,\n\t\t8180,\n\t\t8182,\n\t\t8188,\n\t\t8203,\n\t\t8207,\n\t\t8234,\n\t\t8238,\n\t\t8255,\n\t\t8256,\n\t\t8276,\n\t\t8276,\n\t\t8288,\n\t\t8292,\n\t\t8294,\n\t\t8303,\n\t\t8305,\n\t\t8305,\n\t\t8319,\n\t\t8319,\n\t\t8336,\n\t\t8348,\n\t\t8400,\n\t\t8412,\n\t\t8417,\n\t\t8417,\n\t\t8421,\n\t\t8432,\n\t\t8450,\n\t\t8450,\n\t\t8455,\n\t\t8455,\n\t\t8458,\n\t\t8467,\n\t\t8469,\n\t\t8469,\n\t\t8473,\n\t\t8477,\n\t\t8484,\n\t\t8484,\n\t\t8486,\n\t\t8486,\n\t\t8488,\n\t\t8488,\n\t\t8490,\n\t\t8493,\n\t\t8495,\n\t\t8505,\n\t\t8508,\n\t\t8511,\n\t\t8517,\n\t\t8521,\n\t\t8526,\n\t\t8526,\n\t\t8544,\n\t\t8584,\n\t\t11264,\n\t\t11492,\n\t\t11499,\n\t\t11507,\n\t\t11520,\n\t\t11557,\n\t\t11559,\n\t\t11559,\n\t\t11565,\n\t\t11565,\n\t\t11568,\n\t\t11623,\n\t\t11631,\n\t\t11631,\n\t\t11647,\n\t\t11670,\n\t\t11680,\n\t\t11686,\n\t\t11688,\n\t\t11694,\n\t\t11696,\n\t\t11702,\n\t\t11704,\n\t\t11710,\n\t\t11712,\n\t\t11718,\n\t\t11720,\n\t\t11726,\n\t\t11728,\n\t\t11734,\n\t\t11736,\n\t\t11742,\n\t\t11744,\n\t\t11775,\n\t\t11823,\n\t\t11823,\n\t\t12293,\n\t\t12295,\n\t\t12321,\n\t\t12335,\n\t\t12337,\n\t\t12341,\n\t\t12344,\n\t\t12348,\n\t\t12353,\n\t\t12438,\n\t\t12441,\n\t\t12442,\n\t\t12445,\n\t\t12447,\n\t\t12449,\n\t\t12538,\n\t\t12540,\n\t\t12543,\n\t\t12549,\n\t\t12591,\n\t\t12593,\n\t\t12686,\n\t\t12704,\n\t\t12735,\n\t\t12784,\n\t\t12799,\n\t\t13312,\n\t\t19903,\n\t\t19968,\n\t\t42124,\n\t\t42192,\n\t\t42237,\n\t\t42240,\n\t\t42508,\n\t\t42512,\n\t\t42539,\n\t\t42560,\n\t\t42607,\n\t\t42612,\n\t\t42621,\n\t\t42623,\n\t\t42737,\n\t\t42775,\n\t\t42783,\n\t\t42786,\n\t\t42888,\n\t\t42891,\n\t\t42954,\n\t\t42960,\n\t\t42961,\n\t\t42963,\n\t\t42963,\n\t\t42965,\n\t\t42969,\n\t\t42994,\n\t\t43047,\n\t\t43052,\n\t\t43052,\n\t\t43072,\n\t\t43123,\n\t\t43136,\n\t\t43205,\n\t\t43216,\n\t\t43225,\n\t\t43232,\n\t\t43255,\n\t\t43259,\n\t\t43259,\n\t\t43261,\n\t\t43309,\n\t\t43312,\n\t\t43347,\n\t\t43360,\n\t\t43388,\n\t\t43392,\n\t\t43456,\n\t\t43471,\n\t\t43481,\n\t\t43488,\n\t\t43518,\n\t\t43520,\n\t\t43574,\n\t\t43584,\n\t\t43597,\n\t\t43600,\n\t\t43609,\n\t\t43616,\n\t\t43638,\n\t\t43642,\n\t\t43714,\n\t\t43739,\n\t\t43741,\n\t\t43744,\n\t\t43759,\n\t\t43762,\n\t\t43766,\n\t\t43777,\n\t\t43782,\n\t\t43785,\n\t\t43790,\n\t\t43793,\n\t\t43798,\n\t\t43808,\n\t\t43814,\n\t\t43816,\n\t\t43822,\n\t\t43824,\n\t\t43866,\n\t\t43868,\n\t\t43881,\n\t\t43888,\n\t\t44010,\n\t\t44012,\n\t\t44013,\n\t\t44016,\n\t\t44025,\n\t\t44032,\n\t\t55203,\n\t\t55216,\n\t\t55238,\n\t\t55243,\n\t\t55291,\n\t\t63744,\n\t\t64109,\n\t\t64112,\n\t\t64217,\n\t\t64256,\n\t\t64262,\n\t\t64275,\n\t\t64279,\n\t\t64285,\n\t\t64296,\n\t\t64298,\n\t\t64310,\n\t\t64312,\n\t\t64316,\n\t\t64318,\n\t\t64318,\n\t\t64320,\n\t\t64321,\n\t\t64323,\n\t\t64324,\n\t\t64326,\n\t\t64433,\n\t\t64467,\n\t\t64829,\n\t\t64848,\n\t\t64911,\n\t\t64914,\n\t\t64967,\n\t\t65008,\n\t\t65019,\n\t\t65024,\n\t\t65039,\n\t\t65056,\n\t\t65071,\n\t\t65075,\n\t\t65076,\n\t\t65101,\n\t\t65103,\n\t\t65136,\n\t\t65140,\n\t\t65142,\n\t\t65276,\n\t\t65279,\n\t\t65279,\n\t\t65296,\n\t\t65305,\n\t\t65313,\n\t\t65338,\n\t\t65343,\n\t\t65343,\n\t\t65345,\n\t\t65370,\n\t\t65382,\n\t\t65470,\n\t\t65474,\n\t\t65479,\n\t\t65482,\n\t\t65487,\n\t\t65490,\n\t\t65495,\n\t\t65498,\n\t\t65500,\n\t\t65529,\n\t\t65531,\n\t\t65536,\n\t\t65547,\n\t\t65549,\n\t\t65574,\n\t\t65576,\n\t\t65594,\n\t\t65596,\n\t\t65597,\n\t\t65599,\n\t\t65613,\n\t\t65616,\n\t\t65629,\n\t\t65664,\n\t\t65786,\n\t\t65856,\n\t\t65908,\n\t\t66045,\n\t\t66045,\n\t\t66176,\n\t\t66204,\n\t\t66208,\n\t\t66256,\n\t\t66272,\n\t\t66272,\n\t\t66304,\n\t\t66335,\n\t\t66349,\n\t\t66378,\n\t\t66384,\n\t\t66426,\n\t\t66432,\n\t\t66461,\n\t\t66464,\n\t\t66499,\n\t\t66504,\n\t\t66511,\n\t\t66513,\n\t\t66517,\n\t\t66560,\n\t\t66717,\n\t\t66720,\n\t\t66729,\n\t\t66736,\n\t\t66771,\n\t\t66776,\n\t\t66811,\n\t\t66816,\n\t\t66855,\n\t\t66864,\n\t\t66915,\n\t\t66928,\n\t\t66938,\n\t\t66940,\n\t\t66954,\n\t\t66956,\n\t\t66962,\n\t\t66964,\n\t\t66965,\n\t\t66967,\n\t\t66977,\n\t\t66979,\n\t\t66993,\n\t\t66995,\n\t\t67001,\n\t\t67003,\n\t\t67004,\n\t\t67072,\n\t\t67382,\n\t\t67392,\n\t\t67413,\n\t\t67424,\n\t\t67431,\n\t\t67456,\n\t\t67461,\n\t\t67463,\n\t\t67504,\n\t\t67506,\n\t\t67514,\n\t\t67584,\n\t\t67589,\n\t\t67592,\n\t\t67592,\n\t\t67594,\n\t\t67637,\n\t\t67639,\n\t\t67640,\n\t\t67644,\n\t\t67644,\n\t\t67647,\n\t\t67669,\n\t\t67680,\n\t\t67702,\n\t\t67712,\n\t\t67742,\n\t\t67808,\n\t\t67826,\n\t\t67828,\n\t\t67829,\n\t\t67840,\n\t\t67861,\n\t\t67872,\n\t\t67897,\n\t\t67968,\n\t\t68023,\n\t\t68030,\n\t\t68031,\n\t\t68096,\n\t\t68099,\n\t\t68101,\n\t\t68102,\n\t\t68108,\n\t\t68115,\n\t\t68117,\n\t\t68119,\n\t\t68121,\n\t\t68149,\n\t\t68152,\n\t\t68154,\n\t\t68159,\n\t\t68159,\n\t\t68192,\n\t\t68220,\n\t\t68224,\n\t\t68252,\n\t\t68288,\n\t\t68295,\n\t\t68297,\n\t\t68326,\n\t\t68352,\n\t\t68405,\n\t\t68416,\n\t\t68437,\n\t\t68448,\n\t\t68466,\n\t\t68480,\n\t\t68497,\n\t\t68608,\n\t\t68680,\n\t\t68736,\n\t\t68786,\n\t\t68800,\n\t\t68850,\n\t\t68864,\n\t\t68903,\n\t\t68912,\n\t\t68921,\n\t\t69248,\n\t\t69289,\n\t\t69291,\n\t\t69292,\n\t\t69296,\n\t\t69297,\n\t\t69373,\n\t\t69404,\n\t\t69415,\n\t\t69415,\n\t\t69424,\n\t\t69456,\n\t\t69488,\n\t\t69509,\n\t\t69552,\n\t\t69572,\n\t\t69600,\n\t\t69622,\n\t\t69632,\n\t\t69702,\n\t\t69734,\n\t\t69749,\n\t\t69759,\n\t\t69818,\n\t\t69821,\n\t\t69821,\n\t\t69826,\n\t\t69826,\n\t\t69837,\n\t\t69837,\n\t\t69840,\n\t\t69864,\n\t\t69872,\n\t\t69881,\n\t\t69888,\n\t\t69940,\n\t\t69942,\n\t\t69951,\n\t\t69956,\n\t\t69959,\n\t\t69968,\n\t\t70003,\n\t\t70006,\n\t\t70006,\n\t\t70016,\n\t\t70084,\n\t\t70089,\n\t\t70092,\n\t\t70094,\n\t\t70106,\n\t\t70108,\n\t\t70108,\n\t\t70144,\n\t\t70161,\n\t\t70163,\n\t\t70199,\n\t\t70206,\n\t\t70209,\n\t\t70272,\n\t\t70278,\n\t\t70280,\n\t\t70280,\n\t\t70282,\n\t\t70285,\n\t\t70287,\n\t\t70301,\n\t\t70303,\n\t\t70312,\n\t\t70320,\n\t\t70378,\n\t\t70384,\n\t\t70393,\n\t\t70400,\n\t\t70403,\n\t\t70405,\n\t\t70412,\n\t\t70415,\n\t\t70416,\n\t\t70419,\n\t\t70440,\n\t\t70442,\n\t\t70448,\n\t\t70450,\n\t\t70451,\n\t\t70453,\n\t\t70457,\n\t\t70459,\n\t\t70468,\n\t\t70471,\n\t\t70472,\n\t\t70475,\n\t\t70477,\n\t\t70480,\n\t\t70480,\n\t\t70487,\n\t\t70487,\n\t\t70493,\n\t\t70499,\n\t\t70502,\n\t\t70508,\n\t\t70512,\n\t\t70516,\n\t\t70656,\n\t\t70730,\n\t\t70736,\n\t\t70745,\n\t\t70750,\n\t\t70753,\n\t\t70784,\n\t\t70853,\n\t\t70855,\n\t\t70855,\n\t\t70864,\n\t\t70873,\n\t\t71040,\n\t\t71093,\n\t\t71096,\n\t\t71104,\n\t\t71128,\n\t\t71133,\n\t\t71168,\n\t\t71232,\n\t\t71236,\n\t\t71236,\n\t\t71248,\n\t\t71257,\n\t\t71296,\n\t\t71352,\n\t\t71360,\n\t\t71369,\n\t\t71424,\n\t\t71450,\n\t\t71453,\n\t\t71467,\n\t\t71472,\n\t\t71481,\n\t\t71488,\n\t\t71494,\n\t\t71680,\n\t\t71738,\n\t\t71840,\n\t\t71913,\n\t\t71935,\n\t\t71942,\n\t\t71945,\n\t\t71945,\n\t\t71948,\n\t\t71955,\n\t\t71957,\n\t\t71958,\n\t\t71960,\n\t\t71989,\n\t\t71991,\n\t\t71992,\n\t\t71995,\n\t\t72003,\n\t\t72016,\n\t\t72025,\n\t\t72096,\n\t\t72103,\n\t\t72106,\n\t\t72151,\n\t\t72154,\n\t\t72161,\n\t\t72163,\n\t\t72164,\n\t\t72192,\n\t\t72254,\n\t\t72263,\n\t\t72263,\n\t\t72272,\n\t\t72345,\n\t\t72349,\n\t\t72349,\n\t\t72368,\n\t\t72440,\n\t\t72704,\n\t\t72712,\n\t\t72714,\n\t\t72758,\n\t\t72760,\n\t\t72768,\n\t\t72784,\n\t\t72793,\n\t\t72818,\n\t\t72847,\n\t\t72850,\n\t\t72871,\n\t\t72873,\n\t\t72886,\n\t\t72960,\n\t\t72966,\n\t\t72968,\n\t\t72969,\n\t\t72971,\n\t\t73014,\n\t\t73018,\n\t\t73018,\n\t\t73020,\n\t\t73021,\n\t\t73023,\n\t\t73031,\n\t\t73040,\n\t\t73049,\n\t\t73056,\n\t\t73061,\n\t\t73063,\n\t\t73064,\n\t\t73066,\n\t\t73102,\n\t\t73104,\n\t\t73105,\n\t\t73107,\n\t\t73112,\n\t\t73120,\n\t\t73129,\n\t\t73440,\n\t\t73462,\n\t\t73472,\n\t\t73488,\n\t\t73490,\n\t\t73530,\n\t\t73534,\n\t\t73538,\n\t\t73552,\n\t\t73561,\n\t\t73648,\n\t\t73648,\n\t\t73728,\n\t\t74649,\n\t\t74752,\n\t\t74862,\n\t\t74880,\n\t\t75075,\n\t\t77712,\n\t\t77808,\n\t\t77824,\n\t\t78933,\n\t\t82944,\n\t\t83526,\n\t\t92160,\n\t\t92728,\n\t\t92736,\n\t\t92766,\n\t\t92768,\n\t\t92777,\n\t\t92784,\n\t\t92862,\n\t\t92864,\n\t\t92873,\n\t\t92880,\n\t\t92909,\n\t\t92912,\n\t\t92916,\n\t\t92928,\n\t\t92982,\n\t\t92992,\n\t\t92995,\n\t\t93008,\n\t\t93017,\n\t\t93027,\n\t\t93047,\n\t\t93053,\n\t\t93071,\n\t\t93760,\n\t\t93823,\n\t\t93952,\n\t\t94026,\n\t\t94031,\n\t\t94087,\n\t\t94095,\n\t\t94111,\n\t\t94176,\n\t\t94177,\n\t\t94179,\n\t\t94180,\n\t\t94192,\n\t\t94193,\n\t\t94208,\n\t\t100343,\n\t\t100352,\n\t\t101589,\n\t\t101632,\n\t\t101640,\n\t\t110576,\n\t\t110579,\n\t\t110581,\n\t\t110587,\n\t\t110589,\n\t\t110590,\n\t\t110592,\n\t\t110882,\n\t\t110898,\n\t\t110898,\n\t\t110928,\n\t\t110930,\n\t\t110933,\n\t\t110933,\n\t\t110948,\n\t\t110951,\n\t\t110960,\n\t\t111355,\n\t\t113664,\n\t\t113770,\n\t\t113776,\n\t\t113788,\n\t\t113792,\n\t\t113800,\n\t\t113808,\n\t\t113817,\n\t\t113821,\n\t\t113822,\n\t\t113824,\n\t\t113827,\n\t\t118528,\n\t\t118573,\n\t\t118576,\n\t\t118598,\n\t\t119141,\n\t\t119145,\n\t\t119149,\n\t\t119170,\n\t\t119173,\n\t\t119179,\n\t\t119210,\n\t\t119213,\n\t\t119362,\n\t\t119364,\n\t\t119808,\n\t\t119892,\n\t\t119894,\n\t\t119964,\n\t\t119966,\n\t\t119967,\n\t\t119970,\n\t\t119970,\n\t\t119973,\n\t\t119974,\n\t\t119977,\n\t\t119980,\n\t\t119982,\n\t\t119993,\n\t\t119995,\n\t\t119995,\n\t\t119997,\n\t\t120003,\n\t\t120005,\n\t\t120069,\n\t\t120071,\n\t\t120074,\n\t\t120077,\n\t\t120084,\n\t\t120086,\n\t\t120092,\n\t\t120094,\n\t\t120121,\n\t\t120123,\n\t\t120126,\n\t\t120128,\n\t\t120132,\n\t\t120134,\n\t\t120134,\n\t\t120138,\n\t\t120144,\n\t\t120146,\n\t\t120485,\n\t\t120488,\n\t\t120512,\n\t\t120514,\n\t\t120538,\n\t\t120540,\n\t\t120570,\n\t\t120572,\n\t\t120596,\n\t\t120598,\n\t\t120628,\n\t\t120630,\n\t\t120654,\n\t\t120656,\n\t\t120686,\n\t\t120688,\n\t\t120712,\n\t\t120714,\n\t\t120744,\n\t\t120746,\n\t\t120770,\n\t\t120772,\n\t\t120779,\n\t\t120782,\n\t\t120831,\n\t\t121344,\n\t\t121398,\n\t\t121403,\n\t\t121452,\n\t\t121461,\n\t\t121461,\n\t\t121476,\n\t\t121476,\n\t\t121499,\n\t\t121503,\n\t\t121505,\n\t\t121519,\n\t\t122624,\n\t\t122654,\n\t\t122661,\n\t\t122666,\n\t\t122880,\n\t\t122886,\n\t\t122888,\n\t\t122904,\n\t\t122907,\n\t\t122913,\n\t\t122915,\n\t\t122916,\n\t\t122918,\n\t\t122922,\n\t\t122928,\n\t\t122989,\n\t\t123023,\n\t\t123023,\n\t\t123136,\n\t\t123180,\n\t\t123184,\n\t\t123197,\n\t\t123200,\n\t\t123209,\n\t\t123214,\n\t\t123214,\n\t\t123536,\n\t\t123566,\n\t\t123584,\n\t\t123641,\n\t\t124112,\n\t\t124153,\n\t\t124896,\n\t\t124902,\n\t\t124904,\n\t\t124907,\n\t\t124909,\n\t\t124910,\n\t\t124912,\n\t\t124926,\n\t\t124928,\n\t\t125124,\n\t\t125136,\n\t\t125142,\n\t\t125184,\n\t\t125259,\n\t\t125264,\n\t\t125273,\n\t\t126464,\n\t\t126467,\n\t\t126469,\n\t\t126495,\n\t\t126497,\n\t\t126498,\n\t\t126500,\n\t\t126500,\n\t\t126503,\n\t\t126503,\n\t\t126505,\n\t\t126514,\n\t\t126516,\n\t\t126519,\n\t\t126521,\n\t\t126521,\n\t\t126523,\n\t\t126523,\n\t\t126530,\n\t\t126530,\n\t\t126535,\n\t\t126535,\n\t\t126537,\n\t\t126537,\n\t\t126539,\n\t\t126539,\n\t\t126541,\n\t\t126543,\n\t\t126545,\n\t\t126546,\n\t\t126548,\n\t\t126548,\n\t\t126551,\n\t\t126551,\n\t\t126553,\n\t\t126553,\n\t\t126555,\n\t\t126555,\n\t\t126557,\n\t\t126557,\n\t\t126559,\n\t\t126559,\n\t\t126561,\n\t\t126562,\n\t\t126564,\n\t\t126564,\n\t\t126567,\n\t\t126570,\n\t\t126572,\n\t\t126578,\n\t\t126580,\n\t\t126583,\n\t\t126585,\n\t\t126588,\n\t\t126590,\n\t\t126590,\n\t\t126592,\n\t\t126601,\n\t\t126603,\n\t\t126619,\n\t\t126625,\n\t\t126627,\n\t\t126629,\n\t\t126633,\n\t\t126635,\n\t\t126651,\n\t\t130032,\n\t\t130041,\n\t\t131072,\n\t\t173791,\n\t\t173824,\n\t\t177977,\n\t\t177984,\n\t\t178205,\n\t\t178208,\n\t\t183969,\n\t\t183984,\n\t\t191456,\n\t\t194560,\n\t\t195101,\n\t\t196608,\n\t\t201546,\n\t\t201552,\n\t\t205743,\n\t\t917505,\n\t\t917505,\n\t\t917536,\n\t\t917631,\n\t\t917760,\n\t\t917999,\n\t\t662,\n\t\t0,\n\t\t65,\n\t\t90,\n\t\t97,\n\t\t122,\n\t\t170,\n\t\t170,\n\t\t181,\n\t\t181,\n\t\t186,\n\t\t186,\n\t\t192,\n\t\t214,\n\t\t216,\n\t\t246,\n\t\t248,\n\t\t705,\n\t\t710,\n\t\t721,\n\t\t736,\n\t\t740,\n\t\t748,\n\t\t748,\n\t\t750,\n\t\t750,\n\t\t880,\n\t\t884,\n\t\t886,\n\t\t887,\n\t\t890,\n\t\t893,\n\t\t895,\n\t\t895,\n\t\t902,\n\t\t902,\n\t\t904,\n\t\t906,\n\t\t908,\n\t\t908,\n\t\t910,\n\t\t929,\n\t\t931,\n\t\t1013,\n\t\t1015,\n\t\t1153,\n\t\t1162,\n\t\t1327,\n\t\t1329,\n\t\t1366,\n\t\t1369,\n\t\t1369,\n\t\t1376,\n\t\t1416,\n\t\t1488,\n\t\t1514,\n\t\t1519,\n\t\t1522,\n\t\t1568,\n\t\t1610,\n\t\t1646,\n\t\t1647,\n\t\t1649,\n\t\t1747,\n\t\t1749,\n\t\t1749,\n\t\t1765,\n\t\t1766,\n\t\t1774,\n\t\t1775,\n\t\t1786,\n\t\t1788,\n\t\t1791,\n\t\t1791,\n\t\t1808,\n\t\t1808,\n\t\t1810,\n\t\t1839,\n\t\t1869,\n\t\t1957,\n\t\t1969,\n\t\t1969,\n\t\t1994,\n\t\t2026,\n\t\t2036,\n\t\t2037,\n\t\t2042,\n\t\t2042,\n\t\t2048,\n\t\t2069,\n\t\t2074,\n\t\t2074,\n\t\t2084,\n\t\t2084,\n\t\t2088,\n\t\t2088,\n\t\t2112,\n\t\t2136,\n\t\t2144,\n\t\t2154,\n\t\t2160,\n\t\t2183,\n\t\t2185,\n\t\t2190,\n\t\t2208,\n\t\t2249,\n\t\t2308,\n\t\t2361,\n\t\t2365,\n\t\t2365,\n\t\t2384,\n\t\t2384,\n\t\t2392,\n\t\t2401,\n\t\t2417,\n\t\t2432,\n\t\t2437,\n\t\t2444,\n\t\t2447,\n\t\t2448,\n\t\t2451,\n\t\t2472,\n\t\t2474,\n\t\t2480,\n\t\t2482,\n\t\t2482,\n\t\t2486,\n\t\t2489,\n\t\t2493,\n\t\t2493,\n\t\t2510,\n\t\t2510,\n\t\t2524,\n\t\t2525,\n\t\t2527,\n\t\t2529,\n\t\t2544,\n\t\t2545,\n\t\t2556,\n\t\t2556,\n\t\t2565,\n\t\t2570,\n\t\t2575,\n\t\t2576,\n\t\t2579,\n\t\t2600,\n\t\t2602,\n\t\t2608,\n\t\t2610,\n\t\t2611,\n\t\t2613,\n\t\t2614,\n\t\t2616,\n\t\t2617,\n\t\t2649,\n\t\t2652,\n\t\t2654,\n\t\t2654,\n\t\t2674,\n\t\t2676,\n\t\t2693,\n\t\t2701,\n\t\t2703,\n\t\t2705,\n\t\t2707,\n\t\t2728,\n\t\t2730,\n\t\t2736,\n\t\t2738,\n\t\t2739,\n\t\t2741,\n\t\t2745,\n\t\t2749,\n\t\t2749,\n\t\t2768,\n\t\t2768,\n\t\t2784,\n\t\t2785,\n\t\t2809,\n\t\t2809,\n\t\t2821,\n\t\t2828,\n\t\t2831,\n\t\t2832,\n\t\t2835,\n\t\t2856,\n\t\t2858,\n\t\t2864,\n\t\t2866,\n\t\t2867,\n\t\t2869,\n\t\t2873,\n\t\t2877,\n\t\t2877,\n\t\t2908,\n\t\t2909,\n\t\t2911,\n\t\t2913,\n\t\t2929,\n\t\t2929,\n\t\t2947,\n\t\t2947,\n\t\t2949,\n\t\t2954,\n\t\t2958,\n\t\t2960,\n\t\t2962,\n\t\t2965,\n\t\t2969,\n\t\t2970,\n\t\t2972,\n\t\t2972,\n\t\t2974,\n\t\t2975,\n\t\t2979,\n\t\t2980,\n\t\t2984,\n\t\t2986,\n\t\t2990,\n\t\t3001,\n\t\t3024,\n\t\t3024,\n\t\t3077,\n\t\t3084,\n\t\t3086,\n\t\t3088,\n\t\t3090,\n\t\t3112,\n\t\t3114,\n\t\t3129,\n\t\t3133,\n\t\t3133,\n\t\t3160,\n\t\t3162,\n\t\t3165,\n\t\t3165,\n\t\t3168,\n\t\t3169,\n\t\t3200,\n\t\t3200,\n\t\t3205,\n\t\t3212,\n\t\t3214,\n\t\t3216,\n\t\t3218,\n\t\t3240,\n\t\t3242,\n\t\t3251,\n\t\t3253,\n\t\t3257,\n\t\t3261,\n\t\t3261,\n\t\t3293,\n\t\t3294,\n\t\t3296,\n\t\t3297,\n\t\t3313,\n\t\t3314,\n\t\t3332,\n\t\t3340,\n\t\t3342,\n\t\t3344,\n\t\t3346,\n\t\t3386,\n\t\t3389,\n\t\t3389,\n\t\t3406,\n\t\t3406,\n\t\t3412,\n\t\t3414,\n\t\t3423,\n\t\t3425,\n\t\t3450,\n\t\t3455,\n\t\t3461,\n\t\t3478,\n\t\t3482,\n\t\t3505,\n\t\t3507,\n\t\t3515,\n\t\t3517,\n\t\t3517,\n\t\t3520,\n\t\t3526,\n\t\t3585,\n\t\t3632,\n\t\t3634,\n\t\t3635,\n\t\t3648,\n\t\t3654,\n\t\t3713,\n\t\t3714,\n\t\t3716,\n\t\t3716,\n\t\t3718,\n\t\t3722,\n\t\t3724,\n\t\t3747,\n\t\t3749,\n\t\t3749,\n\t\t3751,\n\t\t3760,\n\t\t3762,\n\t\t3763,\n\t\t3773,\n\t\t3773,\n\t\t3776,\n\t\t3780,\n\t\t3782,\n\t\t3782,\n\t\t3804,\n\t\t3807,\n\t\t3840,\n\t\t3840,\n\t\t3904,\n\t\t3911,\n\t\t3913,\n\t\t3948,\n\t\t3976,\n\t\t3980,\n\t\t4096,\n\t\t4138,\n\t\t4159,\n\t\t4159,\n\t\t4176,\n\t\t4181,\n\t\t4186,\n\t\t4189,\n\t\t4193,\n\t\t4193,\n\t\t4197,\n\t\t4198,\n\t\t4206,\n\t\t4208,\n\t\t4213,\n\t\t4225,\n\t\t4238,\n\t\t4238,\n\t\t4256,\n\t\t4293,\n\t\t4295,\n\t\t4295,\n\t\t4301,\n\t\t4301,\n\t\t4304,\n\t\t4346,\n\t\t4348,\n\t\t4680,\n\t\t4682,\n\t\t4685,\n\t\t4688,\n\t\t4694,\n\t\t4696,\n\t\t4696,\n\t\t4698,\n\t\t4701,\n\t\t4704,\n\t\t4744,\n\t\t4746,\n\t\t4749,\n\t\t4752,\n\t\t4784,\n\t\t4786,\n\t\t4789,\n\t\t4792,\n\t\t4798,\n\t\t4800,\n\t\t4800,\n\t\t4802,\n\t\t4805,\n\t\t4808,\n\t\t4822,\n\t\t4824,\n\t\t4880,\n\t\t4882,\n\t\t4885,\n\t\t4888,\n\t\t4954,\n\t\t4992,\n\t\t5007,\n\t\t5024,\n\t\t5109,\n\t\t5112,\n\t\t5117,\n\t\t5121,\n\t\t5740,\n\t\t5743,\n\t\t5759,\n\t\t5761,\n\t\t5786,\n\t\t5792,\n\t\t5866,\n\t\t5870,\n\t\t5880,\n\t\t5888,\n\t\t5905,\n\t\t5919,\n\t\t5937,\n\t\t5952,\n\t\t5969,\n\t\t5984,\n\t\t5996,\n\t\t5998,\n\t\t6e3,\n\t\t6016,\n\t\t6067,\n\t\t6103,\n\t\t6103,\n\t\t6108,\n\t\t6108,\n\t\t6176,\n\t\t6264,\n\t\t6272,\n\t\t6276,\n\t\t6279,\n\t\t6312,\n\t\t6314,\n\t\t6314,\n\t\t6320,\n\t\t6389,\n\t\t6400,\n\t\t6430,\n\t\t6480,\n\t\t6509,\n\t\t6512,\n\t\t6516,\n\t\t6528,\n\t\t6571,\n\t\t6576,\n\t\t6601,\n\t\t6656,\n\t\t6678,\n\t\t6688,\n\t\t6740,\n\t\t6823,\n\t\t6823,\n\t\t6917,\n\t\t6963,\n\t\t6981,\n\t\t6988,\n\t\t7043,\n\t\t7072,\n\t\t7086,\n\t\t7087,\n\t\t7098,\n\t\t7141,\n\t\t7168,\n\t\t7203,\n\t\t7245,\n\t\t7247,\n\t\t7258,\n\t\t7293,\n\t\t7296,\n\t\t7304,\n\t\t7312,\n\t\t7354,\n\t\t7357,\n\t\t7359,\n\t\t7401,\n\t\t7404,\n\t\t7406,\n\t\t7411,\n\t\t7413,\n\t\t7414,\n\t\t7418,\n\t\t7418,\n\t\t7424,\n\t\t7615,\n\t\t7680,\n\t\t7957,\n\t\t7960,\n\t\t7965,\n\t\t7968,\n\t\t8005,\n\t\t8008,\n\t\t8013,\n\t\t8016,\n\t\t8023,\n\t\t8025,\n\t\t8025,\n\t\t8027,\n\t\t8027,\n\t\t8029,\n\t\t8029,\n\t\t8031,\n\t\t8061,\n\t\t8064,\n\t\t8116,\n\t\t8118,\n\t\t8124,\n\t\t8126,\n\t\t8126,\n\t\t8130,\n\t\t8132,\n\t\t8134,\n\t\t8140,\n\t\t8144,\n\t\t8147,\n\t\t8150,\n\t\t8155,\n\t\t8160,\n\t\t8172,\n\t\t8178,\n\t\t8180,\n\t\t8182,\n\t\t8188,\n\t\t8305,\n\t\t8305,\n\t\t8319,\n\t\t8319,\n\t\t8336,\n\t\t8348,\n\t\t8450,\n\t\t8450,\n\t\t8455,\n\t\t8455,\n\t\t8458,\n\t\t8467,\n\t\t8469,\n\t\t8469,\n\t\t8473,\n\t\t8477,\n\t\t8484,\n\t\t8484,\n\t\t8486,\n\t\t8486,\n\t\t8488,\n\t\t8488,\n\t\t8490,\n\t\t8493,\n\t\t8495,\n\t\t8505,\n\t\t8508,\n\t\t8511,\n\t\t8517,\n\t\t8521,\n\t\t8526,\n\t\t8526,\n\t\t8544,\n\t\t8584,\n\t\t11264,\n\t\t11492,\n\t\t11499,\n\t\t11502,\n\t\t11506,\n\t\t11507,\n\t\t11520,\n\t\t11557,\n\t\t11559,\n\t\t11559,\n\t\t11565,\n\t\t11565,\n\t\t11568,\n\t\t11623,\n\t\t11631,\n\t\t11631,\n\t\t11648,\n\t\t11670,\n\t\t11680,\n\t\t11686,\n\t\t11688,\n\t\t11694,\n\t\t11696,\n\t\t11702,\n\t\t11704,\n\t\t11710,\n\t\t11712,\n\t\t11718,\n\t\t11720,\n\t\t11726,\n\t\t11728,\n\t\t11734,\n\t\t11736,\n\t\t11742,\n\t\t11823,\n\t\t11823,\n\t\t12293,\n\t\t12295,\n\t\t12321,\n\t\t12329,\n\t\t12337,\n\t\t12341,\n\t\t12344,\n\t\t12348,\n\t\t12353,\n\t\t12438,\n\t\t12445,\n\t\t12447,\n\t\t12449,\n\t\t12538,\n\t\t12540,\n\t\t12543,\n\t\t12549,\n\t\t12591,\n\t\t12593,\n\t\t12686,\n\t\t12704,\n\t\t12735,\n\t\t12784,\n\t\t12799,\n\t\t13312,\n\t\t19903,\n\t\t19968,\n\t\t42124,\n\t\t42192,\n\t\t42237,\n\t\t42240,\n\t\t42508,\n\t\t42512,\n\t\t42527,\n\t\t42538,\n\t\t42539,\n\t\t42560,\n\t\t42606,\n\t\t42623,\n\t\t42653,\n\t\t42656,\n\t\t42735,\n\t\t42775,\n\t\t42783,\n\t\t42786,\n\t\t42888,\n\t\t42891,\n\t\t42954,\n\t\t42960,\n\t\t42961,\n\t\t42963,\n\t\t42963,\n\t\t42965,\n\t\t42969,\n\t\t42994,\n\t\t43009,\n\t\t43011,\n\t\t43013,\n\t\t43015,\n\t\t43018,\n\t\t43020,\n\t\t43042,\n\t\t43072,\n\t\t43123,\n\t\t43138,\n\t\t43187,\n\t\t43250,\n\t\t43255,\n\t\t43259,\n\t\t43259,\n\t\t43261,\n\t\t43262,\n\t\t43274,\n\t\t43301,\n\t\t43312,\n\t\t43334,\n\t\t43360,\n\t\t43388,\n\t\t43396,\n\t\t43442,\n\t\t43471,\n\t\t43471,\n\t\t43488,\n\t\t43492,\n\t\t43494,\n\t\t43503,\n\t\t43514,\n\t\t43518,\n\t\t43520,\n\t\t43560,\n\t\t43584,\n\t\t43586,\n\t\t43588,\n\t\t43595,\n\t\t43616,\n\t\t43638,\n\t\t43642,\n\t\t43642,\n\t\t43646,\n\t\t43695,\n\t\t43697,\n\t\t43697,\n\t\t43701,\n\t\t43702,\n\t\t43705,\n\t\t43709,\n\t\t43712,\n\t\t43712,\n\t\t43714,\n\t\t43714,\n\t\t43739,\n\t\t43741,\n\t\t43744,\n\t\t43754,\n\t\t43762,\n\t\t43764,\n\t\t43777,\n\t\t43782,\n\t\t43785,\n\t\t43790,\n\t\t43793,\n\t\t43798,\n\t\t43808,\n\t\t43814,\n\t\t43816,\n\t\t43822,\n\t\t43824,\n\t\t43866,\n\t\t43868,\n\t\t43881,\n\t\t43888,\n\t\t44002,\n\t\t44032,\n\t\t55203,\n\t\t55216,\n\t\t55238,\n\t\t55243,\n\t\t55291,\n\t\t63744,\n\t\t64109,\n\t\t64112,\n\t\t64217,\n\t\t64256,\n\t\t64262,\n\t\t64275,\n\t\t64279,\n\t\t64285,\n\t\t64285,\n\t\t64287,\n\t\t64296,\n\t\t64298,\n\t\t64310,\n\t\t64312,\n\t\t64316,\n\t\t64318,\n\t\t64318,\n\t\t64320,\n\t\t64321,\n\t\t64323,\n\t\t64324,\n\t\t64326,\n\t\t64433,\n\t\t64467,\n\t\t64829,\n\t\t64848,\n\t\t64911,\n\t\t64914,\n\t\t64967,\n\t\t65008,\n\t\t65019,\n\t\t65136,\n\t\t65140,\n\t\t65142,\n\t\t65276,\n\t\t65313,\n\t\t65338,\n\t\t65345,\n\t\t65370,\n\t\t65382,\n\t\t65470,\n\t\t65474,\n\t\t65479,\n\t\t65482,\n\t\t65487,\n\t\t65490,\n\t\t65495,\n\t\t65498,\n\t\t65500,\n\t\t65536,\n\t\t65547,\n\t\t65549,\n\t\t65574,\n\t\t65576,\n\t\t65594,\n\t\t65596,\n\t\t65597,\n\t\t65599,\n\t\t65613,\n\t\t65616,\n\t\t65629,\n\t\t65664,\n\t\t65786,\n\t\t65856,\n\t\t65908,\n\t\t66176,\n\t\t66204,\n\t\t66208,\n\t\t66256,\n\t\t66304,\n\t\t66335,\n\t\t66349,\n\t\t66378,\n\t\t66384,\n\t\t66421,\n\t\t66432,\n\t\t66461,\n\t\t66464,\n\t\t66499,\n\t\t66504,\n\t\t66511,\n\t\t66513,\n\t\t66517,\n\t\t66560,\n\t\t66717,\n\t\t66736,\n\t\t66771,\n\t\t66776,\n\t\t66811,\n\t\t66816,\n\t\t66855,\n\t\t66864,\n\t\t66915,\n\t\t66928,\n\t\t66938,\n\t\t66940,\n\t\t66954,\n\t\t66956,\n\t\t66962,\n\t\t66964,\n\t\t66965,\n\t\t66967,\n\t\t66977,\n\t\t66979,\n\t\t66993,\n\t\t66995,\n\t\t67001,\n\t\t67003,\n\t\t67004,\n\t\t67072,\n\t\t67382,\n\t\t67392,\n\t\t67413,\n\t\t67424,\n\t\t67431,\n\t\t67456,\n\t\t67461,\n\t\t67463,\n\t\t67504,\n\t\t67506,\n\t\t67514,\n\t\t67584,\n\t\t67589,\n\t\t67592,\n\t\t67592,\n\t\t67594,\n\t\t67637,\n\t\t67639,\n\t\t67640,\n\t\t67644,\n\t\t67644,\n\t\t67647,\n\t\t67669,\n\t\t67680,\n\t\t67702,\n\t\t67712,\n\t\t67742,\n\t\t67808,\n\t\t67826,\n\t\t67828,\n\t\t67829,\n\t\t67840,\n\t\t67861,\n\t\t67872,\n\t\t67897,\n\t\t67968,\n\t\t68023,\n\t\t68030,\n\t\t68031,\n\t\t68096,\n\t\t68096,\n\t\t68112,\n\t\t68115,\n\t\t68117,\n\t\t68119,\n\t\t68121,\n\t\t68149,\n\t\t68192,\n\t\t68220,\n\t\t68224,\n\t\t68252,\n\t\t68288,\n\t\t68295,\n\t\t68297,\n\t\t68324,\n\t\t68352,\n\t\t68405,\n\t\t68416,\n\t\t68437,\n\t\t68448,\n\t\t68466,\n\t\t68480,\n\t\t68497,\n\t\t68608,\n\t\t68680,\n\t\t68736,\n\t\t68786,\n\t\t68800,\n\t\t68850,\n\t\t68864,\n\t\t68899,\n\t\t69248,\n\t\t69289,\n\t\t69296,\n\t\t69297,\n\t\t69376,\n\t\t69404,\n\t\t69415,\n\t\t69415,\n\t\t69424,\n\t\t69445,\n\t\t69488,\n\t\t69505,\n\t\t69552,\n\t\t69572,\n\t\t69600,\n\t\t69622,\n\t\t69635,\n\t\t69687,\n\t\t69745,\n\t\t69746,\n\t\t69749,\n\t\t69749,\n\t\t69763,\n\t\t69807,\n\t\t69840,\n\t\t69864,\n\t\t69891,\n\t\t69926,\n\t\t69956,\n\t\t69956,\n\t\t69959,\n\t\t69959,\n\t\t69968,\n\t\t70002,\n\t\t70006,\n\t\t70006,\n\t\t70019,\n\t\t70066,\n\t\t70081,\n\t\t70084,\n\t\t70106,\n\t\t70106,\n\t\t70108,\n\t\t70108,\n\t\t70144,\n\t\t70161,\n\t\t70163,\n\t\t70187,\n\t\t70207,\n\t\t70208,\n\t\t70272,\n\t\t70278,\n\t\t70280,\n\t\t70280,\n\t\t70282,\n\t\t70285,\n\t\t70287,\n\t\t70301,\n\t\t70303,\n\t\t70312,\n\t\t70320,\n\t\t70366,\n\t\t70405,\n\t\t70412,\n\t\t70415,\n\t\t70416,\n\t\t70419,\n\t\t70440,\n\t\t70442,\n\t\t70448,\n\t\t70450,\n\t\t70451,\n\t\t70453,\n\t\t70457,\n\t\t70461,\n\t\t70461,\n\t\t70480,\n\t\t70480,\n\t\t70493,\n\t\t70497,\n\t\t70656,\n\t\t70708,\n\t\t70727,\n\t\t70730,\n\t\t70751,\n\t\t70753,\n\t\t70784,\n\t\t70831,\n\t\t70852,\n\t\t70853,\n\t\t70855,\n\t\t70855,\n\t\t71040,\n\t\t71086,\n\t\t71128,\n\t\t71131,\n\t\t71168,\n\t\t71215,\n\t\t71236,\n\t\t71236,\n\t\t71296,\n\t\t71338,\n\t\t71352,\n\t\t71352,\n\t\t71424,\n\t\t71450,\n\t\t71488,\n\t\t71494,\n\t\t71680,\n\t\t71723,\n\t\t71840,\n\t\t71903,\n\t\t71935,\n\t\t71942,\n\t\t71945,\n\t\t71945,\n\t\t71948,\n\t\t71955,\n\t\t71957,\n\t\t71958,\n\t\t71960,\n\t\t71983,\n\t\t71999,\n\t\t71999,\n\t\t72001,\n\t\t72001,\n\t\t72096,\n\t\t72103,\n\t\t72106,\n\t\t72144,\n\t\t72161,\n\t\t72161,\n\t\t72163,\n\t\t72163,\n\t\t72192,\n\t\t72192,\n\t\t72203,\n\t\t72242,\n\t\t72250,\n\t\t72250,\n\t\t72272,\n\t\t72272,\n\t\t72284,\n\t\t72329,\n\t\t72349,\n\t\t72349,\n\t\t72368,\n\t\t72440,\n\t\t72704,\n\t\t72712,\n\t\t72714,\n\t\t72750,\n\t\t72768,\n\t\t72768,\n\t\t72818,\n\t\t72847,\n\t\t72960,\n\t\t72966,\n\t\t72968,\n\t\t72969,\n\t\t72971,\n\t\t73008,\n\t\t73030,\n\t\t73030,\n\t\t73056,\n\t\t73061,\n\t\t73063,\n\t\t73064,\n\t\t73066,\n\t\t73097,\n\t\t73112,\n\t\t73112,\n\t\t73440,\n\t\t73458,\n\t\t73474,\n\t\t73474,\n\t\t73476,\n\t\t73488,\n\t\t73490,\n\t\t73523,\n\t\t73648,\n\t\t73648,\n\t\t73728,\n\t\t74649,\n\t\t74752,\n\t\t74862,\n\t\t74880,\n\t\t75075,\n\t\t77712,\n\t\t77808,\n\t\t77824,\n\t\t78895,\n\t\t78913,\n\t\t78918,\n\t\t82944,\n\t\t83526,\n\t\t92160,\n\t\t92728,\n\t\t92736,\n\t\t92766,\n\t\t92784,\n\t\t92862,\n\t\t92880,\n\t\t92909,\n\t\t92928,\n\t\t92975,\n\t\t92992,\n\t\t92995,\n\t\t93027,\n\t\t93047,\n\t\t93053,\n\t\t93071,\n\t\t93760,\n\t\t93823,\n\t\t93952,\n\t\t94026,\n\t\t94032,\n\t\t94032,\n\t\t94099,\n\t\t94111,\n\t\t94176,\n\t\t94177,\n\t\t94179,\n\t\t94179,\n\t\t94208,\n\t\t100343,\n\t\t100352,\n\t\t101589,\n\t\t101632,\n\t\t101640,\n\t\t110576,\n\t\t110579,\n\t\t110581,\n\t\t110587,\n\t\t110589,\n\t\t110590,\n\t\t110592,\n\t\t110882,\n\t\t110898,\n\t\t110898,\n\t\t110928,\n\t\t110930,\n\t\t110933,\n\t\t110933,\n\t\t110948,\n\t\t110951,\n\t\t110960,\n\t\t111355,\n\t\t113664,\n\t\t113770,\n\t\t113776,\n\t\t113788,\n\t\t113792,\n\t\t113800,\n\t\t113808,\n\t\t113817,\n\t\t119808,\n\t\t119892,\n\t\t119894,\n\t\t119964,\n\t\t119966,\n\t\t119967,\n\t\t119970,\n\t\t119970,\n\t\t119973,\n\t\t119974,\n\t\t119977,\n\t\t119980,\n\t\t119982,\n\t\t119993,\n\t\t119995,\n\t\t119995,\n\t\t119997,\n\t\t120003,\n\t\t120005,\n\t\t120069,\n\t\t120071,\n\t\t120074,\n\t\t120077,\n\t\t120084,\n\t\t120086,\n\t\t120092,\n\t\t120094,\n\t\t120121,\n\t\t120123,\n\t\t120126,\n\t\t120128,\n\t\t120132,\n\t\t120134,\n\t\t120134,\n\t\t120138,\n\t\t120144,\n\t\t120146,\n\t\t120485,\n\t\t120488,\n\t\t120512,\n\t\t120514,\n\t\t120538,\n\t\t120540,\n\t\t120570,\n\t\t120572,\n\t\t120596,\n\t\t120598,\n\t\t120628,\n\t\t120630,\n\t\t120654,\n\t\t120656,\n\t\t120686,\n\t\t120688,\n\t\t120712,\n\t\t120714,\n\t\t120744,\n\t\t120746,\n\t\t120770,\n\t\t120772,\n\t\t120779,\n\t\t122624,\n\t\t122654,\n\t\t122661,\n\t\t122666,\n\t\t122928,\n\t\t122989,\n\t\t123136,\n\t\t123180,\n\t\t123191,\n\t\t123197,\n\t\t123214,\n\t\t123214,\n\t\t123536,\n\t\t123565,\n\t\t123584,\n\t\t123627,\n\t\t124112,\n\t\t124139,\n\t\t124896,\n\t\t124902,\n\t\t124904,\n\t\t124907,\n\t\t124909,\n\t\t124910,\n\t\t124912,\n\t\t124926,\n\t\t124928,\n\t\t125124,\n\t\t125184,\n\t\t125251,\n\t\t125259,\n\t\t125259,\n\t\t126464,\n\t\t126467,\n\t\t126469,\n\t\t126495,\n\t\t126497,\n\t\t126498,\n\t\t126500,\n\t\t126500,\n\t\t126503,\n\t\t126503,\n\t\t126505,\n\t\t126514,\n\t\t126516,\n\t\t126519,\n\t\t126521,\n\t\t126521,\n\t\t126523,\n\t\t126523,\n\t\t126530,\n\t\t126530,\n\t\t126535,\n\t\t126535,\n\t\t126537,\n\t\t126537,\n\t\t126539,\n\t\t126539,\n\t\t126541,\n\t\t126543,\n\t\t126545,\n\t\t126546,\n\t\t126548,\n\t\t126548,\n\t\t126551,\n\t\t126551,\n\t\t126553,\n\t\t126553,\n\t\t126555,\n\t\t126555,\n\t\t126557,\n\t\t126557,\n\t\t126559,\n\t\t126559,\n\t\t126561,\n\t\t126562,\n\t\t126564,\n\t\t126564,\n\t\t126567,\n\t\t126570,\n\t\t126572,\n\t\t126578,\n\t\t126580,\n\t\t126583,\n\t\t126585,\n\t\t126588,\n\t\t126590,\n\t\t126590,\n\t\t126592,\n\t\t126601,\n\t\t126603,\n\t\t126619,\n\t\t126625,\n\t\t126627,\n\t\t126629,\n\t\t126633,\n\t\t126635,\n\t\t126651,\n\t\t131072,\n\t\t173791,\n\t\t173824,\n\t\t177977,\n\t\t177984,\n\t\t178205,\n\t\t178208,\n\t\t183969,\n\t\t183984,\n\t\t191456,\n\t\t194560,\n\t\t195101,\n\t\t196608,\n\t\t201546,\n\t\t201552,\n\t\t205743,\n\t\t47,\n\t\t0,\n\t\t1,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t3,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t5,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t7,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t9,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t15,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t1,\n\t\t17,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t3,\n\t\t20,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t5,\n\t\t22,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t7,\n\t\t24,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t9,\n\t\t26,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t11,\n\t\t35,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t13,\n\t\t37,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t15,\n\t\t39,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t17,\n\t\t18,\n\t\t5,\n\t\t47,\n\t\t0,\n\t\t0,\n\t\t18,\n\t\t19,\n\t\t5,\n\t\t47,\n\t\t0,\n\t\t0,\n\t\t19,\n\t\t2,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t20,\n\t\t21,\n\t\t5,\n\t\t47,\n\t\t0,\n\t\t0,\n\t\t21,\n\t\t4,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t22,\n\t\t23,\n\t\t5,\n\t\t42,\n\t\t0,\n\t\t0,\n\t\t23,\n\t\t6,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t24,\n\t\t25,\n\t\t5,\n\t\t33,\n\t\t0,\n\t\t0,\n\t\t25,\n\t\t8,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t26,\n\t\t30,\n\t\t3,\n\t\t13,\n\t\t6,\n\t\t0,\n\t\t27,\n\t\t29,\n\t\t3,\n\t\t11,\n\t\t5,\n\t\t0,\n\t\t28,\n\t\t27,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t29,\n\t\t32,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t30,\n\t\t28,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t30,\n\t\t31,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t31,\n\t\t33,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t32,\n\t\t30,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t33,\n\t\t34,\n\t\t6,\n\t\t4,\n\t\t0,\n\t\t0,\n\t\t34,\n\t\t10,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t35,\n\t\t36,\n\t\t7,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t36,\n\t\t12,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t37,\n\t\t38,\n\t\t7,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t38,\n\t\t14,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t39,\n\t\t43,\n\t\t5,\n\t\t39,\n\t\t0,\n\t\t0,\n\t\t40,\n\t\t42,\n\t\t9,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t41,\n\t\t40,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t42,\n\t\t45,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t43,\n\t\t44,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t43,\n\t\t41,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t44,\n\t\t46,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t45,\n\t\t43,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t46,\n\t\t47,\n\t\t5,\n\t\t39,\n\t\t0,\n\t\t0,\n\t\t47,\n\t\t16,\n\t\t1,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t3,\n\t\t0,\n\t\t30,\n\t\t43,\n\t\t1,\n\t\t1,\n\t\t4,\n\t\t0\n\t];\n\tstatic __ATN;\n\tstatic get _ATN() {\n\t\tif (!_XPathLexer.__ATN) _XPathLexer.__ATN = new ATNDeserializer().deserialize(_XPathLexer._serializedATN);\n\t\treturn _XPathLexer.__ATN;\n\t}\n\tstatic vocabulary = new Vocabulary(_XPathLexer.literalNames, _XPathLexer.symbolicNames, []);\n\tget vocabulary() {\n\t\treturn _XPathLexer.vocabulary;\n\t}\n\tstatic decisionsToDFA = _XPathLexer._ATN.decisionToState.map((ds, index) => {\n\t\treturn new DFA(ds, index);\n\t});\n};\nvar XPathLexerErrorListener = class extends BaseErrorListener {\n\tstatic {\n\t\t__name(this, \"XPathLexerErrorListener\");\n\t}\n\tsyntaxError(_recognizer, _offendingSymbol, _line, _charPositionInLine, _msg, _e) {}\n};\nvar XPathElement = class {\n\tstatic {\n\t\t__name(this, \"XPathElement\");\n\t}\n\tinvert;\n\tnodeName;\n\t/**\n\t* Construct element like `/ID` or `ID` or `/*` etc... `nodeName` is undefined if just node\n\t*\n\t* @param nodeName The name of the node; may be undefined for any node.\n\t*/\n\tconstructor(nodeName) {\n\t\tthis.nodeName = nodeName;\n\t\tthis.invert = false;\n\t}\n\ttoString() {\n\t\treturn \"XPathElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPathRuleAnywhereElement = class extends XPathElement {\n\tstatic {\n\t\t__name(this, \"XPathRuleAnywhereElement\");\n\t}\n\truleIndex;\n\tconstructor(ruleName, ruleIndex) {\n\t\tsuper(ruleName);\n\t\tthis.ruleIndex = ruleIndex;\n\t}\n\tevaluate(t) {\n\t\treturn Trees.findAllRuleNodes(t, this.ruleIndex);\n\t}\n\ttoString() {\n\t\treturn \"XPathRuleAnywhereElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPathRuleElement = class extends XPathElement {\n\tstatic {\n\t\t__name(this, \"XPathRuleElement\");\n\t}\n\truleIndex;\n\tconstructor(ruleName, ruleIndex) {\n\t\tsuper(ruleName);\n\t\tthis.ruleIndex = ruleIndex;\n\t}\n\tevaluate(t) {\n\t\tconst nodes = [];\n\t\tfor (const c of Trees.getChildren(t)) if (c instanceof ParserRuleContext) {\n\t\t\tif (c.ruleIndex === this.ruleIndex && !this.invert || c.ruleIndex !== this.ruleIndex && this.invert) nodes.push(c);\n\t\t}\n\t\treturn nodes;\n\t}\n\ttoString() {\n\t\treturn \"XPathRuleElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPathTokenAnywhereElement = class extends XPathElement {\n\tstatic {\n\t\t__name(this, \"XPathTokenAnywhereElement\");\n\t}\n\ttokenType;\n\tconstructor(tokenName, tokenType) {\n\t\tsuper(tokenName);\n\t\tthis.tokenType = tokenType;\n\t}\n\tevaluate(t) {\n\t\treturn Trees.findAllTokenNodes(t, this.tokenType);\n\t}\n\ttoString() {\n\t\treturn \"XPathTokenAnywhereElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPathTokenElement = class extends XPathElement {\n\tstatic {\n\t\t__name(this, \"XPathTokenElement\");\n\t}\n\ttokenType;\n\tconstructor(tokenName, tokenType) {\n\t\tsuper(tokenName);\n\t\tthis.tokenType = tokenType;\n\t}\n\tevaluate(t) {\n\t\tconst nodes = [];\n\t\tfor (const c of Trees.getChildren(t)) if (c instanceof TerminalNode && c.symbol) {\n\t\t\tif (c.symbol.type === this.tokenType && !this.invert || c.symbol.type !== this.tokenType && this.invert) nodes.push(c);\n\t\t}\n\t\treturn nodes;\n\t}\n\ttoString() {\n\t\treturn \"XPathTokenElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPathWildcardAnywhereElement = class extends XPathElement {\n\tstatic {\n\t\t__name(this, \"XPathWildcardAnywhereElement\");\n\t}\n\tconstructor() {\n\t\tsuper(XPath.WILDCARD);\n\t}\n\tevaluate(t) {\n\t\tif (this.invert) return [];\n\t\treturn Trees.descendants(t);\n\t}\n\ttoString() {\n\t\treturn \"XPathWildcardAnywhereElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPathWildcardElement = class extends XPathElement {\n\tstatic {\n\t\t__name(this, \"XPathWildcardElement\");\n\t}\n\tconstructor() {\n\t\tsuper(XPath.WILDCARD);\n\t}\n\tevaluate(t) {\n\t\tconst kids = [];\n\t\tif (this.invert) return kids;\n\t\tfor (const c of Trees.getChildren(t)) kids.push(c);\n\t\treturn kids;\n\t}\n\ttoString() {\n\t\treturn \"XPathWildcardElement[\" + (this.invert ? \"!\" : \"\") + this.nodeName + \"]\";\n\t}\n};\nvar XPath = class _XPath {\n\tstatic {\n\t\t__name(this, \"XPath\");\n\t}\n\tstatic WILDCARD = \"*\";\n\tstatic NOT = \"!\";\n\tpath;\n\telements;\n\tparser;\n\tconstructor(parser, path) {\n\t\tthis.parser = parser;\n\t\tthis.path = path;\n\t\tthis.elements = this.split(path);\n\t}\n\tstatic findAll(tree, xpath, parser) {\n\t\treturn new _XPath(parser, xpath).evaluate(tree);\n\t}\n\tsplit(path) {\n\t\tconst lexer = new XPathLexer(CharStream.fromString(path));\n\t\tlexer.recover = (e) => {\n\t\t\tthrow e;\n\t\t};\n\t\tlexer.removeErrorListeners();\n\t\tlexer.addErrorListener(new XPathLexerErrorListener());\n\t\tconst tokenStream = new CommonTokenStream(lexer);\n\t\ttry {\n\t\t\ttokenStream.fill();\n\t\t} catch (e) {\n\t\t\tif (e instanceof LexerNoViableAltException) {\n\t\t\t\tconst msg = \"Invalid tokens or characters at index \" + lexer.column + \" in path '\" + path + \"' -- \" + e.message;\n\t\t\t\tthrow new RangeError(msg);\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t\tconst tokens = tokenStream.getTokens();\n\t\tconst elements = [];\n\t\tconst n2 = tokens.length;\n\t\tlet i = 0;\n\t\tloop: while (i < n2) {\n\t\t\tconst el = tokens[i];\n\t\t\tlet next;\n\t\t\tswitch (el.type) {\n\t\t\t\tcase XPathLexer.ROOT:\n\t\t\t\tcase XPathLexer.ANYWHERE:\n\t\t\t\t\tconst anywhere = el.type === XPathLexer.ANYWHERE;\n\t\t\t\t\ti++;\n\t\t\t\t\tnext = tokens[i];\n\t\t\t\t\tconst invert = next.type === XPathLexer.BANG;\n\t\t\t\t\tif (invert) {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tnext = tokens[i];\n\t\t\t\t\t}\n\t\t\t\t\tconst pathElement = this.getXPathElement(next, anywhere);\n\t\t\t\t\tpathElement.invert = invert;\n\t\t\t\t\telements.push(pathElement);\n\t\t\t\t\ti++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase XPathLexer.TOKEN_REF:\n\t\t\t\tcase XPathLexer.RULE_REF:\n\t\t\t\tcase XPathLexer.WILDCARD:\n\t\t\t\t\telements.push(this.getXPathElement(el, false));\n\t\t\t\t\t++i;\n\t\t\t\t\tbreak;\n\t\t\t\tcase Token.EOF: break loop;\n\t\t\t\tdefault: throw new Error(\"Unknown path element \" + el);\n\t\t\t}\n\t\t}\n\t\treturn elements;\n\t}\n\t/**\n\t* Return a list of all nodes starting at `t` as root that satisfy the\n\t* path. The root `/` is relative to the node passed to {@link evaluate}.\n\t*/\n\tevaluate(t) {\n\t\tconst dummyRoot = new ParserRuleContext(null);\n\t\tdummyRoot.addChild(t);\n\t\tlet work = /* @__PURE__ */ new Set([dummyRoot]);\n\t\tlet i = 0;\n\t\twhile (i < this.elements.length) {\n\t\t\tconst next = /* @__PURE__ */ new Set();\n\t\t\tfor (const node of work) if (node.getChildCount() > 0) this.elements[i].evaluate(node).forEach((tree) => {\n\t\t\t\tnext.add(tree);\n\t\t\t}, next);\n\t\t\ti++;\n\t\t\twork = next;\n\t\t}\n\t\treturn work;\n\t}\n\t/**\n\t* Convert word like `*` or `ID` or `expr` to a path\n\t* element. `anywhere` is `true` if `//` precedes the\n\t* word.\n\t*/\n\tgetXPathElement(wordToken, anywhere) {\n\t\tif (wordToken.type === Token.EOF) throw new Error(\"Missing path element at end of path\");\n\t\tconst word = wordToken.text;\n\t\tif (word == null) throw new Error(\"Expected wordToken to have text content.\");\n\t\tconst ttype = this.parser.getTokenType(word);\n\t\tconst ruleIndex = this.parser.getRuleIndex(word);\n\t\tswitch (wordToken.type) {\n\t\t\tcase XPathLexer.WILDCARD: return anywhere ? new XPathWildcardAnywhereElement() : new XPathWildcardElement();\n\t\t\tcase XPathLexer.TOKEN_REF:\n\t\t\tcase XPathLexer.STRING:\n\t\t\t\tif (ttype === Token.INVALID_TYPE) throw new Error(word + \" at index \" + wordToken.start + \" isn't a valid token name\");\n\t\t\t\treturn anywhere ? new XPathTokenAnywhereElement(word, ttype) : new XPathTokenElement(word, ttype);\n\t\t\tdefault:\n\t\t\t\tif (ruleIndex === -1) throw new Error(word + \" at index \" + wordToken.start + \" isn't a valid rule name\");\n\t\t\t\treturn anywhere ? new XPathRuleAnywhereElement(word, ruleIndex) : new XPathRuleElement(word, ruleIndex);\n\t\t}\n\t}\n};\nvar Chunk = class {\n\tstatic {\n\t\t__name(this, \"Chunk\");\n\t}\n};\nvar ParseTreeMatch = class {\n\tstatic {\n\t\t__name(this, \"ParseTreeMatch\");\n\t}\n\t/**\n\t* This is the backing field for {@link #getTree()}.\n\t*/\n\ttree;\n\t/**\n\t* This is the backing field for {@link #getPattern()}.\n\t*/\n\tpattern;\n\t/**\n\t* This is the backing field for {@link #getLabels()}.\n\t*/\n\tlabels;\n\t/**\n\t* This is the backing field for {@link #getMismatchedNode()}.\n\t*/\n\tmismatchedNode;\n\t/**\n\t* Constructs a new instance of {@link ParseTreeMatch} from the specified\n\t* parse tree and pattern.\n\t*\n\t* @param tree The parse tree to match against the pattern.\n\t* @param pattern The parse tree pattern.\n\t* @param labels A mapping from label names to collections of\n\t* {@link ParseTree} objects located by the tree pattern matching process.\n\t* @param mismatchedNode The first node which failed to match the tree\n\t* pattern during the matching process.\n\t*/\n\tconstructor(tree, pattern, labels, mismatchedNode) {\n\t\tthis.tree = tree;\n\t\tthis.pattern = pattern;\n\t\tthis.labels = labels;\n\t\tthis.mismatchedNode = mismatchedNode;\n\t}\n\t/**\n\t* Get the last node associated with a specific `label`.\n\t*\n\t* For example, for pattern `<id:ID>`, `get(\"id\")` returns the\n\t* node matched for that `ID`. If more than one node\n\t* matched the specified label, only the last is returned. If there is\n\t* no node associated with the label, this returns `null`.\n\t*\n\t* Pattern tags like `<ID>` and `<expr>` without labels are\n\t* considered to be labeled with `ID` and `expr`, respectively.\n\t*\n\t* @param label The label to check.\n\t*\n\t* @returns The last {@link ParseTree} to match a tag with the specified\n\t* label, or `null` if no parse tree matched a tag with the label.\n\t*/\n\tget(label) {\n\t\tconst parseTrees = this.labels.get(label);\n\t\tif (!parseTrees || parseTrees.length === 0) return null;\n\t\treturn parseTrees[parseTrees.length - 1];\n\t}\n\t/**\n\t* Return all nodes matching a rule or token tag with the specified label.\n\t*\n\t* If the `label` is the name of a parser rule or token in the\n\t* grammar, the resulting list will contain both the parse trees matching\n\t* rule or tags explicitly labeled with the label and the complete set of\n\t* parse trees matching the labeled and unlabeled tags in the pattern for\n\t* the parser rule or token. For example, if `label` is `\"foo\"`,\n\t* the result will contain *all* of the following.\n\t*\n\t* - Parse tree nodes matching tags of the form `<foo:anyRuleName>` and\n\t* `<foo:AnyTokenName>`.\n\t* - Parse tree nodes matching tags of the form `<anyLabel:foo>`.\n\t* - Parse tree nodes matching tags of the form `<foo>`.\n\t*\n\t* @param label The label.\n\t*\n\t* @returns A collection of all {@link ParseTree} nodes matching tags with\n\t* the specified `label`. If no nodes matched the label, an empty list\n\t* is returned.\n\t*/\n\tgetAll(label) {\n\t\treturn this.labels.get(label) ?? [];\n\t}\n\t/**\n\t* Return a mapping from label -> [list of nodes].\n\t*\n\t* The map includes special entries corresponding to the names of rules and\n\t* tokens referenced in tags in the original pattern. For additional\n\t* information, see the description of {@link getAll(String)}.\n\t*\n\t* @returns A mapping from labels to parse tree nodes. If the parse tree\n\t* pattern did not contain any rule or token tags, this map will be empty.\n\t*/\n\tgetLabels() {\n\t\treturn this.labels;\n\t}\n\t/**\n\t* Get the node at which we first detected a mismatch.\n\t*\n\t* @returns the node at which we first detected a mismatch, or `null`\n\t* if the match was successful.\n\t*/\n\tgetMismatchedNode() {\n\t\treturn this.mismatchedNode;\n\t}\n\t/**\n\t* Gets a value indicating whether the match operation succeeded.\n\t*\n\t* @returns `true` if the match operation succeeded; otherwise, `false`.\n\t*/\n\tsucceeded() {\n\t\treturn !this.mismatchedNode;\n\t}\n\t/**\n\t* Get the tree pattern we are matching against.\n\t*\n\t* @returns The tree pattern we are matching against.\n\t*/\n\tgetPattern() {\n\t\treturn this.pattern;\n\t}\n\t/**\n\t* Get the parse tree we are trying to match to a pattern.\n\t*\n\t* @returns The {@link ParseTree} we are trying to match to a pattern.\n\t*/\n\tgetTree() {\n\t\treturn this.tree;\n\t}\n\ttoString() {\n\t\treturn `Match ${this.succeeded() ? \"succeeded\" : \"failed\"}; found ${this.getLabels().size} labels`;\n\t}\n};\nvar ParseTreePattern = class {\n\tstatic {\n\t\t__name(this, \"ParseTreePattern\");\n\t}\n\t/**\n\t* This is the backing field for {@link #getPatternRuleIndex()}.\n\t*/\n\tpatternRuleIndex;\n\t/**\n\t* This is the backing field for {@link #getPattern()}.\n\t*/\n\tpattern;\n\t/**\n\t* This is the backing field for {@link #getPatternTree()}.\n\t*/\n\tpatternTree;\n\t/**\n\t* This is the backing field for {@link #getMatcher()}.\n\t*/\n\tmatcher;\n\t/**\n\t* Construct a new instance of the {@link ParseTreePattern} class.\n\t*\n\t* @param matcher The {@link ParseTreePatternMatcher} which created this\n\t* tree pattern.\n\t* @param pattern The tree pattern in concrete syntax form.\n\t* @param patternRuleIndex The parser rule which serves as the root of the\n\t* tree pattern.\n\t* @param patternTree The tree pattern in {@link ParseTree} form.\n\t*/\n\tconstructor(matcher, pattern, patternRuleIndex, patternTree) {\n\t\tthis.matcher = matcher;\n\t\tthis.patternRuleIndex = patternRuleIndex;\n\t\tthis.pattern = pattern;\n\t\tthis.patternTree = patternTree;\n\t}\n\t/**\n\t* Match a specific parse tree against this tree pattern.\n\t*\n\t* @param tree The parse tree to match against this tree pattern.\n\t* @returns A {@link ParseTreeMatch} object describing the result of the\n\t* match operation. The {@link ParseTreeMatch#succeeded()} method can be\n\t* used to determine whether or not the match was successful.\n\t*/\n\tmatch(tree) {\n\t\treturn this.matcher.match(tree, this);\n\t}\n\t/**\n\t* Determine whether or not a parse tree matches this tree pattern.\n\t*\n\t* @param tree The parse tree to match against this tree pattern.\n\t* @returns `true` if `tree` is a match for the current tree\n\t* pattern; otherwise, `false`.\n\t*/\n\tmatches(tree) {\n\t\treturn this.matcher.match(tree, this).succeeded();\n\t}\n\t/**\n\t* Find all nodes using XPath and then try to match those subtrees against\n\t* this tree pattern.\n\t*\n\t* @param tree The {@link ParseTree} to match against this pattern.\n\t* @param xpath An expression matching the nodes\n\t*\n\t* @returns A collection of {@link ParseTreeMatch} objects describing the\n\t* successful matches. Unsuccessful matches are omitted from the result,\n\t* regardless of the reason for the failure.\n\t*/\n\tfindAll(tree, xpath) {\n\t\tconst subtrees = XPath.findAll(tree, xpath, this.matcher.getParser());\n\t\tconst matches = new Array();\n\t\tfor (const t of subtrees) {\n\t\t\tconst match = this.match(t);\n\t\t\tif (match.succeeded()) matches.push(match);\n\t\t}\n\t\treturn matches;\n\t}\n\t/**\n\t* Get the {@link ParseTreePatternMatcher} which created this tree pattern.\n\t*\n\t* @returns The {@link ParseTreePatternMatcher} which created this tree\n\t* pattern.\n\t*/\n\tgetMatcher() {\n\t\treturn this.matcher;\n\t}\n\t/**\n\t* Get the tree pattern in concrete syntax form.\n\t*\n\t* @returns The tree pattern in concrete syntax form.\n\t*/\n\tgetPattern() {\n\t\treturn this.pattern;\n\t}\n\t/**\n\t* Get the parser rule which serves as the outermost rule for the tree\n\t* pattern.\n\t*\n\t* @returns The parser rule which serves as the outermost rule for the tree\n\t* pattern.\n\t*/\n\tgetPatternRuleIndex() {\n\t\treturn this.patternRuleIndex;\n\t}\n\t/**\n\t* Get the tree pattern as a {@link ParseTree}. The rule and token tags from\n\t* the pattern are present in the parse tree as terminal nodes with a symbol\n\t* of type {@link RuleTagToken} or {@link TokenTagToken}.\n\t*\n\t* @returns The tree pattern as a {@link ParseTree}.\n\t*/\n\tgetPatternTree() {\n\t\treturn this.patternTree;\n\t}\n};\nvar InputMismatchException = class extends RecognitionException {\n\tstatic {\n\t\t__name(this, \"InputMismatchException\");\n\t}\n\tconstructor(recognizer) {\n\t\tsuper({\n\t\t\tmessage: \"\",\n\t\t\trecognizer,\n\t\t\tinput: recognizer.inputStream,\n\t\t\tctx: recognizer.context\n\t\t});\n\t\tthis.offendingToken = recognizer.getCurrentToken();\n\t}\n};\nvar FailedPredicateException = class extends RecognitionException {\n\tstatic {\n\t\t__name(this, \"FailedPredicateException\");\n\t}\n\truleIndex = 0;\n\tpredicateIndex = 0;\n\tpredicate;\n\tconstructor(recognizer, predicate, message = null) {\n\t\tsuper({\n\t\t\tmessage: formatMessage(predicate ?? \"no predicate\", message ?? null),\n\t\t\trecognizer,\n\t\t\tinput: recognizer.inputStream,\n\t\t\tctx: recognizer.context\n\t\t});\n\t\tconst trans = recognizer.atn.states[recognizer.state].transitions[0];\n\t\tif (trans instanceof PredicateTransition) {\n\t\t\tthis.ruleIndex = trans.ruleIndex;\n\t\t\tthis.predicateIndex = trans.predIndex;\n\t\t} else {\n\t\t\tthis.ruleIndex = 0;\n\t\t\tthis.predicateIndex = 0;\n\t\t}\n\t\tthis.predicate = predicate;\n\t\tthis.offendingToken = recognizer.getCurrentToken();\n\t}\n};\nvar formatMessage = /* @__PURE__ */ __name((predicate, message) => {\n\tif (message !== null) return message;\n\treturn \"failed predicate: {\" + predicate + \"}?\";\n}, \"formatMessage\");\nvar DefaultErrorStrategy = class {\n\tstatic {\n\t\t__name(this, \"DefaultErrorStrategy\");\n\t}\n\t/**\n\t* Indicates whether the error strategy is currently \"recovering from an\n\t* error\". This is used to suppress reporting multiple error messages while\n\t* attempting to recover from a detected syntax error.\n\t*\n\t* @see #inErrorRecoveryMode\n\t*/\n\terrorRecoveryMode = false;\n\t/**\n\t* The index into the input stream where the last error occurred.\n\t* \tThis is used to prevent infinite loops where an error is found\n\t*  but no token is consumed during recovery...another error is found,\n\t*  ad nauseam.  This is a failsafe mechanism to guarantee that at least\n\t*  one token/tree node is consumed for two errors.\n\t*/\n\tlastErrorIndex = -1;\n\tlastErrorStates = new IntervalSet();\n\t/**\n\t* This field is used to propagate information about the lookahead following\n\t* the previous match. Since prediction prefers completing the current rule\n\t* to error recovery efforts, error reporting may occur later than the\n\t* original point where it was discoverable. The original context is used to\n\t* compute the true expected sets as though the reporting occurred as early\n\t* as possible.\n\t*/\n\tnextTokensContext = null;\n\tnextTokenState = 0;\n\t/**\n\t* The default implementation simply calls {@link endErrorCondition} to\n\t* ensure that the handler is not in error recovery mode.\n\t*/\n\treset(recognizer) {\n\t\tthis.endErrorCondition(recognizer);\n\t}\n\t/**\n\t* This method is called to enter error recovery mode when a recognition\n\t* exception is reported.\n\t*\n\t* @param _recognizer the parser instance\n\t*/\n\tbeginErrorCondition(_recognizer) {\n\t\tthis.errorRecoveryMode = true;\n\t}\n\tinErrorRecoveryMode(_recognizer) {\n\t\treturn this.errorRecoveryMode;\n\t}\n\t/**\n\t* This method is called to leave error recovery mode after recovering from\n\t* a recognition exception.\n\t*/\n\tendErrorCondition(_recognizer) {\n\t\tthis.errorRecoveryMode = false;\n\t\tthis.lastErrorStates = new IntervalSet();\n\t\tthis.lastErrorIndex = -1;\n\t}\n\t/**\n\t* The default implementation simply calls {@link endErrorCondition}.\n\t*/\n\treportMatch(recognizer) {\n\t\tthis.endErrorCondition(recognizer);\n\t}\n\t/**\n\t* The default implementation returns immediately if the handler is already\n\t* in error recovery mode. Otherwise, it calls {@link beginErrorCondition}\n\t* and dispatches the reporting task based on the runtime type of `e`\n\t* according to the following table.\n\t*\n\t* - {@link NoViableAltException}: Dispatches the call to {@link reportNoViableAlternative}\n\t* - {@link InputMismatchException}: Dispatches the call to {@link reportInputMismatch}\n\t* - {@link FailedPredicateException}: Dispatches the call to {@link reportFailedPredicate}\n\t* - All other types: calls {@link Parser.notifyErrorListeners} to report the exception\n\t*/\n\treportError(recognizer, e) {\n\t\tif (this.inErrorRecoveryMode(recognizer)) return;\n\t\tthis.beginErrorCondition(recognizer);\n\t\tif (e instanceof NoViableAltException) this.reportNoViableAlternative(recognizer, e);\n\t\telse if (e instanceof InputMismatchException) this.reportInputMismatch(recognizer, e);\n\t\telse if (e instanceof FailedPredicateException) this.reportFailedPredicate(recognizer, e);\n\t\telse recognizer.notifyErrorListeners(e.message, e.offendingToken, e);\n\t}\n\t/**\n\t* The default implementation resynchronizes the parser by consuming tokens\n\t* until we find one in the resynchronization set--loosely the set of tokens\n\t* that can follow the current rule.\n\t*\n\t*/\n\trecover(recognizer, _e) {\n\t\tif (this.lastErrorIndex === recognizer.inputStream?.index && this.lastErrorStates.contains(recognizer.state)) recognizer.consume();\n\t\tthis.lastErrorIndex = recognizer.inputStream?.index ?? 0;\n\t\tthis.lastErrorStates.addOne(recognizer.state);\n\t\tconst followSet = this.getErrorRecoverySet(recognizer);\n\t\tthis.consumeUntil(recognizer, followSet);\n\t}\n\t/**\n\t* The default implementation of {@link ANTLRErrorStrategy.sync} makes sure\n\t* that the current lookahead symbol is consistent with what were expecting\n\t* at this point in the ATN. You can call this anytime but ANTLR only\n\t* generates code to check before subrules/loops and each iteration.\n\t*\n\t* Implements Jim Idle's magic sync mechanism in closures and optional\n\t* subrules. E.g.,\n\t*\n\t* ```\n\t* a : sync ( stuff sync )* ;\n\t* sync : {consume to what can follow sync} ;\n\t* ```\n\t*\n\t* At the start of a sub rule upon error, {@link sync} performs single\n\t* token deletion, if possible. If it can't do that, it bails on the current\n\t* rule and uses the default error recovery, which consumes until the\n\t* resynchronization set of the current rule.\n\t*\n\t* If the sub rule is optional (`(...)?`, `(...)*`, or block\n\t* with an empty alternative), then the expected set includes what follows\n\t* the subrule.\n\t*\n\t* During loop iteration, it consumes until it sees a token that can start a\n\t* sub rule or what follows loop. Yes, that is pretty aggressive. We opt to\n\t* stay in the loop as long as possible.\n\t*\n\t* **ORIGINS**\n\t*\n\t* Previous versions of ANTLR did a poor job of their recovery within loops.\n\t* A single mismatch token or missing token would force the parser to bail\n\t* out of the entire rules surrounding the loop. So, for rule\n\t*\n\t* ```\n\t* classDef : 'class' ID '{' member* '}'\n\t* ```\n\t*\n\t* input with an extra token between members would force the parser to\n\t* consume until it found the next class definition rather than the next\n\t* member definition of the current class.\n\t*\n\t* This functionality cost a little bit of effort because the parser has to\n\t* compare token set at the start of the loop and at each iteration. If for\n\t* some reason speed is suffering for you, you can turn off this\n\t* functionality by simply overriding this method as a blank { }.\n\t*\n\t*/\n\tsync(recognizer) {\n\t\tif (this.inErrorRecoveryMode(recognizer)) return;\n\t\tconst s = recognizer.atn.states[recognizer.state];\n\t\tconst la = recognizer.tokenStream.LA(1);\n\t\tconst nextTokens = recognizer.atn.nextTokens(s);\n\t\tif (nextTokens.contains(la)) {\n\t\t\tthis.nextTokensContext = null;\n\t\t\tthis.nextTokenState = ATNState.INVALID_STATE_NUMBER;\n\t\t\treturn;\n\t\t}\n\t\tif (nextTokens.contains(Token.EPSILON)) {\n\t\t\tif (this.nextTokensContext === null) {\n\t\t\t\tthis.nextTokensContext = recognizer.context;\n\t\t\t\tthis.nextTokenState = recognizer.state;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tswitch (s.constructor.stateType) {\n\t\t\tcase ATNState.BLOCK_START:\n\t\t\tcase ATNState.STAR_BLOCK_START:\n\t\t\tcase ATNState.PLUS_BLOCK_START:\n\t\t\tcase ATNState.STAR_LOOP_ENTRY:\n\t\t\t\tif (this.singleTokenDeletion(recognizer) !== null) return;\n\t\t\t\tthrow new InputMismatchException(recognizer);\n\t\t\tcase ATNState.PLUS_LOOP_BACK:\n\t\t\tcase ATNState.STAR_LOOP_BACK: {\n\t\t\t\tthis.reportUnwantedToken(recognizer);\n\t\t\t\tconst expecting = new IntervalSet();\n\t\t\t\texpecting.addSet(recognizer.getExpectedTokens());\n\t\t\t\tconst whatFollowsLoopIterationOrRule = expecting.addSet(this.getErrorRecoverySet(recognizer));\n\t\t\t\tthis.consumeUntil(recognizer, whatFollowsLoopIterationOrRule);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t}\n\t}\n\t/**\n\t* This is called by {@link reportError} when the exception is a\n\t* {@link NoViableAltException}.\n\t*\n\t* @see reportError\n\t*\n\t* @param recognizer the parser instance\n\t* @param e the recognition exception\n\t*/\n\treportNoViableAlternative(recognizer, e) {\n\t\tif (e.message.length > 0) {\n\t\t\trecognizer.notifyErrorListeners(e.message, e.offendingToken, e);\n\t\t\treturn;\n\t\t}\n\t\tconst tokens = recognizer.tokenStream;\n\t\tlet input;\n\t\tif (tokens !== null && e.startToken) if (e.startToken.type === Token.EOF) input = \"<EOF>\";\n\t\telse input = tokens.getTextFromRange(e.startToken, e.offendingToken);\n\t\telse input = \"<unknown input>\";\n\t\tconst msg = \"no viable alternative at input \" + this.escapeWSAndQuote(input);\n\t\trecognizer.notifyErrorListeners(msg, e.offendingToken, e);\n\t}\n\t/**\n\t* This is called by {@link reportError} when the exception is an {@link InputMismatchException}.\n\t*\n\t* @see reportError\n\t*\n\t* @param recognizer the parser instance\n\t* @param e the recognition exception\n\t*/\n\treportInputMismatch(recognizer, e) {\n\t\tif (e.message.length > 0) {\n\t\t\trecognizer.notifyErrorListeners(e.message, e.offendingToken, e);\n\t\t\treturn;\n\t\t}\n\t\tconst msg = \"mismatched input \" + this.getTokenErrorDisplay(e.offendingToken) + \" expecting \" + e.getExpectedTokens().toStringWithVocabulary(recognizer.vocabulary);\n\t\trecognizer.notifyErrorListeners(msg, e.offendingToken, e);\n\t}\n\t/**\n\t* This is called by {@link reportError} when the exception is a\n\t* {@link FailedPredicateException}.\n\t*\n\t* @see reportError\n\t*\n\t* @param recognizer the parser instance\n\t* @param e the recognition exception\n\t*/\n\treportFailedPredicate(recognizer, e) {\n\t\tconst msg = \"rule \" + recognizer.ruleNames[recognizer.context.ruleIndex] + \" \" + e.message;\n\t\trecognizer.notifyErrorListeners(msg, e.offendingToken, e);\n\t}\n\t/**\n\t* This method is called to report a syntax error which requires the removal\n\t* of a token from the input stream. At the time this method is called, the\n\t* erroneous symbol is current `LT(1)` symbol and has not yet been\n\t* removed from the input stream. When this method returns,\n\t* `recognizer` is in error recovery mode.\n\t*\n\t* This method is called when {@link singleTokenDeletion} identifies\n\t* single-token deletion as a viable recovery strategy for a mismatched\n\t* input error.\n\t*\n\t* The default implementation simply returns if the handler is already in\n\t* error recovery mode. Otherwise, it calls {@link beginErrorCondition} to\n\t* enter error recovery mode, followed by calling\n\t* {@link Parser.notifyErrorListeners}.\n\t*\n\t* @param recognizer the parser instance\n\t*/\n\treportUnwantedToken(recognizer) {\n\t\tif (this.inErrorRecoveryMode(recognizer)) return;\n\t\tthis.beginErrorCondition(recognizer);\n\t\tconst t = recognizer.getCurrentToken();\n\t\tconst tokenName = this.getTokenErrorDisplay(t);\n\t\tconst expecting = this.getExpectedTokens(recognizer);\n\t\tconst msg = \"extraneous input \" + tokenName + \" expecting \" + expecting.toStringWithVocabulary(recognizer.vocabulary);\n\t\trecognizer.notifyErrorListeners(msg, t, null);\n\t}\n\t/**\n\t* This method is called to report a syntax error which requires the\n\t* insertion of a missing token into the input stream. At the time this\n\t* method is called, the missing token has not yet been inserted. When this\n\t* method returns, `recognizer` is in error recovery mode.\n\t*\n\t* This method is called when {@link singleTokenInsertion} identifies\n\t* single-token insertion as a viable recovery strategy for a mismatched\n\t* input error.\n\t*\n\t* The default implementation simply returns if the handler is already in\n\t* error recovery mode. Otherwise, it calls {@link beginErrorCondition} to\n\t* enter error recovery mode, followed by calling\n\t* {@link Parser.notifyErrorListeners}.\n\t*\n\t* @param recognizer the parser instance\n\t*/\n\treportMissingToken(recognizer) {\n\t\tif (this.inErrorRecoveryMode(recognizer)) return;\n\t\tthis.beginErrorCondition(recognizer);\n\t\tconst t = recognizer.getCurrentToken();\n\t\tconst msg = \"missing \" + this.getExpectedTokens(recognizer).toStringWithVocabulary(recognizer.vocabulary) + \" at \" + this.getTokenErrorDisplay(t);\n\t\trecognizer.notifyErrorListeners(msg, t, null);\n\t}\n\t/**\n\t* The default implementation attempts to recover from the mismatched input\n\t* by using single token insertion and deletion as described below. If the\n\t* recovery attempt fails, this method throws an\n\t* {@link InputMismatchException}.\n\t*\n\t* **EXTRA TOKEN** (single token deletion)\n\t*\n\t* `LA(1)` is not what we are looking for. If `LA(2)` has the\n\t* right token, however, then assume `LA(1)` is some extra spurious\n\t* token and delete it. Then consume and return the next token (which was\n\t* the `LA(2)` token) as the successful result of the match operation.\n\t*\n\t* This recovery strategy is implemented by {@link singleTokenDeletion}.\n\t*\n\t* **MISSING TOKEN** (single token insertion)\n\t*\n\t* If current token (at `LA(1)`) is consistent with what could come\n\t* after the expected `LA(1)` token, then assume the token is missing\n\t* and use the parser's {@link TokenFactory} to create it on the fly. The\n\t* \"insertion\" is performed by returning the created token as the successful\n\t* result of the match operation.\n\t*\n\t* This recovery strategy is implemented by {@link singleTokenInsertion}.\n\t*\n\t* **EXAMPLE**\n\t*\n\t* For example, Input `i=(3;` is clearly missing the `')'`. When\n\t* the parser returns from the nested call to `expr`, it will have\n\t* call chain:\n\t*\n\t* ```\n\t* stat -> expr -> atom\n\t* ```\n\t*\n\t* and it will be trying to match the `')'` at this point in the\n\t* derivation:\n\t*\n\t* ```\n\t* => ID '=' '(' INT ')' ('+' atom)* ';'\n\t* ^\n\t* ```\n\t*\n\t* The attempt to match `')'` will fail when it sees `';'` and\n\t* call {@link recoverInline}. To recover, it sees that `LA(1)==';'`\n\t* is in the set of tokens that can follow the `')'` token reference\n\t* in rule `atom`. It can assume that you forgot the `')'`.\n\t*/\n\trecoverInline(recognizer) {\n\t\tconst matchedSymbol = this.singleTokenDeletion(recognizer);\n\t\tif (matchedSymbol) {\n\t\t\trecognizer.consume();\n\t\t\treturn matchedSymbol;\n\t\t}\n\t\tif (this.singleTokenInsertion(recognizer)) return this.getMissingSymbol(recognizer);\n\t\tthrow new InputMismatchException(recognizer);\n\t}\n\t/**\n\t* This method implements the single-token insertion inline error recovery\n\t* strategy. It is called by {@link recoverInline} if the single-token\n\t* deletion strategy fails to recover from the mismatched input. If this\n\t* method returns `true`, `recognizer` will be in error recovery\n\t* mode.\n\t*\n\t* This method determines whether or not single-token insertion is viable by\n\t* checking if the `LA(1)` input symbol could be successfully matched\n\t* if it were instead the `LA(2)` symbol. If this method returns\n\t* `true`, the caller is responsible for creating and inserting a\n\t* token with the correct type to produce this behavior.\n\t*\n\t* @param recognizer the parser instance\n\t* @returns `true` if single-token insertion is a viable recovery\n\t* strategy for the current mismatched input, otherwise `false`\n\t*/\n\tsingleTokenInsertion(recognizer) {\n\t\tconst currentSymbolType = recognizer.tokenStream?.LA(1) ?? -1;\n\t\tconst atn = recognizer.atn;\n\t\tconst next = atn.states[recognizer.state].transitions[0].target;\n\t\tif (atn.nextTokens(next, recognizer.context ?? void 0).contains(currentSymbolType)) {\n\t\t\tthis.reportMissingToken(recognizer);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t/**\n\t* This method implements the single-token deletion inline error recovery\n\t* strategy. It is called by {@link recoverInline} to attempt to recover\n\t* from mismatched input. If this method returns null, the parser and error\n\t* handler state will not have changed. If this method returns non-null,\n\t* `recognizer` will *not* be in error recovery mode since the\n\t* returned token was a successful match.\n\t*\n\t* If the single-token deletion is successful, this method calls\n\t* {@link reportUnwantedToken} to report the error, followed by\n\t* {@link Parser.consume} to actually \"delete\" the extraneous token. Then,\n\t* before returning {@link reportMatch} is called to signal a successful\n\t* match.\n\t*\n\t* @param recognizer the parser instance\n\t* @returns the successfully matched {@link Token} instance if single-token\n\t* deletion successfully recovers from the mismatched input, otherwise\n\t* `null`\n\t*/\n\tsingleTokenDeletion(recognizer) {\n\t\tconst nextTokenType = recognizer.tokenStream?.LA(2) ?? -1;\n\t\tif (this.getExpectedTokens(recognizer).contains(nextTokenType)) {\n\t\t\tthis.reportUnwantedToken(recognizer);\n\t\t\trecognizer.consume();\n\t\t\tconst matchedSymbol = recognizer.getCurrentToken();\n\t\t\tthis.reportMatch(recognizer);\n\t\t\treturn matchedSymbol;\n\t\t}\n\t\treturn null;\n\t}\n\t/**\n\t* Conjure up a missing token during error recovery.\n\t*\n\t* The recognizer attempts to recover from single missing\n\t* symbols. But, actions might refer to that missing symbol.\n\t* For example, x=ID {f($x);}. The action clearly assumes\n\t* that there has been an identifier matched previously and that\n\t* $x points at that token. If that token is missing, but\n\t* the next token in the stream is what we want we assume that\n\t* this token is missing and we keep going. Because we\n\t* have to return some token to replace the missing token,\n\t* we have to conjure one up. This method gives the user control\n\t* over the tokens returned for missing tokens. Mostly,\n\t* you will want to create something special for identifier\n\t* tokens. For literals such as '{' and ',', the default\n\t* action in the parser or tree parser works. It simply creates\n\t* a CommonToken of the appropriate type. The text will be the token.\n\t* If you change what tokens must be created by the lexer,\n\t* override this method to create the appropriate tokens.\n\t*/\n\tgetMissingSymbol(recognizer) {\n\t\tconst currentSymbol = recognizer.getCurrentToken();\n\t\tconst expecting = this.getExpectedTokens(recognizer);\n\t\tlet expectedTokenType = Token.INVALID_TYPE;\n\t\tif (expecting.length !== 0) expectedTokenType = expecting.minElement;\n\t\tlet tokenText;\n\t\tif (expectedTokenType === Token.EOF) tokenText = \"<missing EOF>\";\n\t\telse tokenText = \"<missing \" + recognizer.vocabulary.getDisplayName(expectedTokenType) + \">\";\n\t\tlet current = currentSymbol;\n\t\tconst lookBack = recognizer.tokenStream?.LT(-1);\n\t\tif (current.type === Token.EOF && lookBack !== null) current = lookBack;\n\t\treturn recognizer.getTokenFactory().create(current.source, expectedTokenType, tokenText, Token.DEFAULT_CHANNEL, -1, -1, current.line, current.column);\n\t}\n\tgetExpectedTokens(recognizer) {\n\t\treturn recognizer.getExpectedTokens();\n\t}\n\t/**\n\t* How should a token be displayed in an error message? The default\n\t* is to display just the text, but during development you might\n\t* want to have a lot of information spit out. Override in that case\n\t* to use t.toString() (which, for CommonToken, dumps everything about\n\t* the token). This is better than forcing you to override a method in\n\t* your token objects because you don't have to go modify your lexer\n\t* so that it creates a new Java type.\n\t*/\n\tgetTokenErrorDisplay(t) {\n\t\tif (t === null) return \"<no token>\";\n\t\tlet s = t.text;\n\t\tif (!s) if (t.type === Token.EOF) s = \"<EOF>\";\n\t\telse s = \"<\" + t.type + \">\";\n\t\treturn this.escapeWSAndQuote(s);\n\t}\n\tescapeWSAndQuote(s) {\n\t\ts = s.replace(/\\n/g, \"\\\\n\");\n\t\ts = s.replace(/\\r/g, \"\\\\r\");\n\t\ts = s.replace(/\\t/g, \"\\\\t\");\n\t\treturn \"'\" + s + \"'\";\n\t}\n\t/**\n\t* Compute the error recovery set for the current rule. During\n\t* rule invocation, the parser pushes the set of tokens that can\n\t* follow that rule reference on the stack; this amounts to\n\t* computing FIRST of what follows the rule reference in the\n\t* enclosing rule. See LinearApproximator.FIRST().\n\t* This local follow set only includes tokens\n\t* from within the rule; i.e., the FIRST computation done by\n\t* ANTLR stops at the end of a rule.\n\t*\n\t* EXAMPLE\n\t*\n\t* When you find a \"no viable alt exception\", the input is not\n\t* consistent with any of the alternatives for rule r. The best\n\t* thing to do is to consume tokens until you see something that\n\t* can legally follow a call to r//or* any rule that called r.\n\t* You don't want the exact set of viable next tokens because the\n\t* input might just be missing a token--you might consume the\n\t* rest of the input looking for one of the missing tokens.\n\t*\n\t* Consider grammar:\n\t*\n\t* a : '[' b ']'\n\t* | '(' b ')'\n\t* ;\n\t* b : c '^' INT ;\n\t* c : ID\n\t* | INT\n\t* ;\n\t*\n\t* At each rule invocation, the set of tokens that could follow\n\t* that rule is pushed on a stack. Here are the various\n\t* context-sensitive follow sets:\n\t*\n\t* FOLLOW(b1_in_a) = FIRST(']') = ']'\n\t* FOLLOW(b2_in_a) = FIRST(')') = ')'\n\t* FOLLOW(c_in_b) = FIRST('^') = '^'\n\t*\n\t* Upon erroneous input \"[]\", the call chain is\n\t*\n\t* a -> b -> c\n\t*\n\t* and, hence, the follow context stack is:\n\t*\n\t* depth follow set start of rule execution\n\t* 0 <EOF> a (from main())\n\t* 1 ']' b\n\t* 2 '^' c\n\t*\n\t* Notice that ')' is not included, because b would have to have\n\t* been called from a different context in rule a for ')' to be\n\t* included.\n\t*\n\t* For error recovery, we cannot consider FOLLOW(c)\n\t* (context-sensitive or otherwise). We need the combined set of\n\t* all context-sensitive FOLLOW sets--the set of all tokens that\n\t* could follow any reference in the call chain. We need to\n\t* resync to one of those tokens. Note that FOLLOW(c)='^' and if\n\t* we resync'd to that token, we'd consume until EOF. We need to\n\t* sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.\n\t* In this case, for input \"[]\", LA(1) is ']' and in the set, so we would\n\t* not consume anything. After printing an error, rule c would\n\t* return normally. Rule b would not find the required '^' though.\n\t* At this point, it gets a mismatched token error and throws an\n\t* exception (since LA(1) is not in the viable following token\n\t* set). The rule exception handler tries to recover, but finds\n\t* the same recovery set and doesn't consume anything. Rule b\n\t* exits normally returning to rule a. Now it finds the ']' (and\n\t* with the successful match exits errorRecovery mode).\n\t*\n\t* So, you can see that the parser walks up the call chain looking\n\t* for the token that was a member of the recovery set.\n\t*\n\t* Errors are not generated in errorRecovery mode.\n\t*\n\t* ANTLR's error recovery mechanism is based upon original ideas:\n\t*\n\t* \"Algorithms + Data Structures = Programs\" by Niklaus Wirth\n\t*\n\t* and\n\t*\n\t* \"A note on error recovery in recursive descent parsers\":\n\t* http://portal.acm.org/citation.cfm?id=947902.947905\n\t*\n\t* Later, Josef Grosch had some good ideas:\n\t*\n\t* \"Efficient and Comfortable Error Recovery in Recursive Descent\n\t* Parsers\":\n\t* ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip\n\t*\n\t* Like Grosch I implement context-sensitive FOLLOW sets that are combined\n\t* at run-time upon error to avoid overhead during parsing.\n\t*/\n\tgetErrorRecoverySet(recognizer) {\n\t\tconst atn = recognizer.atn;\n\t\tlet ctx = recognizer.context;\n\t\tconst recoverSet = new IntervalSet();\n\t\twhile (ctx !== null && ctx.invokingState >= 0) {\n\t\t\tconst rt = atn.states[ctx.invokingState].transitions[0];\n\t\t\tconst follow = atn.nextTokens(rt.followState);\n\t\t\trecoverSet.addSet(follow);\n\t\t\tctx = ctx.parent;\n\t\t}\n\t\trecoverSet.removeOne(Token.EPSILON);\n\t\treturn recoverSet;\n\t}\n\t/** Consume tokens until one matches the given token set. */\n\tconsumeUntil(recognizer, set) {\n\t\tlet ttype = recognizer.tokenStream?.LA(1) ?? -1;\n\t\twhile (ttype !== Token.EOF && !set.contains(ttype)) {\n\t\t\trecognizer.consume();\n\t\t\tttype = recognizer.tokenStream?.LA(1) ?? -1;\n\t\t}\n\t}\n};\nvar BailErrorStrategy = class extends DefaultErrorStrategy {\n\tstatic {\n\t\t__name(this, \"BailErrorStrategy\");\n\t}\n\t/**\n\t* Instead of recovering from exception `e`, re-throw it wrapped\n\t* in a {@link ParseCancellationException} so it is not caught by the\n\t* rule function catches. Use {@link Exception//getCause()} to get the\n\t* original {@link RecognitionException}.\n\t*/\n\trecover(recognizer, e) {\n\t\tthrow new ParseCancellationException(e);\n\t}\n\t/**\n\t* Make sure we don't attempt to recover inline; if the parser\n\t* successfully recovers, it won't throw an exception.\n\t*/\n\trecoverInline(recognizer) {\n\t\tthrow new ParseCancellationException(new InputMismatchException(recognizer));\n\t}\n\tsync(_recognizer) {}\n};\nvar ListTokenSource = class {\n\tstatic {\n\t\t__name(this, \"ListTokenSource\");\n\t}\n\t/**\n\t* The name of the input source. If this value is `null`, a call to\n\t* {@link #getSourceName} should return the source name used to create the\n\t* the next token in {@link #tokens} (or the previous token if the end of\n\t* the input has been reached).\n\t*/\n\tsourceName;\n\ttokenFactory = CommonTokenFactory.DEFAULT;\n\t/**\n\t* The wrapped collection of {@link Token} objects to return.\n\t*/\n\ttokens = [];\n\t/**\n\t* The index into {@link tokens} of token to return by the next call to\n\t* {@link #nextToken}. The end of the input is indicated by this value\n\t* being greater than or equal to the number of items in {@link #tokens}.\n\t*/\n\ti = 0;\n\t/**\n\t* This field caches the EOF token for the token source.\n\t*/\n\teofToken = null;\n\tconstructor(tokens, sourceName) {\n\t\tthis.tokens = tokens;\n\t\tthis.sourceName = sourceName ?? \"\";\n\t}\n\tget column() {\n\t\tif (this.i < this.tokens.length) return this.tokens[this.i].column;\n\t\tif (this.eofToken !== null) return this.eofToken.column;\n\t\tif (this.tokens.length > 0) {\n\t\t\tconst lastToken = this.tokens[this.tokens.length - 1];\n\t\t\tconst tokenText = lastToken.text;\n\t\t\tif (tokenText) {\n\t\t\t\tconst lastNewLine = tokenText.lastIndexOf(\"\\n\");\n\t\t\t\tif (lastNewLine >= 0) return tokenText.length - lastNewLine - 1;\n\t\t\t}\n\t\t\treturn lastToken.column + lastToken.stop - lastToken.start + 1;\n\t\t}\n\t\treturn 0;\n\t}\n\tnextToken() {\n\t\tif (this.i >= this.tokens.length) {\n\t\t\tif (this.eofToken === null) {\n\t\t\t\tlet start = -1;\n\t\t\t\tif (this.tokens.length > 0) {\n\t\t\t\t\tconst previousStop = this.tokens[this.tokens.length - 1].stop;\n\t\t\t\t\tif (previousStop !== -1) start = previousStop + 1;\n\t\t\t\t}\n\t\t\t\tconst stop = Math.max(-1, start - 1);\n\t\t\t\tthis.eofToken = this.tokenFactory.create([this, this.inputStream], Token.EOF, \"EOF\", Token.DEFAULT_CHANNEL, start, stop, this.line, this.column);\n\t\t\t}\n\t\t\treturn this.eofToken;\n\t\t}\n\t\tconst t = this.tokens[this.i];\n\t\tif (this.i === this.tokens.length - 1 && t.type === Token.EOF) this.eofToken = t;\n\t\tthis.i++;\n\t\treturn t;\n\t}\n\tget line() {\n\t\tif (this.i < this.tokens.length) return this.tokens[this.i].line;\n\t\tif (this.eofToken !== null) return this.eofToken.line;\n\t\tif (this.tokens.length > 0) {\n\t\t\tconst lastToken = this.tokens[this.tokens.length - 1];\n\t\t\tlet line = lastToken.line;\n\t\t\tconst tokenText = lastToken.text;\n\t\t\tif (tokenText) {\n\t\t\t\tfor (const char of tokenText) if (char === \"\\n\") line++;\n\t\t\t}\n\t\t\treturn line;\n\t\t}\n\t\treturn 1;\n\t}\n\tget inputStream() {\n\t\tif (this.i < this.tokens.length) return this.tokens[this.i].inputStream;\n\t\tif (this.eofToken !== null) return this.eofToken.inputStream;\n\t\tif (this.tokens.length > 0) return this.tokens[this.tokens.length - 1].inputStream;\n\t\treturn null;\n\t}\n\tgetSourceName() {\n\t\tif (this.sourceName !== null) return this.sourceName;\n\t\tconst inputStream = this.inputStream;\n\t\tif (inputStream !== null) return inputStream.getSourceName();\n\t\treturn \"List\";\n\t}\n};\nvar InterpreterRuleContext = class extends ParserRuleContext {\n\tstatic {\n\t\t__name(this, \"InterpreterRuleContext\");\n\t}\n\t/** This is the backing field for {@link #getRuleIndex}. */\n\t#ruleIndex;\n\tconstructor(ruleIndex, parent, invokingStateNumber) {\n\t\tsuper(parent, invokingStateNumber);\n\t\tthis.#ruleIndex = ruleIndex;\n\t}\n\tget ruleIndex() {\n\t\treturn this.#ruleIndex;\n\t}\n};\nvar TraceListener = class {\n\tstatic {\n\t\t__name(this, \"TraceListener\");\n\t}\n\tparser;\n\tconstructor(parser) {\n\t\tthis.parser = parser;\n\t}\n\tenterEveryRule(ctx) {\n\t\tconsole.log(\"enter   \" + this.parser.ruleNames[ctx.ruleIndex] + \", LT(1)=\" + this.parser.inputStream?.LT(1)?.text);\n\t}\n\tvisitTerminal(node) {\n\t\tconsole.log(\"consume \" + node.getSymbol() + \" rule \" + this.parser.ruleNames[this.parser.context.ruleIndex]);\n\t}\n\texitEveryRule(ctx) {\n\t\tconsole.log(\"exit    \" + this.parser.ruleNames[ctx.ruleIndex] + \", LT(1)=\" + this.parser.inputStream?.LT(1)?.text);\n\t}\n\tvisitErrorNode(_node) {}\n};\nvar Parser = class extends Recognizer {\n\tstatic {\n\t\t__name(this, \"Parser\");\n\t}\n\t/** For testing only. */\n\tprinter = null;\n\t/**\n\t* Specifies whether or not the parser should construct a parse tree during\n\t* the parsing process. The default value is `true`.\n\t*\n\t* @see #getBuildParseTree\n\t* @see #setBuildParseTree\n\t*/\n\tbuildParseTrees = true;\n\t/**\n\t* The error handling strategy for the parser. The default value is a new\n\t* instance of {@link DefaultErrorStrategy}.\n\t*\n\t* @see #getErrorHandler\n\t* @see #setErrorHandler\n\t*/\n\terrorHandler = new DefaultErrorStrategy();\n\t/**\n\t* The {@link ParserRuleContext} object for the currently executing rule.\n\t* This is always non-null during the parsing process.\n\t*/\n\tcontext = null;\n\tprecedenceStack = [];\n\t/**\n\t* The list of {@link ParseTreeListener} listeners registered to receive\n\t* events during the parse.\n\t*\n\t* @see #addParseListener\n\t*/\n\tparseListeners = null;\n\t/**\n\t* The number of syntax errors reported during parsing. This value is\n\t* incremented each time {@link #notifyErrorListeners} is called.\n\t*/\n\tsyntaxErrors = 0;\n\t/** Indicates parser has matched EOF token. See {@link #exitRule()}. */\n\tmatchedEOF = false;\n\t/**\n\t* When {@link #setTrace}`(true)` is called, a reference to the\n\t* {@link TraceListener} is stored here so it can be easily removed in a\n\t* later call to {@link #setTrace}`(false)`. The listener itself is\n\t* implemented as a parser listener so this field is not directly used by\n\t* other parser methods.\n\t*/\n\ttracer = null;\n\t/**\n\t* This field holds the deserialized {@link ATN} with bypass alternatives, created\n\t* lazily upon first demand. In 4.10 I changed from map<serializedATNString, ATN>\n\t* since we only need one per parser object and also it complicates other targets\n\t* that don't use ATN strings.\n\t*\n\t* @see ATNDeserializationOptions#isGenerateRuleBypassTransitions()\n\t*/\n\tbypassAltsAtnCache = null;\n\t#inputStream;\n\t/**\n\t* This is all the parsing support code essentially. Most of it is error recovery stuff.\n\t*/\n\tconstructor(input) {\n\t\tsuper();\n\t\tthis.precedenceStack.push(0);\n\t\tthis.syntaxErrors = 0;\n\t\tthis.#inputStream = input;\n\t}\n\t/** reset the parser's state */\n\treset(rewindInputStream = true) {\n\t\tif (rewindInputStream) this.inputStream.seek(0);\n\t\tthis.errorHandler.reset(this);\n\t\tthis.context = null;\n\t\tthis.syntaxErrors = 0;\n\t\tthis.matchedEOF = false;\n\t\tthis.setTrace(false);\n\t\tthis.precedenceStack = [];\n\t\tthis.precedenceStack.push(0);\n\t\tif (this.interpreter) this.interpreter.reset();\n\t}\n\t/**\n\t* Match current input symbol against `ttype`. If the symbol type\n\t* matches, {@link ANTLRErrorStrategy//reportMatch} and {@link consume} are\n\t* called to complete the match process.\n\t*\n\t* If the symbol type does not match,\n\t* {@link ANTLRErrorStrategy//recoverInline} is called on the current error\n\t* strategy to attempt recovery. If {@link buildParseTree} is\n\t* `true` and the token index of the symbol returned by\n\t* {@link ANTLRErrorStrategy//recoverInline} is -1, the symbol is added to\n\t* the parse tree by calling {@link ParserRuleContext//addErrorNode}.\n\t*\n\t* @param ttype the token type to match\n\t* @returns the matched symbol\n\t* @throws RecognitionException if the current input symbol did not match\n\t* `ttype` and the error strategy could not recover from the\n\t* mismatched symbol\n\t*/\n\tmatch(ttype) {\n\t\tlet t = this.getCurrentToken();\n\t\tif (t.type === ttype) {\n\t\t\tif (ttype === Token.EOF) this.matchedEOF = true;\n\t\t\tthis.errorHandler.reportMatch(this);\n\t\t\tthis.consume();\n\t\t} else {\n\t\t\tt = this.errorHandler.recoverInline(this);\n\t\t\tif (this.buildParseTrees && t.tokenIndex === -1) this.context.addErrorNode(this.createErrorNode(this.context, t));\n\t\t}\n\t\treturn t;\n\t}\n\t/**\n\t* Match current input symbol as a wildcard. If the symbol type matches\n\t* (i.e. has a value greater than 0), {@link ANTLRErrorStrategy//reportMatch}\n\t* and {@link consume} are called to complete the match process.\n\t*\n\t* If the symbol type does not match,\n\t* {@link ANTLRErrorStrategy//recoverInline} is called on the current error\n\t* strategy to attempt recovery. If {@link buildParseTree} is\n\t* `true` and the token index of the symbol returned by\n\t* {@link ANTLRErrorStrategy//recoverInline} is -1, the symbol is added to\n\t* the parse tree by calling {@link ParserRuleContext//addErrorNode}.\n\t*\n\t* @returns the matched symbol\n\t* @throws RecognitionException if the current input symbol did not match\n\t* a wildcard and the error strategy could not recover from the mismatched\n\t* symbol\n\t*/\n\tmatchWildcard() {\n\t\tlet t = this.getCurrentToken();\n\t\tif (t.type > 0) {\n\t\t\tthis.errorHandler.reportMatch(this);\n\t\t\tthis.consume();\n\t\t} else {\n\t\t\tt = this.errorHandler.recoverInline(this);\n\t\t\tif (this.buildParseTrees && t.tokenIndex === -1) this.context.addErrorNode(this.createErrorNode(this.context, t));\n\t\t}\n\t\treturn t;\n\t}\n\tgetParseListeners() {\n\t\treturn this.parseListeners ?? [];\n\t}\n\t/**\n\t* Registers `listener` to receive events during the parsing process.\n\t*\n\t* To support output-preserving grammar transformations (including but not\n\t* limited to left-recursion removal, automated left-factoring, and\n\t* optimized code generation), calls to listener methods during the parse\n\t* may differ substantially from calls made by\n\t* {@link ParseTreeWalker//DEFAULT} used after the parse is complete. In\n\t* particular, rule entry and exit events may occur in a different order\n\t* during the parse than after the parser. In addition, calls to certain\n\t* rule entry methods may be omitted.\n\t*\n\t* With the following specific exceptions, calls to listener events are\n\t* deterministic*, i.e. for identical input the calls to listener\n\t* methods will be the same.\n\t*\n\t* - Alterations to the grammar used to generate code may change the\n\t* behavior of the listener calls.\n\t* - Alterations to the command line options passed to ANTLR 4 when\n\t* generating the parser may change the behavior of the listener calls.\n\t* - Changing the version of the ANTLR Tool used to generate the parser\n\t* may change the behavior of the listener calls.\n\t*\n\t* @param listener the listener to add\n\t*\n\t* @throws NullPointerException if {@code} listener is `null`\n\t*/\n\taddParseListener(listener) {\n\t\tif (listener === null) throw new Error(\"listener\");\n\t\tif (this.parseListeners === null) this.parseListeners = [];\n\t\tthis.parseListeners.push(listener);\n\t}\n\t/**\n\t* Remove `listener` from the list of parse listeners.\n\t*\n\t* If `listener` is `null` or has not been added as a parse\n\t* listener, this method does nothing.\n\t*\n\t* @param listener the listener to remove\n\t*/\n\tremoveParseListener(listener) {\n\t\tif (this.parseListeners !== null && listener !== null) {\n\t\t\tconst idx = this.parseListeners.indexOf(listener);\n\t\t\tif (idx >= 0) this.parseListeners.splice(idx, 1);\n\t\t\tif (this.parseListeners.length === 0) this.parseListeners = null;\n\t\t}\n\t}\n\tremoveParseListeners() {\n\t\tthis.parseListeners = null;\n\t}\n\ttriggerEnterRuleEvent() {\n\t\tif (this.parseListeners !== null) {\n\t\t\tconst ctx = this.context;\n\t\t\tthis.parseListeners.forEach((listener) => {\n\t\t\t\tlistener.enterEveryRule(ctx);\n\t\t\t\tctx.enterRule(listener);\n\t\t\t});\n\t\t}\n\t}\n\t/**\n\t* Notify any parse listeners of an exit rule event.\n\t*\n\t* @see //addParseListener\n\t*/\n\ttriggerExitRuleEvent() {\n\t\tif (this.parseListeners !== null) {\n\t\t\tconst ctx = this.context;\n\t\t\tthis.parseListeners.slice(0).reverse().forEach((listener) => {\n\t\t\t\tctx.exitRule(listener);\n\t\t\t\tlistener.exitEveryRule(ctx);\n\t\t\t});\n\t\t}\n\t}\n\tgetTokenFactory() {\n\t\treturn this.inputStream.tokenSource.tokenFactory;\n\t}\n\tsetTokenFactory(factory) {\n\t\tthis.inputStream.tokenSource.tokenFactory = factory;\n\t}\n\t/**\n\t* The preferred method of getting a tree pattern. For example, here's a\n\t* sample use:\n\t*\n\t* ```\n\t* const t = parser.expr();\n\t* const p = parser.compileParseTreePattern(\"<ID>+0\", MyParser.RULE_expr);\n\t* const m = p.match(t);\n\t* const id = m.get(\"ID\");\n\t* ```\n\t*/\n\tcompileParseTreePattern(pattern, patternRuleIndex, lexer) {\n\t\tif (!lexer) {\n\t\t\tif (this.tokenStream !== null) {\n\t\t\t\tconst tokenSource = this.tokenStream.tokenSource;\n\t\t\t\tif (tokenSource instanceof Lexer) lexer = tokenSource;\n\t\t\t}\n\t\t}\n\t\tif (!lexer) throw new Error(\"Parser can't discover a lexer to use\");\n\t\treturn new ParseTreePatternMatcher(lexer, this).compile(pattern, patternRuleIndex);\n\t}\n\t/**\n\t* The ATN with bypass alternatives is expensive to create so we create it\n\t* lazily.\n\t*\n\t* @throws UnsupportedOperationException if the current parser does not\n\t* implement the {@link getSerializedATN()} method.\n\t*/\n\tgetATNWithBypassAlts() {\n\t\tconst serializedAtn = this.serializedATN;\n\t\tif (serializedAtn === null) throw new Error(\"The current parser does not support an ATN with bypass alternatives.\");\n\t\tif (this.bypassAltsAtnCache !== null) return this.bypassAltsAtnCache;\n\t\tthis.bypassAltsAtnCache = new ATNDeserializer({\n\t\t\treadOnly: false,\n\t\t\tverifyATN: true,\n\t\t\tgenerateRuleBypassTransitions: true\n\t\t}).deserialize(serializedAtn);\n\t\treturn this.bypassAltsAtnCache;\n\t}\n\t/**\n\t* Gets the number of syntax errors reported during parsing. This value is\n\t* incremented each time {@link notifyErrorListeners} is called.\n\t*/\n\tget numberOfSyntaxErrors() {\n\t\treturn this.syntaxErrors;\n\t}\n\tget inputStream() {\n\t\treturn this.#inputStream;\n\t}\n\tset inputStream(input) {\n\t\tthis.tokenStream = input;\n\t}\n\tget tokenStream() {\n\t\treturn this.#inputStream;\n\t}\n\t/** Set the token stream and reset the parser. */\n\tset tokenStream(input) {\n\t\tthis.reset(false);\n\t\tthis.#inputStream = input;\n\t}\n\t/**\n\t* Match needs to return the current input symbol, which gets put\n\t* into the label for the associated token ref; e.g., x=ID.\n\t*/\n\tgetCurrentToken() {\n\t\treturn this.inputStream.LT(1);\n\t}\n\tnotifyErrorListeners(msg, offendingToken, err) {\n\t\toffendingToken = offendingToken ?? null;\n\t\terr = err ?? null;\n\t\tif (offendingToken === null) offendingToken = this.getCurrentToken();\n\t\tthis.syntaxErrors += 1;\n\t\tconst line = offendingToken.line;\n\t\tconst column = offendingToken.column;\n\t\tthis.errorListenerDispatch.syntaxError(this, offendingToken, line, column, msg, err);\n\t}\n\t/**\n\t* Consume and return the {@link getCurrentToken current symbol}.\n\t*\n\t* E.g., given the following input with `A` being the current\n\t* lookahead symbol, this function moves the cursor to `B` and returns\n\t* `A`.\n\t*\n\t* ```\n\t* A B\n\t* ^\n\t* ```\n\t*\n\t* If the parser is not in error recovery mode, the consumed symbol is added\n\t* to the parse tree using {@link ParserRuleContext//addChild(Token)}, and\n\t* {@link ParseTreeListener//visitTerminal} is called on any parse listeners.\n\t* If the parser *is* in error recovery mode, the consumed symbol is\n\t* added to the parse tree using\n\t* {@link ParserRuleContext//addErrorNode(Token)}, and\n\t* {@link ParseTreeListener//visitErrorNode} is called on any parse\n\t* listeners.\n\t*/\n\tconsume() {\n\t\tconst o = this.getCurrentToken();\n\t\tif (o.type !== Token.EOF) this.tokenStream.consume();\n\t\tconst hasListener = this.parseListeners !== null && this.parseListeners.length > 0;\n\t\tif (this.buildParseTrees || hasListener) {\n\t\t\tlet node;\n\t\t\tif (this.errorHandler.inErrorRecoveryMode(this)) node = this.context.addErrorNode(this.createErrorNode(this.context, o));\n\t\t\telse node = this.context.addTokenNode(o);\n\t\t\tif (hasListener) this.parseListeners.forEach((listener) => {\n\t\t\t\tif (node instanceof ErrorNode) listener.visitErrorNode(node);\n\t\t\t\telse listener.visitTerminal(node);\n\t\t\t});\n\t\t}\n\t\treturn o;\n\t}\n\taddContextToParseTree() {\n\t\tif (this.context?.parent) this.context.parent.addChild(this.context);\n\t}\n\t/**\n\t* Always called by generated parsers upon entry to a rule. Access field\n\t* {@link context} get the current context.\n\t*/\n\tenterRule(localctx, state, _ruleIndex) {\n\t\tthis.state = state;\n\t\tthis.context = localctx;\n\t\tthis.context.start = this.inputStream.LT(1);\n\t\tif (this.buildParseTrees) this.addContextToParseTree();\n\t\tthis.triggerEnterRuleEvent();\n\t}\n\texitRule() {\n\t\tif (this.matchedEOF) this.context.stop = this.inputStream.LT(1);\n\t\telse this.context.stop = this.inputStream.LT(-1);\n\t\tthis.triggerExitRuleEvent();\n\t\tthis.state = this.context.invokingState;\n\t\tthis.context = this.context.parent;\n\t}\n\tenterOuterAlt(localctx, altNum) {\n\t\tlocalctx.setAltNumber(altNum);\n\t\tif (this.buildParseTrees && this.context !== localctx) {\n\t\t\tif (this.context?.parent) {\n\t\t\t\tthis.context.parent.removeLastChild();\n\t\t\t\tthis.context.parent.addChild(localctx);\n\t\t\t}\n\t\t}\n\t\tthis.context = localctx;\n\t}\n\t/**\n\t* Get the precedence level for the top-most precedence rule.\n\t*\n\t* @returns The precedence level for the top-most precedence rule, or -1 if\n\t* the parser context is not nested within a precedence rule.\n\t*/\n\tgetPrecedence() {\n\t\tif (this.precedenceStack.length === 0) return -1;\n\t\treturn this.precedenceStack[this.precedenceStack.length - 1];\n\t}\n\tenterRecursionRule(localctx, state, ruleIndex, precedence) {\n\t\tthis.state = state;\n\t\tthis.precedenceStack.push(precedence);\n\t\tthis.context = localctx;\n\t\tthis.context.start = this.inputStream.LT(1);\n\t\tthis.triggerEnterRuleEvent();\n\t}\n\t/** Like {@link enterRule} but for recursive rules. */\n\tpushNewRecursionContext(localctx, state, _ruleIndex) {\n\t\tconst previous = this.context;\n\t\tprevious.parent = localctx;\n\t\tprevious.invokingState = state;\n\t\tprevious.stop = this.inputStream.LT(-1);\n\t\tthis.context = localctx;\n\t\tthis.context.start = previous.start;\n\t\tif (this.buildParseTrees) this.context.addChild(previous);\n\t\tthis.triggerEnterRuleEvent();\n\t}\n\tunrollRecursionContexts(parent) {\n\t\tthis.precedenceStack.pop();\n\t\tthis.context.stop = this.inputStream.LT(-1);\n\t\tconst retCtx = this.context;\n\t\tconst parseListeners = this.getParseListeners();\n\t\tif (parseListeners !== null && parseListeners.length > 0) while (this.context !== parent) {\n\t\t\tthis.triggerExitRuleEvent();\n\t\t\tthis.context = this.context.parent;\n\t\t}\n\t\telse this.context = parent;\n\t\tretCtx.parent = parent;\n\t\tif (this.buildParseTrees && parent !== null) parent.addChild(retCtx);\n\t}\n\tgetInvokingContext(ruleIndex) {\n\t\tlet ctx = this.context;\n\t\twhile (ctx !== null) {\n\t\t\tif (ctx.ruleIndex === ruleIndex) return ctx;\n\t\t\tctx = ctx.parent;\n\t\t}\n\t\treturn null;\n\t}\n\tprecpred(_localctx, precedence) {\n\t\treturn precedence >= this.precedenceStack[this.precedenceStack.length - 1];\n\t}\n\t/**\n\t* Checks whether or not `symbol` can follow the current state in the\n\t* ATN. The behavior of this method is equivalent to the following, but is\n\t* implemented such that the complete context-sensitive follow set does not\n\t* need to be explicitly constructed.\n\t*\n\t* ```\n\t* return getExpectedTokens().contains(symbol);\n\t* ```\n\t*\n\t* @param symbol the symbol type to check\n\t* @returns `true` if `symbol` can follow the current state in\n\t* the ATN, otherwise `false`.\n\t*/\n\tisExpectedToken(symbol) {\n\t\tconst atn = this.interpreter.atn;\n\t\tlet ctx = this.context;\n\t\tconst s = atn.states[this.state];\n\t\tlet following = atn.nextTokens(s);\n\t\tif (following.contains(symbol)) return true;\n\t\tif (!following.contains(Token.EPSILON)) return false;\n\t\twhile (ctx !== null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {\n\t\t\tconst rt = atn.states[ctx.invokingState].transitions[0];\n\t\t\tfollowing = atn.nextTokens(rt.followState);\n\t\t\tif (following.contains(symbol)) return true;\n\t\t\tctx = ctx.parent;\n\t\t}\n\t\tif (following.contains(Token.EPSILON) && symbol === Token.EOF) return true;\n\t\telse return false;\n\t}\n\t/**\n\t* Computes the set of input symbols which could follow the current parser\n\t* state and context, as given by {@link getState} and {@link getContext},\n\t* respectively.\n\t*\n\t* {@link ATN.getExpectedTokens ATN.getExpectedTokens(int, RuleContext)}\n\t*/\n\tgetExpectedTokens() {\n\t\treturn this.interpreter.atn.getExpectedTokens(this.state, this.context);\n\t}\n\tgetExpectedTokensWithinCurrentRule() {\n\t\tconst atn = this.interpreter.atn;\n\t\tconst s = atn.states[this.state];\n\t\treturn atn.nextTokens(s);\n\t}\n\t/** Get a rule's index (i.e., `RULE_ruleName` field) or -1 if not found. */\n\tgetRuleIndex(ruleName) {\n\t\treturn this.getRuleIndexMap().get(ruleName) ?? -1;\n\t}\n\t/**\n\t* @returns an array of string of the rule names in your parser instance\n\t* leading up to a call to the current rule. You could override if\n\t* you want more details such as the file/line info of where\n\t* in the ATN a rule is invoked.\n\t*\n\t* this is very useful for error messages.\n\t*/\n\tgetRuleInvocationStack(p) {\n\t\tp = p ?? null;\n\t\tif (p === null) p = this.context;\n\t\tconst stack = [];\n\t\twhile (p !== null) {\n\t\t\tconst ruleIndex = p.ruleIndex;\n\t\t\tif (ruleIndex < 0) stack.push(\"n/a\");\n\t\t\telse stack.push(this.ruleNames[ruleIndex]);\n\t\t\tp = p.parent;\n\t\t}\n\t\treturn stack;\n\t}\n\t/**\n\t* For debugging and other purposes.\n\t*\n\t* TODO: this differs from the Java version. Change it.\n\t*/\n\tgetDFAStrings() {\n\t\treturn this.interpreter.decisionToDFA.toString();\n\t}\n\t/** For debugging and other purposes. */\n\tdumpDFA() {\n\t\tlet seenOne = false;\n\t\tfor (const dfa of this.interpreter.decisionToDFA) if (dfa.length > 0) {\n\t\t\tif (seenOne) console.log();\n\t\t\tif (this.printer) {\n\t\t\t\tthis.printer.println(\"Decision \" + dfa.decision + \":\");\n\t\t\t\tthis.printer.print(dfa.toString(this.vocabulary));\n\t\t\t}\n\t\t\tseenOne = true;\n\t\t}\n\t}\n\tgetSourceName() {\n\t\treturn this.inputStream.getSourceName();\n\t}\n\tgetParseInfo() {\n\t\tconst interp = this.interpreter;\n\t\tif (interp instanceof ProfilingATNSimulator) return new ParseInfo(interp);\n\t}\n\tsetProfile(profile) {\n\t\tconst interp = this.interpreter;\n\t\tconst saveMode = interp.predictionMode;\n\t\tif (profile) {\n\t\t\tif (!(interp instanceof ProfilingATNSimulator)) this.interpreter = new ProfilingATNSimulator(this);\n\t\t} else if (interp instanceof ProfilingATNSimulator) {\n\t\t\tconst sharedContextCache = interp.sharedContextCache;\n\t\t\tif (sharedContextCache) this.interpreter = new ParserATNSimulator(this, this.atn, interp.decisionToDFA, sharedContextCache);\n\t\t}\n\t\tthis.interpreter.predictionMode = saveMode;\n\t}\n\t/**\n\t* During a parse is sometimes useful to listen in on the rule entry and exit\n\t* events as well as token matches. this is for quick and dirty debugging.\n\t*/\n\tsetTrace(trace) {\n\t\tif (!trace) {\n\t\t\tthis.removeParseListener(this.tracer);\n\t\t\tthis.tracer = null;\n\t\t} else {\n\t\t\tif (this.tracer !== null) this.removeParseListener(this.tracer);\n\t\t\tthis.tracer = new TraceListener(this);\n\t\t\tthis.addParseListener(this.tracer);\n\t\t}\n\t}\n\tcreateTerminalNode(parent, t) {\n\t\treturn new TerminalNode(t);\n\t}\n\tcreateErrorNode(parent, t) {\n\t\treturn new ErrorNode(t);\n\t}\n};\nvar ParserInterpreter = class extends Parser {\n\tstatic {\n\t\t__name(this, \"ParserInterpreter\");\n\t}\n\trootContext;\n\toverrideDecisionRoot = null;\n\tparentContextStack = [];\n\toverrideDecisionAlt = -1;\n\toverrideDecisionReached = false;\n\tdecisionToDFA;\n\tsharedContextCache = new PredictionContextCache();\n\tpushRecursionContextStates;\n\t#overrideDecision = -1;\n\t#overrideDecisionInputIndex = -1;\n\t#grammarFileName;\n\t#atn;\n\t#ruleNames;\n\t#vocabulary;\n\tconstructor(grammarFileName, vocabulary, ruleNames, atn, input) {\n\t\tsuper(input);\n\t\tthis.#grammarFileName = grammarFileName;\n\t\tthis.#atn = atn;\n\t\tthis.#ruleNames = ruleNames.slice(0);\n\t\tthis.#vocabulary = vocabulary;\n\t\tthis.pushRecursionContextStates = new BitSet();\n\t\tfor (const state of atn.states) if (state instanceof StarLoopEntryState && state.precedenceRuleDecision) this.pushRecursionContextStates.set(state.stateNumber);\n\t\tthis.decisionToDFA = atn.decisionToState.map((ds, i) => {\n\t\t\treturn new DFA(ds, i);\n\t\t});\n\t\tthis.interpreter = new ParserATNSimulator(this, atn, this.decisionToDFA, this.sharedContextCache);\n\t}\n\treset() {\n\t\tsuper.reset();\n\t\tthis.overrideDecisionReached = false;\n\t\tthis.overrideDecisionRoot = null;\n\t}\n\tget atn() {\n\t\treturn this.#atn;\n\t}\n\tget vocabulary() {\n\t\treturn this.#vocabulary;\n\t}\n\tget ruleNames() {\n\t\treturn this.#ruleNames;\n\t}\n\tget grammarFileName() {\n\t\treturn this.#grammarFileName;\n\t}\n\tget atnState() {\n\t\treturn this.#atn.states[this.state];\n\t}\n\tparse(startRuleIndex) {\n\t\tconst startRuleStartState = this.#atn.ruleToStartState[startRuleIndex];\n\t\tthis.rootContext = this.createInterpreterRuleContext(null, ATNState.INVALID_STATE_NUMBER, startRuleIndex);\n\t\tif (startRuleStartState.isLeftRecursiveRule) this.enterRecursionRule(this.rootContext, startRuleStartState.stateNumber, startRuleIndex, 0);\n\t\telse this.enterRule(this.rootContext, startRuleStartState.stateNumber, startRuleIndex);\n\t\twhile (true) {\n\t\t\tconst p = this.atnState;\n\t\t\tswitch (p.constructor.stateType) {\n\t\t\t\tcase ATNState.RULE_STOP:\n\t\t\t\t\tif (this.context?.isEmpty()) if (startRuleStartState.isLeftRecursiveRule) {\n\t\t\t\t\t\tconst result = this.context;\n\t\t\t\t\t\tconst parentContext = this.parentContextStack.pop();\n\t\t\t\t\t\tthis.unrollRecursionContexts(parentContext[0]);\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.exitRule();\n\t\t\t\t\t\treturn this.rootContext;\n\t\t\t\t\t}\n\t\t\t\t\tthis.visitRuleStopState(p);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.visitState(p);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (e instanceof RecognitionException) {\n\t\t\t\t\t\t\tthis.state = this.#atn.ruleToStopState[p.ruleIndex].stateNumber;\n\t\t\t\t\t\t\tthis.errorHandler.reportError(this, e);\n\t\t\t\t\t\t\tthis.recover(e);\n\t\t\t\t\t\t} else throw e;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\taddDecisionOverride(decision, tokenIndex, forcedAlt) {\n\t\tthis.#overrideDecision = decision;\n\t\tthis.#overrideDecisionInputIndex = tokenIndex;\n\t\tthis.overrideDecisionAlt = forcedAlt;\n\t}\n\tget overrideDecision() {\n\t\treturn this.#overrideDecision;\n\t}\n\tget overrideDecisionInputIndex() {\n\t\treturn this.#overrideDecisionInputIndex;\n\t}\n\tenterRecursionRule(localctx, state, ruleIndex, precedence) {\n\t\tthis.parentContextStack.push([this.context, localctx.invokingState]);\n\t\tsuper.enterRecursionRule(localctx, state, ruleIndex, precedence);\n\t}\n\tget serializedATN() {\n\t\tthrow new Error(\"The ParserInterpreter does not support the serializedATN property.\");\n\t}\n\tvisitState(p) {\n\t\tlet predictedAlt = 1;\n\t\tif (p instanceof DecisionState) predictedAlt = this.visitDecisionState(p);\n\t\tconst transition = p.transitions[predictedAlt - 1];\n\t\tswitch (transition.transitionType) {\n\t\t\tcase Transition.EPSILON:\n\t\t\t\tif (this.pushRecursionContextStates.get(p.stateNumber) && !(transition.target.constructor.stateType === ATNState.LOOP_END)) {\n\t\t\t\t\tconst parentContext = this.parentContextStack[this.parentContextStack.length - 1];\n\t\t\t\t\tconst localctx = this.createInterpreterRuleContext(parentContext[0], parentContext[1], this.context.ruleIndex);\n\t\t\t\t\tthis.pushNewRecursionContext(localctx, this.#atn.ruleToStartState[p.ruleIndex].stateNumber, this.context.ruleIndex);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase Transition.ATOM:\n\t\t\t\tthis.match(transition.label.minElement);\n\t\t\t\tbreak;\n\t\t\tcase Transition.RANGE:\n\t\t\tcase Transition.SET:\n\t\t\tcase Transition.NOT_SET:\n\t\t\t\tif (!transition.matches(this.inputStream.LA(1), Token.MIN_USER_TOKEN_TYPE, 65535)) this.recoverInline();\n\t\t\t\tthis.matchWildcard();\n\t\t\t\tbreak;\n\t\t\tcase Transition.WILDCARD:\n\t\t\t\tthis.matchWildcard();\n\t\t\t\tbreak;\n\t\t\tcase Transition.RULE:\n\t\t\t\tconst ruleStartState = transition.target;\n\t\t\t\tconst ruleIndex = ruleStartState.ruleIndex;\n\t\t\t\tconst newContext = this.createInterpreterRuleContext(this.context, p.stateNumber, ruleIndex);\n\t\t\t\tif (ruleStartState.isLeftRecursiveRule) this.enterRecursionRule(newContext, ruleStartState.stateNumber, ruleIndex, transition.precedence);\n\t\t\t\telse this.enterRule(newContext, transition.target.stateNumber, ruleIndex);\n\t\t\t\tbreak;\n\t\t\tcase Transition.PREDICATE:\n\t\t\t\tconst predicateTransition = transition;\n\t\t\t\tif (!this.sempred(this.context, predicateTransition.ruleIndex, predicateTransition.predIndex)) throw new FailedPredicateException(this);\n\t\t\t\tbreak;\n\t\t\tcase Transition.ACTION:\n\t\t\t\tconst actionTransition = transition;\n\t\t\t\tthis.action(this.context, actionTransition.ruleIndex, actionTransition.actionIndex);\n\t\t\t\tbreak;\n\t\t\tcase Transition.PRECEDENCE:\n\t\t\t\tif (!this.precpred(this.context, transition.precedence)) {\n\t\t\t\t\tconst precedence = transition.precedence;\n\t\t\t\t\tthrow new FailedPredicateException(this, `precpred(_ctx, ${precedence})`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault: throw new Error(\"UnsupportedOperationException: Unrecognized ATN transition type.\");\n\t\t}\n\t\tthis.state = transition.target.stateNumber;\n\t}\n\tvisitDecisionState(p) {\n\t\tlet predictedAlt = 1;\n\t\tif (p.transitions.length > 1) {\n\t\t\tthis.errorHandler.sync(this);\n\t\t\tconst decision = p.decision;\n\t\t\tif (decision === this.#overrideDecision && this.inputStream.index === this.#overrideDecisionInputIndex && !this.overrideDecisionReached) {\n\t\t\t\tpredictedAlt = this.overrideDecisionAlt;\n\t\t\t\tthis.overrideDecisionReached = true;\n\t\t\t} else predictedAlt = this.interpreter.adaptivePredict(this.inputStream, decision, this.context);\n\t\t}\n\t\treturn predictedAlt;\n\t}\n\tcreateInterpreterRuleContext(parent, invokingStateNumber, ruleIndex) {\n\t\treturn new InterpreterRuleContext(ruleIndex, parent, invokingStateNumber);\n\t}\n\tvisitRuleStopState(p) {\n\t\tif (this.#atn.ruleToStartState[p.ruleIndex].isLeftRecursiveRule) {\n\t\t\tconst [parentContext, state] = this.parentContextStack.pop();\n\t\t\tthis.unrollRecursionContexts(parentContext);\n\t\t\tthis.state = state;\n\t\t} else this.exitRule();\n\t\tthis.state = this.#atn.states[this.state].transitions[0].followState.stateNumber;\n\t}\n\trecover(e) {\n\t\tconst i = this.inputStream.index;\n\t\tthis.errorHandler.recover(this, e);\n\t\tif (this.inputStream.index === i) {\n\t\t\tconst tok = e.offendingToken;\n\t\t\tif (!tok) throw new Error(\"Expected exception to have an offending token\");\n\t\t\tconst source = tok.tokenSource;\n\t\t\tconst sourcePair = [source, source?.inputStream ?? null];\n\t\t\tif (e instanceof InputMismatchException) {\n\t\t\t\tconst expectedTokens = e.getExpectedTokens();\n\t\t\t\tif (!expectedTokens) throw new Error(\"Expected the exception to provide expected tokens\");\n\t\t\t\tlet expectedTokenType = Token.INVALID_TYPE;\n\t\t\t\tif (expectedTokens.length !== 0) expectedTokenType = expectedTokens.minElement;\n\t\t\t\tconst errToken = this.getTokenFactory().create(sourcePair, expectedTokenType, tok.text, Token.DEFAULT_CHANNEL, -1, -1, tok.line, tok.column);\n\t\t\t\tthis.context.addErrorNode(this.createErrorNode(this.context, errToken));\n\t\t\t} else {\n\t\t\t\tconst errToken = this.getTokenFactory().create(sourcePair, Token.INVALID_TYPE, tok.text, Token.DEFAULT_CHANNEL, -1, -1, tok.line, tok.column);\n\t\t\t\tthis.context.addErrorNode(this.createErrorNode(this.context, errToken));\n\t\t\t}\n\t\t}\n\t}\n\trecoverInline() {\n\t\treturn this.errorHandler.recoverInline(this);\n\t}\n};\nvar MultiMap = class extends Map {\n\tstatic {\n\t\t__name(this, \"MultiMap\");\n\t}\n\tmap(key, value) {\n\t\tlet elementsForKey = this.get(key);\n\t\tif (!elementsForKey) {\n\t\t\telementsForKey = new Array();\n\t\t\tthis.set(key, elementsForKey);\n\t\t}\n\t\telementsForKey.push(value);\n\t}\n\tgetPairs() {\n\t\tconst pairs = new Array();\n\t\tfor (const key of this.keys()) {\n\t\t\tconst keys = this.get(key) ?? [];\n\t\t\tfor (const value of keys) pairs.push([key, value]);\n\t\t}\n\t\treturn pairs;\n\t}\n\ttoString() {\n\t\tconst entries = [];\n\t\tthis.forEach((value, key) => {\n\t\t\tentries.push(`${key}=[${value.join(\", \")}]`);\n\t\t});\n\t\treturn `{${entries.join(\", \")}}`;\n\t}\n};\nvar CannotInvokeStartRuleError = class extends Error {\n\tstatic {\n\t\t__name(this, \"CannotInvokeStartRuleError\");\n\t}\n\tconstructor(e) {\n\t\tsuper();\n\t\tthis.cause = e;\n\t}\n};\nvar RuleTagToken = class {\n\tstatic {\n\t\t__name(this, \"RuleTagToken\");\n\t}\n\t/** The name of the label associated with the rule tag. */\n\tlabel;\n\t/** The name of the parser rule associated with this rule tag. */\n\truleName;\n\t/**\n\t* The token type for the current token. This is the token type assigned to\n\t* the bypass alternative for the rule during ATN deserialization.\n\t*/\n\tbypassTokenType;\n\tconstructor(ruleName, bypassTokenType, label) {\n\t\tthis.ruleName = ruleName;\n\t\tthis.bypassTokenType = bypassTokenType;\n\t\tthis.label = label;\n\t}\n\t/**\n\t* Rule tag tokens are always placed on the {@link #DEFAULT_CHANNEL}.\n\t*/\n\tget channel() {\n\t\treturn Token.DEFAULT_CHANNEL;\n\t}\n\t/**\n\t* This method returns the rule tag formatted with `<` and `>`\n\t* delimiters.\n\t*/\n\tget text() {\n\t\tif (this.label !== void 0) return \"<\" + this.label + \":\" + this.ruleName + \">\";\n\t\treturn \"<\" + this.ruleName + \">\";\n\t}\n\t/**\n\t* Rule tag tokens have types assigned according to the rule bypass\n\t* transitions created during ATN deserialization.\n\t*/\n\tget type() {\n\t\treturn this.bypassTokenType;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns 0.\n\t*/\n\tget line() {\n\t\treturn 0;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns -1.\n\t*/\n\tget column() {\n\t\treturn -1;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns -1.\n\t*/\n\tget tokenIndex() {\n\t\treturn -1;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns -1.\n\t*/\n\tget start() {\n\t\treturn -1;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns -1.\n\t*/\n\tget stop() {\n\t\treturn -1;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns `null`.\n\t*/\n\tget tokenSource() {\n\t\treturn null;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} always returns `null`.\n\t*/\n\tget inputStream() {\n\t\treturn null;\n\t}\n\t/**\n\t* The implementation for {@link RuleTagToken} returns a string of the form\n\t* `ruleName:bypassTokenType`.\n\t*/\n\ttoString() {\n\t\treturn this.ruleName + \":\" + this.bypassTokenType;\n\t}\n};\nvar StartRuleDoesNotConsumeFullPatternError = class extends Error {\n\tstatic {\n\t\t__name(this, \"StartRuleDoesNotConsumeFullPatternError\");\n\t}\n};\nvar TagChunk = class extends Chunk {\n\tstatic {\n\t\t__name(this, \"TagChunk\");\n\t}\n\ttag;\n\tlabel;\n\tconstructor(...args) {\n\t\tlet label;\n\t\tlet tag;\n\t\tif (args.length === 1) tag = args[0];\n\t\telse {\n\t\t\tlabel = args[0];\n\t\t\ttag = args[1];\n\t\t}\n\t\tsuper();\n\t\tif (!tag) throw new Error(\"tag cannot be null or empty\");\n\t\tthis.label = label;\n\t\tthis.tag = tag;\n\t}\n\t/**\n\t* @returns a text representation of the tag chunk. Labeled tags\n\t* are returned in the form `label:tag`, and unlabeled tags are\n\t* returned as just the tag name.\n\t*/\n\ttoString() {\n\t\tif (this.label !== void 0) return this.label + \":\" + this.tag;\n\t\treturn this.tag;\n\t}\n};\nvar TextChunk = class extends Chunk {\n\tstatic {\n\t\t__name(this, \"TextChunk\");\n\t}\n\ttext;\n\t/**\n\t* Constructs a new instance of {@link TextChunk} with the specified text.\n\t*\n\t* @param text The text of this chunk.\n\t*/\n\tconstructor(text) {\n\t\tsuper();\n\t\tthis.text = text;\n\t}\n\t/**\n\t* @returns the result of {@link #getText()} in single quotes.\n\t*/\n\ttoString() {\n\t\treturn \"'\" + this.text + \"'\";\n\t}\n};\nvar TokenTagToken = class extends CommonToken {\n\tstatic {\n\t\t__name(this, \"TokenTagToken\");\n\t}\n\ttokenName;\n\t/**\n\t* The name of the label associated with the rule tag, or undefined if this is an unlabeled rule tag.\n\t*/\n\tlabel;\n\tconstructor(tokenName, type, label) {\n\t\tsuper({\n\t\t\ttype,\n\t\t\tsource: CommonToken.EMPTY_SOURCE\n\t\t});\n\t\tthis.tokenName = tokenName;\n\t\tthis.label = label;\n\t}\n\t/**\n\t*\n\t* @returns the token tag formatted with `<` and `>` delimiters.\n\t*/\n\tget text() {\n\t\tif (this.label !== void 0) return \"<\" + this.label + \":\" + this.tokenName + \">\";\n\t\treturn \"<\" + this.tokenName + \">\";\n\t}\n\t/**\n\t* @returns a string of the form `tokenName:type`.\n\t*/\n\ttoString() {\n\t\treturn this.tokenName + \":\" + this.type;\n\t}\n};\nvar ParseTreePatternMatcher = class {\n\tstatic {\n\t\t__name(this, \"ParseTreePatternMatcher\");\n\t}\n\tstart = \"<\";\n\tstop = \">\";\n\tescape = \"\\\\\";\n\t/**\n\t* This is the backing field for {@link #getLexer()}.\n\t*/\n\tlexer;\n\t/**\n\t* This is the backing field for {@link #getParser()}.\n\t*/\n\tparser;\n\t/**\n\t* Constructs a {@link ParseTreePatternMatcher} or from a {@link Lexer} and\n\t* {@link Parser} object. The lexer input stream is altered for tokenizing\n\t* the tree patterns. The parser is used as a convenient mechanism to get\n\t* the grammar name, plus token, rule names.\n\t*/\n\tconstructor(lexer, parser) {\n\t\tthis.lexer = lexer;\n\t\tthis.parser = parser;\n\t}\n\t/**\n\t* Set the delimiters used for marking rule and token tags within concrete\n\t* syntax used by the tree pattern parser.\n\t*\n\t* @param start The start delimiter.\n\t* @param stop The stop delimiter.\n\t* @param escapeLeft The escape sequence to use for escaping a start or stop delimiter.\n\t*\n\t* @throws Error if `start` is `null` or empty.\n\t* @throws Error if `stop` is `null` or empty.\n\t*/\n\tsetDelimiters(start, stop, escapeLeft) {\n\t\tif (start === null || start.length === 0) throw new Error(\"start cannot be null or empty\");\n\t\tif (stop === null || stop.length === 0) throw new Error(\"stop cannot be null or empty\");\n\t\tthis.start = start;\n\t\tthis.stop = stop;\n\t\tthis.escape = escapeLeft;\n\t}\n\tmatches(...args) {\n\t\tswitch (args.length) {\n\t\t\tcase 2: {\n\t\t\t\tconst [tree, pattern] = args;\n\t\t\t\tconst labels = new MultiMap();\n\t\t\t\treturn this.matchImpl(tree, pattern.getPatternTree(), labels) === null;\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\tconst [tree, pattern, patternRuleIndex] = args;\n\t\t\t\tconst p = this.compile(pattern, patternRuleIndex);\n\t\t\t\treturn this.matches(tree, p);\n\t\t\t}\n\t\t\tdefault: throw new Error(\"Invalid number of arguments\");\n\t\t}\n\t}\n\tmatch(...args) {\n\t\tswitch (args.length) {\n\t\t\tcase 2: {\n\t\t\t\tconst [tree, pattern] = args;\n\t\t\t\tconst labels = new MultiMap();\n\t\t\t\treturn new ParseTreeMatch(tree, pattern, labels, this.matchImpl(tree, pattern.getPatternTree(), labels));\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\tconst [tree, pattern, patternRuleIndex] = args;\n\t\t\t\tconst p = this.compile(pattern, patternRuleIndex);\n\t\t\t\treturn this.match(tree, p);\n\t\t\t}\n\t\t\tdefault: throw new Error(\"Invalid number of arguments\");\n\t\t}\n\t}\n\t/**\n\t* For repeated use of a tree pattern, compile it to a\n\t* {@link ParseTreePattern} using this method.\n\t*/\n\tcompile(pattern, patternRuleIndex) {\n\t\tconst tokens = new CommonTokenStream(new ListTokenSource(this.tokenize(pattern)));\n\t\tconst parserInterp = new ParserInterpreter(this.parser.grammarFileName, this.parser.vocabulary, this.parser.ruleNames, this.parser.getATNWithBypassAlts(), tokens);\n\t\tparserInterp.removeErrorListeners();\n\t\tlet tree = null;\n\t\ttry {\n\t\t\tparserInterp.errorHandler = new BailErrorStrategy();\n\t\t\ttree = parserInterp.parse(patternRuleIndex);\n\t\t} catch (error) {\n\t\t\tif (error instanceof ParseCancellationException) throw error.cause;\n\t\t\telse if (error instanceof RecognitionException) throw error;\n\t\t\telse if (error instanceof Error) throw new CannotInvokeStartRuleError(error);\n\t\t\telse throw error;\n\t\t}\n\t\tif (tokens.LA(1) !== Token.EOF) throw new StartRuleDoesNotConsumeFullPatternError();\n\t\treturn new ParseTreePattern(this, pattern, patternRuleIndex, tree);\n\t}\n\t/**\n\t* Used to convert the tree pattern string into a series of tokens. The\n\t* input stream is reset.\n\t*/\n\tgetLexer() {\n\t\treturn this.lexer;\n\t}\n\t/**\n\t* Used to collect to the grammar file name, token names, rule names for\n\t* used to parse the pattern into a parse tree.\n\t*/\n\tgetParser() {\n\t\treturn this.parser;\n\t}\n\ttokenize(pattern) {\n\t\tconst chunks = this.split(pattern);\n\t\tconst tokens = new Array();\n\t\tfor (const chunk of chunks) if (chunk instanceof TagChunk) {\n\t\t\tconst tagChunk = chunk;\n\t\t\tconst char = tagChunk.tag[0];\n\t\t\tif (char === char.toUpperCase()) {\n\t\t\t\tconst ttype = this.parser.getTokenType(tagChunk.tag);\n\t\t\t\tif (ttype === Token.INVALID_TYPE) throw new Error(\"Unknown token \" + tagChunk.tag + \" in pattern: \" + pattern);\n\t\t\t\tconst t = new TokenTagToken(tagChunk.tag, ttype, tagChunk.label);\n\t\t\t\ttokens.push(t);\n\t\t\t} else if (char === char.toLowerCase()) {\n\t\t\t\tconst ruleIndex = this.parser.getRuleIndex(tagChunk.tag);\n\t\t\t\tif (ruleIndex === -1) throw new Error(\"Unknown rule \" + tagChunk.tag + \" in pattern: \" + pattern);\n\t\t\t\tconst ruleImaginaryTokenType = this.parser.getATNWithBypassAlts().ruleToTokenType[ruleIndex];\n\t\t\t\ttokens.push(new RuleTagToken(tagChunk.tag, ruleImaginaryTokenType, tagChunk.label));\n\t\t\t} else throw new Error(\"invalid tag: \" + tagChunk.tag + \" in pattern: \" + pattern);\n\t\t} else {\n\t\t\tconst textChunk = chunk;\n\t\t\tconst input = CharStream.fromString(textChunk.text);\n\t\t\tthis.lexer.inputStream = input;\n\t\t\tlet t = this.lexer.nextToken();\n\t\t\twhile (t.type !== Token.EOF) {\n\t\t\t\ttokens.push(t);\n\t\t\t\tt = this.lexer.nextToken();\n\t\t\t}\n\t\t}\n\t\treturn tokens;\n\t}\n\t/**\n\t* Split `<ID> = <e:expr> ;` into 4 chunks for tokenizing by {@link #tokenize}.\n\t*/\n\tsplit(pattern) {\n\t\tlet p = 0;\n\t\tconst n2 = pattern.length;\n\t\tconst chunks = new Array();\n\t\tconst starts = new Array();\n\t\tconst stops = new Array();\n\t\twhile (p < n2) if (p === pattern.indexOf(this.escape + this.start, p)) p += this.escape.length + this.start.length;\n\t\telse if (p === pattern.indexOf(this.escape + this.stop, p)) p += this.escape.length + this.stop.length;\n\t\telse if (p === pattern.indexOf(this.start, p)) {\n\t\t\tstarts.push(p);\n\t\t\tp += this.start.length;\n\t\t} else if (p === pattern.indexOf(this.stop, p)) {\n\t\t\tstops.push(p);\n\t\t\tp += this.stop.length;\n\t\t} else p++;\n\t\tif (starts.length > stops.length) throw new Error(\"unterminated tag in pattern: \" + pattern);\n\t\tif (starts.length < stops.length) throw new Error(\"missing start tag in pattern: \" + pattern);\n\t\tconst tagCount = starts.length;\n\t\tfor (let i = 0; i < tagCount; i++) if (starts[i] >= stops[i]) throw new Error(\"tag delimiters out of order in pattern: \" + pattern);\n\t\tif (tagCount === 0) {\n\t\t\tconst text = pattern.substring(0, n2);\n\t\t\tchunks.push(new TextChunk(text));\n\t\t}\n\t\tif (tagCount > 0 && starts[0] > 0) {\n\t\t\tconst text = pattern.substring(0, starts[0]);\n\t\t\tchunks.push(new TextChunk(text));\n\t\t}\n\t\tfor (let i = 0; i < tagCount; i++) {\n\t\t\tconst tag = pattern.substring(starts[i] + this.start.length, stops[i]);\n\t\t\tlet ruleOrToken = tag;\n\t\t\tlet label;\n\t\t\tconst colon = tag.indexOf(\":\");\n\t\t\tif (colon >= 0) {\n\t\t\t\tlabel = tag.substring(0, colon);\n\t\t\t\truleOrToken = tag.substring(colon + 1, tag.length);\n\t\t\t}\n\t\t\tchunks.push(new TagChunk(label, ruleOrToken));\n\t\t\tif (i + 1 < tagCount) {\n\t\t\t\tconst text = pattern.substring(stops[i] + this.stop.length, starts[i + 1]);\n\t\t\t\tchunks.push(new TextChunk(text));\n\t\t\t}\n\t\t}\n\t\tif (tagCount > 0) {\n\t\t\tconst afterLastTag = stops[tagCount - 1] + this.stop.length;\n\t\t\tif (afterLastTag < n2) {\n\t\t\t\tconst text = pattern.substring(afterLastTag, n2);\n\t\t\t\tchunks.push(new TextChunk(text));\n\t\t\t}\n\t\t}\n\t\tfor (let i = 0; i < chunks.length; i++) {\n\t\t\tconst c = chunks[i];\n\t\t\tif (c instanceof TextChunk) {\n\t\t\t\tconst tc = c;\n\t\t\t\tconst unescaped = tc.text.replaceAll(this.escape, \"\");\n\t\t\t\tif (unescaped.length < tc.text.length) chunks[i] = new TextChunk(unescaped);\n\t\t\t}\n\t\t}\n\t\treturn chunks;\n\t}\n\t/**\n\t* Recursively walk `tree` against `patternTree`, filling\n\t* `match.`{@link ParseTreeMatch#labels labels}.\n\t*\n\t* @returns the first node encountered in `tree` which does not match\n\t* a corresponding node in `patternTree`, or `null` if the match\n\t* was successful. The specific node returned depends on the matching\n\t* algorithm used by the implementation, and may be overridden.\n\t*/\n\tmatchImpl(tree, patternTree, labels) {\n\t\tif (tree instanceof TerminalNode && patternTree instanceof TerminalNode) {\n\t\t\tconst t1 = tree;\n\t\t\tconst t2 = patternTree;\n\t\t\tlet mismatchedNode;\n\t\t\tif (t1.getSymbol().type === t2.getSymbol().type) {\n\t\t\t\tif (t2.getSymbol() instanceof TokenTagToken) {\n\t\t\t\t\tconst tokenTagToken = t2.getSymbol();\n\t\t\t\t\tlabels.map(tokenTagToken.tokenName, tree);\n\t\t\t\t\tif (tokenTagToken.label !== void 0) labels.map(tokenTagToken.label, tree);\n\t\t\t\t} else if (t1.getText() === t2.getText()) {} else if (!mismatchedNode) mismatchedNode = t1;\n\t\t\t} else if (!mismatchedNode) mismatchedNode = t1;\n\t\t\treturn mismatchedNode;\n\t\t}\n\t\tif (tree instanceof ParserRuleContext && patternTree instanceof ParserRuleContext) {\n\t\t\tlet mismatchedNode;\n\t\t\tconst ruleTagToken = this.getRuleTagToken(patternTree);\n\t\t\tif (ruleTagToken) {\n\t\t\t\tif (tree.ruleIndex === patternTree.ruleIndex) {\n\t\t\t\t\tlabels.map(ruleTagToken.ruleName, tree);\n\t\t\t\t\tif (ruleTagToken.label) labels.map(ruleTagToken.label, tree);\n\t\t\t\t} else if (!mismatchedNode) mismatchedNode = tree;\n\t\t\t\treturn mismatchedNode;\n\t\t\t}\n\t\t\tif (tree.getChildCount() !== patternTree.getChildCount()) {\n\t\t\t\tif (!mismatchedNode) mismatchedNode = tree;\n\t\t\t\treturn mismatchedNode;\n\t\t\t}\n\t\t\tconst n2 = tree.getChildCount();\n\t\t\tfor (let i = 0; i < n2; i++) {\n\t\t\t\tconst childMatch = this.matchImpl(tree.getChild(i), patternTree.getChild(i), labels);\n\t\t\t\tif (childMatch) return childMatch;\n\t\t\t}\n\t\t\treturn mismatchedNode;\n\t\t}\n\t\treturn tree;\n\t}\n\t/**\n\t* Is `t` `(expr <expr>)` subtree?\n\t*/\n\tgetRuleTagToken(t) {\n\t\tif (t instanceof ParserRuleContext) {\n\t\t\tif (t.getChildCount() === 1 && t.getChild(0) instanceof TerminalNode) {\n\t\t\t\tconst c = t.getChild(0);\n\t\t\t\tif (c.getSymbol() instanceof RuleTagToken) return c.getSymbol();\n\t\t\t}\n\t\t}\n\t}\n};\nvar DiagnosticErrorListener = class extends BaseErrorListener {\n\tstatic {\n\t\t__name(this, \"DiagnosticErrorListener\");\n\t}\n\t/**\n\t* When `true`, only exactly known ambiguities are reported.\n\t*/\n\texactOnly;\n\tconstructor(exactOnly) {\n\t\tsuper();\n\t\tthis.exactOnly = exactOnly ?? true;\n\t}\n\treportAmbiguity = /* @__PURE__ */ __name((recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) => {\n\t\tif (this.exactOnly && !exact) return;\n\t\tconst message = `reportAmbiguity d=${this.getDecisionDescription(recognizer, dfa)}: ambigAlts=${this.getConflictingAlts(ambigAlts, configs)}, input='${recognizer.tokenStream?.getTextFromInterval(Interval.of(startIndex, stopIndex))}'`;\n\t\trecognizer.notifyErrorListeners(message, null, null);\n\t}, \"reportAmbiguity\");\n\treportAttemptingFullContext = /* @__PURE__ */ __name((recognizer, dfa, startIndex, stopIndex, _conflictingAlts, _configs) => {\n\t\tconst message = `reportAttemptingFullContext d=${this.getDecisionDescription(recognizer, dfa)}, input='${recognizer.tokenStream?.getTextFromInterval(Interval.of(startIndex, stopIndex))}'`;\n\t\trecognizer.notifyErrorListeners(message, null, null);\n\t}, \"reportAttemptingFullContext\");\n\treportContextSensitivity = /* @__PURE__ */ __name((recognizer, dfa, startIndex, stopIndex, _prediction, _configs) => {\n\t\tconst message = `reportContextSensitivity d=${this.getDecisionDescription(recognizer, dfa)}, input='${recognizer.tokenStream?.getTextFromInterval(Interval.of(startIndex, stopIndex))}'`;\n\t\trecognizer.notifyErrorListeners(message, null, null);\n\t}, \"reportContextSensitivity\");\n\tgetDecisionDescription = /* @__PURE__ */ __name((recognizer, dfa) => {\n\t\tconst decision = dfa.decision;\n\t\tconst ruleIndex = dfa.atnStartState.ruleIndex;\n\t\tconst ruleNames = recognizer.ruleNames;\n\t\tif (ruleIndex < 0 || ruleIndex >= ruleNames.length) return decision.toString();\n\t\tconst ruleName = ruleNames[ruleIndex];\n\t\tif (ruleName.length === 0) return decision.toString();\n\t\treturn `${decision} (${ruleName})`;\n\t}, \"getDecisionDescription\");\n\t/**\n\t* Computes the set of conflicting or ambiguous alternatives from a\n\t* configuration set, if that information was not already provided by the\n\t* parser.\n\t*\n\t* @param reportedAlts The set of conflicting or ambiguous alternatives, as\n\t* reported by the parser.\n\t* @param configs The conflicting or ambiguous configuration set.\n\t* @returns Returns `reportedAlts` if it is not `null`, otherwise\n\t* returns the set of alternatives represented in `configs`.\n\t*/\n\tgetConflictingAlts = /* @__PURE__ */ __name((reportedAlts, configs) => {\n\t\tif (reportedAlts) return reportedAlts;\n\t\tconst result = new BitSet();\n\t\tfor (let i = 0; i < configs.configs.length; i++) result.set(configs.configs[i].alt);\n\t\treturn result;\n\t}, \"getConflictingAlts\");\n};\nvar LexerInterpreter = class extends Lexer {\n\tstatic {\n\t\t__name(this, \"LexerInterpreter\");\n\t}\n\tdecisionToDFA;\n\tsharedContextCache = new PredictionContextCache();\n\t#grammarFileName;\n\t#atn;\n\t#ruleNames;\n\t#channelNames;\n\t#modeNames;\n\t#vocabulary;\n\tconstructor(grammarFileName, vocabulary, ruleNames, channelNames, modeNames, atn, input) {\n\t\tsuper(input);\n\t\tif (atn.grammarType !== ATN.LEXER) throw new Error(\"IllegalArgumentException: The ATN must be a lexer ATN.\");\n\t\tthis.#grammarFileName = grammarFileName;\n\t\tthis.#atn = atn;\n\t\tthis.#ruleNames = ruleNames.slice(0);\n\t\tthis.#channelNames = channelNames.slice(0);\n\t\tthis.#modeNames = modeNames.slice(0);\n\t\tthis.#vocabulary = vocabulary;\n\t\tthis.decisionToDFA = atn.decisionToState.map((ds, i) => {\n\t\t\treturn new DFA(ds, i);\n\t\t});\n\t\tthis.interpreter = new LexerATNSimulator(this, atn, this.decisionToDFA, this.sharedContextCache);\n\t}\n\tget atn() {\n\t\treturn this.#atn;\n\t}\n\tget grammarFileName() {\n\t\treturn this.#grammarFileName;\n\t}\n\tget ruleNames() {\n\t\treturn this.#ruleNames;\n\t}\n\tget channelNames() {\n\t\treturn this.#channelNames;\n\t}\n\tget modeNames() {\n\t\treturn this.#modeNames;\n\t}\n\tget vocabulary() {\n\t\treturn this.#vocabulary;\n\t}\n\tget serializedATN() {\n\t\tthrow new Error(\"The LexerInterpreter does not support the serializedATN property.\");\n\t}\n};\nvar RuntimeMetaData = class _RuntimeMetaData {\n\tstatic {\n\t\t__name(this, \"RuntimeMetaData\");\n\t}\n\t/**\n\t* A compile-time constant containing the current version of the ANTLR 4\n\t* runtime library.\n\t*\n\t* This compile-time constant value allows generated parsers and other\n\t* libraries to include a literal reference to the version of the ANTLR 4\n\t* runtime library the code was compiled against. At each release, we\n\t* change this value.\n\t*\n\t* Version numbers are assumed to have the form\n\t*\n\t* major.minor.patch.revision-suffix,\n\t*\n\t* with the individual components defined as follows.\n\t*\n\t* - major is a required non-negative integer, and is equal to `4` for ANTLR 4.\n\t* - minor is a required non-negative integer.\n\t* - patch is an optional non-negative integer. When patch is omitted, the `.` (dot) appearing before it is\n\t*   also omitted.\n\t* - revision is an optional non-negative integer, and may only be included when patch is also included.\n\t*   When revision is omitted, the `.` (dot) appearing before it is also omitted.\n\t* - suffix is an optional string. When suffix is omitted, the `-` (hyphen-minus) appearing before it is also\n\t*   omitted.\n\t*/\n\tstatic VERSION = \"4.13.1\";\n\t/**\n\t* Gets the currently executing version of the ANTLR 4 runtime library.\n\t*\n\t* This method provides runtime access to the {@link VERSION} field, as\n\t* opposed to directly referencing the field as a compile-time constant.\n\t*\n\t* @returns The currently executing version of the ANTLR 4 library\n\t*/\n\tstatic getRuntimeVersion() {\n\t\treturn _RuntimeMetaData.VERSION;\n\t}\n\t/**\n\t* This method provides the ability to detect mismatches between the version\n\t* of ANTLR 4 used to generate a parser, the version of the ANTLR runtime a\n\t* parser was compiled against, and the version of the ANTLR runtime which\n\t* is currently executing.\n\t*\n\t* The version check is designed to detect the following two specific\n\t* scenarios.\n\t*\n\t* - The ANTLR Tool version used for code generation does not match the\n\t* currently executing runtime version.\n\t* - The ANTLR Runtime version referenced at the time a parser was\n\t* compiled does not match the currently executing runtime version.\n\t*\n\t*\n\t* Starting with ANTLR 4.3, the code generator emits a call to this method\n\t* using two constants in each generated lexer and parser: a hard-coded\n\t* constant indicating the version of the tool used to generate the parser\n\t* and a reference to the compile-time constant {@link VERSION}. At\n\t* runtime, this method is called during the initialization of the generated\n\t* parser to detect mismatched versions, and notify the registered listeners\n\t* prior to creating instances of the parser.\n\t*\n\t*\n\t* This method does not perform any detection or filtering of semantic\n\t* changes between tool and runtime versions. It simply checks for a\n\t* version match and emits an error to stderr if a difference\n\t* is detected.\n\t*\n\t*\n\t* Note that some breaking changes between releases could result in other\n\t* types of runtime exceptions, such as a {@link LinkageError}, prior to\n\t* calling this method. In these cases, the underlying version mismatch will\n\t* not be reported here. This method is primarily intended to\n\t* notify users of potential semantic changes between releases that do not\n\t* result in binary compatibility problems which would be detected by the\n\t* class loader. As with semantic changes, changes that break binary\n\t* compatibility between releases are mentioned in the release notes\n\t* accompanying the affected release.\n\t*\n\t*\n\t* **Additional note for target developers:** The version check\n\t* implemented by this class is designed to address specific compatibility\n\t* concerns that may arise during the execution of Java applications. Other\n\t* targets should consider the implementation of this method in the context\n\t* of that target's known execution environment, which may or may not\n\t* resemble the design provided for the Java target.\n\t*\n\t* @param generatingToolVersion The version of the tool used to generate a parser.\n\t* This value may be null when called from user code that was not generated\n\t* by, and does not reference, the ANTLR 4 Tool itself.\n\t* @param compileTimeVersion The version of the runtime the parser was\n\t* compiled against. This should always be passed using a direct reference\n\t* to {@link VERSION}.\n\t*/\n\tstatic checkVersion(generatingToolVersion, compileTimeVersion) {\n\t\tconst runtimeVersion = _RuntimeMetaData.VERSION;\n\t\tlet runtimeConflictsWithGeneratingTool = false;\n\t\tlet runtimeConflictsWithCompileTimeTool = false;\n\t\truntimeConflictsWithGeneratingTool = runtimeVersion !== generatingToolVersion && _RuntimeMetaData.getMajorMinorVersion(runtimeVersion) !== _RuntimeMetaData.getMajorMinorVersion(generatingToolVersion);\n\t\truntimeConflictsWithCompileTimeTool = runtimeVersion !== compileTimeVersion && _RuntimeMetaData.getMajorMinorVersion(runtimeVersion) !== _RuntimeMetaData.getMajorMinorVersion(compileTimeVersion);\n\t\tif (runtimeConflictsWithGeneratingTool) console.error(`ANTLR Tool version ${generatingToolVersion} used for code generation does not match the current runtime version ${runtimeVersion}`);\n\t\tif (runtimeConflictsWithCompileTimeTool) console.error(`ANTLR Runtime version ${compileTimeVersion} used for parser compilation does not match the current runtime version ${runtimeVersion}`);\n\t}\n\t/**\n\t* Gets the major and minor version numbers from a version string. For\n\t* details about the syntax of the input `version`.\n\t* E.g., from x.y.z return x.y.\n\t*\n\t* @param version The complete version string.\n\t* @returns A string of the form *major*.*minor* containing\n\t* only the major and minor components of the version string.\n\t*/\n\tstatic getMajorMinorVersion(version) {\n\t\tconst firstDot = version.indexOf(\".\");\n\t\tconst secondDot = firstDot >= 0 ? version.indexOf(\".\", firstDot + 1) : -1;\n\t\tconst firstDash = version.indexOf(\"-\");\n\t\tlet referenceLength = version.length;\n\t\tif (secondDot >= 0) referenceLength = Math.min(referenceLength, secondDot);\n\t\tif (firstDash >= 0) referenceLength = Math.min(referenceLength, firstDash);\n\t\treturn version.substring(0, referenceLength);\n\t}\n};\nvar TokenStreamRewriter = class _TokenStreamRewriter {\n\tstatic {\n\t\t__name(this, \"TokenStreamRewriter\");\n\t}\n\tstatic DEFAULT_PROGRAM_NAME = \"default\";\n\tstatic PROGRAM_INIT_SIZE = 100;\n\tstatic MIN_TOKEN_INDEX = 0;\n\t/** Our source stream */\n\ttokens;\n\t/**\n\t* You may have multiple, named streams of rewrite operations.\n\t*  I'm calling these things \"programs.\"\n\t*  Maps String (name) -> rewrite (List)\n\t*/\n\tprograms = /* @__PURE__ */ new Map();\n\t/** Map String (program name) -> Integer index */\n\tlastRewriteTokenIndexes;\n\t/**\n\t* @param tokens The token stream to modify\n\t*/\n\tconstructor(tokens) {\n\t\tthis.tokens = tokens;\n\t}\n\tgetTokenStream() {\n\t\treturn this.tokens;\n\t}\n\t/**\n\t* Insert the supplied text after the specified token (or token index)\n\t*/\n\tinsertAfter(tokenOrIndex, text, programName = _TokenStreamRewriter.DEFAULT_PROGRAM_NAME) {\n\t\tlet index;\n\t\tif (typeof tokenOrIndex === \"number\") index = tokenOrIndex;\n\t\telse index = tokenOrIndex.tokenIndex;\n\t\tconst rewrites = this.getProgram(programName);\n\t\tconst op = new InsertAfterOp(this.tokens, index, rewrites.length, text);\n\t\trewrites.push(op);\n\t}\n\t/**\n\t* Insert the supplied text before the specified token (or token index)\n\t*/\n\tinsertBefore(tokenOrIndex, text, programName = _TokenStreamRewriter.DEFAULT_PROGRAM_NAME) {\n\t\tlet index;\n\t\tif (typeof tokenOrIndex === \"number\") index = tokenOrIndex;\n\t\telse index = tokenOrIndex.tokenIndex;\n\t\tconst rewrites = this.getProgram(programName);\n\t\tconst op = new InsertBeforeOp(this.tokens, index, rewrites.length, text);\n\t\trewrites.push(op);\n\t}\n\t/**\n\t* Replace the specified token with the supplied text\n\t*/\n\treplaceSingle(tokenOrIndex, text, programName = _TokenStreamRewriter.DEFAULT_PROGRAM_NAME) {\n\t\tthis.replace(tokenOrIndex, tokenOrIndex, text, programName);\n\t}\n\t/**\n\t* Replace the specified range of tokens with the supplied text.\n\t*/\n\treplace(from, to, text, programName = _TokenStreamRewriter.DEFAULT_PROGRAM_NAME) {\n\t\tif (typeof from !== \"number\") from = from.tokenIndex;\n\t\tif (typeof to !== \"number\") to = to.tokenIndex;\n\t\tif (from > to || from < 0 || to < 0 || to >= this.tokens.size) throw new RangeError(`replace: range invalid: ${from}..${to}(size=${this.tokens.size})`);\n\t\tconst rewrites = this.getProgram(programName);\n\t\tconst op = new ReplaceOp(this.tokens, from, to, rewrites.length, text);\n\t\trewrites.push(op);\n\t}\n\t/**\n\t* Delete the specified range of tokens\n\t*/\n\tdelete(from, to, programName = _TokenStreamRewriter.DEFAULT_PROGRAM_NAME) {\n\t\tif (to == null) to = from;\n\t\tthis.replace(from, to, null, programName);\n\t}\n\tgetProgram(name) {\n\t\tlet is = this.programs.get(name);\n\t\tif (is == null) is = this.initializeProgram(name);\n\t\treturn is;\n\t}\n\tinitializeProgram(name) {\n\t\tconst is = [];\n\t\tthis.programs.set(name, is);\n\t\treturn is;\n\t}\n\t/**\n\t* @returns the text from the original tokens altered per the instructions given to this rewriter\n\t*/\n\tgetText(intervalOrProgram, programName = _TokenStreamRewriter.DEFAULT_PROGRAM_NAME) {\n\t\tlet interval;\n\t\tif (intervalOrProgram instanceof Interval) interval = intervalOrProgram;\n\t\telse interval = new Interval(0, this.tokens.size - 1);\n\t\tif (typeof intervalOrProgram === \"string\") programName = intervalOrProgram;\n\t\tconst rewrites = this.programs.get(programName);\n\t\tlet start = interval.start;\n\t\tlet stop = interval.stop;\n\t\tif (stop > this.tokens.size - 1) stop = this.tokens.size - 1;\n\t\tif (start < 0) start = 0;\n\t\tif (rewrites == null || rewrites.length === 0) return this.tokens.getTextFromInterval(new Interval(start, stop));\n\t\tconst buf = [];\n\t\tconst indexToOp = this.reduceToSingleOperationPerIndex(rewrites);\n\t\tlet i = start;\n\t\twhile (i <= stop && i < this.tokens.size) {\n\t\t\tconst op = indexToOp.get(i);\n\t\t\tindexToOp.delete(i);\n\t\t\tconst t = this.tokens.get(i);\n\t\t\tif (op == null) {\n\t\t\t\tif (t.type !== Token.EOF) buf.push(String(t.text));\n\t\t\t\ti++;\n\t\t\t} else i = op.execute(buf);\n\t\t}\n\t\tif (stop === this.tokens.size - 1) {\n\t\t\tfor (const op of indexToOp.values()) if (op && op.index >= this.tokens.size - 1) buf.push(String(op.text));\n\t\t}\n\t\treturn buf.join(\"\");\n\t}\n\t/**\n\t* @returns a map from token index to operation\n\t*/\n\treduceToSingleOperationPerIndex(rewrites) {\n\t\tfor (let i = 0; i < rewrites.length; i++) {\n\t\t\tconst op = rewrites[i];\n\t\t\tif (op == null) continue;\n\t\t\tif (!(op instanceof ReplaceOp)) continue;\n\t\t\tconst rop = op;\n\t\t\tconst inserts = this.getKindOfOps(rewrites, InsertBeforeOp, i);\n\t\t\tfor (const iop of inserts) if (iop.index === rop.index) {\n\t\t\t\trewrites[iop.instructionIndex] = null;\n\t\t\t\trop.text = String(iop.text) + (rop.text != null ? rop.text.toString() : \"\");\n\t\t\t} else if (iop.index > rop.index && iop.index <= rop.lastIndex) rewrites[iop.instructionIndex] = null;\n\t\t\tconst prevReplaces = this.getKindOfOps(rewrites, ReplaceOp, i);\n\t\t\tfor (const prevRop of prevReplaces) {\n\t\t\t\tif (prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex) {\n\t\t\t\t\trewrites[prevRop.instructionIndex] = null;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst disjoint = prevRop.lastIndex < rop.index || prevRop.index > rop.lastIndex;\n\t\t\t\tif (prevRop.text == null && rop.text == null && !disjoint) {\n\t\t\t\t\trewrites[prevRop.instructionIndex] = null;\n\t\t\t\t\trop.index = Math.min(prevRop.index, rop.index);\n\t\t\t\t\trop.lastIndex = Math.max(prevRop.lastIndex, rop.lastIndex);\n\t\t\t\t} else if (!disjoint) throw new Error(`replace op boundaries of ${rop} overlap with previous ${prevRop}`);\n\t\t\t}\n\t\t}\n\t\tfor (let i = 0; i < rewrites.length; i++) {\n\t\t\tconst op = rewrites[i];\n\t\t\tif (op == null) continue;\n\t\t\tif (!(op instanceof InsertBeforeOp)) continue;\n\t\t\tconst iop = op;\n\t\t\tconst prevInserts = this.getKindOfOps(rewrites, InsertBeforeOp, i);\n\t\t\tfor (const prevIop of prevInserts) if (prevIop.index === iop.index) {\n\t\t\t\tif (prevIop instanceof InsertAfterOp) {\n\t\t\t\t\tiop.text = this.catOpText(prevIop.text, iop.text);\n\t\t\t\t\trewrites[prevIop.instructionIndex] = null;\n\t\t\t\t} else if (prevIop instanceof InsertBeforeOp) {\n\t\t\t\t\tiop.text = this.catOpText(iop.text, prevIop.text);\n\t\t\t\t\trewrites[prevIop.instructionIndex] = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst prevReplaces = this.getKindOfOps(rewrites, ReplaceOp, i);\n\t\t\tfor (const rop of prevReplaces) {\n\t\t\t\tif (iop.index === rop.index) {\n\t\t\t\t\trop.text = this.catOpText(iop.text, rop.text);\n\t\t\t\t\trewrites[i] = null;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (iop.index >= rop.index && iop.index <= rop.lastIndex) throw new Error(`insert op ${iop} within boundaries of previous ${rop}`);\n\t\t\t}\n\t\t}\n\t\tconst m2 = /* @__PURE__ */ new Map();\n\t\tfor (const op of rewrites) {\n\t\t\tif (op == null) continue;\n\t\t\tif (m2.get(op.index) != null) throw new Error(\"should only be one op per index\");\n\t\t\tm2.set(op.index, op);\n\t\t}\n\t\treturn m2;\n\t}\n\tcatOpText(a, b) {\n\t\tlet x = \"\";\n\t\tlet y = \"\";\n\t\tif (a != null) x = a.toString();\n\t\tif (b != null) y = b.toString();\n\t\treturn x + y;\n\t}\n\t/**\n\t* Get all operations before an index of a particular kind\n\t*/\n\tgetKindOfOps(rewrites, kind, before) {\n\t\treturn rewrites.slice(0, before).filter((op) => {\n\t\t\treturn op && op instanceof kind;\n\t\t});\n\t}\n};\nvar RewriteOperation = class {\n\tstatic {\n\t\t__name(this, \"RewriteOperation\");\n\t}\n\t/** What index into rewrites List are we? */\n\tinstructionIndex;\n\t/** Token buffer index. */\n\tindex;\n\ttext;\n\ttokens;\n\tconstructor(tokens, index, instructionIndex, text) {\n\t\tthis.tokens = tokens;\n\t\tthis.instructionIndex = instructionIndex;\n\t\tthis.index = index;\n\t\tthis.text = text === void 0 ? \"\" : text;\n\t}\n\texecute(_buf) {\n\t\treturn this.index;\n\t}\n\ttoString() {\n\t\treturn \"<RewriteOperation@\" + this.tokens.get(this.index) + \":\\\"\" + this.text + \"\\\">\";\n\t}\n};\nvar InsertBeforeOp = class extends RewriteOperation {\n\tstatic {\n\t\t__name(this, \"InsertBeforeOp\");\n\t}\n\tconstructor(tokens, index, instructionIndex, text) {\n\t\tsuper(tokens, index, instructionIndex, text);\n\t}\n\t/**\n\t* @returns the index of the next token to operate on\n\t*/\n\texecute(buf) {\n\t\tif (this.text) buf.push(this.text.toString());\n\t\tif (this.tokens.get(this.index).type !== Token.EOF) buf.push(String(this.tokens.get(this.index).text));\n\t\treturn this.index + 1;\n\t}\n\ttoString() {\n\t\treturn \"<InsertBeforeOp@\" + this.tokens.get(this.index) + \":\\\"\" + this.text + \"\\\">\";\n\t}\n};\nvar InsertAfterOp = class extends InsertBeforeOp {\n\tstatic {\n\t\t__name(this, \"InsertAfterOp\");\n\t}\n\tconstructor(tokens, index, instructionIndex, text) {\n\t\tsuper(tokens, index + 1, instructionIndex, text);\n\t}\n\ttoString() {\n\t\treturn \"<InsertAfterOp@\" + this.tokens.get(this.index) + \":\\\"\" + this.text + \"\\\">\";\n\t}\n};\nvar ReplaceOp = class extends RewriteOperation {\n\tstatic {\n\t\t__name(this, \"ReplaceOp\");\n\t}\n\tlastIndex;\n\tconstructor(tokens, from, to, instructionIndex, text) {\n\t\tsuper(tokens, from, instructionIndex, text);\n\t\tthis.lastIndex = to;\n\t}\n\t/**\n\t* @returns the index of the next token to operate on\n\t*/\n\texecute(buf) {\n\t\tif (this.text) buf.push(this.text.toString());\n\t\treturn this.lastIndex + 1;\n\t}\n\ttoString() {\n\t\tif (this.text == null) return \"<DeleteOp@\" + this.tokens.get(this.index) + \"..\" + this.tokens.get(this.lastIndex) + \">\";\n\t\treturn \"<ReplaceOp@\" + this.tokens.get(this.index) + \"..\" + this.tokens.get(this.lastIndex) + \":\\\"\" + this.text + \"\\\">\";\n\t}\n};\nvar UnbufferedTokenStream = class {\n\tstatic {\n\t\t__name(this, \"UnbufferedTokenStream\");\n\t}\n\ttokenSource;\n\t/**\n\t* A moving window buffer of the data being scanned. While there's a marker,\n\t* we keep adding to buffer. Otherwise, {@link #consume consume()} resets so\n\t* we start filling at index 0 again.\n\t*/\n\ttokens;\n\t/**\n\t* The number of tokens currently in {@link #tokens tokens}.\n\t*\n\t* This is not the buffer capacity, that's `tokens.length`.\n\t*/\n\tn;\n\t/**\n\t* 0..n-1 index into {@link #tokens tokens} of next token.\n\t*\n\t* The `LT(1)` token is `tokens[p]`. If `p == n`, we are\n\t* out of buffered tokens.\n\t*/\n\tp = 0;\n\t/**\n\t* Count up with {@link #mark mark()} and down with\n\t* {@link #release release()}. When we `release()` the last mark,\n\t* `numMarkers` reaches 0 and we reset the buffer. Copy\n\t* `tokens[p]..tokens[n-1]` to `tokens[0]..tokens[(n-1)-p]`.\n\t*/\n\tnumMarkers = 0;\n\t/**\n\t* This is the `LT(-1)` token for the current position.\n\t*/\n\tlastToken;\n\t/**\n\t* When `numMarkers > 0`, this is the `LT(-1)` token for the\n\t* first token in {@link #tokens}. Otherwise, this is `null`.\n\t*/\n\tlastTokenBufferStart;\n\t/**\n\t* Absolute token index. It's the index of the token about to be read via\n\t* `LT(1)`. Goes from 0 to the number of tokens in the entire stream,\n\t* although the stream size is unknown before the end is reached.\n\t*\n\t* This value is used to set the token indexes if the stream provides tokens\n\t* that implement {@link WritableToken}.\n\t*/\n\tcurrentTokenIndex = 0;\n\tconstructor(tokenSource, bufferSize) {\n\t\tthis.tokenSource = tokenSource;\n\t\tbufferSize = bufferSize ?? 256;\n\t\tthis.tokens = new Array(bufferSize);\n\t\tthis.n = 0;\n\t\tthis.fill(1);\n\t}\n\tget(i) {\n\t\tconst bufferStartIndex = this.getBufferStartIndex();\n\t\tif (i < bufferStartIndex || i >= bufferStartIndex + this.n) throw new Error(\"get(\" + i + \") outside buffer: \" + bufferStartIndex + \"..\" + (bufferStartIndex + this.n));\n\t\treturn this.tokens[i - bufferStartIndex];\n\t}\n\tLT(i) {\n\t\tif (i === -1) return this.lastToken;\n\t\tthis.sync(i);\n\t\tconst index = this.p + i - 1;\n\t\tif (index < 0) throw new Error(\"LT(\" + i + \") gives negative index\");\n\t\tif (index >= this.n) return this.tokens[this.n - 1];\n\t\treturn this.tokens[index];\n\t}\n\tLA(i) {\n\t\treturn this.LT(i).type;\n\t}\n\tgetText() {\n\t\treturn \"\";\n\t}\n\tgetTextFromContext(ctx) {\n\t\treturn this.getTextFromInterval(ctx.getSourceInterval());\n\t}\n\tgetTextFromInterval(interval) {\n\t\tconst bufferStartIndex = this.getBufferStartIndex();\n\t\tconst bufferStopIndex = bufferStartIndex + this.tokens.length - 1;\n\t\tconst start = interval.start;\n\t\tconst stop = interval.stop;\n\t\tif (start < bufferStartIndex || stop > bufferStopIndex) throw new Error(\"interval \" + interval + \" not in token buffer window: \" + bufferStartIndex + \"..\" + bufferStopIndex);\n\t\tconst a = start - bufferStartIndex;\n\t\tconst b = stop - bufferStartIndex;\n\t\tlet result = \"\";\n\t\tfor (let i = a; i <= b; i++) {\n\t\t\tconst t = this.tokens[i];\n\t\t\tresult += t.text;\n\t\t}\n\t\treturn result;\n\t}\n\tgetTextFromRange(start, stop) {\n\t\treturn this.getTextFromInterval(Interval.of(start.tokenIndex, stop.tokenIndex));\n\t}\n\tconsume() {\n\t\tif (this.LA(1) === Token.EOF) throw new Error(\"cannot consume EOF\");\n\t\tthis.lastToken = this.tokens[this.p];\n\t\tif (this.p === this.n - 1 && this.numMarkers === 0) {\n\t\t\tthis.n = 0;\n\t\t\tthis.p = -1;\n\t\t\tthis.lastTokenBufferStart = this.lastToken;\n\t\t}\n\t\tthis.p++;\n\t\tthis.currentTokenIndex++;\n\t\tthis.sync(1);\n\t}\n\t/**\n\t* Return a marker that we can release later.\n\t*\n\t* The specific marker value used for this class allows for some level of\n\t* protection against misuse where `seek()` is called on a mark or\n\t* `release()` is called in the wrong order.\n\t*/\n\tmark() {\n\t\tif (this.numMarkers === 0) this.lastTokenBufferStart = this.lastToken;\n\t\tconst mark = -this.numMarkers - 1;\n\t\tthis.numMarkers++;\n\t\treturn mark;\n\t}\n\trelease(marker) {\n\t\tif (marker !== -this.numMarkers) throw new Error(\"release() called with an invalid marker.\");\n\t\tthis.numMarkers--;\n\t\tif (this.numMarkers === 0) {\n\t\t\tif (this.p > 0) {\n\t\t\t\tthis.tokens.copyWithin(0, this.p, this.n);\n\t\t\t\tthis.n = this.n - this.p;\n\t\t\t\tthis.p = 0;\n\t\t\t}\n\t\t\tthis.lastTokenBufferStart = this.lastToken;\n\t\t}\n\t}\n\tget index() {\n\t\treturn this.currentTokenIndex;\n\t}\n\tseek(index) {\n\t\tif (index === this.currentTokenIndex) return;\n\t\tif (index > this.currentTokenIndex) {\n\t\t\tthis.sync(index - this.currentTokenIndex);\n\t\t\tindex = Math.min(index, this.getBufferStartIndex() + this.n - 1);\n\t\t}\n\t\tconst bufferStartIndex = this.getBufferStartIndex();\n\t\tconst i = index - bufferStartIndex;\n\t\tif (i < 0) throw new Error(\"cannot seek to negative index \" + index);\n\t\telse if (i >= this.n) throw new Error(\"seek to index outside buffer: \" + index + \" not in \" + bufferStartIndex + \"..\" + (bufferStartIndex + this.n));\n\t\tthis.p = i;\n\t\tthis.currentTokenIndex = index;\n\t\tif (this.p === 0) this.lastToken = this.lastTokenBufferStart;\n\t\telse this.lastToken = this.tokens[this.p - 1];\n\t}\n\tget size() {\n\t\tthrow new Error(\"Unbuffered stream cannot know its size\");\n\t}\n\tgetSourceName() {\n\t\treturn this.tokenSource.sourceName;\n\t}\n\tsetLine(line) {\n\t\tthis.tokenSource.line = line;\n\t}\n\tsetColumn(column) {\n\t\tthis.tokenSource.column = column;\n\t}\n\t/**\n\t* Make sure we have 'need' elements from current position {@link #p p}. Last valid\n\t* `p` index is `tokens.length-1`.  `p+need-1` is the tokens index 'need' elements\n\t* ahead.  If we need 1 element, `(p+1-1)==p` must be less than `tokens.length`.\n\t*/\n\tsync(want) {\n\t\tconst need = this.p + want - 1 - this.n + 1;\n\t\tif (need > 0) this.fill(need);\n\t}\n\t/**\n\t* Add `n` elements to the buffer. Returns the number of tokens\n\t* actually added to the buffer. If the return value is less than `n`,\n\t* then EOF was reached before `n` tokens could be added.\n\t*/\n\tfill(n2) {\n\t\tfor (let i = 0; i < n2; i++) {\n\t\t\tif (this.n > 0 && this.tokens[this.n - 1].type === Token.EOF) return i;\n\t\t\tconst t = this.tokenSource.nextToken();\n\t\t\tthis.add(t);\n\t\t}\n\t\treturn n2;\n\t}\n\tadd(t) {\n\t\tif (this.n >= this.tokens.length) this.tokens.length = this.tokens.length * 2;\n\t\tif (isWritableToken(t)) t.setTokenIndex(this.getBufferStartIndex() + this.n);\n\t\tthis.tokens[this.n++] = t;\n\t}\n\tgetBufferStartIndex() {\n\t\treturn this.currentTokenIndex - this.p;\n\t}\n};\n\n//#endregion\nexport { ATN, ATNConfig, ATNConfigSet, ATNDeserializer, ATNSerializer, ATNSimulator, ATNState, AbstractParseTreeVisitor, AbstractPredicateTransition, ActionTransition, ArrayPredictionContext, AtomTransition, BailErrorStrategy, BaseErrorListener, BasicBlockStartState, BasicState, BitSet, BlockEndState, BlockStartState, BufferedTokenStream, CannotInvokeStartRuleError, CharStream, CharStreamImpl, Chunk, CodePointTransitions, CommonToken, CommonTokenFactory, CommonTokenStream, ConsoleErrorListener, DFA, DFASerializer, DFAState, DecisionInfo, DecisionState, DefaultErrorStrategy, DiagnosticErrorListener, DoubleDict, EmptyPredictionContext, EpsilonTransition, ErrorNode, FailedPredicateException, HashMap, HashSet, InputMismatchException, IntStream, InterpreterDataReader, InterpreterRuleContext, Interval, IntervalSet, LL1Analyzer, Lexer, LexerATNConfig, LexerATNSimulator, LexerActionExecutor, LexerActionType, LexerChannelAction, LexerCustomAction, LexerDFASerializer, LexerIndexedCustomAction, LexerInterpreter, LexerModeAction, LexerMoreAction, LexerNoViableAltException, LexerPopModeAction, LexerPushModeAction, LexerSkipAction, LexerTypeAction, ListTokenSource, LoopEndState, MurmurHash, NoViableAltException, NotSetTransition, OrderedATNConfigSet, OrderedHashMap, OrderedHashSet, ParseCancellationException, ParseInfo, ParseTreeMatch, ParseTreePattern, ParseTreePatternMatcher, ParseTreeWalker, Parser, ParserATNSimulator, ParserInterpreter, ParserRuleContext, PlusBlockStartState, PlusLoopbackState, PrecedencePredicateTransition, PredPrediction, PredicateTransition, PredictionContext, PredictionContextCache, PredictionMode, ProfilingATNSimulator, ProxyErrorListener, RangeTransition, RecognitionException, Recognizer, RuleStartState, RuleStopState, RuleTagToken, RuleTransition, RuntimeMetaData, SemanticContext, SetTransition, SingletonPredictionContext, StarBlockStartState, StarLoopEntryState, StarLoopbackState, StartRuleDoesNotConsumeFullPatternError, TagChunk, TerminalNode, TextChunk, Token, TokenStreamRewriter, TokenTagToken, TokensStartState, TraceListener, Transition, Trees, UnbufferedTokenStream, Vocabulary, WildcardTransition, XPath, XPathElement, XPathLexer, XPathLexerErrorListener, XPathRuleAnywhereElement, XPathRuleElement, XPathTokenAnywhereElement, XPathTokenElement, XPathWildcardAnywhereElement, XPathWildcardElement, arrayToString, combineCommonParents, createSingletonPredictionContext, equalArrays, equalNumberArrays, escapeWhitespace, getCachedPredictionContext, isComparable, isToken, isWritableToken, merge, mergeRoot, mergeSingletons, predictionContextFromRuleContext };", "src/Constants.js": "import { DOMImplementation } from \"../vendor/xmldom/dom.js\";\n\n/** @type {Object<string, any>} */\nexport const nodeBase = Object.create(null);\nexport const defaultSolver = JSON.stringify({\n  enabled: false,\n  algorithm: \"RK1\",\n  timeStep: 1\n});\n\n// If we're in a window use the standard doc implementation, otherwise (e.g. node), use xmldom\nlet DI = typeof window === \"undefined\" ? new DOMImplementation() : document.implementation;\n\nlet doc = DI.createDocument(\"\", \"\", null);\n\nnodeBase.text = doc.createElement(\"Text\");\nnodeBase.text.setAttribute(\"name\", \"Text Area\");\nnodeBase.text.setAttribute(\"LabelPosition\", \"Middle\");\n\nnodeBase.folder = doc.createElement(\"Folder\");\nnodeBase.folder.setAttribute(\"name\", \"New Folder\");\nnodeBase.folder.setAttribute(\"Note\", \"\");\nnodeBase.folder.setAttribute(\"Type\", \"None\");\nnodeBase.folder.setAttribute(\"Solver\", defaultSolver);\nnodeBase.folder.setAttribute(\"Image\", \"None\");\nnodeBase.folder.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.folder.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.folder.setAttribute(\"LabelPosition\", \"Middle\");\nnodeBase.folder.setAttribute(\"AgentBase\", \"\");\n\nnodeBase.ghost = doc.createElement(\"Ghost\");\nnodeBase.ghost.setAttribute(\"Source\", \"\");\n\nnodeBase.picture = doc.createElement(\"Picture\");\nnodeBase.picture.setAttribute(\"name\", \"\");\nnodeBase.picture.setAttribute(\"Note\", \"\");\nnodeBase.picture.setAttribute(\"Image\", \"Growth\");\nnodeBase.picture.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.picture.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.picture.setAttribute(\"LabelPosition\", \"Bottom\");\n\nnodeBase.display = doc.createElement(\"Display\");\nnodeBase.display.setAttribute(\"name\", \"Default Display\");\nnodeBase.display.setAttribute(\"Note\", \"\");\nnodeBase.display.setAttribute(\"Type\", \"Time Series\");\nnodeBase.display.setAttribute(\"xAxis\", \"Time (%u)\");\nnodeBase.display.setAttribute(\"yAxis\", \"\");\nnodeBase.display.setAttribute(\"yAxis2\", \"\");\nnodeBase.display.setAttribute(\"showMarkers\", \"false\");\nnodeBase.display.setAttribute(\"showLines\", \"true\");\nnodeBase.display.setAttribute(\"showArea\", \"false\");\nnodeBase.display.setAttribute(\"Primitives\", \"\");\nnodeBase.display.setAttribute(\"Primitives2\", \"\");\nnodeBase.display.setAttribute(\"AutoAddPrimitives\", \"false\");\nnodeBase.display.setAttribute(\"ScatterplotOrder\", \"X Primitive, Y Primitive\");\nnodeBase.display.setAttribute(\"Image\", \"Display\");\nnodeBase.display.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.display.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.display.setAttribute(\"LabelPosition\", \"Bottom\");\n\nfunction setValuedProperties(cell) {\n  cell.setAttribute(\"Units\", \"Unitless\");\n  cell.setAttribute(\"MaxConstraintUsed\", \"false\");\n  cell.setAttribute(\"MinConstraintUsed\", \"false\");\n  cell.setAttribute(\"MaxConstraint\", \"100\");\n  cell.setAttribute(\"MinConstraint\", \"0\");\n  cell.setAttribute(\"ShowSlider\", \"false\");\n  cell.setAttribute(\"SliderMax\", 100);\n  cell.setAttribute(\"SliderMin\", 0);\n  cell.setAttribute(\"SliderStep\", \"\");\n}\n\nnodeBase.stock = doc.createElement(\"Stock\");\nnodeBase.stock.setAttribute(\"name\", \"New Stock\");\nnodeBase.stock.setAttribute(\"Note\", \"\");\nnodeBase.stock.setAttribute(\"InitialValue\", \"0\");\nnodeBase.stock.setAttribute(\"StockMode\", \"Store\");\nnodeBase.stock.setAttribute(\"Delay\", \"10\");\nnodeBase.stock.setAttribute(\"Volume\", \"100\");\nnodeBase.stock.setAttribute(\"NonNegative\", \"false\");\nsetValuedProperties(nodeBase.stock);\nnodeBase.stock.setAttribute(\"Image\", \"None\");\nnodeBase.stock.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.stock.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.stock.setAttribute(\"LabelPosition\", \"Middle\");\n\nnodeBase.state = doc.createElement(\"State\");\nnodeBase.state.setAttribute(\"name\", \"New State\");\nnodeBase.state.setAttribute(\"Note\", \"\");\nnodeBase.state.setAttribute(\"Active\", \"false\");\nnodeBase.state.setAttribute(\"Residency\", \"0\");\nnodeBase.state.setAttribute(\"Image\", \"None\");\nnodeBase.state.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.state.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.state.setAttribute(\"LabelPosition\", \"Middle\");\n\nnodeBase.transition = doc.createElement(\"Transition\");\nnodeBase.transition.setAttribute(\"name\", \"Transition\");\nnodeBase.transition.setAttribute(\"Note\", \"\");\nnodeBase.transition.setAttribute(\"Trigger\", \"Timeout\");\nnodeBase.transition.setAttribute(\"Value\", \"1\");\nnodeBase.transition.setAttribute(\"Repeat\", \"false\");\nnodeBase.transition.setAttribute(\"Recalculate\", \"false\");\nsetValuedProperties(nodeBase.transition);\n\nnodeBase.action = doc.createElement(\"Action\");\nnodeBase.action.setAttribute(\"name\", \"New Action\");\nnodeBase.action.setAttribute(\"Note\", \"\");\nnodeBase.action.setAttribute(\"Trigger\", \"Probability\");\nnodeBase.action.setAttribute(\"Value\", \"0.5\");\nnodeBase.action.setAttribute(\"Repeat\", \"true\");\nnodeBase.action.setAttribute(\"Recalculate\", \"false\");\nnodeBase.action.setAttribute(\"Action\", \"Self.Move({Rand(), Rand()})\");\n\nnodeBase.agents = doc.createElement(\"Agents\");\nnodeBase.agents.setAttribute(\"name\", \"New Agent Population\");\nnodeBase.agents.setAttribute(\"Note\", \"\");\nnodeBase.agents.setAttribute(\"Size\", \"100\");\nnodeBase.agents.setAttribute(\"GeoWrap\", \"false\");\nnodeBase.agents.setAttribute(\"GeoDimUnits\", \"Unitless\");\nnodeBase.agents.setAttribute(\"GeoWidth\", \"200\");\nnodeBase.agents.setAttribute(\"GeoHeight\", \"100\");\nnodeBase.agents.setAttribute(\"Placement\", \"Random\");\nnodeBase.agents.setAttribute(\"PlacementFunction\", \"{Rand()*Width(Self), Rand()*Height(Self)}\");\nnodeBase.agents.setAttribute(\"Network\", \"None\");\nnodeBase.agents.setAttribute(\"NetworkFunction\", \"RandBoolean(0.02)\");\nnodeBase.agents.setAttribute(\"Agent\", \"\");\nnodeBase.agents.setAttribute(\"Image\", \"None\");\nnodeBase.agents.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.agents.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.agents.setAttribute(\"LabelPosition\", \"Middle\");\nnodeBase.agents.setAttribute(\"ShowSlider\", \"false\");\nnodeBase.agents.setAttribute(\"SliderMax\", \"100\");\nnodeBase.agents.setAttribute(\"SliderMin\", \"0\");\nnodeBase.agents.setAttribute(\"SliderStep\", \"1\");\n\nnodeBase.variable = doc.createElement(\"Variable\");\nnodeBase.variable.setAttribute(\"name\", \"New Variable\");\nnodeBase.variable.setAttribute(\"Note\", \"\");\nnodeBase.variable.setAttribute(\"Equation\", \"0\");\nsetValuedProperties(nodeBase.variable);\nnodeBase.variable.setAttribute(\"Image\", \"None\");\nnodeBase.variable.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.variable.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.variable.setAttribute(\"LabelPosition\", \"Middle\");\n\nnodeBase.button = doc.createElement(\"Button\");\nnodeBase.button.setAttribute(\"name\", \"New Button\");\nnodeBase.button.setAttribute(\"Note\", \"\");\nnodeBase.button.setAttribute(\"Function\", \"showMessage(\\\"Button action triggered!\\\\n\\\\nIf you want to edit this Action, click on the button while holding down the Shift key on your keyboard.\\\")\");\nnodeBase.button.setAttribute(\"Image\", \"None\");\nnodeBase.button.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.button.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.button.setAttribute(\"LabelPosition\", \"Middle\");\n\nnodeBase.converter = doc.createElement(\"Converter\");\nnodeBase.converter.setAttribute(\"name\", \"New Converter\");\nnodeBase.converter.setAttribute(\"Note\", \"\");\nnodeBase.converter.setAttribute(\"Source\", \"Time\");\nnodeBase.converter.setAttribute(\"Data\", \"0,0; 1,1; 2,4; 3,9\");\nnodeBase.converter.setAttribute(\"Interpolation\", \"Linear\");\nsetValuedProperties(nodeBase.converter);\nnodeBase.converter.setAttribute(\"Image\", \"None\");\nnodeBase.converter.setAttribute(\"FlipHorizontal\", \"false\");\nnodeBase.converter.setAttribute(\"FlipVertical\", \"false\");\nnodeBase.converter.setAttribute(\"LabelPosition\", \"Middle\");\n\nnodeBase.flow = doc.createElement(\"Flow\");\nnodeBase.flow.setAttribute(\"name\", \"Flow\");\nnodeBase.flow.setAttribute(\"Note\", \"\");\nnodeBase.flow.setAttribute(\"FlowRate\", \"0\");\nnodeBase.flow.setAttribute(\"OnlyPositive\", \"true\");\nnodeBase.flow.setAttribute(\"TimeIndependent\", \"false\");\nsetValuedProperties(nodeBase.flow);\n\nnodeBase.link = doc.createElement(\"Link\");\nnodeBase.link.setAttribute(\"name\", \"Link\");\nnodeBase.link.setAttribute(\"Note\", \"\");\nnodeBase.link.setAttribute(\"BiDirectional\", \"false\");\n\nnodeBase.setting = doc.createElement(\"Setting\");\nnodeBase.setting.setAttribute(\"Note\", \"\");\nnodeBase.setting.setAttribute(\"Version\", \"38\");\nnodeBase.setting.setAttribute(\"Throttle\", \"1\");\nnodeBase.setting.setAttribute(\"TimeLength\", \"100\");\nnodeBase.setting.setAttribute(\"TimeStart\", \"0\");\nnodeBase.setting.setAttribute(\"TimeStep\", \"1\");\nnodeBase.setting.setAttribute(\"TimeUnits\", \"Years\");\nnodeBase.setting.setAttribute(\"Units\", \"\");\nnodeBase.setting.setAttribute(\"SolutionAlgorithm\", \"RK1\");\nnodeBase.setting.setAttribute(\"BackgroundColor\", \"white\");\nnodeBase.setting.setAttribute(\"Macros\", \"\");\nnodeBase.setting.setAttribute(\"SensitivityPrimitives\", \"\");\nnodeBase.setting.setAttribute(\"SensitivityRuns\", \"50\");\nnodeBase.setting.setAttribute(\"SensitivityBounds\", \"50, 80, 95, 100\");\nnodeBase.setting.setAttribute(\"SensitivityShowRuns\", \"false\");\nnodeBase.setting.setAttribute(\"StyleSheet\", \"{}\");\n", "src/SharedTypes.js": "/**\n * @typedef {MaterialType|VectorType|import(\"./Primitives\").SAgent|String|Boolean} VectorElementType\n */\n\n\n/**\n * @typedef {MaterialType|VectorType} ValueType\n */\n\n\n/**\n * @typedef {import(\"./formula/Vector\").Vector} VectorType\n */\n\n\n/**\n * @typedef {import(\"./formula/Material\").Material} MaterialType\n */\n\n\n/**\n * @typedef {InstanceType<mxCell>} GraphNode\n */\n\n\n/**\n * @typedef {\"Timeout\"|\"Probability\"|\"Condition\"} TriggerType\n */\n\n\n/**\n * @typedef {\"Store\"|\"Conveyor\"} StockTypeType\n */\n\n\n/**\n * @typedef {\"Flow\"|\"Link\"|\"Transition\"} PrimitiveConnectorType\n */\n\n\n/**\n * @typedef {\"Stock\"|\"Text\"|\"Button\"|\"Picture\"|\"Converter\"|\"Variable\"|\"State\"|\"Action\"|\"Folder\"|\"Display\"|\"Agents\"|\"Ghost\"} PrimitiveNodeType\n */\n\n\n/**\n * @typedef {PrimitiveNodeType|PrimitiveConnectorType|\"Setting\"} PrimitiveNameType\n */\n\n\n/**\n * @typedef {\"None\"|\"Agent\"} FolderTypeType\n */\n\n\n/**\n * @typedef {\"None\"|\"Custom Function\"} NetworkType\n */\n\n\n/**\n * @typedef {\"Random\"|\"Network\"|\"Grid\"|\"Ellipse\"|\"Custom Function\"} PlacementType\n */\n\nexport {};", "src/Primitives.js": "import { simpleNum, simpleEquation, decodeDNA, linkPrimitive, simpleUnitsTest, setAgentInitialValues, getPrimitiveNeighborhood, validateAgentLocation } from \"./Modeler.js\";\nimport { div, plus, mult, evaluateTree, trimTree, trueValue, lessThanEq, greaterThan, minus, eq, createTree, negate, toNum, lessThan, PARENT_SYMBOL } from \"./formula/Formula.js\";\nimport { Material } from \"./formula/Material.js\";\nimport { convertUnits } from \"./formula/Units.js\";\nimport { Task } from \"./TaskScheduler.js\";\nimport { Rand, RandExp } from \"./formula/Rand.js\";\nimport { Vector } from \"./formula/Vector.js\";\nimport { ModelError } from \"./formula/ModelError.js\";\nimport { sanitizeText } from \"./Utilities.js\";\nimport { stringify } from \"./formula/Utilities.js\";\nimport Big from \"../vendor/bigjs/big.js\";\nimport { fn } from \"./CalcMap.js\";\n\n/** @typedef {import(\"./SharedTypes.js\").ValueType} ValueType */\n/** @typedef {import(\"./SharedTypes.js\").PlacementType} PlacementType */\n/** @typedef {import(\"./SharedTypes.js\").NetworkType} NetworkType */\n\nexport class SPrimitive {\n  /**\n   * @param {import(\"./Simulator\").Simulator} simulate\n   */\n  constructor(simulate) {\n    /** @type {string} */\n    this.id = null;\n\n    /** @type {string} */\n    this.agentId = null;\n\n    /** @type {number} */\n    this.index = null;\n\n    /** @type {number} */\n    this.instanceId = null;\n\n    /** @type {SAgent} */\n    this.container = null;\n\n    this.constructorFunction = null; // is overridden\n\n    /** @type {import(\"./DNA\").DNA} */\n    this.dna = null;\n\n    /** @type {import(\"./DNA\").DNA[]} */\n    this.DNAs = null;\n\n    /** @type {any} */\n    this.equation = null;\n\n    /** @type {ValueType} */\n    this.cachedValue = undefined;\n\n    /** @type {ValueType[]} */\n    this.pastValues = [];\n\n    /** @type {boolean} */\n    this.frozen = false;\n\n    this.simulate = simulate;\n\n    /** @type {Map<import(\"./formula/Units\").UnitStore, number>} */\n    this.unitToVariableUnits = new Map();\n\n    /** @type {SPrimitive} */\n    this.neighborProxyPrimitive = null;\n\n    this.parent = simulate.coreBank.get(\"primitivebase\");\n  }\n\n\n  orig() {\n    return this.neighborProxyPrimitive || this;\n  }\n\n\n  /**\n   * @param {import(\"./formula/Units\").UnitStore} u\n   *\n   * @returns\n   */\n  matchPrimitiveUnits(u) {\n    if (!u) {\n      return 1;\n    }\n\n    if (this.unitToVariableUnits.has(u)) {\n      return this.unitToVariableUnits.get(u);\n    }\n\n    let timer = this.dna.toBase;\n\n\n    if ((this instanceof SFlow) && this.dna.flowUnitless) {\n      timer = fn[\"*\"](timer || 1, this.simulate.timeUnits.toBase);\n    }\n\n    if (!this.dna.units) {\n      if (u.isDeepUnitless()) {\n        this.unitToVariableUnits.set(u, u.toBase);\n        return u.toBase;\n      }\n    }\n\n    u.addBase();\n    timer = fn[\"/\"](u.toBase, timer);\n\n\n    this.unitToVariableUnits.set(u, timer);\n\n    return timer;\n  }\n\n\n\n  clone() {\n    /** @type {SPrimitive} */\n    let p = new this.constructorFunction(this.simulate);\n\n    p.dna = this.dna;\n    p.container = this.container;\n    p.agentId = this.agentId;\n    p.index = this.index;\n    p.id = this.id;\n    p.createIds();\n    p.pastValues = this.pastValues.slice();\n\n\n    p.neighborProxyPrimitive = this.neighborProxyPrimitive;\n\n    if (this.dna.slider) {\n      if (this.simulate.sliders[this.dna.id]) {\n        this.simulate.sliders[this.dna.id].push(p);\n      } else {\n        this.simulate.sliders[this.dna.id] = [p];\n      }\n\n    }\n\n    p.cachedValue = this.cachedValue?.fullClone ? this.cachedValue.fullClone() : this.cachedValue;\n\n    this.innerClone(p);\n\n    return p;\n  }\n\n  innerClone(_p) { }\n\n  clearCached() {\n    this.cachedValue = undefined;\n  }\n\n  storeValue() {\n    if (this.cachedValue === undefined) {\n      this.value();\n    }\n    this.pastValues.push(this.cachedValue);\n  }\n\n  toNum() {\n    let oldPosition = this.simulate.evaluatingPosition;\n    let val = this.value();\n    if (typeof val === \"string\") {\n      this.simulate.evaluatingPosition = oldPosition;\n      // if it is a string, properly stringify it\n      return stringify(val, this.simulate);\n    }\n    this.simulate.evaluatingPosition = oldPosition;\n    return val;\n  }\n\n  /**\n   * @return {ValueType}\n   */\n  calculateValue() {\n    throw new ModelError(`<i>[${sanitizeText(this.dna.name)}]</i> does not have a value and can not be used as a value in an equation.`, {\n      code: 1080\n    });\n  }\n\n  createIds() {\n    this.instanceId = this.simulate.getID(this.agentId + \"-\" + this.index);\n  }\n\n  /**\n   * @param {Material=} length\n   *\n   * @return {ValueType[]}\n   */\n  getPastValues(length) {\n    let items = this.pastValues.slice();\n\n    /* Add current value to array if needed */\n    let bins = Math.ceil(div(this.simulate.time(), this.dna.solver.userTimeStep).value) + 1;\n    if (items.length < bins) {\n      items.push(this.value());\n    }\n\n    let res;\n    if (length === undefined) {\n      res = items.map(x => x.fullClone ? x.fullClone() : x);\n    } else {\n      let bins = Math.ceil(div(length.forceUnits(this.simulate.timeUnits), this.dna.solver.userTimeStep).value);\n\n      res = [];\n      for (let i = Math.max(0, items.length - 1 - bins); i < items.length; i++) {\n        res.push(items[i].fullClone ? items[i].fullClone() : items[i]);\n      }\n    }\n\n    return res;\n  }\n\n  /**\n   * @param {Material} delay\n   * @param {ValueType=} defaultValue\n   *\n   * @returns {ValueType}\n   */\n  pastValue(delay, defaultValue = null) {\n    let periods;\n\n    // check whether we have evaluated the current time period and stored it\n    if (this.pastValues.length - 1 < Math.round((this.simulate.time().value - this.simulate.timeStart.value) / this.dna.solver.userTimeStep.value)) {\n      periods = div(delay.forceUnits(this.simulate.timeUnits), this.dna.solver.userTimeStep).value;\n    } else {\n      periods = div(delay.forceUnits(this.simulate.timeUnits), this.dna.solver.userTimeStep).value + 1;\n    }\n\n\n    if (periods === 0) {\n      return this.value();\n    }\n\n    if (Math.ceil(periods) > this.pastValues.length) {\n      // prior to when we have data, use the default\n      if (defaultValue === null) {\n        if (this.pastValues.length > 0) {\n          return this.pastValues[0].fullClone ? this.pastValues[0].fullClone() : this.pastValues[0];\n        } else {\n          return this.value();\n        }\n      } else {\n        return defaultValue.fullClone ? defaultValue.fullClone() : defaultValue;\n      }\n    }\n\n\n    if (periods === Math.round(periods)) {\n      // we have an exact value get it\n      let x = this.pastValues[this.pastValues.length - periods];\n      return x.fullClone ? x.fullClone() : x;\n    }\n\n\n    // it's between two past values, average them proportionally\n    let fraction = periods - Math.floor(periods);\n    let entry = Math.floor(periods);\n    let firstPeriod, secondPeriod;\n    if (entry === 0) {\n      firstPeriod = this.value();\n    } else {\n      firstPeriod = this.pastValues[this.pastValues.length - entry];\n    }\n    secondPeriod = this.pastValues[this.pastValues.length - 1 - entry];\n\n    return plus(mult(firstPeriod, new Material(1 - fraction)), mult(secondPeriod, new Material(fraction)));\n  }\n\n\n  /**\n   * @param {ValueType} m\n   * @param {boolean=} ignoreFlow\n   */\n  testUnits(m, ignoreFlow) {\n\n    if (m instanceof Vector) {\n      m.recurseApply(x => {\n        this.testUnits(x, ignoreFlow);\n        return x;\n      });\n      return;\n    }\n\n    if (this.dna.adoptUnits) {\n      if (!m.units) {\n        m.units = this.simulate.unitManager.getUnitStore([], [], false, true);\n      }\n\n      this.dna.units = m.units;\n      this.dna.flowUnitless = false;\n    }\n\n    if (!this.dna.units && m.units && m.units.isDeepUnitless()) {\n      m.units.addBase();\n      m.value = m.value * m.units.toBase;\n      m.units = null;\n      m.explicitUnits = true;\n    }\n\n    if (!this.dna.units && m.units && !m.units.isUnitless()) {\n      throw new ModelError(`Wrong units generated for <i>[${sanitizeText(this.dna.name)}]</i>. Expected no units and got <i>${m.units.toString()}</i>. Either specify units for the primitive or adjust the equation.`, {\n        primitive: this.orig(),\n        showEditor: true,\n        code: 1081\n      });\n    } else if (this.dna.units !== m.units) {\n      if (typeof m === \"boolean\" || typeof m === \"string\" || m instanceof String || m instanceof Boolean) {\n        if (!this.dna.units) {\n          return;\n        }\n        throw new ModelError(`Cannot add units to a String or Boolean in <i>[${sanitizeText(this.dna.name)}]</i>.`, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1082\n        });\n      }\n\n      // we allow applying the primitive units onto a unitless value so\n      // the allow unit application is true\n      let scale = convertUnits(m.units, this.dna.units, true);\n\n      if (scale === 0) {\n        throw new ModelError(`Wrong units generated for <i>[${sanitizeText(this.dna.name)}]</i>. Expected <i>${this.dna.units ? this.dna.units.toString() : \"unitless\"}</i>, and got <i>${m.units ? m.units.toString() : \"unitless\"}</i>.`, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1083\n        });\n      } else {\n        m.value = m.value * scale;\n        m.units = this.dna.units;\n        m.explicitUnits = true;\n      }\n    } else if (this.dna.units && this.dna.units === m.units && !m.explicitUnits) {\n      m.explicitUnits = true;\n    }\n\n    if (this instanceof SFlow && ignoreFlow !== true && this.dna.flowUnitless) {\n      let x = mult(m, new Material(1, this.simulate.timeUnits));\n      m.value = x.value;\n      m.units = x.units;\n      m.explicitUnits = true;\n    }\n  }\n\n  setValue(_v) {\n    throw new ModelError(\"You cannot set the value for that primitive.\", {\n      code: 1084\n    });\n  }\n\n  /**\n   * @returns {ValueType}\n   */\n  value() {\n    if (this.cachedValue === undefined && this.frozen && this.pastValues.length > 0) {\n      let v = this.pastValues[this.pastValues.length - 1];\n      if (v.fullClone) {\n        this.cachedValue = v.fullClone();\n      } else {\n        this.cachedValue = v;\n      }\n    }\n\n    if (this.cachedValue === undefined) {\n      if (this.simulate.evaluatedPrimitives.has(this)) {\n        let arrayed = [...this.simulate.evaluatedPrimitives.values()];\n        throw new ModelError(`Circular equation loop identified including the primitives: ${sanitizeText(arrayed.slice(arrayed.indexOf(this)).map(x => x.dna.name).join(\", \"))}`, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1085\n        });\n      }\n      this.simulate.evaluatedPrimitives.add(this);\n\n      let x;\n      try {\n        x = toNum(this.calculateValue());\n        if (x instanceof Material && !isFinite(x.value)) {\n          if (this instanceof SStock) {\n            throw new ModelError(\"The stock has become infinite in size. Check the flows into it for rapid growth.\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1086\n            });\n          } else {\n            throw new ModelError(\"The result of this calculation is not finite (are you dividing by 0?).\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1087\n            });\n          }\n        }\n      } catch (err) {\n        if (err instanceof ModelError) {\n          if (err.primitive && err.showEditor) {\n            throw err; // don't want to override the target primitive\n          }\n          throw new ModelError(err.message, {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1088\n          });\n        } else {\n          throw err;\n        }\n      }\n      if (!(this instanceof SState)) {\n        this.testUnits(x);\n        this.testConstraints(x);\n      }\n\n      this.cachedValue = x;\n    }\n\n\n    if (this.cachedValue instanceof Material) {\n      return new Material(this.cachedValue.value, this.cachedValue.units, this.cachedValue.explicitUnits);\n    }\n    if (this.cachedValue && this.cachedValue.fullClone) {\n      return this.cachedValue.fullClone();\n    }\n    return this.cachedValue;\n  }\n\n  testConstraints(x) {\n    let test = (x) => {\n      if (this.dna.useMaxConstraint && x.value > this.dna.maxConstraint) {\n        constraintAlert(this, \"max\", x, this.simulate);\n      }\n      if (this.dna.useMinConstraint && x.value < this.dna.minConstraint) {\n        constraintAlert(this, \"min\", x, this.simulate);\n      }\n      return x;\n    };\n    if (x instanceof Vector) {\n      x.recurseApply(test);\n    } else {\n      test(x);\n    }\n  }\n\n  /**\n   * @param {any} tree\n   * @param {Map} neighborhood\n   */\n  setEquation(tree, neighborhood) {\n\n    try {\n      this.equation = trimTree(tree, neighborhood, this.simulate);\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1089\n        });\n      } else {\n        throw err;\n      }\n    }\n  }\n}\n\n\nexport class Placeholder extends SPrimitive {\n  /**\n   * @param {import(\"./DNA\").DNA} dna\n   * @param {SPrimitive | SPopulation} primitive\n   * @param {import(\"./Simulator\").Simulator} simulate\n   */\n  constructor(dna, primitive, simulate) {\n    super(simulate);\n\n    /** @type {import(\"./DNA\").DNA} */\n    this.dna = dna;\n    /** @type {string} */\n    this.id = dna.id;\n    /** @type {SPrimitive | SPopulation} */\n    this.primitive = primitive;\n  }\n\n  // @ts-ignore\n  calculateValue() {\n    throw new ModelError(`<i>[${sanitizeText(this.dna.name)}]</i> is a placeholder and cannot be used as a direct value in equations.`, {\n      primitive: this.primitive.dna.primitive,\n      showEditor: true,\n      code: 1091\n    });\n  }\n}\n\n\nexport class SState extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n    /** @type {boolean} */\n    this.active = null;\n\n    /** @type {STransition[]} */\n    this.downStreamTransitions = [];\n\n    this.constructorFunction = SState;\n  }\n\n\n  innerClone(p) {\n    p.setValue(this.active);\n  }\n\n  /**\n   * @param {Material|Vector} value\n   */\n  setValue(value) {\n    this.setActive(trueValue(value));\n    this.cachedValue = undefined;\n    // so recursive warning is not triggered\n    this.simulate.evaluatedPrimitives.clear();\n    this.value();\n    if (this.agentId) {\n      this.container.updateStates();\n    }\n  }\n\n  calculateValue() {\n    if (this.active === null) {\n      this.setInitialActive(true);\n    }\n\n    if (this.active) {\n      return new Material(1);\n    } else {\n      return new Material(0);\n    }\n\n  }\n\n  /**\n   * @param {boolean=} suppress\n   */\n  setInitialActive(suppress) {\n    let init;\n\n    try {\n      init = toNum(evaluateTree(this.equation, localVars(this, this.simulate), this.simulate));\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1092\n        });\n      } else {\n        throw err;\n      }\n    }\n\n    this.setActive(trueValue(init), suppress);\n    if (this.agentId) {\n      this.container.updateStates();\n    }\n\n  }\n\n  setActive(active, suppress) {\n    this.active = active;\n\n    if (!active || this.dna.residency === null) {\n      if (!suppress) {\n        if (active) {\n          if (!this.simulate.transitionPrimitives) {\n            this.simulate.transitionPrimitives = [];\n          }\n\n          if (this.simulate.transitionPrimitives.length > 1200 && this.simulate.transitionPrimitives.includes(this)) {\n            throw new ModelError(`Circular fully active transition loop identified including the states: ${sanitizeText(this.simulate.transitionPrimitives.slice(0, 5).map(x => \"[\" + x.dna.name + \"]\").join(\", \"))}`, {\n              code: 1105\n            });\n          }\n          this.simulate.transitionPrimitives.push(this);\n        }\n\n        for (let transition of this.downStreamTransitions) {\n          scheduleTrigger.call(transition);\n        }\n\n        if (active) {\n          this.simulate.transitionPrimitives = [];\n        }\n\n      }\n    } else {\n      this.simulate.tasks.add(new Task({\n        name: \"State Residency\",\n        time: plus(this.simulate.time(), this.dna.residency),\n        priority: 5,\n        expires: 1,\n        action: (_task) => {\n          for (let transition of this.downStreamTransitions) {\n            scheduleTrigger.call(transition);\n          }\n        }\n      }));\n    }\n\n  }\n\n  /**\n   * @returns {boolean}\n   */\n  getActive() {\n    if (this.active === null) {\n      this.setInitialActive(true);\n    }\n    return this.active;\n  }\n}\n\n\nexport class STransition extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n    /** @type {SState} */\n    this.alpha = null;\n\n    /** @type {SState} */\n    this.omega = null;\n\n    /** @type {Task} */\n    this.scheduledTrigger = null;\n\n    this.initialized = false;\n\n    this.constructorFunction = STransition;\n  }\n\n  innerClone() { }\n\n  /**\n   * @param {SState} alpha\n   * @param {SState} omega\n   */\n  setEnds(alpha, omega) {\n    this.alpha = alpha;\n    this.omega = omega;\n    if (alpha) {\n      alpha.downStreamTransitions.push(this);\n    }\n  }\n\n  /**\n   * @returns {boolean}\n   */\n  canTrigger() {\n    return !this.alpha || (this.alpha && this.alpha.getActive()) || (this.dna.repeat && this.dna.trigger !== \"Condition\");\n  }\n\n  trigger() {\n    this.scheduledTrigger = null;\n\n    if (this.frozen) {\n      return;\n    }\n\n    if (this.alpha) {\n      this.alpha.setActive(false);\n    }\n    if (this.omega) {\n      this.omega.setActive(true);\n    }\n    if (this.agentId) {\n      this.container.updateStates();\n    }\n    if (this.dna.repeat && this.dna.trigger !== \"Condition\") {\n      scheduleTrigger.call(this);\n    }\n  }\n}\n\n\n/**\n * @this {STransition|SAction}\n */\nfunction scheduleTrigger() {\n  updateTrigger.call(this, true);\n}\n\n\n/**\n * @this {STransition|SAction}\n *\n * @param {boolean=} force\n */\nfunction clearTrigger(force) {\n  if (this.scheduledTrigger && (force || !this.dna.repeat)) {\n    this.scheduledTrigger.kill();\n    this.scheduledTrigger = null;\n  }\n}\n\n\n/**\n * @this {STransition|SAction}\n *\n * @param {boolean=} clear\n */\nexport function updateTrigger(clear) {\n  this.initialized = true;\n\n  if (clear) {\n    clearTrigger.call(this);\n  }\n\n\n  if (this.canTrigger()) {\n    let v;\n    try {\n      v = toNum(evaluateTree(this.equation, localVars(this, this.simulate), this.simulate));\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: false,\n          code: 1090\n        });\n      } else {\n        throw err;\n      }\n    }\n\n    try {\n      if (this.dna.trigger === \"Condition\") {\n        if (trueValue(v)) {\n          this.trigger();\n        }\n      } else {\n        if (!(v instanceof Material)) {\n          throw new ModelError(`The value of this trigger must evaluate to a number. Got <i>${sanitizeText(\"\" + v)}</i>.`, {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1112\n          });\n        }\n\n        /** @type {Material} */\n        let t;\n\n        if (this.dna.trigger === \"Timeout\") {\n\n          if (!v.units) {\n            verifyValuedType(v, this);\n\n            v.units = this.simulate.timeUnits;\n          } else {\n            v.units.addBase();\n            let base = /** @type {import(\"./formula/Units\").UnitStore} */ (v.units.baseUnits);\n            if (base.names.length !== 1 || base.names[0] !== \"seconds\" || base.exponents[0] !== 1) {\n              throw new ModelError(`A trigger Timeout must have units of time, got <i>${v.units.toString()}</i>.`, {\n                primitive: this.orig(),\n                showEditor: true,\n                code: 1113\n              });\n            }\n          }\n\n          if (this.scheduledTrigger && eq(v, this.scheduledTrigger.data.value)) {\n            return;\n          }\n\n          if (v.value === 0) {\n            if (this.dna.repeat) {\n              throw new ModelError(\"A trigger Timeout of 0 with 'Repeat' set to true results in an infinite loop.\", {\n                primitive: this.orig(),\n                showEditor: true,\n                code: 1114\n              });\n            } else {\n              this.trigger();\n              return;\n            }\n          }\n\n\n          if (v.value < 0) {\n            throw new ModelError(\"The timeout for a transition cannot be less than 0.\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1115\n            });\n          }\n\n          if (isNaN(v.value)) {\n            throw new ModelError(\"The timeout for the transition is not a valid number.\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1116\n            });\n          }\n\n          t = v;\n\n        } else if (this.dna.trigger === \"Probability\") {\n          if (v.units && !v.units.isUnitless()) {\n            throw new ModelError(`The probability for the trigger had units of <i>${v.units.toString()}</i>. Probabilities must be unitless.`, {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1121\n            });\n          }\n\n          if (isNaN(v.value)) {\n            throw new ModelError(\"The probability for the transition is not a valid number.\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1117\n            });\n          }\n\n          v = v.value;\n          if (this.scheduledTrigger && eq(v, this.scheduledTrigger.data.value)) {\n            return;\n          }\n\n          if (v === 1) {\n            if (this.dna.repeat) {\n              throw new ModelError(\"A trigger probability of 1 with 'Repeat' as true results in an infinite loop.\", {\n                primitive: this.orig(),\n                showEditor: true,\n                code: 1118\n              });\n            } else {\n              this.trigger();\n              return;\n            }\n          } else if (v > 1) {\n            throw new ModelError(\"The probability for the trigger must be less than or equal to 1.\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1119\n            });\n          } else if (v < 0) {\n            throw new ModelError(\"The probability for the trigger must be greater than or equal to 0.\", {\n              primitive: this.orig(),\n              showEditor: true,\n              code: 1120\n            });\n          } else if (v === 0) {\n            if (!this.scheduledTrigger) {\n              return;\n            }\n          } else {\n            // v is the probability of at least one event happening in the time period\n            // we use the exponential distribution to determine the time until the next event\n            let l = -Math.log1p(-v);\n            t = new Material(RandExp(this.simulate, l), this.simulate.timeUnits);\n          }\n\n        }\n\n        let start = this.simulate.time();\n\n        if (this.scheduledTrigger) {\n          this.scheduledTrigger.kill();\n          if (this.dna.trigger === \"Timeout\") {\n            if (lessThanEq(t, minus(this.simulate.time(), this.scheduledTrigger.data.start))) {\n              this.scheduledTrigger = null;\n              this.trigger();\n              return;\n            } else {\n              start = this.scheduledTrigger.data.start;\n              t = minus(t, minus(this.simulate.time(), start));\n              this.scheduledTrigger = null;\n            }\n          } else if (this.dna.trigger === \"Probability\") {\n            if (v === 0) {\n              this.scheduledTrigger = null;\n              return;\n            }\n            t = minus(this.scheduledTrigger.time, this.simulate.time());\n\n            let v0 = this.scheduledTrigger.data.value;\n            if (v0 !== v) {\n              let l0 = -Math.log1p(-v0);\n              let l = -Math.log1p(-v);\n\n              t = mult(t, new Material(l0 / l));\n            }\n\n            start = this.scheduledTrigger.data.start;\n\n            this.scheduledTrigger = null;\n          }\n        }\n\n        if (isNaN(t.value)) {\n          throw new ModelError(\"The time until activation is not a valid number.\", {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1122\n          });\n        }\n\n        t = plus(t, this.simulate.time());\n\n        this.scheduledTrigger = new Task({\n          name: \"Trigger\",\n          time: t,\n          priority: 5,\n          expires: 1,\n          action: (_task) => {\n            this.trigger();\n          },\n          data: { start: start, value: v }\n        });\n\n        this.simulate.tasks.add(this.scheduledTrigger);\n\n      }\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1094\n        });\n      } else {\n        throw err;\n      }\n    }\n  }\n}\n\n\nexport class SAction extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n\n    /** @type {any} */\n    this.action = null;\n\n    /** @type {Task} */\n    this.scheduledTrigger = null;\n\n    /** @type {boolean} */\n    this.block = false;\n\n    this.initialized = false;\n\n    this.constructorFunction = SAction;\n  }\n\n  innerClone() { }\n\n  /**\n   * @returns {boolean}\n   */\n  canTrigger() {\n    return !this.block;\n  }\n\n  resetTimer() {\n    scheduleTrigger.call(this);\n  }\n\n  trigger() {\n    this.scheduledTrigger = null;\n\n    if (this.frozen) {\n      return;\n    }\n\n    try {\n      evaluateTree(this.action, localVars(this, this.simulate), this.simulate);\n\n      if (this.dna.repeat) {\n        if (this.dna.trigger !== \"Condition\") {\n          scheduleTrigger.call(this);\n        }\n      } else {\n        this.block = true;\n      }\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1096\n        });\n      } else {\n        throw err;\n      }\n    }\n  }\n}\n\nexport class SPopulation extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n\n    /** @type {number} */\n    this.size = null;\n    /** @type {SAgent[]} */\n    this.agents = null;\n    /** @type {Material} */\n    this.geoWidth = null;\n    /** @type {Material} */\n    this.geoHeight = null;\n    /** @type {Material} */\n    this.halfWidth = null;\n    /** @type {Material} */\n    this.halfHeight = null;\n    /** @type {string} */\n    this.geoDimUnits = null;\n    /** @type {import('./formula/Units').UnitStore} */\n    this.geoDimUnitsObject = null;\n    /** @type {boolean} */\n    this.geoWrap = null;\n    /** @type {import(\"./DNA\").DNA[]} */\n    this.DNAs = null;\n    /** @type {Set<string>} */\n    this.stateIds = new Set();\n    /** @type {PlacementType} */\n    this.placement = undefined;\n    /** @type {string} */\n    this.placementFunction = undefined;\n    /** @type {NetworkType} */\n    this.network = undefined;\n    /** @type {string} */\n    this.networkFunction = undefined;\n    /** @type {any} */\n    this.agentBase = undefined;\n\n    this.constructorFunction = SPopulation;\n\n    this.vector = new Vector([], simulate, [], simulate.coreBank.get(\"primitivebase\"));\n  }\n\n  collectData() {\n    let x = [];\n    for (let agent of this.agents) {\n      x.push({\n        instanceId: agent.instanceId,\n        connected: agent.connected.map(x => x.instanceId),\n        location: simpleNum(agent.location.clone(), this.geoDimUnitsObject, this.simulate),\n        state: agent.states.length > 0 ? agent.states.slice() : null\n      });\n    }\n    return x;\n  }\n\n  /**\n   * @returns {Set<string>}\n   */\n  states() {\n    return this.stateIds;\n  }\n\n  /**\n   * @returns {Material}\n   */\n  toNum() {\n    throw new ModelError(`<i>[${sanitizeText(this.dna.name)}]</i> is a population of agents and cannot be used as a direct value in equations.`, {\n      code: 1107\n    });\n  }\n\n  /**\n   * @param {SAgent=} base\n   * @returns\n   */\n  add(base) {\n    this.size = 1 + this.size;\n    /** @type {SAgent} */\n    let agent;\n\n    if (base) {\n      agent = base.agentClone();\n      agent.agentId = this.agentId;\n      agent.setIndex(this.size - 1);\n      agent.createAgentIds();\n\n      for (let i = 0; i < this.DNAs.length; i++) {\n        let x = agent.children[i];\n        let dna = this.DNAs[i];\n\n        x.container = agent;\n\n        linkPrimitive(x, dna, this.simulate);\n      }\n\n      agent.updateStates();\n\n    } else {\n      agent = new SAgent(this.simulate);\n      agent.container = this;\n      agent.children = [];\n      agent.childrenId = {};\n      agent.agentId = this.agentId;\n\n      for (let dna of this.DNAs) {\n        decodeDNA(dna, agent, this.simulate, true);\n      }\n\n      agent.setIndex(this.size - 1);\n      agent.createAgentIds();\n\n      for (let i = 0; i < this.DNAs.length; i++) {\n        linkPrimitive(agent.children[i], this.DNAs[i], this.simulate);\n      }\n\n      setAgentInitialValues(agent);\n\n      let neighbors = getPrimitiveNeighborhood(this, this.dna, this.simulate, []);\n\n      if (this.placement === \"Custom Function\") {\n        // @ts-ignore - Agent is equivalent to Primitive for this use case\n        neighbors.set(\"self\", agent);\n        // @ts-ignore\n        agent.location = simpleUnitsTest(/** @type {Vector} */(simpleEquation(this.placementFunction, this.simulate, new Map([\n          [PARENT_SYMBOL, this.simulate.varBank],\n          [\"self\", agent]\n        ]), neighbors)), this.geoDimUnitsObject, this.simulate, null, null, \"Agent placement functions must return a two element vector\");\n\n        validateAgentLocation(agent.location, this);\n\n        if (!agent.location.names) {\n          agent.location.names = [\"x\", \"y\"];\n          agent.location.namesLC = [\"x\", \"y\"];\n        }\n      } else {\n        agent.location = new Vector([mult(this.geoWidth, new Material(Rand(this.simulate))), mult(this.geoHeight, new Material(Rand(this.simulate)))], this.simulate, [\"x\", \"y\"]);\n      }\n      if (this.network === \"Custom Function\") {\n        let tree = trimTree(createTree(this.networkFunction, \"p:\" + this.id + \":networkFunction\", this.simulate), neighbors, this.simulate);\n        for (let a of this.agents) {\n          if (agent !== a) {\n            // @ts-ignore\n            if (trueValue(simpleEquation(this.networkFunction, this.simulate, new Map([\n              [PARENT_SYMBOL, this.simulate.varBank],\n              [\"a\", agent],\n              [\"b\", a]\n            ]), neighbors, tree))) {\n              agent.connect(a);\n            }\n          }\n        }\n      }\n    }\n\n    this.simulate.tasks.add(new Task({\n      priority: 10,\n      expires: 1,\n      name: \"Add Agent\",\n      time: this.simulate.time(),\n      action: (_task) => {\n        this.agents.push(agent);\n\n        for (let i = 0; i < agent.children.length; i++) {\n          let x = agent.children[i];\n\n          let dna = this.DNAs[i];\n\n          if (x instanceof SAction || x instanceof STransition) {\n            if (dna.trigger !== \"Condition\") {\n              scheduleTrigger.call(x);\n            }\n          }\n\n          if (base) {\n            if (x instanceof SAction) {\n              dna.solver.actions.push(x);\n            } else if (x instanceof STransition) {\n              dna.solver.transitions.push(x);\n            } else if (!(x instanceof SPopulation)) {\n              dna.solver.valued.push(x);\n              if (x instanceof SFlow) {\n                dna.solver.flows.push(x);\n              } else if (x instanceof SStock) {\n                dna.solver.stocks.push(x);\n              } else if (x instanceof SState) {\n                dna.solver.states.push(x);\n              }\n            }\n          }\n\n\n        }\n\n\n      }\n    }));\n\n    return agent;\n  }\n}\n\n\nexport class SAgent {\n  constructor(simulate) {\n    /** @type {string} */\n    this.agentId = null;\n\n    /** @type {string} */\n    this.instanceId = null;\n\n    /** @type {number} */\n    this.index = null;\n\n    /** @type {SPrimitive[]} */\n    this.children = null;\n\n    /** @type {Vector<Material>} */\n    this.location = null;\n\n    /** @type {SAgent[]} */\n    this.connected = [];\n\n    /** @type {Material[]} */\n    this.connectedWeights = [];\n\n    /** @type {boolean} */\n    this.dead = false;\n\n    this.constructorFunction = SAgent;\n\n    /** @type {Set<string>} */\n    this.stateIDs = new Set();\n\n    /** @type {SState[]} */\n    this.states = [];\n\n    /** @type {Partial<SPopulation>} */\n    this.container = undefined;\n\n    /** @type {import(\"./DNA\").DNA} */\n    this.dna = undefined;\n\n    /** @type {Object<string, SPrimitive>} */\n    this.childrenId = undefined;\n\n    this.simulate = simulate;\n\n    this.vector = new Vector([], simulate, [], simulate.coreBank.get(\"agentbase\"));\n  }\n\n  createIds() {\n    // same as Primitive\n    this.instanceId = this.simulate.getID(this.agentId + \"-\" + this.index);\n  }\n\n  /**\n   * @returns {string}\n   */\n  toString() {\n    return \"Agent \" + (this.index + 1);\n  }\n\n  toNum() {\n    return this;\n  }\n\n  updateStates() {\n    this.states = [];\n    this.stateIDs = new Set();\n    for (let child of this.children) {\n      if (child instanceof SState) {\n        if (child.active) {\n          this.states.push(child);\n          this.stateIDs.add(child.dna.id);\n        }\n      }\n    }\n  }\n\n  /**\n   * @returns {SAgent}\n   */\n  agentClone() {\n    let agent = new SAgent(this.simulate);\n    agent.dna = this.dna;\n    agent.children = [];\n    agent.childrenId = {};\n\n    for (let child of this.children) {\n      let newChild = child.clone();\n      agent.children.push(newChild);\n      agent.childrenId[child.dna.id] = newChild;\n    }\n\n    agent.location = this.location.clone();\n    agent.connected = this.connected.slice();\n    agent.connectedWeights = this.connectedWeights.slice();\n    agent.container = this.container;\n\n\n    return agent;\n  }\n\n  /**\n   * @param {number} index\n   */\n  setIndex(index) {\n    this.index = index;\n    for (let child of this.children) {\n      child.index = index;\n    }\n  }\n\n  createAgentIds() {\n    this.createIds();\n    for (let child of this.children) {\n      child.createIds();\n    }\n  }\n\n  die() {\n    while (this.connected.length > 0) {\n      this.unconnect(this.connected[0]);\n    }\n\n    for (let i = 0; i < this.container.agents.length; i++) {\n      if (this.container.agents[i] === this) {\n        this.container.agents.splice(i, 1);\n        break;\n      }\n    }\n\n    for (let child of this.children) {\n      let solver = child.dna.solver;\n      if (child instanceof SAction) {\n        solver.actions.splice(solver.actions.indexOf(child), 1);\n        clearTrigger.call(child, true);\n      } else if (child instanceof STransition) {\n        solver.transitions.splice(solver.transitions.indexOf(child), 1);\n        clearTrigger.call(child, true);\n      } else if (!(child instanceof SPopulation)) {\n        solver.valued.splice(solver.valued.indexOf(child), 1);\n        if (child instanceof SFlow) {\n          solver.flows.splice(solver.flows.indexOf(child), 1);\n        } else if (child instanceof SStock) {\n          solver.stocks.splice(solver.stocks.indexOf(child), 1);\n        } else if (child instanceof SState) {\n          solver.states.splice(solver.states.indexOf(child), 1);\n        }\n      }\n    }\n\n\n    this.dead = true;\n  }\n\n  /**\n   * @param {SAgent} x\n   * @param {Material=} weight\n   */\n  connect(x, weight) {\n    let w = weight === undefined ? new Material(1) : weight;\n    if (x !== this) {\n      if (!this.connected.includes(x)) {\n        if (x instanceof SAgent) {\n          this.connected.push(x);\n          this.connectedWeights.push(w);\n          x.connected.push(this);\n          x.connectedWeights.push(w);\n        } else {\n          throw new ModelError(\"Only agents may be connected.\", {\n            code: 1106\n          });\n        }\n      } else if (weight !== undefined) {\n        this.connectedWeights[this.connected.indexOf(x)] = weight;\n        x.connectedWeights[x.connected.indexOf(this)] = weight;\n      }\n    }\n\n  }\n\n  /**\n   * @param {SAgent} x\n   */\n  unconnect(x) {\n    if (x !== this) {\n      let i = this.connected.indexOf(x);\n      if (i !== -1) {\n        this.connected.splice(i, 1);\n        this.connectedWeights.splice(i, 1);\n        i = x.connected.indexOf(this);\n        x.connected.splice(i, 1);\n        x.connectedWeights.splice(i, 1);\n      }\n    }\n  }\n\n  /**\n   * @param {SAgent} x\n   * @returns {Material}\n   */\n  connectionWeight(x) {\n    if (x !== this) {\n      let i = this.connected.indexOf(x);\n\n      if (i !== -1) {\n        return this.connectedWeights[i].fullClone();\n      }\n    }\n    throw new ModelError(\"Agents are not connected and so do not have a connection weight.\", {\n      code: 1108\n    });\n  }\n\n\n  /**\n   * @param {SAgent} x\n   * @param {Material} w\n   */\n  setConnectionWeight(x, w) {\n    let set = false;\n    if (x !== this) {\n      let i = this.connected.indexOf(x);\n      if (i !== -1) {\n        set = true;\n        this.connectedWeights[i] = w.fullClone();\n      }\n      let j = x.connected.indexOf(this);\n      if (j !== -1) {\n        set = true;\n        x.connectedWeights[j] = w.fullClone();\n      }\n    }\n    if (!set) {\n      throw new ModelError(\"Agents are not connected and so do not have a connection weight.\", {\n        code: 1109\n      });\n    }\n  }\n}\n\n\nfunction verifyValuedType(x, primitive) {\n  if (x instanceof Vector || x instanceof Material) {\n    // pass\n    return;\n  }\n\n  throw new ModelError(`This value may only be numbers or vectors, found a ${typeof x}.`, {\n    primitive: primitive,\n    showEditor: false,\n    code: 1110\n  });\n}\n\n\nexport class SStock extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n\n    /** @type {ValueType} */\n    this.level = null;\n    this.constructorFunction = SStock;\n    /** @type {Material} */\n    this.delay = undefined;\n    /** @type {Task[]} */\n    this.tasks = [];\n    /** @type {ValueType} */\n    this.initRate = null;\n    /** @type {ValueType} */\n    this.oldLevel = null;\n  }\n\n  innerClone(p) {\n    p.level = this.level.fullClone();\n    p.oldLevel = this.oldLevel?.fullClone();\n    p.tasks = this.tasks.slice();\n    p.delay = this.delay?.fullClone();\n  }\n\n  /**\n   * @param {Material|Vector} value\n   */\n  setValue(value) {\n    this.level = value;\n    this.cachedValue = undefined;\n    // so recursive warning is not triggered\n    this.simulate.evaluatedPrimitives.clear();\n    this.value();\n  }\n\n\n  preserveLevel() {\n    for (let i = this.tasks.length - 1; i >= 0; i--) {\n      this.tasks[i].data.tentative = false;\n    }\n    this.oldLevel = this.level;\n  }\n\n  restoreLevel() {\n    for (let i = this.tasks.length - 1; i >= 0; i--) {\n      if (this.tasks[i].data.tentative) {\n        this.tasks[i].remove();\n        this.tasks.splice(i, 1);\n      }\n    }\n    this.level = this.oldLevel;\n  }\n\n  /**\n   * @param {Material=} delay\n   */\n  setDelay(delay) {\n    delay = delay || this.dna.delay;\n    this.delay = delay;\n    if (this.delay?.value === 0) {\n      // if the delay is 0, treat it as if there was no delay\n      this.delay = undefined;\n    }\n  }\n\n  setInitialValue() {\n    /** @type {ValueType} */\n    let init;\n\n    try {\n      init = toNum(evaluateTree(this.equation, localVars(this, this.simulate), this.simulate));\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1098\n        });\n      } else {\n        throw err;\n      }\n    }\n\n    if (typeof init === \"boolean\") {\n      if (init) {\n        init = new Material(1);\n      } else {\n        init = new Material(0);\n      }\n    }\n\n    if (init instanceof Vector) {\n      let d = this.dna;\n      init.recurseApply((x) => {\n        verifyValuedType(x);\n\n        if (d.nonNegative && x.value < 0) {\n          x = new Material(0, d.units);\n        }\n        if (!x.units) {\n          x.units = d.units;\n        }\n        return x;\n      });\n    } else {\n      verifyValuedType(init);\n\n      if (this.dna.nonNegative && init.value < 0) {\n        init = new Material(0, this.dna.units);\n      }\n      if (!init.units) {\n        init.units = this.dna.units;\n        init.explicitUnits = true;\n      }\n    }\n\n\n    if (\n      this.delay === undefined\n      || lessThanEq(this.delay, this.simulate.timeStep.fullClone())\n    ) {\n      // it's a non-serialized stock;\n      this.level = init;\n    } else {\n      // it's serialized\n      this.initRate = div(init, this.delay.forceUnits(this.simulate.timeUnits));\n      let startValue = mult(this.initRate, this.simulate.userTimeStep.fullClone());\n\n      this.level = startValue;\n\n\n      this.simulate.tasks.addEvent((timeChange, oldTime, newTime) => {\n        if (timeChange.value > 0) {\n          let delaySpanEnd = minus(this.delay, this.simulate.userTimeStep);\n          let eventSpan = [minus(oldTime, this.simulate.timeStart), minus(newTime, this.simulate.timeStart)];\n          // No overlaps between the two spans\n          if (lessThan(delaySpanEnd, eventSpan[0])) {\n            return;\n          }\n\n          let overlap = minus(this.simulate.coreBank.get(\"min\")([delaySpanEnd, eventSpan[1]]), eventSpan[0]);\n\n          this.level = plus(this.level, mult(overlap, this.initRate));\n        }\n      });\n    }\n  }\n\n  /**\n   * @param {ValueType} amnt\n   */\n  subtract(amnt) {\n    this.level = minus(this.level, amnt);\n    if (this.dna.nonNegative) {\n      if (this.level instanceof Vector) {\n        let d = this.dna;\n        this.level.recurseApply((x) => {\n          if (x.value < 0) {\n            return new Material(0, d.units);\n          } else {\n            return x;\n          }\n        });\n      } else if (this.level.value < 0) {\n        this.level = new Material(0, this.dna.units);\n      }\n    }\n  }\n\n  /**\n   * @param {ValueType} amnt\n   * @param {Material} oldTime\n   */\n  add(amnt, oldTime) {\n\n    let targetTime;\n\n    if (this.delay !== undefined) {\n      // @ts-ignore bigjs is misstyped\n      targetTime = new Material(Big(oldTime.value).plus(this.delay.forceUnits(oldTime.units).value).toNumber(), oldTime.units);\n    }\n\n    if (this.delay === undefined || lessThanEq(targetTime, this.simulate.time())) {\n      this.level = plus(this.level, amnt);\n      if (this.dna.nonNegative) {\n        if (this.level instanceof Vector) {\n          let d = this.dna;\n          this.level.recurseApply((x) => {\n            if (x.value < 0) {\n              return new Material(0, d.units);\n            } else {\n              return x;\n            }\n          });\n        } else if (this.level.value < 0) {\n          this.level = new Material(0, this.dna.units);\n        }\n      }\n    } else {\n      this.scheduleAdd(amnt, targetTime);\n    }\n  }\n\n  /**\n   * @param {ValueType} amnt\n   * @param {Material} targetTime\n   */\n  scheduleAdd(amnt, targetTime) {\n    let oldLevel;\n\n    let t = new Task({\n      time: targetTime,\n      data: {\n        amnt: amnt,\n        tentative: true\n      },\n      priority: -100,\n      name: \"Conveyor Add (\" + this.dna.name + \")\",\n      action: (_task) => {\n        oldLevel = this.level;\n        this.level = plus(this.level, amnt);\n\n        if (this.dna.nonNegative) {\n          if (this.level instanceof Vector) {\n            let d = this.dna;\n            this.level.recurseApply((x) => {\n              if (x.value < 0) {\n                return new Material(0, d.units);\n              } else {\n                return x;\n              }\n            });\n          } else if (this.level.value < 0) {\n            this.level = new Material(0, this.dna.units);\n          }\n        }\n      },\n      rollback: () => {\n        this.level = oldLevel;\n      }\n    });\n    this.tasks.push(t);\n    this.simulate.tasks.add(t);\n  }\n\n  /**\n   * @returns {ValueType}\n   */\n  totalContents() {\n    if (this.level === null) {\n      this.setInitialValue();\n    }\n\n    if (this.delay !== undefined) {\n      let res = this.level;\n      let t = this.simulate.time();\n      for (let i = this.tasks.length - 1; i >= 0; i--) {\n        if (greaterThan(this.tasks[i].time, t)) {\n          res = plus(res, /** @type {ValueType} */ (this.tasks[i].data.amnt));\n        } else {\n          break;\n        }\n      }\n\n      // add in any pending `addEvent` mass from initialization\n      let progressed = plus(this.simulate.timeProgressed(), this.simulate.userTimeStep);\n      if (greaterThan(this.delay, progressed)) {\n        let timeLeft = minus(this.delay, progressed);\n        res = plus(res, mult(this.initRate, timeLeft));\n      }\n\n      return res;\n    } else {\n      return this.level;\n    }\n  }\n\n  calculateValue() {\n    if (this.level === null) {\n      this.setInitialValue();\n    }\n    if (this.delay !== undefined && this.dna.solver.RKOrder === 4) {\n      let res = this.level;\n      for (let i = 0; i < this.tasks.length; i++) {\n        if (greaterThan(this.tasks[i].time, this.simulate.time()) && lessThanEq(this.tasks[i].time, plus(this.simulate.time(), this.dna.solver.timeStep))) {\n          res = plus(res, /** @type {ValueType} */(this.tasks[i].data.amnt));\n        }\n      }\n      return res;\n    } else {\n      return this.level;\n    }\n  }\n}\n\n\nexport class SConverter extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n\n    /** @type {SPrimitive|string} */\n    this.source = null;\n    this.constructorFunction = SConverter;\n  }\n\n  innerClone() { }\n\n  /**\n   * @param {SPrimitive|string} source\n   */\n  setSource(source) {\n    this.source = source;\n  }\n\n  /**\n   * @returns {Material|Vector}\n   */\n  getInputValue() {\n    if (this.source === \"*time\") {\n      return this.simulate.time();\n    } else if (this.source instanceof SPrimitive) {\n      let inp = toNum(this.source.value());\n      if (!inp) {\n        throw new ModelError(\"Undefined input value.\", {\n          primitive: this.orig(),\n          showEditor: false,\n          code: 1199\n        });\n      }\n\n      if (!(inp instanceof Vector || inp instanceof Material)) {\n        throw new ModelError(\"Converter inputs must be numbers or vectors.\", {\n          primitive: this.orig(),\n          showEditor: false,\n          code: 1200\n        });\n      }\n\n      return inp;\n    } else {\n      console.error(\"Invalid source\", this.source);\n      throw new Error(\"Invalid source\");\n    }\n  }\n\n  calculateValue() {\n    return this.getOutputValue();\n  }\n\n  /**\n   * @returns {Material|Vector}\n   */\n  getOutputValue() {\n    let input = this.getInputValue();\n\n\n    let processItem = (inp) => {\n      let processItemInner = (inp) => {\n        if (!this.dna.inputs.length) {\n          return new Material(0);\n        }\n        for (let i = 0; i < this.dna.inputs.length; i++) {\n          if (this.dna.interpolation === \"discrete\") {\n\n            if (greaterThan(this.dna.inputs[i], inp)) {\n              if (i === 0) {\n                return this.dna.outputs[0];\n              } else {\n                return this.dna.outputs[i - 1];\n              }\n            }\n\n          } else if (this.dna.interpolation === \"linear\") {\n            if (eq(this.dna.inputs[i], inp)) {\n              return this.dna.outputs[i];\n            } else if (greaterThan(this.dna.inputs[i], inp)) {\n              if (i === 0) {\n                return this.dna.outputs[0];\n              } else {\n                let x = div(\n                  plus(\n                    mult(minus(inp, this.dna.inputs[i - 1]), this.dna.outputs[i]),\n                    mult(minus(this.dna.inputs[i], inp), this.dna.outputs[i - 1])\n                  ),\n                  minus(this.dna.inputs[i], this.dna.inputs[i - 1]));\n                return x;\n              }\n            }\n          }\n        }\n\n        return new Material(this.dna.outputs[this.dna.outputs.length - 1].value);\n      };\n\n      let r = /** @type {Material} */ (processItemInner(inp));\n      return new Material(r.value, this.dna.units);\n    };\n\n\n    if (input instanceof Vector) {\n      return input.clone().recurseApply(processItem);\n    } else if (input instanceof Material) {\n      return processItem(input);\n    } else {\n      throw new ModelError(\"Invalid input value.\", {\n        primitive: this.orig(),\n        showEditor: false,\n        code: 1199\n      });\n    }\n\n  }\n}\n\n\nexport class SVariable extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n\n    this.constructorFunction = SVariable;\n  }\n\n  innerClone() { }\n\n  calculateValue() {\n    let x = evaluateTree(this.equation, localVars(this, this.simulate), this.simulate);\n    if (typeof x === \"boolean\") {\n      if (x) {\n        x = new Material(1);\n      } else {\n        x = new Material(0);\n      }\n    } else if (x instanceof Vector) {\n      return x;\n    } else if (typeof x === \"string\") {\n      return x;\n    }\n    if (!x.units) {\n      x.units = this.dna.units;\n      x.explicitUnits = true;\n    }\n\n    return x;\n  }\n}\n\n\nexport class SFlow extends SPrimitive {\n  constructor(simulate) {\n    super(simulate);\n\n    /** @type {SStock} */\n    this.alpha = null;\n\n    /** @type {SStock} */\n    this.omega = null;\n\n    /** @type {ValueType} */\n    this.rate = null;\n\n    /** @type {ValueType} */\n    this.blendedRate = null;\n\n    /** @type {ValueType[]} */\n    this.RKPrimary = [];\n\n    this.constructorFunction = SFlow;\n  }\n\n  innerClone() { }\n\n  /**\n   * @param {SStock} alpha\n   * @param {SStock} omega\n   */\n  setEnds(alpha, omega) {\n    this.alpha = alpha;\n    this.omega = omega;\n  }\n\n  calculateValue() {\n    this.predict();\n    return this.rate.fullClone();\n  }\n\n  clean() {\n    this.rate = null;\n    this.blendedRate = null;\n\n    this.RKPrimary = [];\n  }\n\n  doRK4Aggregation() {\n    this.blendedRate = div(plus(plus(plus(this.RKPrimary[0], mult(new Material(2), this.RKPrimary[1])), mult(new Material(2), this.RKPrimary[2])), this.RKPrimary[3]), new Material(6));\n\n    this.blendedRate = this.checkRate(this.blendedRate);\n  }\n\n  checkRate(rate) {\n    let newRate = div(rate, this.dna.adoptUnits ? new Material(this.dna.solver.timeStep.value) : this.dna.solver.timeStep.fullClone());\n\n    if (this.dna.nonNegative) {\n      if (newRate instanceof Vector) {\n        newRate.recurseApply((x) => {\n          if (x.value >= 0) {\n            return x;\n          } else {\n            return new Material(0, x.units);\n          }\n        });\n      } else {\n        if (newRate.value <= 0) {\n          newRate = new Material(0, newRate.units);\n        }\n      }\n    }\n\n    return newRate;\n  }\n\n  /**\n   * @param {boolean=} override\n   */\n  predict(override) {\n    if (this.rate === null || override) {\n      let x;\n\n      try {\n        x = toNum(evaluateTree(this.equation, localVars(this, this.simulate), this.simulate));\n\n        if (!(x instanceof Vector || isFinite(x.value))) {\n          verifyValuedType(x, this);\n          throw new ModelError(\"The result of this calculation is not finite. Flows must have finite values. Are you dividing by 0?\", {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1111\n          });\n        }\n\n      } catch (err) {\n        if (err instanceof ModelError) {\n          if (err.primitive && err.showEditor) {\n            throw err; // don't want to override the target primitive\n          }\n          throw new ModelError(err.message, {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1100\n          });\n        } else {\n          throw err;\n        }\n      }\n\n      if (typeof x === \"boolean\") {\n        if (x) {\n          x = new Material(1);\n        } else {\n          x = new Material(0);\n        }\n      }\n\n      this.rate = x.fullClone();\n\n      if (!this.dna.adoptUnits) {\n        if (this.rate instanceof Vector) {\n          let d = this.dna;\n          this.rate.recurseApply((x) => {\n            verifyValuedType(x, this);\n\n            if (!x.units) {\n              x.units = d.units;\n            }\n            return x;\n          });\n        } else if (!this.rate.units) {\n          verifyValuedType(this.rate, this);\n\n          this.rate.units = this.dna.units;\n          this.rate.explicitUnits = true;\n        }\n      }\n\n\n      this.testUnits(this.rate, true);\n\n      this.rate = mult(this.rate, this.dna.adoptUnits ? new Material(this.dna.solver.timeStep.value) : this.dna.solver.timeStep.fullClone());\n\n      if (override) {\n        if (this.RKPrimary.length > 0) {\n          this.RKPrimary[this.RKPrimary.length - 1] = this.rate;\n        } else {\n          this.RKPrimary.push(this.rate);\n        }\n      } else {\n        this.RKPrimary.push(this.rate);\n      }\n\n\n      this.rate = this.checkRate(this.rate);\n    }\n  }\n\n  /**\n   * @param {Material} timeChange\n   * @param {Material} oldTime\n   *\n   * @returns\n   */\n  apply(timeChange, oldTime) {\n\n    try {\n      if (this.rate === null && this.blendedRate === null) {\n        return;\n      }\n\n      let rate = this.blendedRate ? this.blendedRate.fullClone() : this.rate.fullClone();\n\n      rate = mult(rate, this.dna.adoptUnits ? new Material(timeChange.forceUnits(this.simulate.timeUnits).value) : timeChange);\n\n\n\n      let inRate = rate;\n      let outRate = rate;\n      let collapsed = false;\n\n      if (this.alpha !== null) {\n        let v = this.alpha.level;\n        if (rate instanceof Vector && (!(v instanceof Vector) || v.depth() < rate.depth())) {\n          inRate = rate.fullClone().collapseDimensions(v);\n          collapsed = true;\n        } else if (v instanceof Vector && (!(rate instanceof Vector) || v.depth() > rate.depth())) {\n          throw new ModelError(\"The start of the flow is a vector with a higher order than the flow rate. There has to be at least one element in the flow rate for each element in the start.\", {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1201\n          });\n        }\n      }\n      if (this.omega !== null) {\n        let v = this.omega.level;\n        if (rate instanceof Vector && (!(v instanceof Vector) || v.depth() < rate.depth())) {\n          outRate = rate.fullClone().collapseDimensions(v);\n          collapsed = true;\n        } else if (v instanceof Vector && (!(rate instanceof Vector) || v.depth() > rate.depth())) {\n          throw new ModelError(\"The end of the flow is a vector with a higher order than the flow rate. There has to be at least one element in the flow rate for each element in the end.\", {\n            primitive: this.orig(),\n            showEditor: true,\n            code: 1202\n          });\n        }\n      }\n\n      if (!collapsed) {\n\n        if (this.omega !== null && this.omega.dna.nonNegative) {\n          let modifier;\n          try {\n            // Omega + Flow: value(s) will be negative if we need to make\n            // an adjustment to maintain non-negativity\n            modifier = plus(toNum(this.omega.level), rate);\n          } catch (err) {\n            throw new ModelError(`Incompatible units for flow <i>[${sanitizeText(this.dna.name)}]</i> and connected stock <i>[${sanitizeText(this.omega.dna.name)}]</i>. Stock has units of <i>${this.omega.dna.units ? this.omega.dna.units.toString() : \"unitless\"}</i>. The flow should have the equivalent units divided by some time unit such as Years.`, {\n              primitive: this.orig(),\n              showEditor: false,\n              code: 1203\n            });\n          }\n          if (modifier instanceof Vector) {\n            modifier.recurseApply((x) => {\n              if (x.value < 0) {\n                // Added too much to the omega.\n                // Set the modifier so that the applied flow will result\n                // in a stock value of 0\n                return x;\n              } else {\n                return new Material(0, x.units);\n              }\n            });\n            rate = minus(rate, modifier);\n          } else {\n            if (modifier.value < 0) {\n              rate = negate(toNum(this.omega.level));\n            }\n          }\n        }\n\n        if (this.alpha !== null && this.alpha.dna.nonNegative) {\n          let modifier;\n          try {\n            // Alpha - Flow: value(s) will be negative if we need to make\n            // an adjustment to maintain non-negativity\n            modifier = minus(toNum(this.alpha.level), rate);\n          } catch (err) {\n            throw new ModelError(`Incompatible units for flow <i>[${sanitizeText(this.dna.name)}]</i> and connected stock <i>[${sanitizeText(this.alpha.dna.name)}]</i>. Stock has units of <i>${this.alpha.dna.units ? this.alpha.dna.units.toString() : \"unitless\"}</i>. The flow should have the equivalent units divided by some time unit such as Years.`, {\n              primitive: this.orig(),\n              showEditor: false,\n              code: 1204\n            });\n          }\n          if (modifier instanceof Vector) {\n            modifier.recurseApply((x) => {\n              if (x.value < 0) {\n                // Withdrew too much from the alpha.\n                // Set the modifier so that the applied flow will result\n                // in a stock value of 0\n                return x;\n              } else {\n                return new Material(0, x.units);\n              }\n            });\n            rate = plus(rate, modifier);\n          } else {\n            if (modifier.value < 0) {\n              rate = toNum(this.alpha.level);\n            }\n          }\n        }\n\n        if (this.omega && this.omega.dna.nonNegative) {\n          if (rate instanceof Vector) {\n            /** @type {Vector} */\n            let vec = this.simulate.coreBank.get(\"flatten\")([plus(toNum(this.omega.level), rate)]);\n            for (let item of vec.items) {\n              if (item instanceof Material && item.value < 0) {\n                throw new ModelError(\"Inconsistent non-negative constraints for flow.\", {\n                  primitive: this.orig(),\n                  showEditor: false,\n                  code: 1205\n                });\n              }\n            }\n          } else {\n            let n = plus(toNum(this.omega.level), rate);\n            if (n instanceof Material && n.value < 0) {\n              throw new ModelError(\"Inconsistent non-negative constraints for flow.\", {\n                primitive: this.orig(),\n                showEditor: false,\n                code: 1206\n              });\n            }\n          }\n        }\n      } else {\n        if (this.alpha && this.alpha.dna.nonNegative) {\n          throw new ModelError(\"Cannot use non-negative stocks when the flow rate is a vector that needs to be collapsed.\", {\n            primitive: this.alpha.dna.primitive,\n            showEditor: false,\n            code: 1207\n          });\n        }\n        if (this.omega && this.omega.dna.nonNegative) {\n          throw new ModelError(\"Cannot use non-negative stocks when the flow rate is a vector that needs to be collapsed.\", {\n            primitive: this.omega.dna.primitive,\n            showEditor: false,\n            code: 1208\n          });\n        }\n      }\n\n      let additionTest = 0;\n      try {\n        if (this.omega !== null) {\n          additionTest = 1;\n          if (collapsed) {\n            this.omega.add(outRate, oldTime);\n          } else {\n            this.omega.add(rate, oldTime);\n          }\n        }\n        if (this.alpha !== null) {\n          additionTest = 2;\n\n          if (collapsed) {\n            this.alpha.subtract(inRate);\n          } else {\n            this.alpha.subtract(rate);\n          }\n        }\n      } catch (err) {\n        /** @type {SStock} */\n        let stock;\n        if (additionTest === 1) {\n          stock = this.omega;\n        } else if (additionTest === 2) {\n          stock = this.alpha;\n        }\n\n        if (err.code === 2000 || err.code === 2001) {\n          throw new ModelError(`Incompatible vector keys for flow <i>[${sanitizeText(this.dna.name)}]</i> and connected stock <i>[${sanitizeText(stock.dna.name)}]</i>.`, {\n            primitive: this.orig(),\n            showEditor: false,\n            code: 1209\n          });\n        } else {\n          throw new ModelError(`Incompatible units for flow <i>[${sanitizeText(this.dna.name)}]</i> and connected stock <i>[${sanitizeText(stock.dna.name)}]</i>. Stock has units of <i>${stock.dna.units ? stock.dna.units.toString() : \"unitless\"}</i>. The flow should have the equivalent units divided by some time unit such as Years.`, {\n            primitive: this.orig(),\n            showEditor: false,\n            code: 1210\n          });\n        }\n      }\n\n    } catch (err) {\n      if (err instanceof ModelError) {\n        if (err.primitive && err.showEditor) {\n          throw err; // don't want to override the target primitive\n        }\n        throw new ModelError(err.message, {\n          primitive: this.orig(),\n          showEditor: true,\n          code: 1102\n        });\n      } else {\n        throw err;\n      }\n    }\n  }\n}\n\n\n/**\n * @param {SPrimitive} primitive\n * @param {import(\"./Simulator\").Simulator} simulate\n *\n * @return {Map<PARENT_SYMBOL|string, any>}\n */\nfunction localVars(primitive, simulate) {\n  if (primitive instanceof SAgent) {\n    // @ts-ignore\n    return new Map([\n      [PARENT_SYMBOL, simulate.varBank],\n      [\"self\", primitive]\n    ]);\n  } else if (primitive.container) {\n    // @ts-ignore\n    return new Map([\n      [PARENT_SYMBOL, simulate.varBank],\n      [\"self\", primitive.container]\n    ]);\n  } else {\n    return new Map([\n      [PARENT_SYMBOL, simulate.varBank]\n    ]);\n  }\n}\n\n\n/**\n * @param {SPrimitive} item\n * @param {string} type\n * @param {Material} val\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nfunction constraintAlert(item, type, val, simulate) {\n  let msg = \"The \" + (type === \"max\" ? \"maximum\" : \"minimum\") + \" constraint on the primitive [<i>\" + sanitizeText(simulate.model.getId(item.id).name) + \"</i>] has been violated. The primitive's value attempted to become \" + sanitizeText(\"\" + val.value) + \" when the \" + (type === \"max\" ? \"maximum\" : \"minimum\") + \" allowed value is \" + (type === \"max\" ? item.dna.maxConstraint : item.dna.minConstraint) + \".\";\n\n  throw new ModelError(msg, {\n    primitive: item.dna.primitive,\n    showEditor: false,\n    code: 1150\n  });\n}\n", "src/Modeler.js": "import { Simulator } from \"./Simulator.js\";\n// eslint-disable-next-line\nimport { SAgent, SPopulation, STransition, SAction, SState, SStock, SVariable, SFlow, SConverter, Placeholder, SPrimitive } from \"./Primitives.js\";\n// eslint-disable-next-line\nimport { Action, Agent, Converter, Flow, Population, Primitive, State, Stock, Transition, ValuedPrimitive, Variable } from \"./api/Blocks.js\";\nimport { Material } from \"./formula/Material.js\";\nimport { div, plus, mult, evaluateTree, trimTree, trueValue, eq, createTree, bootCalc, TreeNode, PARENT_SYMBOL } from \"./formula/Formula.js\";\nimport { fn } from \"./CalcMap.js\";\nimport { convertUnits } from \"./formula/Units.js\";\nimport { Rand } from \"./formula/Rand.js\";\nimport { Vector } from \"./formula/Vector.js\";\nimport { selectFromMatrix } from \"./formula/Utilities.js\";\nimport { DNA } from \"./DNA.js\";\nimport { ModelError } from \"./formula/ModelError.js\";\nimport { commaStr, sanitizeText } from \"./Utilities.js\";\nimport { Graph, Layout } from \"../vendor/graph.js\";\nimport toposort from \"../vendor/toposort.js\";\nimport { Model } from \"./api/Model.js\";\n\n\n/** @typedef {import(\"./SharedTypes.js\").GraphNode} GraphNode */\n\n\n/**\n * @typedef {SPopulation & { node?: import(\"./api/Blocks\").Primitive }} SubModelType\n */\n\n\n/**\n * @typedef {object} ModelType\n * @property {Object<string, import(\"./Simulator\").SolverType>=} solvers\n * @property {Object<string, SubModelType>=} submodels\n * @property {Material=} timeLength\n * @property {Material=} timeStart\n * @property {Material=} timeStep\n * @property {Material=} timePause\n * @property {import(\"./formula/Units.js\").UnitStore} timeUnits\n */\n\n\n\n\n/**\n * @typedef {object} SimulationConfigType\n * @property {boolean=} silent\n * @property {function(import(\"./Simulator\").SolverType)=} onStep\n * @property {function(import(\"./Simulator\").ResultsType)=} onPause\n * @property {function(import(\"./Simulator\").ResultsType)=} onSuccess\n * @property {function(import(\"./Simulator\").ResultsType)=} onError\n * @property {function(string, \"error\"|\"warning\"|\"notice\"|\"success\"=)=} showNotification\n * @property {function=} processError\n * @property {function=} showMacros\n * @property {function=} handleErrorObject\n * @property {function=} onCompletedFirstPass\n * @property {function(Primitive)=} getColor\n * @property {function(Primitive)=} getIcon\n * @property {any=} resultsWindow\n * @property {GraphNode=} selectedDisplay\n * @property {number=} rate\n * @property {function=} createResultsWindow\n * @property {import(\"./api/Model.js\").Model=} model\n * @property {boolean=} pauseEachTimeStep - if true, will pause each step (including the start)\n */\n\n\n/**\n * @param {SimulationConfigType} config\n *\n * @returns\n */\nexport function runSimulation(config) {\n  let simulate;\n  try {\n    simulate = new Simulator();\n    simulate.model = config.model;\n    return innerRunSimulation(simulate, config); // have an inner function call to escape try-catch performance pathologies\n  } catch (err) {\n    return checkErr(err, config, simulate);\n  }\n}\n\n\n/**\n * @param {*} err\n * @param {*} config\n * @param {import(\"./Simulator\").Simulator} simulate\n * @returns\n */\nexport function checkErr(err, config, simulate) {\n  simulate.terminate();\n\n  /** @type {import(\"./Simulator\").ResultsType} */\n  let errOut;\n  if (err instanceof ModelError) {\n    errOut = {\n      error: err.message,\n      errorPrimitive: err.primitive ? simulate.model.getId(err.primitive.id) : null,\n      errorCode: err.code\n    };\n  } else {\n    console.log(err);\n\n    if (config.processError) {\n      config.processError(err);\n    }\n\n    errOut = {\n      error: \"An unknown simulation error occurred. Please report this issue to the Insight Maker team at <a href='mailto:support@insightmaker.com' style='color: white'>support@insightmaker.com</a>.\",\n      errorPrimitive: null,\n      errorCode: 1\n    };\n\n    err = new ModelError(errOut.error, {\n      code: 1\n    });\n  }\n\n  if (!simulate.results) {\n    simulate.results = {};\n  }\n  simulate.results.error = err.msg;\n\n\n  if (errOut.error) {\n    // remove HTML\n    errOut.error = errOut.error.replace(/<br\\s*\\/?>/g, \"\\n\").replace(/<[^>]*>?/gm, \"\").replaceAll(\"&lt;\", \"<\").replaceAll(\"&gt;\", \">\");\n  }\n\n  if (simulate.evaluatingPosition) {\n    if (simulate.evaluatingPosition.source === \"macros\") {\n      errOut.errorPrimitive = null;\n      errOut.errorSource = \"GLOBALS\";\n      errOut.errorLine = simulate.evaluatingPosition.line;\n    } else {\n      if (errOut.errorPrimitive) {\n        errOut.errorSource = \"PRIMITIVE\";\n        if (simulate.evaluatingPosition.source?.startsWith(\"p:\" + errOut.errorPrimitive.id + \":\")) {\n          errOut.errorLine = simulate.evaluatingPosition.line;\n          let part = simulate.evaluatingPosition.source.split(\":\")[2];\n          if (part) {\n            errOut.errorSource += \":\" + part.toUpperCase();\n          }\n        }\n      }\n    }\n  }\n\n  if (config.onError) {\n    config.onError(errOut);\n  }\n\n  if (config.handleErrorObject) {\n    err.primitive = errOut.errorPrimitive ? err.primitive : null;\n    err.line = errOut.errorLine;\n    err.source = errOut.errorSource;\n\n    config.handleErrorObject(err, simulate);\n  } else {\n    return errOut;\n  }\n}\n\n\n/**\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {SimulationConfigType} config\n *\n * @returns\n */\nfunction innerRunSimulation(simulate, config) {\n  if (config) {\n    simulate.config = config;\n  }\n\n  simulate.evaluatingPosition = {\n    line: null,\n    source: null\n  };\n\n  if (config.resultsWindow) {\n    if (!config.resultsWindow.windowContext.simulate.completed()) {\n      // kill simulation if still running\n      config.resultsWindow.windowContext.simulate.terminate();\n    }\n    simulate.resultsWindow = config.resultsWindow;\n    config.resultsWindow.windowContext.simulate = simulate;\n    config.resultsWindow.data.simulation = simulate;\n    config.resultsWindow.windowContext.componentRef.rerender();\n    config.resultsWindow.windowContext.notFirstRun = true;\n  }\n\n  bootCalc(simulate);\n\n  /** @type {string} */\n  let timeUnits = simulate.model.timeUnits;\n  if (!timeUnits) {\n    throw new ModelError(\"You must set the time units in the model settings.\", {\n      code: 1072\n    });\n  }\n  timeUnits = timeUnits.toLowerCase();\n  simulate.timeUnitsString = timeUnits;\n\n  /** @type {ModelType} */\n  let model = {};\n  model.submodels = {\n    // @ts-ignore\n    base: {\n      id: \"base\",\n      DNAs: [],\n      agents: [/** @type {SAgent} */ ({\n        children: [],\n        childrenId: {}\n      })],\n      size: 1\n    }\n  };\n\n\n  // Begin custom units setup\n\n  let customUnits = simulate.model.customUnits;\n  if (customUnits) {\n    /** @type {import(\"./formula/Units\").UnitDefinition[]} */\n    let units = [];\n    for (let unit of customUnits) {\n      if (unit.target?.trim()) { // It has a synonym, otherwise we don't need to add it\n        let newUnit = {\n          sourceString: unit.name,\n          scale: unit.scale,\n        };\n        let newTarget = createUnitStore(unit.target, simulate);\n        if (!newTarget) {\n          throw new ModelError(\"You cannot define a units synonym for \\\"unitless\\\".\", {\n            code: 1001\n          });\n        } else {\n          newUnit.target = newTarget;\n        }\n        units.push(newUnit);\n      }\n    }\n    simulate.unitManager.addUnits(units);\n  }\n\n  // End custom units setup\n\n  // Set Up simulation time settings\n\n  model.timeUnits = simulate.unitManager.getUnitStore([timeUnits], [1]);\n  model.timeLength = new Material(simulate.model.timeLength, model.timeUnits);\n  model.timeStart = new Material(simulate.model.timeStart || 0, model.timeUnits);\n  model.timeStep = new Material(simulate.model.timeStep, model.timeUnits);\n\n  if (model.timeStep.value <= 0 || isNaN(model.timeStep.value)) {\n    throw new ModelError(\"The model time step must be a positive number.\", {\n      code: 1002\n    });\n  }\n\n  if (model.timeLength.value <= 0 || isNaN(model.timeLength.value)) {\n    throw new ModelError(\"The model time length must be a positive number.\", {\n      code: 1003\n    });\n  }\n\n\n\n  if (simulate.model.timePause > 0) {\n    model.timePause = new Material(simulate.model.timePause, model.timeUnits);\n\n    if (model.timePause.value < model.timeStep.value) {\n      throw new ModelError(\"Time pause cannot be smaller than the time step.\", {\n        code: 1004\n      });\n    }\n  }\n\n  simulate.timeUnits = model.timeUnits;\n\n\n  // End Simulation time settings setup\n\n  /** @type {Object<string, import('./Simulator').SolverType>} */\n  let solvers = {}; // Simulation solvers\n  solvers.base = {\n    timeStep: new Material(simulate.model.timeStep, model.timeUnits),\n    algorithm: simulate.model.algorithm,\n    id: \"base\",\n    maxLoaded: -1\n  };\n\n\n  model.solvers = solvers;\n  let folders = simulate.model.findFolders().concat(simulate.model.findAgents());\n  for (let i = 0; i < folders.length; i++) {\n    let solver = folders[i].customTimeSettings;\n    if (solver) {\n      if (solver.enabled) {\n        solvers[folders[i].id] = Object.assign({}, solver, { timeStep: new Material(+solver.timeStep, model.timeUnits) });\n        if (solvers[folders[i].id].timeStep.value <= 0 || isNaN(solvers[folders[i].id].timeStep.value)) {\n          throw new ModelError(\"The folder time step must be a positive number.\", {\n            primitive: folders[i],\n            showEditor: false,\n            code: 1005\n          });\n        }\n        solvers[folders[i].id].id = folders[i].id;\n        solvers[folders[i].id].maxLoaded = -1;\n      }\n    }\n  }\n\n  for (let solver of Object.values(solvers)) {\n    solver.userTimeStep = solver.timeStep;\n    if (solver.algorithm === \"RK4\") {\n      solver.RKOrder = 4;\n    } else {\n      solver.RKOrder = 1;\n    }\n    if (solver.RKOrder === 4) {\n      solver.timeStep = div(solver.userTimeStep, new Material(2));\n    }\n\n    solver.stocks = [];\n    solver.flows = [];\n    solver.transitions = [];\n    solver.actions = [];\n    solver.states = [];\n    solver.valued = [];\n    solver.displayed = [];\n  }\n\n\n  try {\n    // Initialize actual simulation\n    simulate.setup(model);\n\n    if (simulate.model.globals !== undefined) {\n      try {\n        evaluateGlobals(simulate.model.globals, simulate);\n      } catch (err) {\n\n        if (err.simulationCommand === \"STOP\") {\n          // pass a STOP() error up\n          throw err;\n        }\n\n        let annotations = [];\n\n        let msg = \"An error with the macros prevented the simulation from running.\";\n\n        if (err instanceof ModelError) {\n          msg = msg + \"<br/><br/>\" + err.message;\n          if (simulate.evaluatingPosition?.line) {\n            annotations.push({\n              type: \"error\",\n              row: simulate.evaluatingPosition.line - 1,\n              text: err.message\n            });\n          }\n        } else {\n          if (err.toString) {\n            if (err.match && err.match(/line (\\d+)/i)) {\n              let l = err.match(/line (\\d+)/i)[1];\n\n              annotations.push({\n                type: \"error\",\n                row: l !== undefined ? l - 1 : simulate.evaluatingPosition.line - 1,\n                text: err\n              });\n            }\n          }\n\n          if (config.processError) {\n            config.processError(err);\n          }\n        }\n\n        if (config.showMacros) {\n          config.showMacros(annotations);\n        }\n\n        throw new ModelError(msg, {\n          code: 1000\n        });\n      }\n    }\n\n    let modelItems = simulate.model.find();\n\n    // generated topological sort of flows allowing\n    // us to evaluate them from \"upstream\" to \"downstream\"\n    // when dealing with non-negative stocks\n    simulate.clusters = makeClusters(simulate);\n\n    for (let item of modelItems) {\n      if (item instanceof Population) {\n        if (item.isInAgent()) {\n          throw new ModelError(`Cannot have the agent population <i>[${sanitizeText(item.name)}]</i> placed within an agent folder.`, {\n            primitive: item,\n            showEditor: false,\n            code: 1006\n          });\n        }\n\n        let agentBase = item.agentBase;\n        if (!agentBase || !(agentBase instanceof Agent)) {\n          throw new ModelError(`You must select a base agent for the primitive <i>[${sanitizeText(item.name)}]</i>. You can create agent definitions using Folder primitives.`, {\n            primitive: item,\n            showEditor: false,\n            code: 1007\n          });\n        }\n\n        let x = new SPopulation(simulate);\n\n        x.dna = new DNA(item, agentBase.id);\n        x.id = item.id;\n\n        x.agentId = agentBase.id;\n        x.createIds();\n\n        x.dna.solver = folderSolvers(item, solvers);\n        x.dna.solver.displayed.push(x);\n\n        x.geoDimUnits = item.geoUnits;\n        x.geoDimUnitsObject = createUnitStore(item.geoUnits, simulate, item);\n        try {\n          x.geoWidth = simpleUnitsTest(/** @type {Material} */(simpleEquation(item.geoWidth, simulate)), x.geoDimUnitsObject, simulate, item);\n        } catch (_err) {\n          throw new ModelError(`Invalid width for the agent population <i>[${sanitizeText(item.name)}]</i>.`, {\n            primitive: item,\n            showEditor: false,\n            code: 1008\n          });\n        }\n        try {\n          x.geoHeight = simpleUnitsTest(/** @type {Material} */(simpleEquation(item.geoHeight, simulate)), x.geoDimUnitsObject, simulate, item);\n        } catch (_err) {\n          throw new ModelError(`Invalid height for the agent population <i>[${sanitizeText(item.name)}]</i>.`, {\n            primitive: item,\n            showEditor: false,\n            code: 1009\n          });\n        }\n        x.halfWidth = div(x.geoWidth, new Material(2));\n        x.halfHeight = div(x.geoHeight, new Material(2));\n        x.geoWrap = item.geoWrapAround;\n        x.placement = item.geoPlacementType;\n        x.placementFunction = item.geoPlacementFunction;\n        x.network = item.networkType;\n        x.networkFunction = item.networkFunction;\n        x.agentBase = agentBase.agentParent;\n        if (x.agentBase && x.agentBase.trim()) {\n          try {\n            let nodeBase = new Map();\n            let tree = trimTree(createTree(x.agentBase, \"p:\" + agentBase.id + \":agentBase\", simulate), nodeBase, simulate);\n\n            x.agentBase = simpleEquation(x.agentBase, simulate, simulate.varBank, null, tree);\n          } catch (err) {\n            console.warn(err);\n            throw new ModelError(`Invalid Agent Parent for the primitive <i>[${sanitizeText(agentBase.name)}]</i>.`, {\n              primitive: agentBase,\n              showEditor: false,\n              code: 1010\n            });\n          }\n        }\n\n        let agentNodes = agentBase.children();\n\n        x.DNAs = [];\n        for (let agentNode of agentNodes) {\n          if (modelType(agentNode)) {\n            x.DNAs.push(getDNA(agentNode, x, solvers, simulate));\n          }\n          if (agentNode instanceof State) {\n            x.stateIds.add(agentNode.id);\n          }\n        }\n\n\n        x.size = item.populationSize;\n\n        x.agents = [];\n\n        x.dna.agents = x;\n\n        model.submodels[item.id] = x;\n        model.submodels.base.DNAs.push(x.dna);\n      } else if (!item.isInAgent()) {\n        if (modelType(item)) {\n          model.submodels.base.DNAs.push(getDNA(item, model.submodels.base, solvers, simulate));\n        }\n      }\n    }\n\n\n\n    for (let submodel of Object.values(model.submodels)) {\n      submodel.DNAs.sort((a, b) => {\n        if (a.neighborProxyDNA && !b.neighborProxyDNA) {\n          return 1;\n        }\n        if (b.neighborProxyDNA && !a.neighborProxyDNA) {\n          return -1;\n        }\n        return 0;\n      });\n\n      for (let j = 0; j < submodel.size; j++) {\n        let agent;\n        if (submodel.id === \"base\") {\n          agent = submodel.agents[0];\n        } else {\n          agent = new SAgent(simulate);\n          agent.container = submodel;\n          agent.index = j;\n          agent.children = [];\n          agent.childrenId = {};\n          agent.agentId = submodel.id;\n          agent.createIds();\n          if (submodel.agentBase) {\n            agent.vector.parent = submodel.agentBase;\n          }\n\n          submodel.agents.push(agent);\n        }\n        for (let dna of submodel.DNAs) {\n          decodeDNA(dna, agent, simulate, submodel.id !== \"base\");\n        }\n      }\n    }\n\n\n    for (let submodelId in model.submodels) {\n      let submodel = model.submodels[submodelId];\n      for (let j = 0; j < submodel.size; j++) {\n        for (let i = 0; i < submodel.DNAs.length; i++) {\n          linkPrimitive(submodel.agents[j].children[i], submodel.DNAs[i], simulate);\n        }\n      }\n    }\n\n    for (let submodelId in model.submodels) {\n      let submodel = model.submodels[submodelId];\n      for (let j = 0; j < submodel.size; j++) {\n        setAgentInitialValues(submodel.agents[j]);\n      }\n    }\n\n    for (let submodel in model.submodels) {\n      if (submodel !== \"base\") {\n        try {\n          buildNetwork(model.submodels[submodel], simulate);\n        } catch (err) {\n          let msg = \"An error with the custom network function prevented the simulation from running.\";\n          if (err instanceof ModelError) {\n            msg = msg + \"<br/><br/>\" + err.message;\n          }\n\n          throw new ModelError(msg, {\n            primitive: model.submodels[submodel].node,\n            showEditor: false,\n            code: 1011\n          });\n        }\n\n\n        try {\n          buildPlacements(model.submodels[submodel], simulate);\n        } catch (err) {\n          let msg = \"An error with the agent placement function prevented the simulation from running.\";\n          if (err instanceof ModelError) {\n            msg = msg + \"<br/><br/>\" + err.message;\n          }\n\n          throw new ModelError(msg, {\n            primitive: model.submodels[submodel].node,\n            showEditor: false,\n            code: 1012\n          });\n        }\n\n      }\n    }\n\n\n\n    simulate.results = {\n      times: [],\n      data: [],\n      timeUnits: simulate.timeUnitsString\n    };\n    simulate.displayInformation = {\n      populated: false,\n      ids: [],\n      times: [],\n      objects: [],\n      maps: [],\n      histograms: []\n    };\n\n    model.submodels[\"base\"].agents[0].children.forEach((x) => {\n      if (!(x instanceof SAction || x instanceof STransition)) {\n\n        if (!x.dna.noOutput) {\n          simulate.displayInformation.objects.push(x);\n          simulate.displayInformation.ids.push(x.id);\n        }\n        let data = {};\n        if (x instanceof SPopulation) {\n          data.width = x.geoWidth;\n          data.height = x.geoHeight;\n          data.units = x.geoDimUnitsObject;\n          data.states = x.states();\n        } else {\n          if (!x.dna.noOutput) {\n            x.dna.solver.displayed.push(x);\n          }\n        }\n        if (!simulate.results.children) {\n          simulate.results.children = {};\n        }\n        simulate.results.children[x.id] = {\n          data: data,\n          results: [],\n          dataMode: \"float\"\n        };\n      }\n    });\n\n\n\n    let hasCompletedFirstPass = false;\n    function completedFirstPass() {\n      if (hasCompletedFirstPass) {\n        return;\n      }\n      hasCompletedFirstPass = true;\n      if (simulate.displayInformation.populated) {\n\n        for (let i = 0; i < simulate.displayInformation.origIds.length; i++) {\n\n          let id = simulate.displayInformation.origIds[i];\n          let object = simulate.displayInformation.objects[i];\n\n          if (object instanceof SPopulation) {\n            simulate.results.children[id].states = object.stateIds;\n\n            simulate.displayInformation.agents[id.toString()].data = simulate.results.children[id].data;\n            simulate.displayInformation.agents[id.toString()].results = simulate.results.children[id].results;\n\n\n          } else if (simulate.results.data[0][id] instanceof Vector && simulate.results.data[0][id].names) {\n\n            let names = simulate.results.data[0][id].fullNames();\n\n            simulate.results.children[id].indexedFullNames = names.slice();\n            for (let j = 0; j < names.length; j++) {\n              names[j] = names[j].join(\", \");\n            }\n            simulate.results.children[id].indexedNames = names;\n\n          }\n        }\n\n      } else {\n        simulate.displayInformation.populated = true;\n        simulate.displayInformation.colors = [];\n        simulate.displayInformation.icons = [];\n        simulate.displayInformation.headers = [];\n        simulate.displayInformation.agents = [];\n        simulate.displayInformation.displayedItems = [];\n        simulate.displayInformation.renderers = [];\n        simulate.displayInformation.elementIds = [];\n        simulate.displayInformation.res = simulate.results;\n\n        let ids = [];\n\n        simulate.displayInformation.origIds = simulate.displayInformation.ids.slice();\n        for (let i = 0; i < simulate.displayInformation.origIds.length; i++) {\n          let id = simulate.displayInformation.origIds[i];\n          let object = simulate.displayInformation.objects[i];\n          let dna = object.dna;\n\n          let image = dna.primitive._node.getAttribute(\"Image\");\n          simulate.displayInformation.displayedItems.push({\n            id,\n            header: dna.name,\n            type: dna.primitive._node.value.nodeName,\n            icon: image?.startsWith(\"emoji:\") ? image.slice(6) : null\n          });\n\n\n          if (object instanceof SPopulation) {\n            let states = object.stateIds;\n\n            simulate.results.children[id].states = states;\n\n            states.forEach(state => {\n              let innerItem = simulate.model.getId(state);\n              ids.push(id);\n              simulate.displayInformation.elementIds.push(\"e\" + id + \"-\" + state);\n              simulate.displayInformation.headers.push(innerItem.name);\n              simulate.displayInformation.icons.push(config.getIcon ? config.getIcon(innerItem) : null);\n              simulate.displayInformation.colors.push(config.getColor ? config.getColor(innerItem) : \"#000000\");\n              if (simulate.results.children[id].dataMode === \"float\") {\n                simulate.displayInformation.renderers.push(commaStr);\n              } else if (simulate.results.children[id].dataMode === \"agents\") {\n                simulate.displayInformation.renderers.push((x) => {\n                  return x;\n                });\n              } else {\n                simulate.displayInformation.renderers.push(undefined);\n              }\n            });\n\n            simulate.displayInformation.agents[id.toString()] = {\n              id: id,\n              item: dna.primitive,\n              data: simulate.results.children[id].data,\n              results: simulate.results.children[id].results\n            };\n\n\n          } else if (simulate.results.data.length && simulate.results.data[0][id] instanceof Vector && simulate.results.data[0][id].names) {\n\n            let col = config.getColor ? config.getColor(dna.primitive) : \"#000000\";\n            let icon = config.getIcon ? config.getIcon(dna.primitive) : null;\n\n            let names = simulate.results.data[0][id].fullNames();\n\n            simulate.results.children[id].indexedFullNames = names.slice();\n            for (let j = 0; j < names.length; j++) {\n              names[j] = names[j].join(\", \");\n            }\n            simulate.results.children[id].indexedNames = names;\n\n            for (let j = 0; j < names.length; j++) {\n              ids.push(id);\n              simulate.displayInformation.elementIds.push(\"e\" + id + \"-\" + j);\n              simulate.displayInformation.headers.push(dna.name + \" (\" + names[j] + \")\");\n              simulate.displayInformation.icons.push(icon);\n              simulate.displayInformation.colors.push(col);\n              simulate.displayInformation.renderers.push(commaStr);\n            }\n\n          } else {\n            ids.push(id);\n            simulate.displayInformation.elementIds.push(\"e\" + id);\n            simulate.displayInformation.headers.push(dna.name);\n            simulate.displayInformation.icons.push(config.getIcon ? config.getIcon(dna.primitive) : null);\n            simulate.displayInformation.colors.push(config.getColor ? config.getColor(dna.primitive) : \"#000000\");\n            if (simulate.results.children[id].dataMode === \"float\") {\n              simulate.displayInformation.renderers.push(commaStr);\n            } else {\n              simulate.displayInformation.renderers.push(undefined);\n            }\n          }\n\n        }\n\n\n\n\n        simulate.displayInformation.store = {\n          data: []\n        };\n        simulate.displayInformation.ids = ids;\n      }\n    }\n\n\n    if (config.silent) {\n      if (config.onPause) {\n        simulate.run(config);\n      } else {\n        return formatSimResults(simulate.run(config));\n      }\n    } else {\n\n      let count = div(model.timeLength, model.timeStep);\n\n      // Max size for a JS array is a 32-bit integer\n      const MAX_ARRAY_LENGTH = 4294967294;\n      function showRangeErrorMessage() {\n        throw new ModelError(`You have ${count.value.toLocaleString()} time steps, you must reduce this. Generally 1,000 to 10,000 time steps is sufficient even for large simulations.`,\n          {\n            code: 9108\n          });\n      }\n\n      if (count.value > MAX_ARRAY_LENGTH) {\n        showRangeErrorMessage();\n      }\n\n      try {\n        for (let i = 0; i <= count.value; i++) {\n          simulate.displayInformation.times.push(plus(model.timeStart, mult(model.timeStep, new Material(i))).value);\n        }\n      } catch (err) {\n        if (err instanceof RangeError) {\n          // The max size may be samller than MAX_ARRAY_LENGTH due to memory constraints\n          showRangeErrorMessage();\n        } else {\n          throw err;\n        }\n      }\n\n\n      let oldSuccess = config.onSuccess;\n      config.onSuccess = function (res) {\n        completedFirstPass(); // simulation may have terminated via stop() before first pass\n\n        for (let solver in simulate.simulationModel.solvers) {\n          updateDisplayed(simulate.simulationModel.solvers[solver], simulate);\n        }\n\n        if (simulate.setResultsCallback) {\n          simulate.setResultsCallback(formatSimResults(simulate.results));\n        }\n\n        if (oldSuccess) {\n          oldSuccess(res);\n        }\n      };\n\n      config.onCompletedFirstPass = function () {\n        completedFirstPass();\n      };\n\n\n\n      let oldStep = config.onStep;\n      config.onStep = function (solver) {\n\n        // See if we should sleep to let the main UI update\n\n        let updated = false;\n        let progress = simulate.progress();\n\n\n        if (!simulate.shouldSleep) {\n          let timeTaken = Date.now() - simulate.wakeUpTime;\n\n          let complexityMultiplier = 1;\n          if (simulate.results.times.length > 20000) {\n            complexityMultiplier = 4;\n          } else if (simulate.results.times.length > 5000) {\n            complexityMultiplier = 2;\n          } else if (simulate.results.times.length > 1000) {\n            complexityMultiplier = 1.3;\n          }\n\n          if ((!simulate.resultsWindow && timeTaken > 100 * complexityMultiplier) || timeTaken > 600 * complexityMultiplier) {\n            updateDisplayed(solver, simulate);\n            updated = true;\n\n            // @ts-ignore\n            simulate.timer = setTimeout(() => {\n              simulate.resume();\n            }, 20 * Math.pow(complexityMultiplier, 1.5));\n\n            simulate.sleep();\n          }\n        }\n\n        if (progress === 1 && !updated) {\n          updateDisplayed(solver, simulate);\n        }\n\n        // Call any user defined step function\n\n        if (oldStep) {\n          oldStep(solver);\n        }\n      };\n\n      let oldError = config.onError;\n      config.onError = function (res) {\n\n        try {\n          for (let solver in simulate.simulationModel.solvers) {\n            updateDisplayed(simulate.simulationModel.solvers[solver], simulate);\n          }\n        } catch (err) {\n        // pass\n        }\n\n        if (simulate.finished) {\n          simulate.finished();\n        }\n\n        if (oldError) {\n          oldError(res);\n        }\n      };\n\n      simulate.run(config);\n    }\n  } catch (err) {\n    // we need to catch STOP() calls during initialization (e.g. stock initial values)\n    if (err.simulationCommand !== \"STOP\") {\n      throw err;\n    } else {\n      if (config.silent) {\n        return {\n          times: [],\n          value: () => {\n            return [];\n          },\n          lastValue: () => {\n          },\n          error: \"stop() called during initialization\",\n        };\n      }\n    }\n  }\n}\n\n\n/**\n * @param {any} x\n * @param {boolean=} removeVectors - if true, Vectors will be converted to basic types\n *\n * @returns\n */\nexport function cleanData(x, removeVectors = false) {\n  if (x instanceof Vector) {\n    if (removeVectors) {\n      if (x.names && x.names.length) {\n        let r = {};\n        for (let i = 0; i < x.names.length; i++) {\n          r[x.names[i]] = cleanData(x.items[i], removeVectors);\n        }\n        return r;\n      } else {\n        return x.items.map((x) => cleanData(x, removeVectors));\n      }\n    } else {\n      return new Vector(x.items.map((x) => cleanData(x, removeVectors)), x.simulate, x.names, x.parent);\n    }\n  } else if (typeof x === \"number\") {\n    return +x.toPrecision(15);\n  } else if (Array.isArray(x)) {\n    return x.map(x => cleanData(x, removeVectors));\n  }\n\n  return x;\n}\n\n\n/**\n * @param {import(\"./Simulator\").ResultsType} res\n *\n * @returns {import(\"./Simulator\").ResultsType}\n */\nexport function formatSimResults(res) {\n  /** @type {import(\"./Simulator\").ResultsType} */\n  let r = {};\n  r.times = res.times.slice();\n  r.data = res.data;\n  r.timeUnits = res.timeUnits;\n  r.children = res.children;\n  r.error = res.error;\n  r.errorPrimitive = res.errorPrimitive;\n  r.stochastic = res.stochastic;\n\n\n  if (!r.error) {\n    r.error = null;\n    r.errorPrimitive = null;\n  }\n  r.value = function (item) {\n    if (!item) {\n      throw new Error(\"Cannot get result value() of null or undefined primitive.\");\n    }\n    let entry = this.children[item.id];\n    if (!entry) {\n      throw new Error(\"Cannot find primitive in value() results.\");\n    }\n    return cleanData(entry.results, true);\n  };\n  r.lastValue = function (item) {\n    if (!item) {\n      throw new Error(\"Cannot get result lastValue() of null or undefined primitive.\");\n    }\n    let entry = this.children[item.id];\n    if (!entry) {\n      throw new Error(\"Cannot find primitive in lastValue() results.\");\n    }\n    return cleanData(entry.results[entry.results.length - 1], true);\n  };\n  if (r.times) {\n    r.periods = r.times.length;\n  }\n\n  return r;\n}\n\n\n/**\n * @param {string} u\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {import(\"./api/Blocks.js\").Primitive=} primitive\n *\n * @returns {import('./formula/Units').UnitStore}\n */\nexport function createUnitStore(u, simulate, primitive) {\n  if (!u || u.trim() === \"\" || u.trim().toLowerCase() === \"unitless\") {\n    return;\n  }\n\n  try {\n    // @ts-ignore\n    return simpleEquation(\"{1 \" + u + \"}\", simulate, new Map()).units;\n  } catch (_err) {\n    throw new ModelError(`Invalid units: \"<i>${u}</i>\"`, {\n      primitive: primitive,\n      showEditor: true,\n      code: 1012\n    });\n  }\n}\n\n\n/**\n * @param {string} eq\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {Map=} scope\n * @param {Map=} nodeBase\n * @param {object=} tree\n */\nexport function simpleEquation(eq, simulate, scope, nodeBase, tree) {\n  if (!scope) {\n    scope = new Map();\n  }\n  if (!nodeBase) {\n    nodeBase = new Map();\n  }\n  if (!tree) {\n    tree = trimTree(createTree(eq, \"_\", simulate), nodeBase, simulate);\n  }\n\n  let res = evaluateTree(tree, scope, simulate);\n\n  return res;\n}\n\n\n/**\n * @template {Material|Vector} T\n * @param {T} mat\n * @param {import('./formula/Units').UnitStore} units\n * @param {import('./Simulator').Simulator} simulate\n *\n * @returns {T extends Vector ? Vector : number}\n */\nexport function simpleNum(mat, units, simulate) {\n  if (mat instanceof Vector) {\n    return /** @type {any} */ (new Vector(mat.items.map((x) => {\n      return simpleNum(x, units, simulate);\n    }), simulate));\n  }\n\n  if (mat instanceof Material) {\n    if (!units && mat.units) {\n      throw new ModelError(`The result of the calculation has units <i>${mat.units.toString()}</i>, but no units are specified for the calculation. Please set the units for the calculation so we can determine the proper output.`,\n        {\n          code: 1013\n        });\n    }\n\n    if (!mat.units) {\n      return /** @type {any} */ (+mat.value);\n    } else {\n\n      mat.units.addBase();\n      units.addBase();\n\n      return /** @type {any} */ (+fn[\"*\"](mat.value, fn[\"/\"](mat.units.toBase, units.toBase)));\n    }\n\n  }\n}\n\n\n/**\n * @template {Material|Vector} T\n * @param {T} mat\n * @param {import('./formula/Units').UnitStore} units\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {(SPrimitive|import(\"./api/Blocks\").Primitive)=} primitive\n * @param {boolean=} showEditor\n * @param {string=} fallbackError\n *\n * @returns {T extends Vector ? Vector : Material}\n */\nexport function simpleUnitsTest(mat, units, simulate, primitive = null, showEditor = false, fallbackError = \"Unknown simpleUnits type\") {\n  if (mat instanceof Vector) {\n    return /** @type {any} */ (new Vector(mat.items.map((x) => {\n      return simpleUnitsTest(x, units, simulate, primitive, showEditor, fallbackError);\n    }), simulate));\n  }\n\n\n  if (mat instanceof Material) {\n    if (!mat.units && !units) {\n      return /** @type {any} */ (mat);\n    } else if (!mat.units) {\n      mat.units = units;\n      return /** @type {any} */ (mat);\n    } else if (mat.units === units) {\n      return /** @type {any} */ (mat);\n    } else {\n      let scale = convertUnits(mat.units, units);\n      if (scale === 0) {\n        throw new ModelError(`Wrong units generated. Expected <i>${units ? units.toString() : \"unitless\"}</i>, and got <i>${mat.units.toString()}</i>.`, {\n          primitive: primitive,\n          showEditor: showEditor,\n          code: 1014\n        });\n      } else {\n        mat.value = mat.value * scale;\n        mat.units = units;\n        return /** @type {any} */ (mat);\n      }\n    }\n  }\n\n  throw new ModelError(fallbackError, {\n    code: 1015\n  });\n\n}\n\n\n/**\n * @param {string} globals\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nfunction evaluateGlobals(globals, simulate) {\n  evaluateTree(trimTree(createTree(globals, \"macros\", simulate), new Map(), simulate), simulate.varBank, simulate);\n}\n\n\n/**\n * @param {import(\"./api/Blocks\").Primitive} node\n * @param {SubModelType} submodel\n * @param {Object<string, import(\"./Simulator\").SolverType>} solvers\n * @param {import(\"./Simulator\").Simulator} simulate\n *\n * @returns {DNA}\n */\nfunction getDNA(node, submodel, solvers, simulate) {\n  let dna = new DNA(node);\n\n  let l;\n  dna.solver = folderSolvers(node, solvers);\n  if (node) {\n    let p = node.parent;\n    if (p) {\n      dna.frozen = p.frozen;\n    }\n  }\n\n  if (node instanceof Variable || node instanceof Flow || node instanceof Transition) {\n    if (node.external) {\n      dna.slider = true;\n    }\n  }\n\n  if (node instanceof Flow || node instanceof Transition) {\n    if (node.end !== null) {\n      dna.targetId = node.end.id;\n    }\n    if (node.start !== null) {\n      dna.sourceId = node.start.id;\n    }\n  }\n\n  if (node instanceof Converter) {\n    dna.value = node.values;\n  } else {\n    try {\n      if (node instanceof Stock) {\n        dna.value = replaceMacros(node, dna, createTree(node.initial, \"p:\" + dna.id + \":initial\", simulate), submodel, solvers, simulate, true);\n      } else if (node instanceof Flow) {\n        dna.value = replaceMacros(node, dna, createTree(node.rate, \"p:\" + dna.id + \":rate\", simulate), submodel, solvers, simulate, false);\n      } else if (node instanceof Variable) {\n        dna.value = replaceMacros(node, dna, createTree(node.value, \"p:\" + dna.id + \":value\", simulate), submodel, solvers, simulate, false);\n      } else if (node instanceof State) {\n        dna.value = replaceMacros(node, dna, createTree(\"\" + node.startActive, \"p:\" + dna.id + \":startActive\", simulate), submodel, solvers, simulate, true);\n      } else if (node instanceof Transition) {\n        dna.value = replaceMacros(node, dna, createTree(\"\" + node.value, \"p:\" + dna.id + \":value\", simulate), submodel, solvers, simulate, false);\n      } else if (node instanceof Action) {\n        dna.value = replaceMacros(node, dna, createTree(node.action, \"p:\" + dna.id + \":action\", simulate), submodel, solvers, simulate, false);\n      }\n    } catch (err) {\n\n      let msg = `The primitive <i>[${sanitizeText(dna.name)}]</i> has an equation error that must be corrected before the model can be run.`;\n      if (err instanceof ModelError) {\n        msg = msg + \"<br/><br/>\" + err.message;\n      } else {\n        console.error(err);\n        msg = msg + \"<br/><br/>Unknown error.\";\n      }\n\n      l = undefined;\n      if (err.match && err.match(/line (\\d+)/i)) {\n        l = err.match(/line (\\d+)/i)[1];\n      }\n\n      throw new ModelError(msg, {\n        code: 1055,\n        primitive: node,\n        showEditor: true,\n        line: l,\n        details: err.match ? err : undefined\n      });\n    }\n  }\n\n\n  if (node instanceof Action) {\n    dna.trigger = node.trigger;\n    dna.repeat = node.repeat;\n    dna.recalculate = node.recalculate || node.trigger === \"Condition\";\n    try {\n      dna.triggerValue = createTree(node.value, \"p:\" + node.id + \":triggerValue\", simulate);\n    } catch (err) {\n      let msg = `The trigger for <i>[${sanitizeText(dna.name)}]</i> has an equation error that must be corrected before the model can be run.`;\n      if (err instanceof ModelError) {\n        msg = msg + \"<br/><br/>\" + err.message;\n      }\n      throw new ModelError(msg, {\n        code: 1056,\n        primitive: node,\n        showEditor: true,\n        line: l\n      });\n    }\n  } else if (node instanceof Transition) {\n    dna.trigger = node.trigger;\n    dna.repeat = node.repeat;\n    dna.recalculate = node.recalculate || node.trigger === \"Condition\";\n  } else if (node instanceof State) {\n    if (node.residency === undefined || node.residency.trim() === \"\") {\n      dna.residency = null;\n    } else {\n      try {\n        dna.residency = evaluateTree(trimTree(createTree(node.residency, \"p:\" + dna.id + \":residency\", simulate), new Map(), simulate), new Map(), simulate);\n        if (!dna.residency.units) {\n          dna.residency.units = simulate.timeUnits;\n        }\n        if (eq(dna.residency, new Material(0, simulate.timeUnits))) {\n          dna.residency = null;\n        }\n      } catch (err) {\n        throw new ModelError(\"Invalid state residency.\", {\n          primitive: node,\n          showEditor: false,\n          code: 1016\n        });\n      }\n    }\n    if (dna.residency) {\n      if (!(dna.residency instanceof Material)) {\n        throw new ModelError(\"State residency must be a number.\", {\n          primitive: node,\n          showEditor: false,\n          code: 1271\n        });\n      }\n      if (dna.residency.value < 0) {\n        throw new ModelError(\"State residency cannot be less than 0.\", {\n          primitive: node,\n          showEditor: false,\n          code: 1272\n        });\n      }\n    }\n  } else if (node instanceof Stock) {\n    dna.nonNegative = node.nonNegative;\n    if (node.type === \"Conveyor\") {\n      dna.stockType = \"Conveyor\";\n      try {\n        dna.delay = evaluateTree(trimTree(createTree(node.delay, \"p:\" + node.id + \":delay\", simulate), new Map(), simulate), new Map(), simulate);\n        if (!dna.delay.units) {\n          dna.delay.units = simulate.timeUnits;\n        }\n      } catch (err) {\n        throw new ModelError(\"Invalid stock delay.\", {\n          primitive: node,\n          showEditor: false,\n          code: 1017\n        });\n      }\n      if (!(dna.delay instanceof Material)) {\n        throw new ModelError(\"Stock delay must be a number.\", {\n          primitive: node,\n          showEditor: false,\n          code: 1073\n        });\n      }\n      if (dna.delay.value < 0) {\n        throw new ModelError(\"Stock delay cannot be less than 0.\", {\n          primitive: node,\n          showEditor: false,\n          code: 1074\n        });\n      }\n    }\n  } else if (node instanceof Flow) {\n    dna.nonNegative = node.nonNegative;\n  } else if (node instanceof Converter) {\n    dna.interpolation = node.interpolation === \"Linear\" ? \"linear\" : \"discrete\";\n\n    let data = node.values;\n\n    if (!data || !data.length) {\n      throw new ModelError(`The converter <i>[${sanitizeText(dna.name)}]</i> does not have any data.`, {\n        primitive: node,\n        showEditor: true,\n        code: 1018\n      });\n    }\n\n    /** @type {Material[]} */\n    let inp = [];\n    /** @type {Material[]} */\n    let out = [];\n\n    /** @type {import('./formula/Units').UnitStore} */\n    let myU;\n\n    if (node.input === \"Time\") {\n      myU = simulate.timeUnits;\n    } else {\n      let sourcePrimitive = node.input;\n      if (sourcePrimitive) {\n        myU = createUnitStore(sourcePrimitive.units, simulate, node);\n      } else {\n        throw new ModelError(`The converter <i>[${sanitizeText(dna.name)}]</i> does not have a source.`, {\n          primitive: node,\n          showEditor: true,\n          code: 1019\n        });\n      }\n    }\n\n    dna.source = node.input === \"Time\" ? node.input : node.input.id;\n\n    for (let i = 0; i < data.length; i++) {\n      inp.push(new Material(data[i].x, myU));\n      out.push(new Material(data[i].y));\n    }\n    dna.inputs = inp;\n    dna.outputs = out;\n  }\n\n  if (node instanceof ValuedPrimitive) {\n    if (!(node instanceof Transition) && !(node instanceof Action)) {\n      let u = node.units;\n      try {\n        if (!(node instanceof Flow) || (u && u.trim() && u.trim().toLowerCase() !== \"unitless\")) {\n          dna.units = createUnitStore(u, simulate, node);\n        } else {\n          dna.units = simulate.timeUnits.power(-1);\n          dna.flowUnitless = true;\n        }\n      } catch (err) {\n        throw new ModelError(`Invalid units specified for primitive: \"<i>${sanitizeText(u)}</i>\"`, {\n          primitive: node,\n          showEditor: true,\n          code: 1020\n        });\n      }\n    } else {\n      if (dna.trigger === \"Timeout\") {\n        dna.units = simulate.timeUnits;\n      }\n    }\n    let constraints = node.constraints;\n    dna.maxConstraint = constraints.max;\n    dna.useMaxConstraint = \"max\" in constraints;\n    dna.minConstraint = constraints.min;\n    dna.useMinConstraint = \"min\" in constraints;\n\n  }\n\n  if (dna.units) {\n    dna.units.addBase();\n    dna.toBase = dna.units.toBase;\n  }\n\n  dna.unitless = !dna.units;\n\n  return dna;\n}\n\n\n/**\n * @param {import(\"./api/Blocks\").Primitive} node\n * @param {Object<string, import(\"./Simulator\").SolverType>} solvers\n *\n * @return {import(\"./Simulator\").SolverType}\n */\nfunction folderSolvers(node, solvers) {\n  if (!node) {\n    return solvers.base;\n  }\n  if (node instanceof Population) {\n    let x = node.agentBase;\n    if (x && solvers[x.id]) {\n      return solvers[x.id];\n    }\n  }\n\n  let p = node.parent;\n  if (p && solvers[p.id]) {\n    return solvers[p.id];\n  }\n\n  return folderSolvers(p, solvers);\n}\n\n\n/**\n * @param {DNA} dna\n * @param {SAgent} agent\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {boolean} inContainer\n */\nexport function decodeDNA(dna, agent, simulate, inContainer) {\n  /** @type {SPrimitive} */\n  let x;\n  if (dna.primitive instanceof Variable) {\n    x = new SVariable(simulate);\n  } else if (dna.primitive instanceof State) {\n    x = new SState(simulate);\n  } else if (dna.primitive instanceof Transition) {\n    x = new STransition(simulate);\n  } else if (dna.primitive instanceof Action) {\n    x = new SAction(simulate);\n  } else if (dna.primitive instanceof Stock) {\n    x = new SStock(simulate);\n  } else if (dna.primitive instanceof Flow) {\n    x = new SFlow(simulate);\n  } else if (dna.primitive instanceof Converter) {\n    x = new SConverter(simulate);\n  }\n\n  if (x) {\n    x.dna = dna;\n    x.id = dna.id;\n    if (inContainer) {\n      x.index = agent.index;\n      x.agentId = agent.agentId;\n      x.container = agent;\n      x.createIds();\n    }\n\n    x.frozen = dna.frozen;\n\n    agent.children.push(x);\n    agent.childrenId[x.id] = x;\n\n    if (dna.slider) {\n      if (simulate.sliders[dna.id]) {\n        simulate.sliders[dna.id].push(x);\n      } else {\n        simulate.sliders[dna.id] = [x];\n      }\n    }\n\n\n    if (x instanceof SAction) {\n      dna.solver.actions.push(x);\n    } else if (x instanceof STransition) {\n      dna.solver.transitions.push(x);\n    } else if (!(x instanceof SPopulation)) {\n      dna.solver.valued.push(x);\n      if (x instanceof SFlow) {\n        dna.solver.flows.push(x);\n      } else if (x instanceof SStock) {\n        dna.solver.stocks.push(x);\n      } else if (x instanceof SState) {\n        dna.solver.states.push(x);\n      }\n    }\n\n    if (dna.neighborProxyDNA) {\n      x.neighborProxyPrimitive = agent.children.find(x => x.dna === dna.neighborProxyDNA);\n    }\n  } else if (dna.primitive instanceof Population) {\n    agent.children.push(dna.agents);\n    agent.childrenId[dna.id] = dna.agents;\n  }\n\n}\n\n\n/**\n * @param {import(\"./Primitives\").SPrimitive} primitive\n * @param {DNA} dna\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nexport function linkPrimitive(primitive, dna, simulate) {\n  if (!(primitive instanceof SPopulation)) {\n    let myNeighborhood = getPrimitiveNeighborhood(primitive.neighborProxyPrimitive ? primitive.neighborProxyPrimitive : primitive, primitive.neighborProxyPrimitive ? primitive.dna.neighborProxyDNA : dna, simulate, primitive.dna.extraLinksPrimitives);\n\n    if (primitive instanceof SFlow || primitive instanceof STransition) {\n      let localNeighborhood = myNeighborhood;\n      if (primitive.neighborProxyPrimitive) {\n        localNeighborhood = getPrimitiveNeighborhood(primitive, dna, simulate, primitive.dna.extraLinksPrimitives);\n      }\n\n      let alpha = null,\n        omega = null;\n\n      if (localNeighborhood.has(\"[alpha\")) {\n        alpha = /** @type {any} */ (localNeighborhood.get(\"[alpha\"));\n      }\n\n      if (localNeighborhood.has(\"[omega\")) {\n        omega = /** @type {any} */ (localNeighborhood.get(\"[omega\"));\n      }\n\n      if (primitive instanceof STransition) {\n        if (alpha && !(alpha instanceof SState)) {\n          throw new ModelError(`The start of the primitive <i>[${dna.name}]</i> must be a state.`, {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1060\n          });\n        }\n        if (omega && !(omega instanceof SState)) {\n          throw new ModelError(`The end of the primitive <i>[${dna.name}]</i> must be a state.`, {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1061\n          });\n        }\n      }\n\n      if (primitive instanceof SFlow) {\n        if (alpha && !(alpha instanceof SStock)) {\n          throw new ModelError(`The start of the primitive <i>[${dna.name}]</i> must be a stock.`, {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1062\n          });\n        }\n        if (omega && !(omega instanceof SStock)) {\n          throw new ModelError(`The end of the primitive <i>[${dna.name}]</i> must be a stock.`, {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1063\n          });\n        }\n      }\n\n      primitive.setEnds(alpha, omega);\n    }\n\n    if (primitive instanceof SAction) {\n      try {\n        primitive.equation = trimTree(dna.triggerValue, myNeighborhood, primitive.simulate);\n      } catch (err) {\n        let msg = `The primitive <i>[${sanitizeText(dna.name)}]</i> has an equation error that must be corrected before the model can be run.`;\n        if (err instanceof ModelError) {\n          msg = msg + \"<br/><br/>\" + err.message;\n        }\n\n        throw new ModelError(msg, {\n          primitive: dna.primitive,\n          showEditor: false,\n          code: 1064\n        });\n      }\n      try {\n        primitive.action = trimTree(dna.value, myNeighborhood, primitive.simulate);\n      } catch (err) {\n\n        let msg = `The primitive <i>[${sanitizeText(dna.name)}]</i> has an equation error that must be corrected before the model can be run.`;\n        if (err instanceof ModelError) {\n          msg = msg + \"<br/><br/>\" + err.message;\n        }\n        let l = undefined;\n        if (err.match && err.match(/line (\\d+)/i)) {\n          l = err.match(/line (\\d+)/i)[1];\n        }\n\n        throw new ModelError(msg, {\n          primitive: dna.primitive,\n          showEditor: true,\n          code: 1065,\n          line: l,\n          details: err.match ? err : undefined\n        });\n      }\n    } else if (primitive instanceof SConverter) {\n      if (dna.source === \"Time\") {\n        primitive.setSource(\"*time\");\n      } else {\n        let source = dna.source;\n        let sourceSet = false;\n        let neighborIds = getPrimitiveNeighborhood(primitive, dna, simulate, [], true);\n        for (let neighborId of neighborIds.keys()) {\n          if (source === neighborId) {\n            primitive.setSource(neighborIds.get(neighborId));\n            sourceSet = true;\n            break;\n          }\n        }\n\n        if (!sourceSet) {\n          throw new ModelError(\"Converter source could not be found. Please redefine it.\", {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1066\n          });\n        }\n\n\n      }\n    } else {\n      primitive.setEquation(dna.value, myNeighborhood);\n    }\n  }\n}\n\n\n/**\n * @param {SAgent} agent\n */\nexport function setAgentInitialValues(agent) {\n  for (let child of agent.children) {\n    if (child instanceof SStock) {\n      child.setDelay();\n      try {\n        child.setInitialValue();\n      } catch (err) {\n        if (err instanceof ModelError) {\n          if (!err.primitive) {\n            // if we don't have a primitive, use this one\n            // otherwise keep the original error source\n            err.primitive = child.orig();\n          }\n          throw err;\n        } else {\n          throw err;\n        }\n      }\n    } else if (child instanceof SState) {\n      try {\n        if (child.active === null) {\n          child.setInitialActive(true);\n        }\n      } catch (err) {\n        if (err instanceof ModelError) {\n          if (!err.primitive) {\n            // if we don't have a primitive, use this one\n            // otherwise keep the original error source\n            err.primitive = child.orig();\n          }\n          throw err;\n        } else {\n          throw err;\n        }\n      }\n    }\n  }\n}\n\n\n/**\n * @param {SubModelType} submodel\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nfunction buildNetwork(submodel, simulate) {\n  if (submodel.network === \"Custom Function\") {\n    let neighbors = getPrimitiveNeighborhood(submodel, submodel.dna, simulate, []);\n    let tree = trimTree(createTree(submodel.networkFunction, \"p:\" + submodel.id + \":networkFunction\", simulate), neighbors, simulate);\n    for (let i = 0; i < submodel.agents.length - 1; i++) {\n      for (let j = i + 1; j < submodel.agents.length; j++) {\n        // @ts-ignore\n        if (trueValue(simpleEquation(submodel.networkFunction, simulate, new Map([\n          [PARENT_SYMBOL, simulate.varBank],\n          [\"a\", submodel.agents[i]],\n          [\"b\", submodel.agents[j]]\n        ]), neighbors, tree))) {\n          submodel.agents[i].connect(submodel.agents[j]);\n        }\n      }\n    }\n  } else if (submodel.network === \"None\") {\n    // nothing to do\n  } else {\n    throw new ModelError(`Unknown network type: ${sanitizeText(submodel.network)}.`, {\n      primitive: submodel.node,\n      showEditor: false,\n      code: 1024\n    });\n  }\n}\n\n\n/**\n * @param {SubModelType} submodel\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nfunction buildPlacements(submodel, simulate) {\n  let tree;\n  /** @type {number} */\n  let wCount;\n  /** @type {number} */\n  let hCount;\n\n\n  if (submodel.placement === \"Random\") {\n    for (let agent of submodel.agents) {\n      agent.location = new Vector([mult(submodel.geoWidth, new Material(Rand(simulate))), mult(submodel.geoHeight, new Material(Rand(simulate)))], simulate, [\"x\", \"y\"]);\n    }\n  } else if (submodel.placement === \"Custom Function\") {\n    submodel.agents.forEach((s) => {\n      let n = getPrimitiveNeighborhood(submodel, submodel.dna, simulate, []);\n      // @ts-ignore\n      n.set(\"self\", s);\n      // @ts-ignore\n      s.location = simpleUnitsTest(/** @type {Vector} */(simpleEquation(submodel.placementFunction, simulate, new Map([\n        [PARENT_SYMBOL, simulate.varBank],\n        [\"self\", s]\n      ]), n)), submodel.geoDimUnitsObject, simulate, null, null, \"Agent placement functions must return a two element vector\");\n\n      validateAgentLocation(s.location, submodel.node);\n\n      if (!s.location.names) {\n        s.location.names = [\"x\", \"y\"];\n        s.location.namesLC = [\"x\", \"y\"];\n      }\n    });\n  } else if (submodel.placement === \"Grid\") {\n    tree = trimTree(createTree(\"{x: x*width(self), y: y*height(self)}\", \"_\", simulate), new Map(), simulate);\n    let size = submodel.agents.length;\n    // @ts-ignore\n    let ratio = /** @type {number} */ (simpleNum(simpleEquation(\"width(self)/height(self)\", simulate, new Map([\n      [PARENT_SYMBOL, simulate.varBank],\n      [\"self\", submodel]\n    ]), new Map()), submodel.geoDimUnitsObject, simulate));\n\n    hCount = Math.sqrt(size / ratio);\n    wCount = Math.floor(hCount * ratio);\n\n    hCount = Math.ceil(hCount);\n    if (hCount * wCount < size) {\n      wCount = wCount + 1;\n    }\n\n    let j = 0;\n    submodel.agents.forEach((s) => {\n      let xPos = (j % wCount + 0.5) / wCount;\n      let yPos = (Math.floor(j / wCount) + 0.5) / hCount;\n      // @ts-ignore\n      s.location = simpleUnitsTest(/** @type {Vector} */(simpleEquation(null, simulate, new Map([\n        [\"self\", s],\n        [\"x\", new Material(xPos)],\n        [\"y\", new Material(yPos)],\n        [PARENT_SYMBOL, simulate.varBank]\n      ]), new Map(), tree)), submodel.geoDimUnitsObject, simulate);\n      j++;\n    });\n  } else if (submodel.placement === \"Ellipse\") {\n    tree = trimTree(createTree(\"{width(self), height(self)}/2+{sin(index(self)/size*2*3.14159), cos(index(self)/size*2*3.14159)}*{width(self), height(self)}/2\", \"_\", simulate), new Map(), simulate);\n    let size = new Material(submodel.agents.length);\n    submodel.agents.forEach((s) => {\n      // @ts-ignore\n      s.location = simpleUnitsTest(/** @type {Vector} */(simpleEquation(null, simulate, new Map([\n        [\"self\", s],\n        [\"size\", size],\n        [PARENT_SYMBOL, simulate.varBank]\n      ]), new Map(), tree)), submodel.geoDimUnitsObject, simulate);\n    });\n  } else if (submodel.placement === \"Network\") {\n    tree = trimTree(createTree(\"{x: x*width(self), y: y*height(self)}\", \"_\", simulate), new Map(), simulate);\n\n    let graph = new Graph();\n\n    let nodes = submodel.agents.map((s) => {\n      return graph.newNode({\n        data: s\n      });\n    });\n    let getNode = function (item) {\n      for (let node of nodes) {\n        if (node.data.data === item) {\n          return node;\n        }\n      }\n      return null;\n    };\n    submodel.agents.forEach((a) => {\n      a.connected.forEach((target) => {\n        graph.newEdge(getNode(a), getNode(target));\n      });\n    });\n\n    let layout = new Layout.ForceDirected(graph, 400.0, 600.0, 0.5);\n    layout.getRandom = () => Rand(simulate);\n\n    for (let i = 0; i < 60; i++) {\n      layout.applyCoulombsLaw();\n      layout.applyHookesLaw();\n      layout.attractToCentre();\n      layout.updateVelocity(0.03);\n      layout.updatePosition(0.03);\n    }\n\n    let bb = layout.getBoundingBox();\n\n    bb.width = bb.topright.x - bb.bottomleft.x;\n    bb.height = bb.topright.y - bb.bottomleft.y;\n\n    let scalePoint = function (p) {\n      return {\n        x: (p.x - bb.bottomleft.x) / bb.width,\n        y: (p.y - bb.bottomleft.y) / bb.height\n      };\n    };\n\n    layout.eachNode((node, point) => {\n      let p = scalePoint(point.p);\n      // @ts-ignore\n      node.data.data.location = simpleUnitsTest(simpleEquation(null, simulate, new Map([\n        [\"self\", submodel],\n        [\"x\", new Material(p.x)],\n        [\"y\", new Material(p.y)],\n        [PARENT_SYMBOL, simulate.varBank]\n      ]), new Map(), tree), submodel.geoDimUnitsObject, simulate);\n    });\n\n  } else {\n    throw new ModelError(`Unknown placement type: ${sanitizeText(submodel.placement)}.`, {\n      primitive: submodel.node,\n      showEditor: false,\n      code: 1021\n    });\n  }\n\n}\n\n\nexport const DUPLICATE_PRIMITIVE_NAMES = Symbol(\"DUPLICATE_PRIMITIVE_NAMES\");\n/**\n * @param {import(\"./Primitives\").SPrimitive} primitive\n * @param {DNA} dna\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {Primitive[]} extraLinksPrimitives\n * @param {boolean=} useIdKeys - use id's as the keys in the returned Map instead of names\n *\n * @returns {Map<string, import('./Primitives').SPrimitive>}\n */\nexport function getPrimitiveNeighborhood(primitive, dna, simulate, extraLinksPrimitives, useIdKeys = false) {\n  let neighbors = dna.primitive.neighbors();\n  if (extraLinksPrimitives) {\n    for (let link of extraLinksPrimitives) {\n      neighbors.push({\n        item: link,\n        type: \"direct\"\n      });\n    }\n  }\n\n  /** @type {Map<string, Placeholder>} */\n  let placeholders = new Map();\n\n  /** @type {Map} */\n  let ns = new Map([[\n    \"self\", primitive\n  ]]);\n\n\n  if (primitive instanceof SPopulation) {\n    for (let dna of primitive.DNAs) {\n      placeholders.set(dna.name.toLowerCase(), new Placeholder(dna, primitive, simulate));\n    }\n  }\n\n  for (let neighbor of neighbors) {\n    let item = neighbor.item;\n    function addNeighbor(name, item) {\n      if (useIdKeys) {\n        ns.set(item.id, item);\n        return;\n      }\n\n      // If it's a placeholder, we don't flag conflicts\n      // non-placeholders take precedence over placeholders and non-placeholders\n      // can be used in place of placeholders during the simulation.\n      let isPlaceholder = item instanceof Placeholder;\n      if (ns.has(name) && !(ns.get(name) instanceof Placeholder)) {\n        if (ns.get(name) !== item) {\n          if (!isPlaceholder) {\n            ns.set(name, DUPLICATE_PRIMITIVE_NAMES);\n          }\n        }\n      } else {\n        ns.set(name, item);\n      }\n\n      if (!isPlaceholder) {\n        if (primitive instanceof SFlow || primitive instanceof STransition) {\n          if (dna.targetId === item.id) {\n            ns.set(\"[omega\", item);\n          } else if (dna.sourceId === item.id) {\n            ns.set(\"[alpha\", item);\n          }\n        }\n      }\n    }\n\n    if (item instanceof Population) {\n      addNeighbor(primitive.simulate.simulationModel.submodels[item.id].dna.name.toLowerCase(), primitive.simulate.simulationModel.submodels[item.id]);\n\n      for (let dna of primitive.simulate.simulationModel.submodels[item.id].DNAs) {\n        addNeighbor(dna.name.toLowerCase(), new Placeholder(dna, primitive, simulate));\n      }\n    } else if (neighbor.type !== \"agent\") {\n      let found = false;\n      if (primitive.container) {\n        if (primitive.container.childrenId[item.id]) {\n          addNeighbor(\n            primitive.container.childrenId[item.id].dna.name.toLowerCase(),\n            primitive.container.childrenId[item.id]\n          );\n          found = true;\n        }\n      }\n      if (!found) {\n        if (primitive.simulate.simulationModel.submodels[\"base\"][\"agents\"][0].childrenId[item.id]) {\n\n          addNeighbor(primitive.simulate.simulationModel.submodels[\"base\"][\"agents\"][0].childrenId[item.id].dna.name.toLowerCase(), primitive.simulate.simulationModel.submodels[\"base\"][\"agents\"][0].childrenId[item.id]);\n          found = true;\n        }\n      }\n\n\n      if (!found && (primitive instanceof SFlow || primitive instanceof STransition) && item === simulate.model.getId(item.id)) {\n        if (primitive instanceof SFlow) {\n          throw new ModelError(\"Flow primitives may not cross agent boundaries.\", {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1070\n          });\n        } else {\n          throw new ModelError(\"Transition primitives may not cross agent boundaries.\", {\n            primitive: dna.primitive,\n            showEditor: false,\n            code: 1071\n          });\n        }\n      }\n    }\n  }\n\n\n  for (let key of placeholders.keys()) {\n    if (!ns.has(key)) {\n      ns.set(key, placeholders.get(key));\n    }\n  }\n\n\n  return ns;\n}\n\n\n/**\n * @param {import(\"./api/Blocks\").Primitive} node\n *\n * @returns {boolean}\n */\nfunction modelType(node) {\n  return (node instanceof Stock) || (node instanceof Flow) || (node instanceof State) || (node instanceof Transition) || (node instanceof Converter) || (node instanceof Variable) || (node instanceof Action) || (node instanceof Population);\n}\n\n\n/**\n * @param {import(\"./Simulator\").SolverType} solver\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nexport function updateDisplayed(solver, simulate) {\n  let displayed = solver.displayed;\n\n  if (simulate.displayInformation.store) {\n    for (let k = simulate.displayInformation.store.data.length; k < simulate.results.times.length; k++) {\n      let inStore = simulate.displayInformation.store.data[k];\n      let d = {};\n      if (!inStore) {\n        d[\"id\"] = k;\n        d[\"Time\"] = simulate.results.times[k];\n      }\n\n      if (displayed.length > 0) {\n        if (simulate.results.data[k][displayed[0].id] === undefined) {\n          // continue;\n        } else {\n          for (let j = 0; j < displayed.length; j++) {\n\n            let i = simulate.displayInformation.ids.indexOf(displayed[j].id);\n\n            if (i > -1) {\n              if (simulate.results.children[simulate.displayInformation.ids[i]].states) {\n                let states = simulate.results.children[simulate.displayInformation.ids[i]].states;\n\n                if (simulate.results.data[k][displayed[j].id]) {\n                  let current = simulate.results.data[k][displayed[j].id].current;\n\n                  /** @type {Object<string, number>} */\n                  let tally = {};\n                  for (let item of current) {\n                    if (item.state) {\n                      for (let state of item.state) {\n                        tally[state.id.toString()] = tally[state.id.toString()] + 1 || 1;\n                      }\n                    }\n                  }\n\n                  let q = 0;\n                  states.forEach(state => {\n                    d[simulate.displayInformation.elementIds[i + q]] = tally[state] || 0;\n                    q++;\n                  });\n                }\n              } else if (simulate.results.children[simulate.displayInformation.ids[i]].indexedNames) {\n                let z = 0;\n                while (i < simulate.displayInformation.ids.length && simulate.displayInformation.ids[i] === displayed[j].id) {\n                  try {\n                    d[simulate.displayInformation.elementIds[i]] = selectFromMatrix(simulate.results.data[k][displayed[j].id].fullClone(), simulate, simulate.results.children[simulate.displayInformation.ids[i]].indexedFullNames[z].slice());\n                  } catch (err) {\n                    throw new ModelError(\"Cannot change vector keys during a simulation.\", {\n                      primitive: displayed[j].dna.primitive,\n                      showEditor: true,\n                      code: 1022\n                    });\n\n                  }\n\n                  z++;\n                  i++;\n                }\n\n              } else {\n                d[simulate.displayInformation.elementIds[i]] = simulate.results.data[k][displayed[j].id];\n              }\n            }\n          }\n        }\n      }\n\n      if (inStore) {\n        Object.assign(inStore, d);\n      } else {\n        simulate.displayInformation.store.data.push(d);\n      }\n    }\n\n    if (!simulate.resultsWindow) {\n      simulate.resultsWindow = simulate.config.createResultsWindow(simulate);\n    }\n  }\n}\n\n\nexport function validateAgentLocation(location, primitive) {\n  let invalidLocationError = () => {\n    throw new ModelError(\"Agent placement functions must return a two element vector\", {\n      primitive,\n      showEditor: false,\n      code: 1023\n    });\n  };\n\n  if (!(location instanceof Vector)) {\n    invalidLocationError();\n  }\n\n  if (location.length() !== 2) {\n    invalidLocationError();\n  }\n\n  if (!(location.items[0] instanceof Material)) {\n    invalidLocationError();\n  }\n\n  if (!(location.items[1] instanceof Material)) {\n    invalidLocationError();\n  }\n\n}\n\n/**\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nfunction makeClusters(simulate) {\n  /** @type {Object<string, { cluster: number, flow: number }>} */\n  let ordering = {};\n\n  let flows = simulate.model.findFlows();\n  let clusterId = 0;\n  while (flows.length) {\n    clusterId++;\n\n    let flow = flows[0];\n\n    let cluster = {\n      availableFlows: flows,\n      edges: [],\n      stockSet: new Set(),\n      flowSet: new Set(),\n      simulate\n    };\n\n    clusterAddFlow(cluster, flow);\n\n    let sorted;\n    try {\n      sorted = toposort(cluster.edges);\n    } catch (_err) {\n      // circular - so order by id.\n      // TODO: explore if there is something better we can do in this\n      // case\n      let items = [...cluster.flowSet.values()];\n      items.sort((a, b) => a.id - b.id);\n      let flowCount = 0;\n      for (let flow of items) {\n        flowCount++;\n        ordering[flow.id] = {\n          cluster: clusterId,\n          flow: flowCount\n        };\n      }\n      continue;\n    }\n\n    let flowCount = 0;\n    for (let item of sorted) {\n      if (item instanceof Flow) {\n        flowCount++;\n        ordering[item.id] = {\n          cluster: clusterId,\n          flow: flowCount\n        };\n      }\n    }\n  }\n\n  return ordering;\n}\n\n\n\n/**\n * @param {*} cluster\n * @param {Flow} flow\n */\nfunction clusterAddFlow(cluster, flow) {\n  cluster.flowSet.add(flow);\n  cluster.availableFlows.splice(cluster.availableFlows.indexOf(flow), 1);\n  let alpha = flow.start;\n  let omega = flow.end;\n\n  if (alpha && alpha.nonNegative) {\n    cluster.edges.push([alpha, flow]);\n    if (!cluster.stockSet.has(alpha)) {\n      cluster.stockSet.add(alpha);\n      clusterAddStock(cluster, alpha);\n    }\n  }\n  if (omega && omega.nonNegative) {\n    cluster.edges.push([flow, omega]);\n    if (!cluster.stockSet.has(omega)) {\n      cluster.stockSet.add(omega);\n      clusterAddStock(cluster, omega);\n    }\n  }\n}\n\n/**\n * @param { {availableFlows: Flow[], simulate: import(\"./Simulator\").Simulator} } cluster\n * @param {Stock} stock\n */\nfunction clusterAddStock(cluster, stock) {\n  let found = true;\n  while (found) {\n    found = false;\n    for (let flow of cluster.availableFlows) {\n      let alpha = flow.start;\n      let omega = flow.end;\n\n      if (alpha === stock || omega === stock) {\n        clusterAddFlow(cluster, flow);\n        found = true;\n        break;\n      }\n    }\n  }\n}\n\n\n// Ensures each macro primitive has a unique name\nlet macroCounter = 0;\n\n\n\n\nfunction delayGenerator(parameters, primitiveDNA, node, submodel, solvers, simulate) {\n  let {\n    input,\n    initialValue,\n    period,\n    order\n  } = parameters;\n\n  order = evaluateTree(trimTree(order, new Map(), simulate), new Map(), simulate).value;\n\n\n  if (order < 1 || order !== Math.floor(order)) {\n    throw new ModelError(\"DelayN order must be an integer greater than or equal to 1.\", {\n      primitive: primitiveDNA.primitive,\n      showEditor: true,\n      code: 1078\n    });\n  }\n\n  let m = new Model();\n\n\n  let outflowName = \"__DelayN Outflow \" + macroCounter++;\n\n  let stockNames = [];\n  let stocks = [];\n  let flows = [];\n\n\n\n  for (let i = 0; i < order; i++) {\n    stockNames.push(\"__DelayN Stock \" + macroCounter++);\n    stocks.push(m.Stock({\n      name: stockNames[stockNames.length - 1],\n      initial: \"(iv) || (i)\"\n    }));\n    stocks[i]._node.id = \"\" + Math.random();\n  }\n\n\n  let f = m.Flow(null, stocks[0], {\n    name: \"DelayN Inflow\",\n    rate: \"(i)\",\n    nonNegative: false\n  });\n  f._node.id = \"\" + Math.random();\n  flows.push(f);\n\n  for (let i = 1; i < order; i++) {\n    f = m.Flow(stocks[i - 1], stocks[i], {\n      name: \"DelayN Flow \" + i,\n      rate: \"(alpha) / (p/order)\",\n      nonNegative: false\n    });\n    f._node.id = \"\" + Math.random();\n    flows.push(f);\n  }\n\n  f = m.Flow(stocks[order - 1], null, {\n    name: outflowName,\n    rate: \"(alpha) / (p/order)\",\n    nonNegative: false\n  });\n  f._node.id = \"\" + Math.random();\n  flows.push(f);\n\n\n\n\n  period = new TreeNode(\"LINES\", \"LINES\", node.position, [\n    // create temp variable with unitless value\n    new TreeNode(\"ASSIGN\", \"ASSIGN\", node.position, [\n      new TreeNode(\"ASSIGNED\", \"ASSIGNED\", node.position, [\n        new TreeNode(\"__tmp_macro_period\", \"IDENT\", node.position)\n      ]),\n      new TreeNode(\"INNER\", \"INNER\", node.position, [\n        new TreeNode(\"RemoveUnits\", \"IDENT\", node.position),\n        new TreeNode(\"FUNCALL\", \"FUNCALL\", node.position, [\n          period,\n          new TreeNode(\"\\\"\" + simulate.timeUnitsString + \"\\\"\", \"STRING\", node.position)\n        ])\n      ])\n    ]),\n    // assert it's greater than 0\n    new TreeNode(\"INNER\", \"INNER\", node.position, [\n      new TreeNode(\"Assert\", \"IDENT\", node.position),\n      new TreeNode(\"FUNCALL\", \"FUNCALL\", node.position, [\n        // Code for:\n        //   > not contains({PERIOD > 0}, false)\n        // this confirms all the values in period are greater than 0\n        // period can be a scalar or vector\n        new TreeNode(\"NOT\", \"NOT\", node.position, [\n\n          new TreeNode(\"INNER\", \"INNER\", node.position, [\n            new TreeNode(\"Contains\", \"IDENT\", node.position),\n            new TreeNode(\"FUNCALL\", \"FUNCALL\", node.position, [\n\n              new TreeNode(\"ARRAY\", \"ARRAY\", node.position, [\n                new TreeNode(\"LABEL\", \"LABEL\", node.position, [\n                  new TreeNode(\"INNER\", \"INNER\", node.position, [\n                    new TreeNode(\">\", \"GT\", node.position, [\n                      new TreeNode(\"__tmp_macro_period\", \"IDENT\", node.position),\n                      new TreeNode(\"0\", \"INTEGER\", node.position)\n                    ])\n                  ])\n                ])\n              ]),\n              new TreeNode(\"FALSE\", \"FALSE\", node.position)\n            ])\n          ]),\n        ]),\n\n        new TreeNode(\"\\\"Period for Delay() must be greater than 0.\\\"\", \"STRING\", node.position)\n      ])\n    ]),\n    // return it\n    new TreeNode(\"__tmp_macro_period\", \"IDENT\", node.position)\n  ]);\n\n  let periodOverOrder = new TreeNode(\"DIV\", \"DIV\", node.position, [\n    period,\n    new TreeNode(\"\" + order, \"INTEGER\", node.position)\n  ]);\n\n  let sDNAs = stocks.map((s) => getDNA(s, submodel, solvers, simulate));\n  let fDNAs = flows.map((i) => getDNA(i, submodel, solvers, simulate));\n\n\n  for (let i = 1; i < fDNAs.length; i++) {\n    fDNAs[i].extraLinksPrimitives.push(stocks[i - 1]);\n  }\n\n  primitiveDNA.extraLinksPrimitives.push(flows[flows.length - 1]);\n\n  fDNAs[0].value = input.cloneStructure();\n  let init = new TreeNode(\"MULT\", \"MULT\", node.position, [\n    initialValue ? initialValue.cloneStructure() : input.cloneStructure(),\n    periodOverOrder.cloneStructure()\n  ]);\n  for (let i = 0; i < sDNAs.length; i++) {\n    sDNAs[i].value = init.cloneStructure();\n  }\n\n  for (let i = 1; i < fDNAs.length; i++) {\n    fDNAs[i].value = new TreeNode(\"DIV\", \"DIV\", node.position, [\n      new TreeNode(\"[\" + stockNames[i - 1] + \"]\", \"PRIMITIVE\", node.position),\n      periodOverOrder.cloneStructure()\n    ]);\n  }\n\n  for (let i = 0; i < sDNAs.length; i++) {\n    sDNAs[i].noOutput = true;\n    sDNAs[i].adoptUnits = true;\n    sDNAs[i].neighborProxyDNA = primitiveDNA;\n    submodel.DNAs.push(sDNAs[i]);\n  }\n\n  for (let i = 0; i < fDNAs.length; i++) {\n    fDNAs[i].noOutput = true;\n    fDNAs[i].adoptUnits = true;\n    fDNAs[i].neighborProxyDNA = primitiveDNA;\n    submodel.DNAs.push(fDNAs[i]);\n  }\n\n\n  return new TreeNode(\"[\" + outflowName + \"]\", \"PRIMITIVE\", node.position);\n}\n\n\nfunction smoothGenerator(parameters, primitiveDNA, node, submodel, solvers, simulate) {\n  let {\n    input,\n    initialValue,\n    period,\n    order\n  } = parameters;\n\n  order = evaluateTree(trimTree(order, new Map(), simulate), new Map(), simulate).value;\n\n  if (order < 1 || order !== Math.floor(order)) {\n    throw new ModelError(\"SmoothN order must be an integer greater than or equal to 1.\", {\n      primitive: primitiveDNA.primitive,\n      showEditor: true,\n      code: 1079\n    });\n  }\n\n  let m = new Model();\n\n\n  let stockNames = [];\n  let stocks = [];\n  let flows = [];\n\n\n  for (let i = 0; i < order; i++) {\n    stockNames.push(\"__SmoothN Stock \" + macroCounter++);\n    stocks.push(m.Stock({\n      name: stockNames[stockNames.length - 1],\n      initial: \"(iv) || (i)\"\n    }));\n    stocks[i]._node.id = \"\" + Math.random();\n  }\n\n  for (let i = 0; i < order; i++) {\n    let f = m.Flow(null, stocks[i], {\n      name: \"SmoothN Flow \" + i,\n      rate: \"(alpha) / (p/order)\",\n      nonNegative: false\n    });\n    f._node.id = \"\" + Math.random();\n    flows.push(f);\n  }\n\n\n\n\n  period = new TreeNode(\"LINES\", \"LINES\", node.position, [\n    // create temp variable with unitless value\n    new TreeNode(\"ASSIGN\", \"ASSIGN\", node.position, [\n      new TreeNode(\"ASSIGNED\", \"ASSIGNED\", node.position, [\n        new TreeNode(\"__tmp_macro_period\", \"IDENT\", node.position)\n      ]),\n      new TreeNode(\"INNER\", \"INNER\", node.position, [\n        new TreeNode(\"RemoveUnits\", \"IDENT\", node.position),\n        new TreeNode(\"FUNCALL\", \"FUNCALL\", node.position, [\n          period,\n          new TreeNode(\"\\\"\" + simulate.timeUnitsString + \"\\\"\", \"STRING\", node.position)\n        ])\n      ])\n    ]),\n    // assert it's greater than 0\n    new TreeNode(\"INNER\", \"INNER\", node.position, [\n      new TreeNode(\"Assert\", \"IDENT\", node.position),\n      new TreeNode(\"FUNCALL\", \"FUNCALL\", node.position, [\n\n\n        // Code for:\n        //   > not contains({PERIOD > 0}, false)\n        // this confirms all the values in period are greater than 0\n        // period can be a scalar or vector\n        new TreeNode(\"NOT\", \"NOT\", node.position, [\n\n          new TreeNode(\"INNER\", \"INNER\", node.position, [\n            new TreeNode(\"Contains\", \"IDENT\", node.position),\n            new TreeNode(\"FUNCALL\", \"FUNCALL\", node.position, [\n\n              new TreeNode(\"ARRAY\", \"ARRAY\", node.position, [\n                new TreeNode(\"LABEL\", \"LABEL\", node.position, [\n                  new TreeNode(\"INNER\", \"INNER\", node.position, [\n                    new TreeNode(\">\", \"GT\", node.position, [\n                      new TreeNode(\"__tmp_macro_period\", \"IDENT\", node.position),\n                      new TreeNode(\"0\", \"INTEGER\", node.position)\n                    ])\n                  ])\n                ])\n              ]),\n              new TreeNode(\"FALSE\", \"FALSE\", node.position)\n            ])\n          ]),\n        ]),\n\n        new TreeNode(\"\\\"Period for Smooth() must be greater than 0.\\\"\", \"STRING\", node.position)\n      ])\n    ]),\n    // return it\n    new TreeNode(\"__tmp_macro_period\", \"IDENT\", node.position)\n  ]);\n\n  let periodOverOrder = new TreeNode(\"DIV\", \"DIV\", node.position, [\n    period,\n    new TreeNode(\"\" + order, \"INTEGER\", node.position)\n  ]);\n\n  let sDNAs = stocks.map((s) => getDNA(s, submodel, solvers, simulate));\n  let fDNAs = flows.map((i) => getDNA(i, submodel, solvers, simulate));\n\n  for (let i = 0; i < order; i++) {\n    fDNAs[i].extraLinksPrimitives.push(stocks[i]);\n    if (i > 0) {\n      fDNAs[i].extraLinksPrimitives.push(stocks[i - 1]);\n    }\n  }\n\n  primitiveDNA.extraLinksPrimitives.push(stocks[stocks.length - 1]);\n\n\n  for (let i = 0; i < order; i++) {\n    sDNAs[i].value = initialValue ? initialValue.cloneStructure() : input.cloneStructure();\n  }\n\n  for (let i = 0; i < order; i++) {\n    fDNAs[i].value = new TreeNode(\"DIV\", \"DIV\", node.position, [\n      new TreeNode(\"MINUS\", \"MINUS\", node.position, [\n        i === 0 ? input.cloneStructure() : new TreeNode(\"[\" + stockNames[i - 1] + \"]\", \"PRIMITIVE\", node.position),\n        new TreeNode(\"[\" + stockNames[i] + \"]\", \"PRIMITIVE\", node.position)\n      ]),\n      periodOverOrder.cloneStructure()\n    ]);\n  }\n\n  for (let i = 0; i < order; i++) {\n    fDNAs[i].noOutput = true;\n    fDNAs[i].adoptUnits = true;\n    fDNAs[i].neighborProxyDNA = primitiveDNA;\n    submodel.DNAs.push(fDNAs[i]);\n    sDNAs[i].noOutput = true;\n    sDNAs[i].adoptUnits = true;\n    sDNAs[i].neighborProxyDNA = primitiveDNA;\n    submodel.DNAs.push(sDNAs[i]);\n  }\n\n\n\n  return new TreeNode(\"[\" + stockNames[stockNames.length - 1] + \"]\", \"PRIMITIVE\", node.position);\n\n}\n\n\n\n\n/** @type {Object<string, { replacement: function(any, DNA, TreeNode, any, any, import(\"./Simulator\").Simulator): TreeNode}>} */\nconst MACRO_FNS = {\n  \"_initial\": {\n    replacement: (parameters) => {\n      let {\n        input,\n        initialValue\n      } = parameters;\n\n      // when used in a stock or state initial value, just replace with the initial value\n      return initialValue ? initialValue.cloneStructure() : input.cloneStructure();\n    }\n  },\n  \"smooth\": {\n    replacement: (parameters, primitiveDNA, node, submodel, solvers, simulate) => {\n      parameters.order = new TreeNode(\"1\", \"INTEGER\", node.position);\n      return smoothGenerator(parameters, primitiveDNA, node, submodel, solvers, simulate);\n    }\n  },\n  \"smoothn\": {\n    replacement: (...params) => smoothGenerator(...params)\n  },\n  \"delay1\": {\n    replacement: (parameters, primitiveDNA, node, submodel, solvers, simulate) => {\n      parameters.order = new TreeNode(\"1\", \"INTEGER\", node.position);\n      return delayGenerator(parameters, primitiveDNA, node, submodel, solvers, simulate);\n    }\n  },\n  \"delay3\": {\n    replacement: (parameters, primitiveDNA, node, submodel, solvers, simulate) => {\n      parameters.order = new TreeNode(\"3\", \"INTEGER\", node.position);\n      return delayGenerator(parameters, primitiveDNA, node, submodel, solvers, simulate);\n    }\n  },\n  \"delayn\": {\n    replacement: (...params) => delayGenerator(...params)\n  }\n};\n\n\n/**\n * @param {TreeNode[]} children\n * @param {string} name\n * @param {{ target: string, value: TreeNode }[]} assigns\n *\n * @returns\n */\nfunction getMacroParameters(children, name, assigns) {\n  let requiresOrder = name.toLowerCase().endsWith(\"n\");\n\n  if (children.length > 3 + (requiresOrder ? 1 : 0) || children.length < 2 + (requiresOrder ? 1 : 0) ) {\n    throw new ModelError(`Wrong number of parameters for ${name}().`, {\n      code: 10001\n    });\n  }\n\n  // We pull in the first level of assigns. fully solving the local state may not be possible\n  // but this will address any reasonable use cases\n  /**\n   * @param {TreeNode} node\n   */\n  function pullInAssigns(node) {\n    if (node.typeName === \"IDENT\") {\n      for (let assign of assigns) {\n        if (assign.target === node.text) {\n          return assign.value.cloneStructure();\n        }\n      }\n    }\n\n    node.children = node.children.map(n => pullInAssigns(n));\n\n    return node;\n  }\n\n  if (assigns.length) {\n    children = children.map(n => pullInAssigns(n));\n  }\n\n  return {\n    input: children[0],\n    period: children[1],\n    order: requiresOrder ? children[2] : null,\n    initialValue: requiresOrder ? children[3] : children[2]\n  };\n}\n\n\nconst MACRO_FNS_NAMES = Object.keys(MACRO_FNS).filter(x => !x.startsWith(\"_\"));\n\n\n/**\n * @param {Primitive} primitive\n * @param {DNA} primitiveDNA\n * @param {import(\"./formula/Formula\").TreeNode} node\n * @param {SubModelType} submodel\n * @param {Object<string, import(\"./Simulator.js\").SolverType>} solvers\n * @param {import(\"./Simulator\").Simulator} simulate\n * @param {boolean} isInitial\n * @param {object[]=} assigns\n *\n * @returns {TreeNode}\n */\nfunction replaceMacros(primitive, primitiveDNA, node, submodel, solvers, simulate, isInitial, assigns = []) {\n  simulate.evaluatingPosition = node.position || simulate.evaluatingPosition;\n\n  let macroName;\n  let parameters;\n\n  if (node.typeName === \"INNER\") {\n    if (node.children.length === 2) {\n      if (node.children[0].typeName === \"IDENT\" && MACRO_FNS_NAMES.includes(node.children[0].text)) {\n        macroName = node.children[0].text;\n        if (node.children[1].typeName === \"FUNCALL\") {\n          parameters = getMacroParameters(node.children[1].children.slice(), macroName, assigns);\n        }\n      }\n    } else if (\n      node.children.length === 3\n      && node.children[0].typeName === \"PRIMITIVE\"\n      && (node.children[1].typeName === \"SELECTOR\"\n        && node.children[1].children[0].typeName === \"DOTSELECTOR\"\n        && MACRO_FNS_NAMES.includes(node.children[1].children[0].children[0].text))\n      && node.children[2].typeName === \"FUNCALL\"\n    ) {\n      macroName = node.children[1].children[0].children[0].text;\n      parameters = getMacroParameters([node.children[0]].concat(node.children[2].children), macroName, assigns);\n    }\n  }\n\n  if (macroName) {\n    if (isInitial) {\n      // for things like stock or state initial values, we can just use the input, and don't\n      // need to create everything else\n      return MACRO_FNS[\"_initial\"].replacement(parameters, primitiveDNA, node, submodel, solvers, simulate);\n    } else {\n      return MACRO_FNS[macroName].replacement(parameters, primitiveDNA, node, submodel, solvers, simulate);\n    }\n  } else {\n    node.children = node.children.map(n => replaceMacros(primitive, primitiveDNA, n, submodel, solvers, simulate, isInitial, assigns));\n  }\n\n\n  if (node.typeName === \"ASSIGN\" && node.children.length === 2 && node.children[0].typeName === \"ASSIGNED\" && node.children[0].children.length) {\n    assigns.push({\n      target: node.children[0].children[0].text,\n      value: node.children[1]\n    });\n  }\n\n  return node;\n}\n", "src/DNA.js": "\n/** @typedef {import(\"./SharedTypes.js\").TriggerType} TriggerType */\n/** @typedef {import(\"./SharedTypes.js\").StockTypeType} StockTypeType */\n\nexport class DNA {\n  /**\n   * @param {import(\"./api/Blocks\").Primitive} primitive\n   * @param {string=} id\n   */\n  constructor(primitive, id) {\n    this.primitive = primitive;\n\n    /** @type {string} */\n    this.id = id || primitive.id;\n\n    /** @type {string} */\n    this.name = primitive.name;\n\n    /** @type {import('./formula/Units').UnitStore} */\n    this.units = null;\n\n    /** @type {import('./Simulator').SolverType} */\n    this.solver = undefined;\n\n    /** @type {boolean} */\n    this.frozen = undefined;\n\n    /** @type {boolean} */\n    this.slider = undefined;\n\n    /** @type {string} */\n    this.targetId = undefined;\n\n    /** @type {string} */\n    this.sourceId = undefined;\n\n    /** @type {any} */\n    this.value = undefined;\n\n    /** @type {TriggerType} */\n    this.trigger = undefined;\n\n    /** @type {boolean} */\n    this.repeat = undefined;\n\n    /** @type {import(\"./formula/Material\").Material} */\n    this.delay = undefined;\n\n    /** @type {StockTypeType} */\n    this.stockType = undefined;\n\n    /** @type {boolean} */\n    this.recalculate = undefined;\n\n    /** @type {boolean} */\n    this.nonNegative = undefined;\n\n    /** @type {import(\"./formula/Material\").Material} */\n    this.residency = undefined;\n\n    /** @type {string} */\n    this.source = undefined;\n\n    /** @type {string} */\n    this.interpolation = undefined;\n\n    /** @type {any} */\n    this.triggerValue = undefined;\n\n    /** @type {import(\"./formula/Material\").Material[]} */\n    this.inputs = undefined;\n\n    /** @type {import(\"./formula/Material\").Material[]} */\n    this.outputs = undefined;\n\n    /** @type {boolean} */\n    this.flowUnitless = undefined;\n\n    /** @type {boolean} */\n    this.useMaxConstraint = undefined;\n\n    /** @type {boolean} */\n    this.useMinConstraint = undefined;\n\n    /** @type {any} */\n    this.minConstraint = undefined;\n\n    /** @type {number} */\n    this.maxConstraint = undefined;\n\n    /** @type {number} */\n    this.toBase = undefined;\n\n    /** @type {boolean} */\n    this.unitless = undefined;\n\n    /** @type {any} */\n    this.equation = undefined;\n\n    /** @type {import('./Primitives').SPopulation} */\n    this.agents = undefined;\n\n    // Don't display in any outputs\n    /** @type {boolean} */\n    this.noOutput = false;\n\n    /** @type {DNA} */\n    this.neighborProxyDNA = null;\n\n    /** @type {import(\"./api/Blocks\").Primitive[]} */\n    this.extraLinksPrimitives = [];\n\n    // Adopt material units on first calculation\n    /** @type {boolean} */\n    this.adoptUnits = false;\n  }\n}", "src/ModelNode.js": "// eslint-disable-next-line\nimport { Stock, Variable, State, Action, Population, Transition, Flow, Link, Folder, Agent, Converter, Primitive } from \"./api/Blocks.js\";\n\n\n/** @typedef {import(\"./SharedTypes.js\").GraphNode} GraphNode */\n/** @typedef {import(\"./SharedTypes.js\").PrimitiveNameType} PrimitiveNameType */\n\n\nexport function modelNodeClone(node, parent) {\n  let obj = new ModelNode();\n  obj.value = node.cloneNode(true);\n  obj.parent = parent;\n\n  let currIds = [1].concat(primitives(findRootParent(parent)).map(x => x.id).filter(x => !!x).map(x => +x));\n\n  if (node.attributes.length > 0) {\n    for (let j = 0; j < node.attributes.length; j++) {\n      let attribute = node.attributes.item(j);\n      obj.setAttribute(attribute.nodeName, attribute.nodeValue);\n    }\n  }\n\n  obj.setAttribute(\"id\", \"\" + (Math.max.apply(null, currIds) + 1));\n\n  return obj;\n}\n\n\n\n\nfunction findRootParent(node) {\n  if (node.parent) {\n    return findRootParent(node.parent);\n  }\n  return node;\n}\n\n\nexport class ModelNode {\n  constructor() {\n    this.attributes = new Map();\n\n    /** @type {ModelNode} */\n    this.parent = null;\n\n    /** @type {ModelNode[]} */\n    this.children = [];\n\n    /** @type {string} */\n    this.id = null;\n\n    /** @type {{ nodeName: string }} */\n    this.value = { nodeName: null };\n\n    /** @type {Primitive} */\n    this._primitive = undefined;\n\n    /** @type {ModelNode} */\n    this.source = null;\n\n    /** @type {ModelNode} */\n    this.target = null;\n\n    // Used for importing and exporting\n    this.geometry = {\n      x: 0,\n      y: 0,\n      width: 40,\n      height: 100,\n      sourcePoint: null,\n      targetPoint: null,\n    };\n    /** @type {string} */\n    this.style = null;\n  }\n\n  /**\n   * @param {import(\"./api/Model\").Model} model\n   * @param {*} config\n   * @returns {Primitive}\n   */\n  primitive(model, config = {}) {\n    if (this._primitive === undefined) {\n      if (this.value.nodeName === \"Stock\") {\n        this._primitive = new Stock(this, config);\n      } else if (this.value.nodeName === \"Variable\") {\n        this._primitive = new Variable(this, config);\n      } else if (this.value.nodeName === \"Converter\") {\n        this._primitive = new Converter(this, config);\n      } else if (this.value.nodeName === \"State\") {\n        this._primitive = new State(this, config);\n      } else if (this.value.nodeName === \"Action\") {\n        this._primitive = new Action(this, config);\n      } else if (this.value.nodeName === \"Agents\") {\n        this._primitive = new Population(this, config);\n      } else if (this.value.nodeName === \"Flow\") {\n        this._primitive = new Flow(this, config);\n      } else if (this.value.nodeName === \"Transition\") {\n        this._primitive = new Transition(this, config);\n      } else if (this.value.nodeName === \"Link\") {\n        this._primitive = new Link(this, config);\n      } else if (this.value.nodeName === \"Folder\") {\n        if (this.getAttribute(\"Type\") === \"Agent\") {\n          this._primitive = new Agent(this, config);\n        } else {\n          this._primitive = new Folder(this, config);\n        }\n      } else {\n        this._primitive = null;\n      }\n      if (this._primitive && !this._primitive.model) {\n        this._primitive.model = model;\n      }\n    }\n\n    return this._primitive;\n  }\n\n\n  /**\n   * @param {ModelNode} newChild\n   */\n  addChild(newChild) {\n    if (newChild.parent) {\n      // remove from prior parent if there is one\n      let index = newChild.parent.children.indexOf(newChild);\n      if (index > -1) {\n        newChild.parent.children.splice(index, 1);\n      }\n    }\n\n    this.children.push(newChild);\n    newChild.parent = this;\n  }\n\n  /**\n   * @param {string} x\n   * @returns {string}\n   */\n  getAttribute(x) {\n    if (x === \"id\") {\n      return this.id;\n    }\n    return this.attributes.get(x);\n  }\n\n  setAttribute(x, value) {\n    if (x === \"id\") {\n      this.id = \"\" + value;\n      return;\n    }\n    this.attributes.set(x, \"\" + value);\n  }\n\n  getValue() {\n    return {\n      removeAttribute: (name) => this.attributes.delete(name)\n    };\n  }\n\n  toString(indent = 0) {\n    let start = \" \".repeat(indent) + `<${this.value.nodeName}${this.getAttribute(\"name\") ? \" [\" + this.getAttribute(\"name\") + \"]\" : \"\"}>`;\n    let end = `</${this.value.nodeName}>`;\n\n    return start + (this.children.length ? \"\\n\" : \"\") + this.children.map(child => \" \".repeat(indent) + child.toString(indent + 2)).join(\"\\n\") + (this.children.length ? (\"\\n\" + \" \".repeat(indent)) : \"\") + end;\n  }\n}\n\n\n\n/**\n * @param {ModelNode} root\n * @param {PrimitiveNameType|PrimitiveNameType[]=} type\n *\n * @returns {GraphNode[]}\n */\nexport function primitives(root, type) {\n  let myNodes = nodeChildren(root.children[0]);\n\n  if (!type) {\n    return myNodes;\n  } else {\n    let targetNodes = [];\n\n    for (let node of myNodes) {\n      if (Array.isArray(type) ? type.includes(node.value.nodeName) : node.value.nodeName === type) {\n        targetNodes.push(node);\n      }\n    }\n\n    return targetNodes;\n  }\n}\n\n\nfunction nodeChildren(node) {\n  const result = [];\n\n  function collect(node) {\n    const children = node.children;\n    const len = children.length;\n\n    for (let i = 0; i < len; i++) {\n      result.push(children[i]);\n    }\n\n    for (let i = 0; i < len; i++) {\n      collect(children[i]);\n    }\n  }\n\n  collect(node);\n  return result;\n}", "src/Functions.js": "import { mult, minus, eq, greaterThanEq, lessThanEq, plus, div, evaluateNode, lessThan, greaterThan, negate, VectorObject, toNum } from \"./formula/Formula.js\";\nimport { defineFunction, makeObjectBase, setFunctionDef, testArgumentsSize } from \"./formula/CalcFunctions.js\";\nimport { Material } from \"./formula/Material.js\";\nimport { ModelError } from \"./formula/ModelError.js\";\nimport { convertUnits } from \"./formula/Units.js\";\nimport { Vector } from \"./formula/Vector.js\";\nimport { AggregateSeries } from \"./AggregateSeries.js\";\nimport { createUnitStore } from \"./Modeler.js\";\nimport { SAction, SAgent, SConverter, SPopulation, SPrimitive, SState, SStock, STransition, SVariable } from \"./Primitives.js\";\nimport { fn } from \"./CalcMap.js\";\nimport { Task } from \"./TaskScheduler.js\";\nimport { State } from \"./api/Blocks.js\";\n\n/** @typedef {import(\"./SharedTypes.js\").ValueType} ValueType */\n\n/**\n * @typedef {{ location: Vector<Material>, agent: SAgent }} LocationType\n */\n\n\n/**\n * @param {import(\"./Simulator\").Simulator} simulate\n */\nexport function createFunctions(simulate) {\n  let AgentObject = Object.create(null);\n  Object.defineProperty(AgentObject, \"_object_type\", {\n    value: \"agent\",\n    enumerable: false,\n    configurable: false,\n    writable: false\n  });\n\n  let PrimitiveObject = Object.create(null);\n  Object.defineProperty(PrimitiveObject, \"_object_type\", {\n    value: \"primitive\",\n    enumerable: false,\n    configurable: false,\n    writable: false\n  });\n\n  defineFunction(simulate, \"Stop\", { params: [] }, () => {\n    if (simulate.config.showNotification) {\n      simulate.config.showNotification(\"Simulation ended early by a call to stop().\");\n    }\n\n    // eslint-disable-next-line\n    throw {\n      simulationCommand: \"STOP\"\n    };\n  });\n\n  defineFunction(simulate, \"Pause\", { params: [] }, () => {\n    simulate.sleep(true);\n    return new Material(0);\n  });\n\n  defineFunction(simulate, \"Time\", { params: [] }, () => {\n    return simulate.time().fullClone();\n  });\n\n  defineFunction(simulate, \"TimeStep\", { params: [] }, () => {\n    return simulate.timeStep.fullClone();\n  });\n\n  defineFunction(simulate, \"TimeLength\", { params: [] }, () => {\n    return simulate.timeLength.fullClone();\n  });\n\n  defineFunction(simulate, \"TimeStart\", { params: [] }, () => {\n    return simulate.timeStart.fullClone();\n  });\n\n  defineFunction(simulate, \"TimeEnd\", { params: [] }, () => {\n    return simulate.timeEnd.fullClone();\n  });\n\n  defineFunction(simulate, \"Seconds\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"seconds\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Minutes\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"minutes\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Hours\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"hours\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Days\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"days\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Weeks\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"weeks\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Months\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"months\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Years\", { params: [{ name: \"Value\", defaultVal: \"time\", silentDefault: true, vectorize: true }] }, (x) => {\n    let item;\n    if (!x.length) {\n      item = simulate.time().fullClone();\n    } else {\n      item = toNum(x[0]);\n    }\n    return mult(item, new Material(1, simulate.unitManager.getUnitStore([\"years\"], [-1])));\n  });\n\n  defineFunction(simulate, \"Seasonal\", { params: [{ name: \"Peak\", defaultVal: \"0\", vectorize: true }] }, (x) => {\n    /** @type {Material} */\n    let peak;\n    if (!x.length) {\n      peak = new Material(0, simulate.timeUnits);\n    } else {\n      peak = toNum(x[0]).fullClone();\n      if (!peak.units) {\n        peak.units = simulate.timeUnits;\n      }\n    }\n    let position = minus(/** @type {Material} */(simulate.coreBank.get(\"time\")([])), peak);\n    let dist = position.forceUnits(createUnitStore(\"years\", simulate)).value * 2 * Math.PI;\n    return new Material(Math.cos(dist));\n  });\n\n  defineFunction(simulate, \"Unitless\", { params: [{ name: \"Value\", noVector: true }], complete: false }, (x) => {\n    return new Material(toNum(x[0]).value);\n  });\n\n\n  defineFunction(simulate, \"RemoveUnits\", {\n    params: [{ name: \"Value\", vectorize: true }, { name: \"ExpectedUnits\", needString: true }],\n    complete: false\n  }, (x) => {\n    let m = toNum(x[0]).fullClone();\n    return new Material(m.forceUnits(createUnitStore(x[1], simulate)).value);\n  });\n\n\n  defineFunction(simulate, \"PastMean\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", defaultVal: \"All Time\", vectorize: true }] }, (x) => {\n    if (x.length === 1) {\n      return simulate.coreBank.get(\"mean\")(x[0].getPastValues());\n    } else {\n      return simulate.coreBank.get(\"mean\")(x[0].getPastValues(toNum(x[1])));\n    }\n  });\n\n  defineFunction(simulate, \"PastMedian\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", defaultVal: \"All Time\", vectorize: true }] }, (x) => {\n\n    if (x.length === 1) {\n      return simulate.coreBank.get(\"median\")(x[0].getPastValues());\n    } else {\n      return simulate.coreBank.get(\"median\")(x[0].getPastValues(toNum(x[1])));\n    }\n  });\n\n  defineFunction(simulate, \"PastValues\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", defaultVal: \"All Time\", vectorize: true }] }, (x) => {\n\n    let items;\n    if (x.length === 1) {\n      items = x[0].getPastValues();\n    } else {\n      items = x[0].getPastValues(toNum(x[1]));\n    }\n    return new Vector(items, simulate);\n  });\n\n  defineFunction(simulate, \"PastStdDev\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", defaultVal: \"All Time\", vectorize: true }] }, (x) => {\n\n    let items;\n    if (x.length === 1) {\n      items = x[0].getPastValues();\n    } else {\n      items = x[0].getPastValues(toNum(x[1]));\n    }\n    if (items.length > 1) {\n      return simulate.coreBank.get(\"stddev\")(items);\n    } else {\n      return new Material(0);\n    }\n  });\n\n  defineFunction(simulate, \"PastCorrelation\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", vectorize: true, defaultVal: \"All Time\" }] }, (x) => {\n    let items1;\n    let items2;\n    if (x.length === 2) {\n      items1 = x[0].getPastValues();\n      items2 = x[1].getPastValues();\n    } else {\n      items1 = x[0].getPastValues(toNum(x[2]));\n      items2 = x[1].getPastValues(toNum(x[2]));\n    }\n\n    if (items1.length > 1) {\n      return simulate.coreBank.get(\"correlation\")([new Vector(items1, simulate), new Vector(items2, simulate)]);\n    } else {\n      return new Material(0);\n    }\n  });\n\n  defineFunction(simulate, \"PastMax\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", defaultVal: \"All Time\", vectorize: true }] }, (x) => {\n\n    if (x.length === 1) {\n      return simulate.coreBank.get(\"max\")(x[0].getPastValues());\n    } else {\n      return simulate.coreBank.get(\"max\")(x[0].getPastValues(toNum(x[1])));\n    }\n  });\n\n  defineFunction(simulate, \"PastMin\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Past Range\", defaultVal: \"All Time\", vectorize: true }] }, (x) => {\n\n    if (x.length === 1) {\n      return simulate.coreBank.get(\"min\")(x[0].getPastValues());\n    } else {\n      return simulate.coreBank.get(\"min\")(x[0].getPastValues(toNum(x[1])));\n    }\n  });\n\n  defineFunction(simulate, \"Pulse\", { params: [{ name: \"Start Time\", vectorize: true }, { name: \"Height\", vectorize: true, defaultVal: 1 }, { name: \"Width\", vectorize: true, defaultVal: 0 }, { name: \"Repeat Period\", vectorize: true, defaultVal: 0 }] },\n    /**\n     * @param {[Material, Material, Material, Material]} x\n     */\n    (x) => {\n\n      /** @type {Material} */\n      let start = toNum(x[0]);\n      let height = new Material(1);\n      let width = new Material(0);\n      let repeat = new Material(0);\n\n      if (x.length > 1) {\n        height = toNum(x[1]);\n        if (x.length > 2) {\n          width = toNum(x[2]);\n          if (x.length > 3) {\n            repeat = toNum(x[3]);\n          }\n        }\n      }\n\n      if (!start.units) {\n        start.units = simulate.timeUnits;\n      }\n      if (!width.units) {\n        width.units = simulate.timeUnits;\n      }\n      if (!repeat.units) {\n        repeat.units = simulate.timeUnits;\n      }\n\n      if (width.value < 0) {\n        throw new ModelError(\"Pulse() width must be greater than or equal to 0.\", {\n          code: 1058\n        });\n      }\n      if (repeat.value < 0 && repeat.value !== -1) {\n        throw new ModelError(\"Pulse() repeat period must be a postive number. It can also be 0 or -1 to disable repeating.\", {\n          code: 1059\n        });\n      }\n\n      if (repeat.value <= 0) {\n        if (eq(simulate.time(), start) || (greaterThanEq(simulate.time(), start) && lessThanEq(simulate.time(), plus(start, width)))) {\n          return height;\n        }\n      } else if (greaterThanEq(simulate.time(), start)) {\n        let x = minus(simulate.time(), mult(simulate.coreBank.get(\"floor\")([div(minus(simulate.time(), start), repeat)]), repeat));\n        let dv = minus(simulate.time(), start);\n        if (minus(/** @type {Material} */(simulate.coreBank.get(\"round\")([div(dv, repeat)])), div(dv, repeat)).value === 0 || (greaterThanEq(x, start) && lessThanEq(x, plus(start, width)))) {\n          return height;\n        }\n      }\n\n      return new Material(0, height.units);\n    });\n\n  defineFunction(simulate, \"Ramp\", { params: [{ name: \"Start Time\", vectorize: true }, { name: \"Finish Time\", vectorize: true }, { name: \"Height\", vectorize: true, defaultVal: 1 }] },\n    /**\n     * @param {[Material, Material, Material]} x\n     */\n    (x) => {\n\n      let start = toNum(x[0]);\n      let finish = toNum(x[1]);\n      let height = new Material(1);\n      if (x.length === 3) {\n        height = toNum(x[2]);\n      }\n      if (!start.units) {\n        start.units = simulate.timeUnits;\n      }\n      if (!finish.units) {\n        finish.units = simulate.timeUnits;\n      }\n      if (lessThan(finish, start)) {\n        throw new ModelError(`Ramp() finish time must be greater than or equal to start time. Got a start of ${start} and a finish of ${finish}.`, {\n          code: 1057\n        });\n      }\n      if (greaterThanEq(simulate.time(), start)) {\n        if (eq(finish, start)) {\n          return height;\n        }\n        let q = div(mult(simulate.coreBank.get(\"min\")([minus(finish, start), minus(simulate.time(), start)]), height), minus(finish, start));\n        return q;\n      }\n      return new Material(0, height.units);\n    });\n\n  defineFunction(simulate, \"Step\", { params: [{ name: \"Start Time\", vectorize: true }, { name: \"Height\", vectorize: true, defaultVal: 1 }] },\n    /**\n     * @param {[Material, Material]} x\n     */\n    (x) => {\n      let start = toNum(x[0]);\n      let height = new Material(1);\n      if (x.length === 2) {\n        height = toNum(x[1]);\n      }\n      if (!start.units) {\n        start.units = simulate.timeUnits;\n      }\n\n      if (greaterThanEq(simulate.time(), start)) {\n        return height;\n      }\n\n      return new Material(0, height.units);\n    });\n  simulate.varBank.set(\"staircase\", simulate.coreBank.get(\"step\"));\n  simulate.coreBank.set(\"staircase\", simulate.varBank.get(\"staircase\"));\n  setFunctionDef(\"Staircase\", {\n    params: [{ name: \"Start Time\", vectorize: true }, { name: \"Height\", vectorize: true, defaultVal: 1 }],\n    complete: false\n  });\n\n\n  defineFunction(simulate, \"ConverterTable\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Converter]\", noVector: true, needPrimitive: true }] },\n    /**\n     * @param {[SPrimitive]} x\n     *\n     * @returns {Vector}\n     */\n    (x) => {\n      if (!(x[0] instanceof SConverter)) {\n        throw new ModelError(\"ConverterTable() requires a Converter primitive as its parameter.\", {\n          code: 1045\n        });\n      }\n\n      let input = x[0].dna.inputs;\n      let outputs = x[0].dna.outputs;\n\n      let items = [];\n\n      let clean = function(x) {\n        if (x instanceof Material) {\n          return new Material(x.value);\n        }\n        return new Material(x);\n      };\n\n      for (let i = 0; i < input.length; i++) {\n        items.push(new Vector([clean(input[i].value), clean(outputs[i])], simulate, [\"x\", \"y\"]));\n      }\n\n      return new Vector(items, simulate);\n    });\n\n\n  defineFunction(simulate, \"Delay\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Primitive]\", noVector: true, needPrimitive: true }, { name: \"Delay\", vectorize: true }, { name: \"Initial Value\", defaultVal: \"None\", allowString: true, allowBoolean: true }] },\n    /**\n     * @param {[SPrimitive, Material, ValueType?]} x\n     *\n     * @returns {ValueType}\n     */\n    (x) => {\n      if (toNum(x[1]).value < 0) {\n        throw new ModelError(\"The delay must be greater than or equal to 0.\", {\n          code: 1026\n        });\n      }\n\n      if (x.length === 2) {\n        return x[0].pastValue(toNum(x[1]));\n      } else {\n        return x[0].pastValue(toNum(x[1]), toNum(x[2])); // With default value\n      }\n    });\n\n  // TODO: consider vectoring the delay/period for DelayN and smoothN\n\n  defineFunction(simulate, \"Smooth\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"Expression\", noVector: true }, { name: \"Period\", vectorize: true, needNum: true }, { name: \"Initial Value\", defaultVal: \"None\" }] },\n    (_x) => {\n      throw new ModelError(\"Smooth() may only be called in a top level primitive equation\", {\n        code: 1052\n      });\n    });\n\n\n  defineFunction(simulate, \"SmoothN\", { object: [simulate.varBank, PrimitiveObject], params: [\n    { name: \"Expression\", noVector: true },\n    { name: \"Period\", vectorize: true, needNum: true },\n    { name: \"Order\", noUnits: true, noVector: true, needNum: true },\n    { name: \"Initial Value\", defaultVal: \"None\" }\n  ] },\n  (_x) => {\n    throw new ModelError(\"SmoothN() may only be called in a top level primitive equation\", {\n      code: 1052\n    });\n  });\n\n  defineFunction(simulate, \"Delay1\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"Expression\", noVector: true }, { name: \"Delay\", vectorize: true, needNum: true }, { name: \"Initial Value\", defaultVal: \"None\" }] },\n    (_x) => {\n      throw new ModelError(\"Delay1() may only be called in a top level primitive equation\", {\n        code: 1053\n      });\n    });\n\n  defineFunction(simulate, \"Delay3\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"Expression\", noVector: true }, { name: \"Delay\", vectorize: true, needNum: true }, { name: \"Initial Value\", defaultVal: \"None\" }] },\n    (_x) => {\n      throw new ModelError(\"Delay3() may only be called in a top level primitive equation\", {\n        code: 1054\n      });\n    });\n\n\n  defineFunction(simulate, \"DelayN\", { object: [simulate.varBank, PrimitiveObject], params: [\n    { name: \"Expression\", noVector: true },\n    { name: \"Delay\", vectorize: true, needNum: true },\n    { name: \"Order\", noUnits: true, noVector: true, needNum: true },\n    { name: \"Initial Value\", defaultVal: \"None\" }\n  ] },\n  (_x) => {\n    throw new ModelError(\"DelayN() may only be called in a top level primitive equation\", {\n      code: 1075\n    });\n  });\n\n\n\n  simulate.varBank.set(\"fix\", (x, id) => {\n    testArgumentsSize(x, \"Fix\", 1, 2);\n\n    /** @type {Material} */\n    let spacing = null;\n    if (x.length === 2) {\n      spacing = toNum(evaluateNode(x[1].node, x[1].scope, simulate));\n\n      if (!(spacing instanceof Material)) {\n        throw new ModelError(\"fix() requires a number for the parameter 'spacing'.\", {\n          code: 6058\n        });\n      }\n    }\n\n    let mySeries = simulate.aggregateSeries.get(id);\n\n    if (!mySeries) {\n      mySeries = new AggregateSeries(simulate, spacing);\n      simulate.aggregateSeries.set(id, mySeries);\n    }\n\n    return mySeries.get(x[0]);\n  });\n  simulate.varBank.get(\"fix\").delayEvalParams = true;\n  simulate.coreBank.set(\"fix\", simulate.varBank.get(\"fix\"));\n  setFunctionDef(\"Fix\", { params: [{ name: \"Value\" }, { name: \"Period\", defaultVal: \"All Time\" }] });\n\n\n  simulate.varBank.set(\"populationsize\", (x) => {\n    testArgumentsSize(x, \"PopulationSize\", 1, 1);\n    if (x[0] instanceof SPopulation) {\n      return new Material(x[0].agents.length);\n    }\n    throw new ModelError(\"PopulationSize must be passed an agent population as an argument.\", {\n      code: 1327\n    });\n  });\n  PrimitiveObject[\"populationsize\"] = simulate.varBank.get(\"populationsize\");\n  simulate.coreBank.set(\"populationsize\", simulate.varBank.get(\"populationsize\"));\n  setFunctionDef(\"PopulationSize\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Agent Population]\", needPopulation: true, noVector: true }] });\n\n  defineFunction(simulate, \"Remove\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent]\" }] }, (x) => {\n    if (x[0].dead) {\n      throw new ModelError(\"Cannot remove an already removed agent.\", {\n        code: 1328\n      });\n    }\n\n    simulate.tasks.add(new Task({\n      time: simulate.time(),\n      priority: 10,\n      expires: 1,\n      name: \"Remove Agent\",\n      action: (_task) => {\n        x[0].die();\n      }\n    }));\n\n\n    return new Material(1);\n  });\n\n  defineFunction(simulate, \"Add\", { object: [simulate.varBank, PrimitiveObject], params: [{ name: \"[Agent Population]\", allowOptionalPrimitive: true }, { needAgent: true, name: \"[Base]\", defaultVal: \"Agent Base\" }] }, (x) => {\n    while ((!(x[0] instanceof SPopulation)) && !(x[0].container === null || x[0].container === undefined)) {\n      x[0] = x[0].container;\n    }\n    if (!(x[0] instanceof SPopulation)) {\n      throw new ModelError(\"You must pass an agent population as the first argument to Add().\", {\n        code: 1029\n      });\n    }\n\n    if (x.length === 2) {\n      return x[0].add(x[1]);\n    } else {\n      return x[0].add();\n    }\n  });\n\n  defineFunction(simulate, \"FindAll\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }] }, (x) => {\n    return x[0];\n  });\n\n  defineFunction(simulate, \"ResetTimer\", { object: [simulate.varBank, PrimitiveObject], params: [{ needPrimitive: true, name: \"[Action]\" }], complete: false }, (x) => {\n    if (!(x[0] instanceof SAction)) {\n      throw new ModelError(\"ResetTimer requires an Action primitive.\", {\n        code: 1030\n      });\n    }\n    x[0].resetTimer();\n    return new Material(0);\n  });\n\n  defineFunction(simulate, \"Transition\", { object: [simulate.varBank, PrimitiveObject], params: [{ needPrimitive: true, name: \"[Transition]\" }], complete: false }, (x) => {\n    if (!(x[0] instanceof STransition)) {\n      throw new ModelError(\"Transition requires an Transition primitive.\", {\n        code: 1031\n      });\n    }\n    x[0].trigger();\n    return new Material(0);\n  });\n\n  defineFunction(simulate, \"Value\", { object: [simulate.varBank, VectorObject, AgentObject], params: [{ name: \"[Population]\" }, { needPrimitive: true, name: \"[Primitive]\" }] }, (x) => { // need population should be false\n\n    let id = x[1].id;\n\n    let population = null;\n\n    if (!((x[0] instanceof SPopulation) || (x[0] instanceof SAgent) || (x[0] instanceof Vector) || (!x[0]))) {\n      x[0] = toNum(x[0]);\n    }\n\n    if (x[0] instanceof SPopulation) {\n      population = getPopulation(x[0], simulate);\n    }\n\n    if (x[0] instanceof Vector) {\n      population = x[0];\n    }\n    if (population !== null) {\n      let res = [];\n      let q = -1;\n      for (let item of population.items) {\n        if (!(item instanceof SAgent)) {\n          throw new ModelError(\"Cannot take \\\"Value()\\\" of vector that does not contain agents.\", {\n            code: 1172\n          });\n        }\n        if (q !== -1) {\n          res.push(item.children[q]);\n        } else {\n          for (let j = 0; j < item.children.length; j++) {\n            if (item.children[j].id === id) {\n              res.push(item.children[j]);\n              q = j;\n              break;\n            }\n          }\n        }\n      }\n\n      return new Vector(res, simulate);\n    } else if (x[0] instanceof SAgent) {\n      for (let child of x[0].children) {\n        if (child.id === id) {\n          return child;\n        }\n      }\n      throw new ModelError(\"Could not find referenced primitive for \\\"Value()\\\".\", {\n        code: 1032\n      });\n    }\n\n    throw new ModelError(\"Invalid type for the first argument of \\\"Value()\\\".\", {\n      code: 1033\n    });\n  });\n\n  defineFunction(simulate, \"SetValue\", { object: [simulate.varBank, VectorObject, PrimitiveObject, AgentObject], params: [{ name: \"[Population]\" }, { needPrimitive: true, name: \"[Primitive]\" }, { name: \"Value\", allowBoolean: true }] }, (x) => { // need population should be false\n    let id = x[1].id;\n\n    let population = null;\n\n    if (x[0] instanceof SPopulation) {\n      population = getPopulation(x[0], simulate);\n    }\n\n    if (x[0] instanceof Vector) {\n      population = x[0];\n    }\n\n    if (population !== null) {\n      for (let i = 0; i < population.length(); i++) {\n        for (let child of population.items[i].children) {\n          if (child.id === id) {\n            child.setValue(x[2]);\n          }\n        }\n      }\n      return new Material(1);\n    } else if (x[0] instanceof SAgent) {\n      for (let child of x[0].children) {\n        if (child.id === id) {\n          child.setValue(x[2]);\n          return new Material(1);\n        }\n      }\n\n      throw new ModelError(\"Could not find referenced primitive for \\\"SetValue()\\\".\", {\n        code: 1034\n      });\n    }\n\n    throw new ModelError(\"Invalid type for the first argument of \\\"SetValue()\\\".\", {\n      code: 1035\n    });\n  });\n\n  defineFunction(simulate, \"FindIndex\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }, { name: \"Index\", noVector: true, needNum: true, noUnits: true }] },\n    /**\n     * @param {[Vector, Material]} x\n     *\n     * @returns\n     */\n    (x) => {\n      let population = x[0];\n      for (let item of population.items) {\n        if (item.index + 1 === x[1].value) {\n          return item;\n        }\n      }\n\n      throw new ModelError(\"Index not found in population.\", {\n        code: 1036\n      });\n    });\n\n  defineFunction(simulate, \"FindState\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }, { needPrimitive: true, name: \"[State]\" }] },\n    /**\n     * @param {[Vector, SPrimitive]} x\n     *\n     * @returns\n     */\n    (x) => {\n\n      let population = x[0];\n\n      if (!((x[1] instanceof SState) || (x[1].dna.primitive instanceof State))) {\n        throw new ModelError(\"FindState() requires a State primitive as its argument.\", {\n          code: 1037\n        });\n      }\n\n      let id = x[1].id;\n      let res = [];\n\n      for (let i = 0; i < population.items.length; i++) {\n        if (population.items[i].stateIDs.has(id)) {\n          res.push(population.items[i]);\n        }\n      }\n\n      return new Vector(res, simulate);\n    });\n\n  defineFunction(simulate, \"FindNotState\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }, { needPrimitive: true, name: \"[State]\" }] },\n    /**\n     * @param {[Vector, SPrimitive]} x\n     *\n     * @returns\n     */\n    (x) => {\n\n      let population = x[0];\n      if (!((x[1] instanceof SState) || (x[1].dna.primitive instanceof State))) {\n        throw new ModelError(\"FindNotState() requires a State primitive as its argument.\", {\n          code: 1038\n        });\n      }\n\n      let id = x[1].id;\n      let res = [];\n\n      for (let item of population.items) {\n        if (!item.stateIDs.has(id)) {\n          res.push(item);\n        }\n      }\n\n      return new Vector(res, simulate);\n    });\n\n  defineFunction(simulate, \"FindNearby\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }, { name: \"Target\", allowOptionalPrimitive: true }, { name: \"Distance Limit\", needNum: true, noVector: true }] },\n    /**\n     * @param {[Vector, SPrimitive, Material]} x\n     *\n     * @returns\n     */\n    (x) => {\n      let population = x[0];\n\n      let loc = locationValue(x[1]);\n\n      let a;\n      try {\n        a = agent(x[1], simulate);\n      } catch (err) {\n        // pass\n      }\n\n\n      let res = [];\n      for (let i = 0; i < population.length(); i++) {\n        let item = agent(population.items[i], simulate);\n        if (item !== a) {\n          if (lessThanEq(distance(loc, locationValue(item), simulate), x[2])) {\n            res.push(item);\n          }\n        }\n      }\n      return new Vector(res, simulate);\n    });\n\n  defineFunction(simulate, \"FindNearest\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }, { name: \"Target\", allowOptionalPrimitive: true }, { noUnits: true, noVector: true, needNum: true, defaultVal: 1, name: \"Count\" }] },\n    /**\n     * @param {[Vector, SPrimitive, Material]} x\n     *\n     * @returns\n     */\n    (x) => {\n      let population = x[0];\n      let count = 1;\n\n      if (x.length === 3) {\n        count = x[2].value;\n\n        if (count < 1) {\n          throw new ModelError(\"You must select at least one agent in FindNearest().\", {\n            code: 1039\n          });\n        }\n        if (count !== Math.floor(count)) {\n          throw new ModelError(\"Count must be an integer.\", {\n            code: 1040\n          });\n        }\n      }\n\n\n      let loc = locationValue(x[1]);\n\n      let a;\n      try {\n        a = agent(x[1], simulate);\n      } catch (err) {\n        // pass\n      }\n\n      let res = [];\n      for (let item of population.items) {\n        item = agent(item, simulate);\n        if (item !== a) {\n          res.push({\n            distance: distance(loc, locationValue(item), simulate),\n            item: item\n          });\n        }\n      }\n\n      if (res.length < count) {\n        throw new ModelError(`Can't find nearest ${count} agents of a population of size ${res.length}.`, {\n          code: 1041\n        });\n      }\n\n\n      let minItems = [res[0]];\n      for (let i = 1; i < res.length; i++) {\n        let added = false;\n        for (let j = 0; j < minItems.length; j++) {\n          if (lessThan(res[i].distance, minItems[j].distance)) {\n            minItems.splice(j, 0, res[i]);\n            added = true;\n            break;\n          }\n        }\n        if ((!added) && minItems.length < count) {\n          minItems.push(res[i]);\n        } else if (minItems.length > count) {\n          minItems.length = count;\n        }\n      }\n\n      if (minItems.length === 1) {\n        return minItems[0].item;\n      } else {\n        return new Vector(minItems.map(x => x.item), simulate);\n      }\n    });\n\n\n  defineFunction(simulate, \"FindFurthest\", { object: [simulate.varBank, VectorObject, PrimitiveObject], params: [{ needPopulation: true, name: \"[Agent Population]\" }, { name: \"Target\", allowOptionalPrimitive: true }, { noUnits: true, noVector: true, needNum: true, defaultVal: 1, name: \"Count\" }] },\n    /**\n     * @param {[Vector, SPrimitive, Material]} x\n     * @returns\n     */\n    (x) => {\n\n      let population = x[0];\n\n      let count = 1;\n      if (x.length === 3) {\n        count = x[2].value;\n\n        if (count < 1) {\n          throw new ModelError(\"You must select at least one agent in FindFurthest().\", {\n            code: 1042\n          });\n        }\n        if (count !== Math.floor(count)) {\n          throw new ModelError(\"Count must be an integer.\", {\n            code: 1043\n          });\n        }\n      }\n\n\n\n      let loc = locationValue(x[1]);\n      /** @type {SAgent} */\n      let a;\n      try {\n        a = agent(x[1], simulate);\n      } catch (err) {\n        // pass\n      }\n\n\n      let res = [];\n      for (let i of population.items) {\n        let item = agent(i, simulate);\n        if (item !== a) {\n          res.push({ distance: distance(loc, locationValue(item), simulate), item: item });\n        }\n      }\n\n      if (res.length < count) {\n        throw new ModelError(`Can't find furthest ${count} agents of a population of size ${res.length}.`, {\n          code: 1044\n        });\n      }\n\n      let minItems = [res[0]];\n      for (let i = 1; i < res.length; i++) {\n        let added = false;\n        for (let j = 0; j < minItems.length; j++) {\n          if (greaterThan(res[i].distance, minItems[j].distance)) {\n            minItems.splice(j, 0, res[i]);\n            added = true;\n            break;\n          }\n        }\n        if ((!added) && minItems.length < count) {\n          minItems.push(res[i]);\n        } else if (minItems.length > count) {\n          minItems.length = count;\n        }\n      }\n\n      if (minItems.length === 1) {\n        return minItems[0].item;\n      } else {\n        return new Vector(minItems.map(x => x.item), simulate);\n      }\n    });\n\n  defineFunction(simulate, \"Index\", { object: [simulate.varBank, AgentObject], params: [{ noVector: true, needAgent: true, name: \"[Agent]\" }] }, (x) => {\n    return new Material(x[0].index + 1);\n  });\n\n  defineFunction(simulate, \"Connect\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent 1]\" }, { name: \"[Agent 2]\" }, { name: \"Weight\", defaultVal: \"missing\", needNum: true }] },\n    /**\n     * @param {[SAgent, SAgent, Material|\"missing\"]} x\n     *\n     * @returns\n     */\n    (x) => {\n\n      let weight = undefined;\n      if (x[2] !== \"missing\") {\n        weight = x[2];\n      }\n\n      if (x[1] instanceof Vector) {\n        x[1].items.forEach((a) => {\n          x[0].connect(a, weight);\n        });\n      } else {\n        x[0].connect(x[1], weight);\n      }\n\n      return new Material(1);\n    });\n\n  defineFunction(simulate, \"Unconnect\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent 1]\" }, { name: \"[Agent 2]\" }] },\n    /**\n     * @param {[SAgent, SAgent]} x\n     *\n     * @returns\n     */\n    (x) => {\n      if (x[1] instanceof Vector) {\n        x[1].items.forEach((a) => {\n          x[0].unconnect(a);\n        });\n      } else {\n        x[0].unconnect(x[1]);\n      }\n\n      return new Material(1);\n    });\n\n  defineFunction(simulate, \"Connected\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent]\" }] }, (x) => {\n    return new Vector(x[0].connected.slice(), simulate);\n  });\n\n  defineFunction(simulate, \"ConnectionWeight\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent 1]\" }, { name: \"[Agent 2]\" }] }, (x) => {\n    if (x[1] instanceof Vector) {\n      return new Vector(x[1].items.map((a) => {\n        return x[0].connectionWeight(a);\n      }), simulate);\n    } else {\n      return x[0].connectionWeight(x[1]);\n    }\n  });\n\n  defineFunction(simulate, \"SetConnectionWeight\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent 1]\" }, { name: \"[Agent 2]\" }, { name: \"Weight\", needNum: true }] },\n    /**\n     * @param {[SAgent, SAgent|Vector, Material]} x\n     */\n    (x) => {\n      if (x[1] instanceof Vector) {\n        x[1].items.forEach((a) => {\n          x[0].setConnectionWeight(a, x[2]);\n        });\n      } else {\n        x[0].setConnectionWeight(x[1], x[2]);\n      }\n      return new Material(1);\n    });\n\n  simulate.varBank.set(\"print\", (x) => {\n    function makePrimitiveString(x) {\n      if (x instanceof String) {\n        x = \"\" + x;\n      }\n      return x;\n    }\n\n    if (x.length === 2) {\n      console.log(makePrimitiveString(x[0].value.toString()));\n      console.log(makePrimitiveString(x[1]));\n      return x[1];\n    } else {\n      console.log(makePrimitiveString(x[0]));\n      return x[0];\n    }\n  });\n  simulate.coreBank.set(\"print\", simulate.varBank.get(\"print\"));\n  setFunctionDef(\"Print\", {\n    params: [{ name: \"Label or Value\", allowString: true, allowBoolean: true }, { name: \"Value\", defaultVal: \"None\", allowString: true, allowBoolean: true }],\n    complete: false\n  });\n\n  defineFunction(simulate, \"Width\", { params: [{ needAgents: true, name: \"[Agent Population]\" }] }, (x) => {\n    return x[0].geoWidth;\n  });\n\n  defineFunction(simulate, \"Height\", { params: [{ needAgents: true, name: \"[Agent Population]\" }] }, (x) => {\n    return x[0].geoHeight;\n  });\n\n  defineFunction(simulate, \"Distance\", { object: [simulate.varBank, AgentObject], params: [{ name: \"Location 1\" }, { name: \"Location 2\" }] }, (x) => {\n    let loc1 = locationValue(x[0]);\n    let loc2 = locationValue(x[1]);\n\n    return distance(loc1, loc2, simulate);\n  });\n\n  defineFunction(simulate, \"Location\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent]\" }] }, (x) => {\n    if (!x[0].location) {\n      throw new ModelError(\"The location is not defined.\", {\n        code: 1046\n      });\n    } else {\n      return x[0].location.fullClone();\n    }\n  });\n\n  /**\n   *\n   * @param {Vector} x\n   */\n  function checkLocationVector(x) {\n    if (x.items.length !== 2 || !(x.items[0] instanceof Material) || !(x.items[1] instanceof Material)) {\n      throw new ModelError(\"Location vector does not contain exactly two numbers.\", {\n        code: 1067\n      });\n    }\n\n    if (x.names && (!x.names.length || x.names.length !== 2 || x.namesLC[0] !== \"x\" || x.namesLC[1] !== \"y\")) {\n      throw new ModelError(\"Location vector must have names 'x' and 'y'.\", {\n        code: 1067\n      });\n    }\n  }\n\n\n  defineFunction(simulate, \"SetLocation\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Agent]\" }, { needVector: true, name: \"Location\" }] },\n    /**\n     * @param {[SAgent, Vector<Material>]} x\n     * @returns\n     */\n    (x) => {\n      let v = toNum(x[1]);\n      checkLocationVector(v);\n\n      let agent = x[0];\n      agent.location = v.fullClone();\n      if (!agent.location.names) {\n        agent.location.names = [\"x\", \"y\"];\n        agent.location.namesLC = [\"x\", \"y\"];\n      }\n      return new Material(0);\n    });\n\n  defineFunction(simulate, \"Move\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Mover]\" }, { needVector: true, name: \"Direction\" }] },\n    /**\n     * @param {[SAgent, Vector<Material>]} x\n     * @returns\n     */\n    (x) => {\n      let v = toNum(x[1]);\n\n      checkLocationVector(v);\n\n      shiftLocation(x[0], plus(x[0].location, v));\n      return new Material(0);\n    });\n\n\n  /**\n   * @param {*} x\n   * @returns {LocationType}\n   */\n  function locationValue(x) {\n    const NOT_INIT = \"Location not initialized yet for agents. Location initialization happens after agent primitive value initialization.\";\n    if (x instanceof Vector) {\n      if (x.items.length !== 2 || !(x.items[0] instanceof Material) || !(x.items[1] instanceof Material)) {\n        throw new ModelError(\"Location vector does not contain exactly two numbers.\", {\n          code: 1047\n        });\n      } else {\n        return {\n          location: x,\n          agent: null\n        };\n      }\n    } else {\n      try {\n        let a = agent(x, simulate);\n        let loc = a.location;\n        if (loc === null) {\n          throw new ModelError(NOT_INIT, {\n            code: 1048\n          });\n        }\n        return {\n          location: loc,\n          agent: a\n        };\n      } catch (err) {\n        if (/** @type {Error} */ (err).message === NOT_INIT) {\n          throw err;\n        }\n        throw new ModelError(\"Location must be a vector or an agent.\", {\n          code: 1049\n        });\n      }\n    }\n  }\n\n  defineFunction(simulate, \"MoveTowards\", { object: [simulate.varBank, AgentObject], params: [{ needAgent: true, name: \"[Mover]\" }, { name: \"[Target]\" }, { name: \"Distance\", noVector: true, needNum: true }] },\n    /**\n     * @param {[SAgent, Vector<Material>, Material]} x\n     * @returns\n     */\n    (x) => {\n\n      let loc1 = locationValue(x[0]);\n      let loc2 = locationValue(x[1]);\n\n      let l1 = loc1.location;\n      let l2 = loc2.location;\n\n      let distX = minus(l2.items[0], l1.items[0]);\n      let distY = minus(l2.items[1], l1.items[1]);\n\n      if (distX.value === 0 && distY.value === 0) {\n        return new Material(1);\n      }\n\n      let a = loc1.agent;\n      if (a.container.geoWrap) {\n        if (greaterThan(distX, a.container.halfWidth)) {\n          distX = minus(distX, a.container.geoWidth);\n        } else if (lessThan(distX, negate(a.container.halfWidth))) {\n          distX = plus(distX, a.container.geoWidth);\n        }\n        if (greaterThan(distY, a.container.halfHeight)) {\n          distY = minus(distY, a.container.geoHeight);\n        } else if (lessThan(distY, negate(a.container.halfHeight))) {\n          distY = plus(distY, a.container.geoHeight);\n        }\n      }\n\n      let dir = new Vector([distX, distY], simulate, [\"x\", \"y\"]);\n\n      shiftLocation(a, plus(a.location, mult(dir, div(x[2], distance(loc1, loc2, simulate)))));\n\n      return new Material(1);\n    });\n\n  simulate.coreBank.set(\"primitivebase\", makeObjectBase(PrimitiveObject, simulate));\n\n  simulate.coreBank.set(\"agentbase\", makeObjectBase(AgentObject, simulate));\n  simulate.varBank.set(\"agentbase\", simulate.coreBank.get(\"agentbase\"));\n\n  simulate.coreBank.get(\"primitivebase\").parent = simulate.coreBank.get(\"agentbase\");\n\n  simulate.coreBank.set(\"vectorbase\", makeObjectBase(VectorObject, simulate));\n  simulate.varBank.set(\"vectorbase\", simulate.coreBank.get(\"vectorbase\"));\n}\n\n\n// Only store these many distance caches. When doing many comparisons,\n// the distance cache may grow too large\nconst MAX_DISTANCE_CACHES = 1e6;\n\n/**\n * @param {LocationType} a\n * @param {LocationType} b\n * @param {import(\"./Simulator\").Simulator} simulate\n *\n * @returns {Material}\n */\nfunction distance(a, b, simulate) {\n  let l1 = a.location;\n  let l2 = b.location;\n\n  simulate.distanceCacheCount++;\n\n  /** @type {Partial<SPopulation>} */\n  let agents = a.agent ? a.agent.container : (b.agent ? b.agent.container : null);\n\n  let m1a = l1.items[0], m1b = l1.items[1];\n  let m2a = l2.items[0], m2b = l2.items[1];\n\n  // Simple path when units are the same and no geowrap\n  // Caching not worth it, just calculated it.\n  let xUnits = m1a.units;\n  let unitsMatch = xUnits === m1b.units && xUnits === m2a.units && xUnits === m2b.units;\n\n  if (unitsMatch && !(agents && agents.geoWrap)) {\n    let dx = m1a.value - m2a.value;\n    let dy = m1b.value - m2b.value;\n    // note Math.hypot is slower in current engines\n    // e.g. https://issues.chromium.org/issues/42203737\n    return new Material(Math.sqrt(dx * dx + dy * dy), xUnits);\n  }\n\n\n  let cacheKey;\n  if (simulate.distanceCacheCount < MAX_DISTANCE_CACHES) {\n    let s1 = l1.items[0].toString() + \",\" + l1.items[1].toString();\n    let s2 = l2.items[0].toString() + \",\" + l2.items[1].toString();\n    if (s2 < s1) {\n      [s1, s2] = [s2, s1];\n    }\n    cacheKey = s1 + \":\" + s2;\n    if (agents) {\n      cacheKey += \"/\" + agents.id;\n    }\n\n    if (cacheKey in simulate.distanceCache) {\n      return simulate.distanceCache[cacheKey];\n    }\n  }\n\n  let distx = /** @type {Material} */ (minus(l1.items[0], l2.items[0]));\n  let disty = /** @type {Material} */ (minus(l1.items[1], l2.items[1]));\n\n\n  if (agents && agents.geoWrap) {\n    if (greaterThan(distx, agents.halfWidth)) {\n      distx = minus(agents.geoWidth, distx);\n    } else if (lessThan(distx, negate(agents.halfWidth))) {\n      distx = minus(distx, negate(agents.geoWidth));\n    }\n    if (greaterThan(disty, agents.halfHeight)) {\n      disty = minus(agents.geoHeight, disty);\n    } else if (lessThan(disty, negate(agents.halfHeight))) {\n      disty = minus(disty, negate(agents.geoHeight));\n    }\n  }\n\n  let v1 = distx.value;\n  let v2 = disty.value;\n\n  if (distx.units !== disty.units) {\n    v2 = fn[\"*\"](v2, convertUnits(disty.units, distx.units));\n  }\n\n  let distN = fn[\"sqrt\"](fn[\"+\"](fn[\"*\"](v1, v1), fn[\"*\"](v2, v2)));\n  let dist = new Material(distN, distx.units);\n\n  if (simulate.distanceCacheCount < MAX_DISTANCE_CACHES) {\n    simulate.distanceCache[cacheKey] = dist;\n  }\n\n  return dist;\n}\n\n\n/**\n * @param {*} obj\n * @param {import(\"./Simulator\").Simulator} simulate\n *\n * @returns {SAgent}\n */\nexport function agent(obj, simulate) {\n  if ((obj instanceof SVariable) || (obj instanceof SStock)) {\n    obj = toNum(obj);\n  }\n  if (obj instanceof SAgent) {\n    return obj;\n  } else if (obj instanceof SPrimitive) {\n    return agent(obj.container, simulate);\n  } else {\n    throw new ModelError(\"An agent is required here.\", {\n      code: 1050\n    });\n  }\n}\n\n\n/**\n * @param {*} obj\n *\n * @returns {SPopulation}\n */\nexport function agents(obj) {\n  if (obj instanceof SPopulation) {\n    return obj;\n  } else if ((obj instanceof SPrimitive) || (obj instanceof SAgent)) {\n    return agents(obj.container);\n  } else {\n    throw new ModelError(\"An agent population is required here.\", {\n      code: 1051\n    });\n  }\n}\n\n\n/**\n * @param {*} item\n * @param {import(\"./Simulator\").Simulator} simulate\n *\n * @returns {Vector}\n */\nexport function getPopulation(item, simulate) {\n  if (item.items) {\n    return item;\n  }\n  if (item instanceof SPopulation) {\n    return new Vector(item.agents.slice(), simulate);\n  } else if (toNum(item) instanceof Vector) {\n    return toNum(item);\n  } else {\n    return new Vector([agent(item, simulate)], simulate);\n  }\n}\n\n\n/**\n * @param {SAgent} agent\n * @param {Vector<Material>} newLocation\n */\nfunction shiftLocation(agent, newLocation) {\n  if (agent.container.geoWrap) {\n    while (lessThan(newLocation.items[0], new Material(0))) {\n      newLocation.items[0] = plus(newLocation.items[0], agent.container.geoWidth);\n    }\n    while (greaterThan(newLocation.items[0], agent.container.geoWidth)) {\n      newLocation.items[0] = minus(newLocation.items[0], agent.container.geoWidth);\n    }\n    while (lessThan(newLocation.items[1], new Material(0))) {\n      newLocation.items[1] = plus(newLocation.items[1], agent.container.geoHeight);\n    }\n    while (greaterThan(newLocation.items[1], agent.container.geoHeight)) {\n      newLocation.items[1] = minus(newLocation.items[1], agent.container.geoHeight);\n    }\n  }\n\n  agent.location = newLocation;\n  if (!agent.location.names) {\n    agent.location.names = [\"x\", \"y\"];\n    agent.location.namesLC = [\"x\", \"y\"];\n  }\n}\n\n\n\nexport function testPrimitive(x, name, primitiveIndexes) {\n  for (let index of primitiveIndexes) {\n    if (!(x[index] instanceof SPrimitive)) {\n      throw new ModelError(`${name}() requires a primitive reference to be passed to it as argument number ${index + 1}.`, {\n        code: 1024\n      });\n    }\n  }\n}\n", "src/Utilities.js": "\n\nexport function isTrue(item) {\n  return item === 1 || item === \"true\" || item === true;\n}\n\n\n/**\n * @param {string} str\n * @returns {string}\n */\nexport function sanitizeText(str) {\n  return str.replace(/[&<>'\"]/g,\n    tag => ({\n      \"&\": \"&amp;\",\n      \"<\": \"&lt;\",\n      \">\": \"&gt;\",\n      \"'\": \"&#39;\",\n      \"\\\"\": \"&quot;\",\n      \"`\": \"&#96;\"\n    }[tag]));\n}\n\n\n/**\n * @param {any} nStr\n * @param {boolean=} sanitize\n * @returns {string}\n */\nexport function commaStr(nStr, sanitize=true) {\n  if (nStr instanceof String) {\n    nStr = nStr.valueOf();\n  }\n\n  if (typeof nStr === \"string\") {\n    return sanitize ? sanitizeText(nStr) : nStr;\n  }\n\n  if (typeof nStr === \"boolean\") {\n    return nStr.toString();\n  }\n\n  if (nStr === undefined || nStr === null) {\n    return \"\";\n  }\n\n  if (Math.abs(nStr) >= 1e9 || (Math.abs(nStr) <= 1e-9 && nStr !== 0)) {\n    return nStr.toPrecision(3);\n  } else {\n    nStr = round(nStr, 9) + \"\";\n    let x = nStr.split(\".\");\n    let x1 = x[0];\n    let x2 = x.length > 1 ? \".\" + x[1] : \"\";\n    let reg = /(\\d+)(\\d{3})/;\n    while (reg.test(x1)) {\n      x1 = x1.replace(reg, \"$1,$2\");\n    }\n    return x1 + x2;\n  }\n}\n\n\n/**\n * @param {number} value\n * @param {number=} precision\n */\nexport function round(value, precision = 15) {\n  return +value.toPrecision(precision);\n}\n\n", "src/AggregateSeries.js": "import { div, evaluateNode, minus, toNum } from \"./formula/Formula.js\";\n// eslint-disable-next-line no-unused-vars\nimport { Material } from \"./formula/Material.js\";\n\n\nexport class AggregateSeries {\n  /**\n   * @param {import(\"./Simulator\").Simulator} simulate\n   * @param {Material} mSpacing\n   */\n  constructor(simulate, mSpacing) {\n    this.simulate = simulate;\n\n    /** @type {Material} */\n    this.spacing = mSpacing;\n    /** @type {Material[]} */\n    this.oldValues = [];\n  }\n\n\n  get(data) {\n    let index = 0;\n\n    if (this.spacing === null) {\n      index = 0;\n    } else if (this.spacing.value < 0) {\n      // we treat negative spacing as the same as no defined spacing\n      index = 0;\n    } else if (this.spacing.value === 0) {\n      index = Math.floor(div(minus(this.simulate.time(), this.simulate.timeStart), this.simulate.userTimeStep).value);\n    } else {\n      index = Math.floor(div(minus(this.simulate.time(), this.simulate.timeStart), this.spacing.forceUnits(this.simulate.timeUnits)).value);\n    }\n\n    while (this.oldValues.length - 1 < index) {\n      let value = evaluateNode(data.node, data.scope, this.simulate);\n\n      // ensure things like primitives or functions are converted to values\n      this.oldValues.push(toNum(value));\n    }\n\n    if (this.oldValues[index].fullClone) {\n      return this.oldValues[index].fullClone();\n    } else {\n      return this.oldValues[index];\n    }\n  }\n}\n", "src/Simulator.js": "import { div, plus, minus, eq, lessThan, toNum, PARENT_SYMBOL } from \"./formula/Formula.js\";\nimport { TaskQueue, Task } from \"./TaskScheduler.js\";\nimport { checkErr, cleanData, formatSimResults, simpleEquation, updateDisplayed } from \"./Modeler.js\";\nimport { Material } from \"./formula/Material.js\";\n// eslint-disable-next-line\nimport { SState, SFlow, SPopulation, SAgent, updateTrigger, SPrimitive } from \"./Primitives.js\";\nimport { fn } from \"./CalcMap.js\";\nimport { Vector } from \"./formula/Vector.js\";\nimport { ModelError } from \"./formula/ModelError.js\";\nimport { UnitManager } from \"./formula/Units.js\";\nimport Big from \"../vendor/bigjs/big.js\";\n\n/**\n * @typedef {object} SolverType\n * @property {string=} SolverType.id\n * @property {string=} SolverType.algorithm\n * @property {number=} SolverType.maxLoaded\n * @property {number=} SolverType.RKOrder\n * @property {number=} SolverType.RKPosition\n * @property {boolean=} SolverType.completedFirstPass\n * @property {Material=} SolverType.timeStep\n * @property {Material=} SolverType.userTimeStep\n * @property {import('./Primitives').SStock[]=} SolverType.stocks\n * @property {import('./Primitives').SFlow[]=} SolverType.flows\n * @property {import('./Primitives').SAction[]=} SolverType.actions\n * @property {import('./Primitives').STransition[]=} SolverType.transitions\n * @property {import('./Primitives').SState[]=} SolverType.states\n * @property {import('./Primitives').SPrimitive[]=} SolverType.valued\n * @property {import('./Primitives').SPrimitive[]=} SolverType.displayed\n */\n\n\n/**\n * @typedef {object} ResultsType\n * @property {number[]=} times\n * @property {string=} timeUnits\n * @property {any=} window\n * @property {ResultsDataType[]=} data\n * @property {boolean=} stochastic\n * @property {string=} error\n * @property {string=} errorSource\n * @property {import(\"./api/Blocks\").Primitive=} errorPrimitive\n * @property {number=} errorLine\n * @property {number=} errorCode\n * @property {function=} value\n * @property {function=} lastValue\n * @property {number=} periods\n * @property {function=} resume\n * @property {function=} setValue\n * @property {Object<string, { indexedNames?: string[], indexedFullNames?: any[], results?: ResultsResultsType[], states?: Set<string>, dataMode?: \"auto\"|\"agents\"|\"float\", data?: ResultsDataType}>=} children\n */\n\n/**\n * @typedef {object} AgentResultsType\n * @property {string} id\n * @property {import(\"./api/Blocks\").Population} item\n * @property {ResultsDataType} data\n * @property {ResultsResultsType} results\n */\n\n\n/**\n * @typedef {object} ResultsDataType\n */\n\n\n/**\n * @typedef {object} ResultsResultsType\n */\n\n\n/**\n * @typedef {object} DisplayInformationType\n * @property {boolean=} populated\n * @property {string[]=} ids\n * @property {string[]=} colors\n * @property {string[]=} icons\n * @property {string[]=} headers\n * @property {AgentResultsType[]=} agents\n * @property {{header: string, id: string, type: string, icon: string}[]=} displayedItems\n * @property {function[]=} renderers\n * @property {string[]=} elementIds\n * @property {ResultsType=} res\n * @property {number[]=} times\n * @property {SPrimitive[]=} objects\n * @property {string[]=} origIds\n * @property {any=} store\n * @property {any=} scripter\n * @property {any[]=} maps\n * @property {any[]=} histograms\n */\n\n\nexport class Simulator {\n  constructor() {\n    this.resultsWindow = undefined;\n\n    /** @type {function} */\n    this.setResultsCallback = undefined;\n    /** @type {function} */\n    this.setStatusCallback = undefined;\n\n    /** @type {function} */\n    this.finished = undefined;\n\n    /** @type {\"RUNNING\"|\"PAUSED\"|\"TERMINATED\"} */\n    this.status = undefined;\n\n    /** @type {boolean} */\n    this.valueChange = undefined;\n\n    /** @type {import(\"./Primitives\").SState[]} */\n    this.transitionPrimitives = undefined;\n\n    /** @type {number} */\n    this.timer = undefined;\n\n    /** @type {DisplayInformationType} */\n    this.displayInformation = undefined;\n\n    this.randLoc = -1;\n\n    /** @type {import(\"./api/Model.js\").Model} */\n    this.model = null;\n\n    this.lastRandPos = -1;\n\n    /** @type {import(\"./formula/Rand\").RandList[]} */\n    this.previousRandLists = [];\n\n    /** @type {Set<SPrimitive>} */\n    this.valuedPrimitives = new Set();\n\n    // Used to prevent evaluation loops\n    /** @type {Set<SPrimitive>} */\n    this.evaluatedPrimitives = new Set();\n\n    /** @type {Object<string, Material>} */\n    this.distanceCache = {};\n\n    /** @type {number} */\n    this.distanceCacheCount = 0;\n\n    /** @type {Object<string, any[]>} */\n    this.sliders = {};\n\n    /** @type {Object<string, number>} */\n    this.ids = {};\n\n    this.timeToStateMapping = new Map();\n\n    this.idCount = 0;\n\n    this.stochastic = false;\n\n    /** @type {number} */\n    this.RKOrder = undefined;\n\n    /** @type {import(\"./Modeler\").SimulationConfigType=} */\n    this.config = null;\n\n    /** @type {ResultsType} */\n    this.results = undefined;\n\n    /** @type {{ line: number, source: string }} */\n    this.evaluatingPosition = null;\n\n    // Used for canonical functions we want a reference to even if users\n    // override them.\n    /** @type {Map<import(\"./formula/Formula.js\").PARENT_SYMBOL|string, any>} */\n    this.coreBank = new Map();\n\n    /** @type {Map<import(\"./formula/Formula.js\").PARENT_SYMBOL|string, any>} */\n    this.varBank = new Map();\n\n    this.unitManager = new UnitManager();\n\n    /** @type {function} */\n    this.random = null;\n\n    /** @type {Object<string, { cluster: number, flow: number }>} */\n    this.clusters = null;\n\n    /** @type {string} */\n    this.timeUnitsString = null;\n  }\n\n\n  /**\n   * @param {import('./Modeler').ModelType} model\n   */\n  setup(model) {\n    this.simulationModel = model;\n\n    this.solversCompletedFirstPass = 0;\n\n    this.timeStart = this.simulationModel.timeStart;\n    this.timeLength = this.simulationModel.timeLength;\n    this.timePause = this.simulationModel.timePause;\n    // @ts-ignore - Big.js is mistyped\n    this.timeEnd = new Material(Big(this.timeStart.value).plus(this.timeLength.value).toNumber(), this.timeLength.units);\n    this.timeStep = this.simulationModel.solvers.base.timeStep;\n    this.userTimeStep = this.simulationModel.solvers.base.userTimeStep;\n    this.timeStepCount = Math.floor(this.timeLength.value / this.userTimeStep.value);\n    this.timeUnits = this.timeStart.units;\n    this.timeUnits.addBase();\n\n    /** @type {Map<string, import(\"./AggregateSeries\").AggregateSeries>} */\n    this.aggregateSeries = new Map();\n\n    this.distanceCache = {};\n\n    this.tasks = new TaskQueue({\n      start: this.timeStart,\n      end: this.timeEnd\n    });\n\n  }\n\n  /**\n   * @param {string} x\n   * @returns {number}\n   */\n  getID(x) {\n    if (!this.ids[x]) {\n      this.idCount++;\n      this.ids[x] = this.idCount;\n    }\n    return this.ids[x];\n  }\n\n  time() {\n    return this.tasks.time.fullClone();\n  }\n\n  timeProgressed() {\n    return minus(this.time(), this.timeStart);\n  }\n\n  /**\n   * @param {SPrimitive[]} valued\n   * @param {SPrimitive[]} displayed\n   */\n  frame(valued, displayed) {\n    let l = valued.length;\n\n    for (let i = 0; i < l; i++) {\n      valued[i].storeValue();\n    }\n\n    this.printStates(displayed);\n  }\n\n  /**\n   * @param {SolverType} solver\n   */\n  step(solver) {\n    if (!solver.completedFirstPass) {\n      solver.completedFirstPass = true;\n      this.solversCompletedFirstPass++;\n      if (this.solversCompletedFirstPass === Object.keys(this.simulationModel.solvers).length) {\n        if (this.config.onCompletedFirstPass) {\n          this.config.onCompletedFirstPass();\n        }\n      }\n    }\n\n    if (solver.displayed.length > 0) {\n      for (let i = this.results.children[solver.displayed[0].id].results.length; i < this.results.times.length; i++) {\n        for (let display of solver.displayed) {\n          this.results.children[display.id].results.push(this.results.data[i][display.id]);\n        }\n      }\n    }\n\n    if (this.config.onStep) {\n      this.config.onStep(solver);\n    }\n  }\n\n  sleep(shouldUpdateValues) {\n    if (this.config) {\n      if (!this.config.silent) {\n        this.shouldSleep = true;\n        this.shouldUpdateValues = shouldUpdateValues;\n      } else {\n        if (this.config.onPause) {\n          this.shouldSleep = true;\n        }\n      }\n    }\n\n  }\n\n  resume() {\n    try {\n      this.run();\n    } catch (err) {\n      return checkErr(err, this.config, this);\n    }\n  }\n\n  completed() {\n    return this.terminated || this.tasks.completed();\n  }\n\n  terminate() {\n    this.setStatus(\"TERMINATED\");\n\n    if (!this.terminated) {\n      clearTimeout(this.timer);\n      this.sleep();\n      this.terminated = true;\n    }\n  }\n\n  setStatus(s) {\n    this.status = s;\n    if (this.setStatusCallback) {\n      this.setStatusCallback(s);\n    }\n  }\n\n  /**\n   * @param {import(\"./Modeler\").SimulationConfigType=} config\n   * @returns\n   */\n  run(config) {\n    this.setStatus(\"RUNNING\");\n\n    let me = this;\n\n    /**\n     * @param {Material} time\n     * @param {boolean} repeat\n     */\n    let addPause = (time, repeat) => {\n      this.tasks.add(new Task({\n        time: time,\n        expires: 1,\n        name: \"Interval Pause\",\n        priority: 1,\n        action: (_task) => {\n          this.sleep(true);\n          if (\n            repeat\n            && (\n              this.config.pauseEachTimeStep ||\n              lessThan(plus(time, this.timePause), this.timeEnd))\n          ) {\n            addPause(plus(time,\n              this.config.pauseEachTimeStep ? this.userTimeStep : this.timePause\n            ), repeat);\n          }\n        }\n      }));\n\n      this.tasks.add(new Task({\n        time: time,\n        expires: 1,\n        name: \"Interval Pause\",\n        priority: 1,\n        action: (_task) => {\n          if (this.valueChange) {\n            me.evaluatedPrimitives = new Set();\n            for (let s in this.simulationModel.solvers) {\n              let solver = this.simulationModel.solvers[s];\n              for (let i = 0; i < solver.valued.length; i++) {\n                solver.valued[i].clearCached();\n              }\n              for (let i = 0; i < solver.flows.length; i++) {\n                solver.flows[i].predict(true);\n              }\n            }\n            this.valueChange = false;\n          }\n        }\n      }));\n    };\n\n    if (config) {\n\n      for (let solver in this.simulationModel.solvers) {\n        this.createSolver(this.simulationModel.solvers[solver]);\n      }\n\n      if (\n        this.config.pauseEachTimeStep\n        || this.timePause\n      ) {\n        addPause(\n          this.config.pauseEachTimeStep ? this.timeStart.fullClone() : plus(this.timeStart, this.timePause),\n          true\n        );\n      }\n\n      this.tasks.cursor = this.tasks.tasks.minNode();\n    }\n\n    this.wakeUpTime = Date.now();\n\n    try {\n      while (!this.completed()) {\n        this.tasks.step();\n\n        if (this.shouldSleep) {\n          for (let solver in this.simulationModel.solvers) {\n            updateDisplayed(this.simulationModel.solvers[solver], this);\n          }\n\n          if (this.setResultsCallback) {\n            this.setResultsCallback(formatSimResults(this.results));\n          }\n\n          if (this.shouldUpdateValues) {\n            this.setStatus(\"PAUSED\");\n            this.shouldUpdateValues = false;\n          }\n\n          if (this.config.onPause) {\n            setTimeout(() => {\n              let res = formatSimResults(this.results);\n              let l = res.data.length;\n              let data = res.data[l - 1];\n              for (let key in data) {\n                if (key === \"time\") {\n                  continue;\n                }\n                if (!res.children[key]) {\n                  return; // stale call\n                }\n                if (res.children[key].results.length < l) {\n                  res.children[key].results.push(data[key]);\n                }\n              }\n\n              res.resume = this.resume.bind(this);\n              res.setValue = (cell, value) => {\n                let val = simpleEquation(\"\" + value, this, new Map([[PARENT_SYMBOL, this.varBank]]));\n\n                let found = false;\n\n                [...this.valuedPrimitives.values()].forEach((x) => {\n                  if (x.id === cell.id) {\n                    found = true;\n                    if (val.fullClone) {\n                      x.dna.equation = val.fullClone();\n                      x.equation = val.fullClone();\n                    } else {\n                      x.dna.equation = val;\n                      x.equation = val;\n                    }\n                  }\n                });\n\n                if (found) {\n                  this.valueChange = true;\n                } else {\n                  throw new ModelError(\"Could not find the primitive to update with setValue().\", {\n                    code: 8002\n                  });\n                }\n              };\n              this.config.onPause(res);\n            }, 10);\n          }\n\n          this.shouldSleep = false;\n          return;\n        }\n      }\n    } catch (err) {\n      if (err.simulationCommand !== \"STOP\") {\n        throw err;\n      }\n    }\n\n\n    this.results = formatSimResults(this.results);\n\n\n    this.results.stochastic = this.stochastic;\n\n    if (this.config.onSuccess) {\n      this.config.onSuccess(this.results);\n    }\n\n    this.terminate();\n\n    if (this.resultsWindow) {\n      this.results.window = this.resultsWindow;\n      for (let solver in this.simulationModel.solvers) {\n        updateDisplayed(this.simulationModel.solvers[solver], this);\n      }\n    }\n\n    return this.results;\n  }\n\n  progress() {\n    return div(minus(this.time(), this.timeStart), this.timeLength).value;\n  }\n\n  /**\n   * @param {SPrimitive[]} displayed\n   */\n  printStates(displayed) {\n    if (!this.timeToStateMapping.has(this.tasks.time.value)) {\n      let t = parseFloat(this.tasks.time.value.toPrecision(20));\n\n      let newData = {};\n      let i;\n      for (i = this.results.times.length; i > 0; i--) {\n        if (this.results.times[i - 1] < t) {\n          this.results.times.splice(i, 0, t);\n          this.results.data.splice(i, 0, newData);\n          break;\n        }\n      }\n      if (i === 0) {\n        this.results.times.splice(0, 0, t);\n        this.results.data.splice(0, 0, newData);\n      }\n      this.timeToStateMapping.set(this.tasks.time.value, newData);\n    }\n\n    let data = this.timeToStateMapping.get(this.tasks.time.value);\n\n    for (let i = 0; i < displayed.length; i++) {\n      let v = displayed[i];\n\n      if (!((v instanceof SState) && data[v.id] !== undefined)) {\n        if (v instanceof SPopulation) {\n          this.results.children[v.id].dataMode = \"agents\";\n          data[v.id] = { current: v.collectData() };\n        } else {\n          let x = v.value();\n\n          if ((x instanceof Vector) && (!x.names)) {\n            x.recurseApply((x) => {\n              return this.adjustNum(v, x);\n            });\n            data[v.id] = cleanData(x);\n            this.results.children[v.id].dataMode = \"auto\";\n          } else if (x instanceof Vector) {\n            x.recurseApply((x) => {\n              return this.adjustNum(v, x);\n            });\n            data[v.id] = cleanData(x);\n          } else if (x instanceof SAgent) {\n            data[v.id] = x;\n            this.results.children[v.id].dataMode = \"auto\";\n          } else {\n            data[v.id] = cleanData(this.adjustNum(v, x));\n          }\n\n        }\n      }\n    }\n  }\n\n\n  /**\n   * @param {SPrimitive} v\n   * @param {Material} x\n   *\n   * @return {number}\n   */\n  adjustNum(v, x) {\n    if (v.dna.unitless && x.units) {\n      throw new ModelError(`The result of the calculation has units <i>${x.units.toString()}</i>, but the primitive is unitless. Please set the units for the primitive so we can determine the proper output.`,\n        {\n          primitive: v,\n          showEditor: true,\n          code: 8000\n        });\n    }\n\n\n    if ((v instanceof SState) || ((!x.units) && !(v instanceof SFlow))) {\n      if (typeof x === \"object\" && \"value\" in x) {\n        return +x.value;\n      }\n      // string, boolean, ...\n      // @ts-ignore\n      return x;\n    } else {\n      let m = v.matchPrimitiveUnits(x.units);\n      if (m === 1) {\n        return x.value;\n      }\n      return +fn[\"*\"](x.value, m);\n    }\n  }\n\n  /**\n   * @param {SolverType} solver\n   */\n  createSolver(solver) {\n    let me = this;\n\n    let stocks = solver.stocks;\n    let flows = solver.flows;\n\n    let actions = solver.actions;\n    let transitions = solver.transitions;\n    let valued = solver.valued;\n    valued.forEach(v => this.valuedPrimitives.add(v));\n    let displayed = solver.displayed;\n\n    let id = solver.id;\n\n    let timeStep = solver.timeStep;\n    let RKOrder = solver.RKOrder;\n    solver.RKPosition = 1;\n\n\n    let index = 0;\n    /** @type {Material[]} */\n    let times = [];\n    // @ts-ignore - Big.js is mistyped\n    let maxIndex = Math.ceil((new Big(this.timeEnd.value)).minus(this.timeStart.value).div(timeStep.value).toNumber());\n    for (let i = 0; i <= maxIndex + 2; i++) {\n      // @ts-ignore - Big.js is mistyped\n      times.push(new Material((new Big(this.timeStart.value).plus(new Big(i).times(timeStep.value))).toNumber(), timeStep.units));\n    }\n\n\n    /**\n     * @param {Material} time\n     * @param {boolean} repeat\n     * @param {boolean=} clear\n     */\n    let addRK1Solver = (time, repeat, clear) => {\n      this.tasks.add(new Task({\n        time: time,\n        expires: 1,\n        priority: 0,\n        name: \"RK1 Solver - \" + solver.id,\n        action: (_task) => {\n          me.evaluatedPrimitives = new Set();\n          if (clear) {\n            let l = flows.length;\n            for (let i = 0; i < l; i++) {\n              flows[i].clean();\n            }\n\n\n            l = valued.length;\n            for (let i = 0; i < l; i++) {\n              valued[i].clearCached();\n            }\n          }\n\n          this.frame(valued, displayed);\n\n          let l = actions.length;\n          for (let i = 0; i < l; i++) {\n            if (!actions[i].initialized || (actions[i].dna.recalculate && !actions[i].block)) {\n              updateTrigger.call(actions[i]);\n            }\n          }\n\n          l = transitions.length;\n          for (let i = 0; i < l; i++) {\n            if (!transitions[i].initialized || transitions[i].dna.recalculate) {\n              updateTrigger.call(transitions[i]);\n            }\n          }\n\n          this.step(solver);\n\n\n          if (repeat && index <= maxIndex) {\n            index++;\n            addRK1Solver(times[index], true, true);\n          }\n\n        }\n      })\n      );\n    };\n\n    /**\n     * @param {Material} time\n     * @param {boolean} repeat\n     */\n    let addRK4Solver = (time, repeat) => {\n      /*\n\n      1. (t=0) Calculate rates at t=0, move to t=0.5 (rollback restore stocks)\n      2. (t=0.5) Calculate rates at t=0.5\n      3. (t=0) Use rate of (t=0.5) to move to t=0.5 (rollback restores stocks)\n      4. (t=0.5) Calculate rates at t=0.5\n      5. (t=0) Use rates of (t=0.5 (2)) to move to t=1 (rollback restores stocks)\n      6. (t=1) Calculate rates at t=1\n      7. (t=0) Use average rates to move to t=0\n\n      */\n\n\n      this.tasks.add(new Task({\n        time: time,\n        name: \"RK4 Solver (Init)  - \" + solver.id,\n        priority: -10,\n        expires: 1,\n        blocker: id + \" init\",\n        action: (task) => {\n          let l = flows.length;\n          for (let i = 0; i < l; i++) {\n            flows[i].clean();\n          }\n\n          me.evaluatedPrimitives = new Set();\n\n          l = valued.length;\n          for (let i = 0; i < l; i++) {\n            valued[i].clearCached();\n          }\n\n          solver.RKPosition = 1;\n\n          task.unblock(id + \" start\");\n          task.block();\n        }\n      })\n      );\n      this.tasks.add(new Task({\n        time: time,\n        name: \"RK4 Solver (step 1) - \" + solver.id,\n        priority: -5,\n        expires: 4,\n        blocker: id + \" start\",\n        action: (task) => {\n          if (solver.RKPosition > 1) {\n            me.evaluatedPrimitives = new Set();\n            let l = valued.length;\n            for (let i = 0; i < l; i++) {\n              valued[i].clearCached();\n              valued[i].pastValues.pop();\n            }\n\n            if (solver.RKPosition === 4) {\n              l = flows.length;\n              for (let i = 0; i < l; i++) {\n                let initialRate = flows[i].checkRate(flows[i].RKPrimary[0].fullClone());\n                flows[i].doRK4Aggregation();\n                flows[i].rate = initialRate;\n              }\n            }\n\n          }\n\n          this.frame(valued, displayed);\n\n          if (solver.RKPosition === 4) {\n\n            let l = actions.length;\n            for (let i = 0; i < l; i++) {\n              if (!actions[i].initialized || (actions[i].dna.recalculate && !actions[i].block)) {\n                updateTrigger.call(actions[i]);\n              }\n            }\n\n            l = transitions.length;\n            for (let i = 0; i < l; i++) {\n              if (!transitions[i].initialized || transitions[i].dna.recalculate) {\n                updateTrigger.call(transitions[i]);\n              }\n            }\n\n            task.unblock(id + \" init\");\n\n            if (repeat && index <= maxIndex) {\n              index += 2;\n              addRK4Solver(times[index], true);\n            }\n\n            this.step(solver);\n          } else if (eq(me.time(), me.timeEnd)) {\n            this.step(solver);\n          } else {\n            let l = stocks.length;\n            for (let i = 0; i < l; i++) {\n              stocks[i].preserveLevel();\n            }\n          }\n\n          task.block();\n          task.unblock(id + \" mid\");\n        },\n        rollback: function () {\n          let l = stocks.length;\n          for (let i = 0; i < l; i++) {\n            stocks[i].restoreLevel();\n          }\n        }\n      })\n      );\n      this.tasks.add(new Task({\n        time: times[index + 1],\n        name: \"RK4 Solver (step 2,3) - \" + solver.id,\n        priority: -10,\n        expires: 2,\n        blocker: id + \" mid\",\n        action: (task) => {\n          me.evaluatedPrimitives = new Set();\n          let l = valued.length;\n          for (let i = 0; i < l; i++) {\n            if (!(valued[i] instanceof SState)) {\n              valued[i].clearCached();\n            }\n          }\n\n\n          solver.RKPosition++;\n\n          l = flows.length;\n          for (let i = 0; i < l; i++) {\n            flows[i].rate = null;\n          }\n\n          for (let i = 0; i < l; i++) {\n            flows[i].value();\n          }\n\n          task.unblock(id + \" start\");\n          task.block();\n        },\n        timeShift: () => {\n          this.tasks.moveTo(times[index]);\n        }\n      })\n      );\n\n      this.tasks.add(new Task({\n        time: times[index + 2],\n        name: \"RK4 Solver (step 4) - \" + solver.id,\n        priority: -30,\n        expires: 1,\n        action: (task) => {\n          me.evaluatedPrimitives = new Set();\n          let l = valued.length;\n          for (let i = 0; i < l; i++) {\n            if (!(valued[i] instanceof SState)) {\n              valued[i].clearCached();\n            }\n          }\n\n          solver.RKPosition++;\n\n          l = flows.length;\n          for (let i = 0; i < l; i++) {\n            flows[i].rate = null;\n          }\n\n          for (let i = 0; i < l; i++) {\n            flows[i].value();\n          }\n\n          task.unblock(id + \" start\");\n        },\n        timeShift: () => {\n          this.tasks.moveTo(times[index]);\n        }\n      })\n      );\n    };\n\n    function valMatches(val, fn) {\n      if (val instanceof Vector) {\n        let matches = false;\n        val.recurseApply((x) => {\n          matches = matches || fn(x);\n        });\n        return matches;\n      } else {\n        return fn(val);\n      }\n    }\n\n    function valHasNegative(val) {\n      return val && valMatches(toNum(val), (x) => {\n        return (x instanceof Material) && x.value < 0;\n      });\n    }\n\n    function valHasPositive(val) {\n      return val && valMatches(toNum(val), (x) => {\n        return (x instanceof Material) && x.value > 0;\n      });\n    }\n\n    /**\n     * @param {Material} timeChange\n     * @param {Material} oldTime\n     */\n    function doFlows(timeChange, oldTime) {\n\n      // first apply flows that won't be limited by non-negative stocks\n      let post = [];\n      for (let flow of flows) {\n        if (flow.alpha && flow.alpha.dna.nonNegative && valHasPositive(flow.rate)) {\n          post.push(flow);\n        } else if (flow.omega && flow.omega.dna.nonNegative && valHasNegative(flow.rate)) {\n          post.push(flow);\n        } else {\n          flow.apply(timeChange, oldTime);\n        }\n      }\n\n\n      // we use the topological sort order for nonnegative stocks so\n      // \"upstream\" flows will be applied before downstream ones\n      post.sort((a, b) => {\n        let aOrder = me.clusters[a.id];\n        let bOrder = me.clusters[b.id];\n        if (aOrder.cluster < bOrder.cluster) {\n          return -1;\n        }\n        if (aOrder.cluster > bOrder.cluster) {\n          return 1;\n        }\n        if (aOrder.flow < bOrder.flow) {\n          return -1;\n        }\n        if (aOrder.flow > bOrder.flow) {\n          return 1;\n        }\n        return 0;\n      });\n\n      for (let p of post) {\n        p.apply(timeChange, oldTime);\n      }\n    }\n\n\n    if (RKOrder === 1) {\n      this.tasks.addEvent((timeChange, oldTime) => {\n        doFlows(timeChange, oldTime);\n      });\n\n      addRK1Solver(this.timeStart, true);\n    } else if (RKOrder === 4) {\n      this.tasks.addEvent((timeChange, oldTime) => {\n        if (timeChange.value > 0) {\n          doFlows(timeChange, oldTime);\n        }\n      });\n\n      addRK4Solver(this.timeStart, true);\n    } else {\n      throw new ModelError(\"Unknown solution algorithm.\", {\n        code: 8001\n      });\n    }\n  }\n}\n", "src/TaskScheduler.js": "import { mult, greaterThan, minus, eq, neq, lessThan } from \"./formula/Formula.js\";\nimport { Material } from \"./formula/Material.js\";\nimport Tree from \"../vendor/avl/avl.js\";\n\n\nexport class TaskQueue {\n  constructor(config) {\n    config = config || {};\n    this.tasks = new Tree(compare);\n    /** @type {(function(Material, Material, Material): void)[]} */\n    this.onMoveEvents = [];\n    this.setTime(config.start);\n    this.debug = false;\n\n    /**\n     * @type {Material}\n     */\n    this.end = config.end;\n\n    /**\n     * @type {Object<string, boolean>}\n     */\n    this.states = {};\n\n    /** @type {import(\"../vendor/avl/avl\").Node} */\n    this.cursor = null;\n  }\n\n  print() {\n    console.log(\"Current Time: \" + this.time.value);\n    let cursor = this.tasks.minNode();\n    while (cursor) {\n      console.log(cursor.key.name);\n      console.log(\"    Time: \" + cursor.key.time.value);\n      console.log(\"    Priority: \" + cursor.key.priority);\n      if (cursor.key.expires !== undefined) {\n        console.log(\"    Expires: \" + cursor.key.expires);\n      }\n      cursor = this.tasks.next(cursor);\n    }\n  }\n\n  /**\n   * @param {(function(Material, Material, Material): void)} event\n   */\n  addEvent(event) {\n    this.onMoveEvents.push(event);\n  }\n\n  /**\n   * @param {Material} timeChange\n   * @param {Material} oldTime\n   * @param {Material} newTime\n   */\n  fireEvents(timeChange, oldTime, newTime) {\n    if (this.debug) {\n      console.log(\"Firing Events\");\n    }\n    for (let i = 0; i < this.onMoveEvents.length; i++) {\n      this.onMoveEvents[i](timeChange, oldTime, newTime);\n    }\n  }\n\n  /**\n   * @param {Material} t\n   */\n  setTime(t) {\n    if (this.time === undefined || neq(t, this.time)) {\n      let oldTime = this.time;\n\n      this.time = t;\n\n      if (oldTime !== undefined) {\n        this.fireEvents(minus(t, oldTime), oldTime, t);\n      }\n\n    }\n  }\n\n  /**\n   * @param {Material} newTime\n   */\n  moveTo(newTime) {\n    if (eq(this.time, newTime)) {\n      return;\n    } else {\n      if (this.debug) {\n        console.log(\"Shifting time to: \" + newTime.value);\n      }\n\n      if (this.cursor) { // we have something defined\n        let maxTime = this.tasks.max().time;\n        let minTime = this.tasks.min().time;\n\n        while (lessThan(this.time, newTime) && (!greaterThan(this.time, maxTime))) {\n          this.step();\n        }\n        while (greaterThan(this.time, newTime) && greaterThan(this.time, minTime)) {\n          this.stepBack();\n        }\n      }\n\n      this.setTime(newTime);\n\n      if (this.debug) {\n        console.log(\"Time shift to  \" + newTime.value + \" completed.\");\n      }\n    }\n  }\n\n  /**\n   * @param {Task} task\n   */\n  add(task) {\n    task.queue = this;\n\n    this.tasks.insert(task);\n  }\n\n  goNext() {\n    this.cursor = this.tasks.next(this.cursor);\n  }\n\n  goPrev() {\n    this.cursor = this.tasks.prev(this.cursor);\n  }\n\n  step() {\n    if (this.time === undefined) {\n      this.cursor = this.tasks.minNode();\n      this.setTime(this.cursor.key.time);\n    }\n\n\n    let current = this.cursor.key;\n    if (current) {\n      let dead = current.deadAction;\n      current.execute();\n\n      if ((!dead) && current.timeShift) {\n        current.timeShift();\n        return;\n      }\n      this.goNext();\n    }\n\n    if (this.cursor) {\n      this.setTime(this.cursor.key.time);\n    } else {\n      this.goNext();\n      this.setTime(mult(/** @type {Material} */(this.tasks.max().time), new Material(10)));\n    }\n  }\n\n  stepBack() {\n    if (this.time === undefined) {\n      this.cursor = this.tasks.minNode();\n      this.setTime(this.cursor.key.time);\n      return;\n    }\n\n    if (!this.cursor) {\n      this.cursor = this.tasks.maxNode();\n    } else {\n      this.goPrev();\n    }\n\n    let t = this.cursor.key.time;\n    while (this.cursor && eq(t, this.cursor.key.time)) {\n      this.cursor.key.rollback();\n      this.goPrev();\n    }\n\n    if (!this.cursor) {\n      this.cursor = this.tasks.minNode();\n    } else {\n      this.goNext();\n    }\n\n    this.setTime(this.cursor.key.time);\n  }\n\n  /**\n   * @returns {boolean}\n   */\n  atStart() {\n    return this.time === undefined || this.cursor.key === this.tasks.min();\n  }\n\n  /**\n   * @returns {boolean}\n   */\n  completed() {\n    return this.time !== undefined && (greaterThan(this.time, this.end) || (!this.cursor));\n  }\n\n  /**\n   * @param {Task} task\n   */\n  remove(task) {\n    if (task === this.cursor.key) {\n      this.goNext();\n    }\n    this.tasks.remove(task);\n  }\n}\n\n\nlet taskIdCounter = 0;\n\n// new Task({name: \"solver\", time: t, action: fn(), rollback: fn(), priority: -10, expires: 1})\nexport class Task {\n  /**\n   * @param {Object} config\n   * @param {string} config.name\n   * @param {Material} config.time\n   * @param {(function(Task) : void) & {task?: Task, reverse?: Task}} config.action\n   * @param {function=} config.rollback\n   * @param {number=} config.priority\n   * @param {number=} config.expires\n   * @param {function=} config.timeShift\n   * @param {any=} config.data\n   * @param {string=} config.blocker\n   */\n  constructor(config) {\n    /** @type {number} */\n    this.id = taskIdCounter++; // must be numeric as we use it in equality comparisons\n    this.name = config.name;\n    this.time = config.time;\n\n    if (!this.time) {\n      throw new TypeError(\"Task time is missing.\");\n    }\n\n    if (isNaN(this.time.value)) {\n      throw new TypeError(\"Task time is a NaN.\");\n    }\n\n    this.action = config.action;\n    this.reverse = config.rollback;\n    this.priority = config.priority || 0; // Lower priorities will be run before higher priorities at the same time\n    this.expires = config.expires; // if defined, the number of times this is called before it expires\n    this.timeShift = config.timeShift;\n    this.data = config.data; // optional data object to be carried along, the task scheduler makes no use of this\n    this.blocker = config.blocker;\n    this.queue = undefined;\n\n    this.deadAction = false; // once dead no longer executes\n    this.deadReverse = false; // once dead no longer executes\n\n    if (this.action) {\n      this.action.task = this;\n    }\n    if (this.reverse) {\n      this.action.reverse = this;\n    }\n\n  }\n\n  execute() {\n    if (this.action && (!this.deadAction) && ((!this.blocker) || !this.queue.states[this.blocker])) {\n\n      if (this.queue.debug) {\n        console.log(\"%c Executing: \" + this.name + \" (Time: \" + this.time.value + \")\", \"color:blue\");\n      }\n\n      if (this.expires !== undefined) {\n        this.expires--;\n        if (this.queue.debug) {\n          console.log(\"    Current count before expire: \" + this.expires);\n        }\n        if (this.expires <= 0) {\n          if (this.queue.debug) {\n            console.log(\"    Task expired.\");\n          }\n          this.deadAction = true;\n        }\n      }\n\n\n      this.action(this);\n    }\n  }\n\n  rollback() {\n    if (this.reverse && (!this.deadReverse) && ((!this.blocker) || !this.queue.states[this.blocker])) {\n      if (this.queue.debug) {\n        console.log(\"Rolling back: \" + this.name + \" (Time: \" + this.time.value + \")\");\n      }\n\n      if (this.expires !== undefined) {\n        if (this.expires <= 0) {\n          if (this.queue.debug) {\n            console.log(\"    Rollback expired.\");\n          }\n          this.deadReverse = true;\n        }\n      }\n\n      this.reverse();\n    }\n  }\n\n  /**\n   * @param {Material} newTime\n   */\n  reschedule(newTime) {\n    this.queue.remove(this);\n    this.time = newTime;\n    this.queue.add(this);\n  }\n\n  remove() {\n    this.queue.remove(this);\n  }\n\n  kill() {\n    this.deadAction = true;\n    this.deadReverse = true;\n  }\n\n  /**\n   * @param {string=} id\n   */\n  block(id) {\n    id = id || this.blocker;\n    this.queue.states[id] = true;\n  }\n\n  /**\n   * @param {string=} id\n   */\n  unblock(id) {\n    id = id || this.blocker;\n    this.queue.states[id] = false;\n  }\n\n  toString() {\n    return this.name + \" - \" + this.id;\n  }\n}\n\n\n\n/**\n * Sorts by:\n *   - first by time\n *   - then by priority\n *   - then by creation order (id)\n *\n * @param {Task} a\n * @param {Task} b\n *\n * @returns {number}\n */\nfunction compare(a, b) {\n  if (eq(b.time, a.time)) {\n    if (b.priority === a.priority) {\n      if (b.id === a.id) {\n        return 0;\n      } else if (b.id < a.id) {\n        return 1;\n      } else {\n        return -1;\n      }\n    } else if (b.priority < a.priority) {\n      return 1;\n    } else {\n      return -1;\n    }\n  } else {\n    if (lessThan(b.time, a.time)) {\n      return 1;\n    } else {\n      return -1;\n    }\n  }\n}\n", "src/CalcMap.js": "\nexport let fn = {\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"+\": function (a, b) {\n    return a + b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number=} b\n   * @returns\n   */\n  \"-\": function (a, b) {\n    if (b !== undefined) {\n      return a - b;\n    } else {\n      return -a;\n    }\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"*\": function (a, b) {\n    return a * b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"/\": function (a, b) {\n    return a / b;\n  },\n\n  \"=\": function (a, b) {\n    return a === b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"<\": function (a, b) {\n    return a < b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"<=\": function (a, b) {\n    return a <= b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \">\": function (a, b) {\n    return a > b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \">=\": function (a, b) {\n    return a >= b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"mod\": function (a, b) {\n    return a % b;\n  },\n\n  /**\n   * @param {number} a\n   * @param {number} b\n   * @returns\n   */\n  \"expt\": function (a, b) {\n    return Math.pow(a, b);\n  },\n  \"abs\": Math.abs,\n  \"sin\": Math.sin,\n  \"asin\": Math.asin,\n  \"cos\": Math.cos,\n  \"acos\": Math.acos,\n  \"tan\": Math.tan,\n  \"atan\": Math.atan,\n  \"sqrt\": Math.sqrt,\n\n  /**\n   * @param {number} a\n   * @param {number=} b\n   * @returns\n   */\n  \"log\": function (a, b) {\n    if (b !== undefined) {\n      return Math.log(a) / Math.log(b);\n    } else {\n      return Math.log(a);\n    }\n  },\n  \"exp\": Math.exp,\n  \"round\": Math.round,\n  \"floor\": Math.floor,\n  \"ceiling\": Math.ceil\n};\n", "src/formula/CalcFunctions.js": "import { agent, agents, getPopulation } from \"../Functions.js\";\nimport { SPrimitive, SAgent, SPopulation } from \"../Primitives.js\";\nimport { fn } from \"../CalcMap.js\";\nimport { div, eq, evaluateNode, greaterThan, lessThan, minus, mult, PARENT_SYMBOL, plus, power, StringObject, toNum, trueValue, UserFunction, VectorObject } from \"./Formula.js\";\nimport { Rand, RandBeta, RandBinomial, RandDist, RandExp, RandGamma, RandLognormal, RandNegativeBinomial, RandNormal, RandPoisson, RandTriangular } from \"./Rand.js\";\nimport { Material, findSharedUnits } from \"./Material.js\";\nimport { convertUnits } from \"./Units.js\";\nimport { stringify, strictEquals } from \"./Utilities.js\";\nimport { Vector } from \"./Vector.js\";\nimport { ModelError } from \"./ModelError.js\";\nimport { jStat } from \"../../vendor/jstat/jstat.js\";\nimport { SeedRandom } from \"../../vendor/random.js\";\nimport { createUnitStore } from \"../Modeler.js\";\n\n\n/**\n * @param {Material} mat\n * @param {import(\"./Units\").UnitStore=} sharedUnits\n * @returns {number}\n */\nfunction standardizedValue(mat, sharedUnits) {\n  if (sharedUnits && mat.units !== sharedUnits) {\n    return fn[\"*\"](mat.value, convertUnits(mat.units, sharedUnits));\n  }\n  return mat.value;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nexport function createFunctions(simulate) {\n  defineFunction(simulate, \"RandBeta\", { params: [{ name: \"Alpha\", noUnits: true, noVector: true }, { name: \"Beta\", noUnits: true, noVector: true }] }, (x) => {\n    return new Material(RandBeta(simulate, x[0].value, x[1].value));\n  });\n\n  defineFunction(simulate, \"RandDist\", { params: [{ name: \"Distribution\", needVector: true }, { name: \"Y (in which case Distribution is X)\", noUnits: true, needVector: true, defaultVal: false }] }, (x) => {\n    let xMats, yMats;\n    if (x.length === 1 || x[1] === false) {\n      let vec = x[0];\n      xMats = [];\n      yMats = [];\n      for (let i = 0; i < vec.items.length; i++) {\n        if (!(vec.items[i] instanceof Vector) || vec.items[i].items.length !== 2) {\n          throw new ModelError(\"Invalid vector provided to RandDist.\", {\n            code: 6000\n          });\n        }\n        xMats.push(toNum(vec.items[i].items[0]));\n        yMats.push(toNum(vec.items[i].items[1]));\n      }\n    } else {\n      xMats = toNum(x[0]).items.map(z => toNum(z));\n      yMats = toNum(x[1]).items.map(z => toNum(z));\n    }\n\n    for (let m of yMats) {\n      if (m && m.units && !m.units.isUnitless()) {\n        throw new ModelError(`RandDist does not accept units for the Y values. Got units of <i>${m.units.toString()}</i>.`, {\n          code: 6063\n        });\n      }\n    }\n\n    let { units: sharedUnits, explicitUnits } = findSharedUnits(xMats);\n    let xVals = xMats.map(m => standardizedValue(m, sharedUnits));\n    let yVals = yMats.map(m => m.value);\n\n    let result = new Material(RandDist(simulate, xVals, yVals));\n    if (sharedUnits) {\n      result.units = sharedUnits;\n      result.explicitUnits = explicitUnits;\n    }\n    return result;\n  });\n\n  defineFunction(simulate, \"RandBoolean\", { params: [{ name: \"Probability\", defaultVal: 0.5, noUnits: true, vectorize: true }] }, (x) => {\n    let p;\n    if (x.length !== 0) {\n      p = toNum(x[0]).value;\n    } else {\n      p = 0.5;\n    }\n\n    if (Rand(simulate) < p) {\n      return true;\n    } else {\n      return false;\n    }\n  });\n  defineFunction(simulate, \"Rand\", { params: [{ name: \"Lower Bound\", defaultVal: 0, vectorize: true }, { name: \"Upper Bound\", defaultVal: 1, vectorize: true }] }, (x) => {\n    if (x.length === 0) {\n      return new Material(Rand(simulate));\n    } else if (x.length === 2) {\n      let lower = toNum(x[0]);\n      let upper = toNum(x[1]);\n      let { units: sharedUnits, explicitUnits } = findSharedUnits([lower, upper]);\n      let result = new Material(Rand(simulate, standardizedValue(lower, sharedUnits), standardizedValue(upper, sharedUnits)));\n      if (sharedUnits) {\n        result.units = sharedUnits;\n        result.explicitUnits = explicitUnits;\n      }\n      return result;\n    } else {\n      throw new ModelError(\"Rand() must either have no parameters or two: Min and Max bounds.\", {\n        code: 6001\n      });\n    }\n  });\n  defineFunction(simulate, \"RandNormal\", { params: [{ name: \"Mean\", defaultVal: 0, noUnits: true, vectorize: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, vectorize: true }] }, (x) => {\n    if (x.length === 0) {\n      return new Material(RandNormal(simulate));\n    } else if (x.length === 2) {\n      return new Material(RandNormal(simulate, toNum(x[0]).value, toNum(x[1]).value));\n    } else {\n      throw new ModelError(\"RandNormal() must either have no parameters or two: Mean and Standard Deviation.\", {\n        code: 6002\n      });\n    }\n  });\n  defineFunction(simulate, \"RandExp\", { params: [{ name: \"Rate\", defaultVal: 1, noUnits: true, vectorize: true }] }, (x) => {\n    if (x.length !== 0) {\n      return new Material(RandExp(simulate, toNum(x[0]).value));\n    } else {\n      return new Material(RandExp(simulate));\n    }\n  });\n  defineFunction(simulate, \"RandLognormal\", { params: [{ name: \"Mean\", noUnits: true, vectorize: true }, { name: \"Standard Deviation\", noUnits: true, vectorize: true }] }, (x) => {\n    return new Material(RandLognormal(simulate, toNum(x[0]).value, toNum(x[1]).value));\n  });\n  defineFunction(simulate, \"RandBinomial\", { params: [{ name: \"Count\", noUnits: true, vectorize: true }, { name: \"Probability\", noUnits: true, vectorize: true }] }, (x) => {\n    return new Material(RandBinomial(simulate, toNum(x[0]).value, toNum(x[1]).value));\n  });\n  defineFunction(simulate, \"RandNegativeBinomial\", { params: [{ name: \"Successes\", noUnits: true, vectorize: true }, { name: \"Probability\", noUnits: true, vectorize: true }] }, (x) => {\n    return new Material(RandNegativeBinomial(simulate, toNum(x[0]).value, toNum(x[1]).value));\n  });\n  defineFunction(simulate, \"RandGamma\", { params: [{ name: \"Alpha\", noUnits: true, vectorize: true }, { name: \"Beta\", noUnits: true, vectorize: true }] }, (x) => {\n    return new Material(RandGamma(simulate, toNum(x[0]).value, toNum(x[1]).value));\n  });\n  defineFunction(simulate, \"RandPoisson\", { params: [{ name: \"Rate\", noUnits: true, vectorize: true }] }, (x) => {\n    return new Material(RandPoisson(simulate, toNum(x[0]).value));\n  });\n  defineFunction(simulate, \"RandTriangular\", { params: [{ name: \"Minimum\", vectorize: true }, { name: \"Maximum\", vectorize: true }, { name: \"Peak\", vectorize: true }] }, (x) => {\n    let min = toNum(x[0]);\n    let max = toNum(x[1]);\n    let peak = toNum(x[2]);\n    let { units: sharedUnits, explicitUnits } = findSharedUnits([min, max, peak]);\n    let result = new Material(RandTriangular(simulate, standardizedValue(min, sharedUnits), standardizedValue(max, sharedUnits), standardizedValue(peak, sharedUnits)));\n    if (sharedUnits) {\n      result.units = sharedUnits;\n      result.explicitUnits = explicitUnits;\n    }\n    return result;\n  });\n\n  defineFunction(simulate, \"Magnitude\", { params: [{ name: \"Vector\", needVector: true }], complete: false }, (x) => {\n    return simulate.coreBank.get(\"sqrt\")([simulate.coreBank.get(\"sum\")([mult(x[0], x[0])])]);\n  });\n\n\n\n  defineFunction(simulate, \"Abs\", { params: [{ name: \"Number\", leafNeedNum: true }], recurse: true }, (x) => {\n    let r = toNum(x[0]);\n    r.value = fn.abs(r.value);\n    return r;\n  });\n  defineFunction(simulate, \"sin\", { params: [{ name: \"Number\", leafNeedNum: true }], recurse: true}, (x) => {\n    let z = toNum(x[0]);\n\n    if (z.units && !z.units.isUnitless()) {\n      z = mult(z, new Material(1, simulate.unitManager.getUnitStore([\"radians\"], [-1])));\n    }\n    if (!z.units) {\n      return new Material(fn.sin(z.value));\n    } else {\n      throw new ModelError(\"Non-angular units cannot be used in Sin().\", {\n        code: 6003\n      });\n    }\n  });\n  defineFunction(simulate, \"cos\", { params: [{ name: \"Number\", leafNeedNum: true }], recurse: true }, (x) => {\n    let z = toNum(x[0]);\n\n    if (z.units && !z.units.isUnitless()) {\n      z = mult(z, new Material(1, simulate.unitManager.getUnitStore([\"radians\"], [-1])));\n    }\n    if (!z.units) {\n      return new Material(fn.cos(z.value));\n    } else {\n      throw new ModelError(\"Non-angular units cannot be used in Cos().\", {\n        code: 6004\n      });\n    }\n  });\n  defineFunction(simulate, \"tan\", { params: [{ name: \"Number\", leafNeedNum: true }], recurse: true }, (x) => {\n    let z = toNum(x[0]);\n\n    if (z.units && !z.units.isUnitless()) {\n      z = mult(z, new Material(1, simulate.unitManager.getUnitStore([\"radians\"], [-1])));\n    }\n    if (!z.units) {\n      return new Material(fn.tan(z.value));\n    } else {\n      throw new ModelError(\"Non-angular units cannot be used in Tan().\", {\n        code: 6005\n      });\n    }\n  });\n  defineFunction(simulate, \"asin\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true, complete: false }, (x) => {\n\n    let val = toNum(x[0]).value;\n    if (val < -1 || val > 1) {\n      throw new ModelError(\"asin() input must be between -1 and 1.\", {\n        code: 6077\n      });\n    }\n\n    return new Material(fn.asin(val));\n  });\n  defineFunction(simulate, \"acos\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true, complete: false }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < -1 || val > 1) {\n      throw new ModelError(\"acos() input must be between -1 and 1.\", {\n        code: 6078\n      });\n    }\n\n    return new Material(fn.acos(val));\n  });\n  defineFunction(simulate, \"atan\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true, complete: false }, (x) => {\n    return new Material(fn.atan(toNum(x[0]).value));\n  });\n\n  defineFunction(simulate, \"arcsin\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < -1 || val > 1) {\n      throw new ModelError(\"arcsin() input must be between -1 and 1.\", {\n        code: 6077\n      });\n    }\n\n    return new Material(fn.asin(val), simulate.unitManager.getUnitStore([\"radians\"], [1]), false);\n  });\n  defineFunction(simulate, \"arccos\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < -1 || val > 1) {\n      throw new ModelError(\"arccos() input must be between -1 and 1.\", {\n        code: 6078\n      });\n    }\n\n    return new Material(fn.acos(val), simulate.unitManager.getUnitStore([\"radians\"], [1]), false);\n  });\n  defineFunction(simulate, \"arctan\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    return new Material(fn.atan(toNum(x[0]).value), simulate.unitManager.getUnitStore([\"radians\"], [1]), false);\n  });\n\n  defineFunction(simulate, \"Sign\", { params: [{ name: \"Number\", leafNeedNum: true }], recurse: true }, (x) => {\n    let r = toNum(x[0]);\n    if (r.value < 0) {\n      return new Material(-1);\n    } else if (r.value > 0) {\n      return new Material(1);\n    } else if (r.value === 0) {\n      return new Material(0);\n    }\n    throw new ModelError(\"Invalid value for <i>Sign</i>.\", {\n      code: 6006\n    });\n  });\n  defineFunction(simulate, \"Sqrt\", { params: [{ name: \"Number\", leafNeedNum: true }], recurse: true }, (x) => {\n    let r = toNum(x[0]).fullClone();\n    if (r.value < 0) {\n      throw new ModelError(\"Sqrt() requires a number greater than or equal to 0.\", {\n        code: 6007\n      });\n    }\n    r.value = fn.sqrt(r.value);\n    if (r.units && !r.units.isUnitless()) {\n      r.units = r.units.power(0.5);\n    }\n    return r;\n  });\n  defineFunction(simulate, \"Ln\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0) {\n      throw new ModelError(\"Ln() requires a number greater than or equal to 0. Got, <i>\" + val + \"</i>.\", {\n        code: 6008\n      });\n    }\n    return new Material(fn.log(val));\n  });\n  defineFunction(simulate, \"Log\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0) {\n      throw new ModelError(\"Log() requires a number greater than or equal to 0. Got, <i>\" + val + \"</i>.\", {\n        code: 6009\n      });\n    }\n    return new Material(fn.log(val, 10));\n  });\n  defineFunction(simulate, \"Logit\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    let r = toNum(x[0]);\n\n    if (r.value < 0 || r.value > 1) {\n      throw new ModelError(\"Logit() requires an input between 0 and 1 (inclusive).\", {\n        code: 6079\n      });\n    }\n\n    r.value = fn[\"-\"](fn.log(r.value), fn.log(fn[\"-\"](1, r.value)));\n    return r;\n  });\n  defineFunction(simulate, \"Expit\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    let r = toNum(x[0]);\n    r.value = fn[\"/\"](1, fn[\"+\"](1, fn.exp(fn[\"-\"](r.value))));\n    return r;\n  });\n  defineFunction(simulate, \"Round\", { params: [\n    { name: \"Number\", noUnits: false, leafNeedNum: true },\n    { name: \"Units\", needString: true, defaultVal: \"<DETECTED>\", silentDefault: true }\n  ], recurse: true }, (x) => {\n    /** @type {Material} */\n    let r = toNum(x[0]);\n\n    if (!x[1]) {\n      if (r.units && !r.explicitUnits && !r.units.isDeepUnitless()) {\n        throw new ModelError(\"Round() requires either no units or units that have been explicitly set. Got: \" + r.units.toString() + \". If those units are correct, try <b>round(number, \\\"\" + r.units.toStringShort() + \"\\\")</b>\", {\n          code: 6463\n        });\n      }\n    } else {\n      r = r.forceUnits(createUnitStore(x[1], simulate));\n    }\n\n\n    r.value = fn.round(r.value);\n    return r;\n  });\n  defineFunction(simulate, \"Ceiling\", { params: [\n    { name: \"Number\", noUnits: false, leafNeedNum: true },\n    { name: \"Units\", needString: true, defaultVal: \"<DETECTED>\", silentDefault: true }\n  ], recurse: true }, (x) => {\n    /** @type {Material} */\n    let r = toNum(x[0]);\n\n    if (!x[1]) {\n      if (r.units && !r.explicitUnits && !r.units.isDeepUnitless()) {\n        throw new ModelError(\"Ceiling() requires either no units or units that have been explicitly set. Current units are \" + r.units.toString() + \". If those units are correct, try <b>ceiling(number, \\\"\" + r.units.toStringShort() + \"\\\")</b>\", {\n          code: 6464\n        });\n      }\n    } else {\n      r = r.forceUnits(createUnitStore(x[1], simulate));\n    }\n\n    r.value = fn.ceiling(r.value);\n    return r;\n  });\n  defineFunction(simulate, \"Floor\", { params: [\n    { name: \"Number\", noUnits: false, leafNeedNum: true },\n    { name: \"Units\", needString: true, defaultVal: \"<DETECTED>\", silentDefault: true }\n  ], recurse: true }, (x) => {\n    /** @type {Material} */\n    let r = toNum(x[0]);\n\n    if (!x[1]) {\n      if (r.units && !r.explicitUnits && !r.units.isDeepUnitless()) {\n        throw new ModelError(\"Floor() requires either no units or units that have been explicitly set. Got: \" + r.units.toString() + \". If those units are correct, try <b>floor(number, \\\"\" + r.units.toStringShort() + \"\\\")</b>\", {\n          code: 6462\n        });\n      }\n    } else {\n      r = r.forceUnits(createUnitStore(x[1], simulate));\n    }\n\n    r.value = fn.floor(r.value);\n    return r;\n  });\n  defineFunction(simulate, \"Exp\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    return new Material(fn.exp(toNum(x[0]).value));\n  });\n\n  simulate.varBank.set(\"ifthenelse\", (x) => {\n    testArgumentsSize(x, \"IfThenElse\", 3, 3);\n\n    let v = toNum(evaluateNode(x[0].node, x[0].scope, simulate));\n\n    if (v instanceof Vector) {\n      return vecIfThenElse(v, evaluateNode(x[1].node, x[1].scope, simulate), evaluateNode(x[2].node, x[2].scope, simulate));\n    }\n\n    if (trueValue(v)) {\n      return evaluateNode(x[1].node, x[1].scope, simulate);\n    } else {\n      return evaluateNode(x[2].node, x[2].scope, simulate);\n    }\n  });\n  simulate.varBank.get(\"ifthenelse\").delayEvalParams = true;\n  simulate.coreBank.set(\"ifthenelse\", simulate.varBank.get(\"ifthenelse\"));\n  setFunctionDef(\"IfThenElse\", {\n    params: [\n      { name: \"Condition\" },\n      { name: \"If True\" },\n      { name: \"If False\" }\n    ]\n  });\n\n\n  simulate.varBank.set(\"assert\", (x) => {\n    testArgumentsSize(x, \"Assert\", 1, 2);\n\n    let v = evaluateNode(x[0].node, x[0].scope, simulate);\n\n    if (!trueValue(v)) {\n      throw new ModelError(x[1] ? evaluateNode(x[1].node, x[1].scope, simulate) : \"Assert() failed\", {\n        code: 20000\n      });\n    } else {\n      return new Material(1);\n    }\n  });\n  simulate.varBank.get(\"assert\").delayEvalParams = true;\n  simulate.coreBank.set(\"assert\", simulate.varBank.get(\"assert\"));\n  setFunctionDef(\"Assert\", {\n    params: [\n      { name: \"Condition\" },\n      { name: \"Message\", defaultVal: \"'Assert() failed'\", allowString: true }\n    ]\n  });\n\n  function vecIfThenElse(test, tVal, fVal) {\n\n    let choiceFn = function (t, f) {\n      if (t instanceof Vector) {\n        return t.combine(f, choiceFn);\n      } else {\n        return [t, f];\n      }\n    };\n\n    tVal = toNum(tVal);\n    fVal = toNum(fVal);\n    let choices;\n    if (tVal instanceof Vector) {\n      choices = tVal.cloneCombine(fVal, choiceFn);\n    } else if (fVal instanceof Vector) {\n      choices = fVal.cloneCombine(tVal, (a, b) => {\n        return choiceFn(b, a);\n      });\n    } else {\n      choices = choiceFn(tVal, fVal);\n    }\n\n    let testFn = function (test, val) {\n      if (test instanceof Vector) {\n        return test.combine(val, testFn);\n      }\n\n      if (!Array.isArray(val)) {\n        throw new ModelError(\"Keys do not match for vectorized IfThenElse().\", {\n          code: 6093\n        });\n      }\n\n      if (trueValue(test)) {\n        return val[0];\n      } else {\n        return val[1];\n      }\n    };\n\n    return test.cloneCombine(choices, testFn);\n  }\n\n\n  simulate.varBank.set(\"map\", (x) => {\n    testArgumentsSize(x, \"Map\", 2, 2);\n    let v;\n    if (x[0].node instanceof Vector) {\n      v = x[0].node;\n    } else if (x[0] instanceof Vector) {\n      v = x[0];\n    } else {\n      v = evaluateNode(x[0].node, x[1].scope, simulate);\n    }\n\n    if (v instanceof SPrimitive) {\n      v = toNum(v);\n    }\n    if (!(v instanceof Vector)) {\n      throw new ModelError(\"Map() requires a vector as its first argument.\", {\n        code: 6010\n      });\n    }\n    v = v.fullClone();\n\n    let fn;\n    /** @type {Array} */\n    let items = [\n      [PARENT_SYMBOL, x[1].scope],\n      [\"x\", null],\n    ];\n    let scope = new Map(items);\n    let node = x[1].node;\n    try {\n      fn = evaluateNode(node, scope, simulate);\n    } catch (err) {\n      // pass\n    }\n\n    let f;\n    if (fn instanceof Function || fn instanceof UserFunction) {\n      if (fn.fn) {\n        fn = fn.fn;\n      }\n      f = function (x) {\n        return fn([x]);\n      };\n    } else {\n      f = function (input, key) {\n        scope.set(\"x\", input);\n        scope.set(\"key\", key || \"\");\n        return evaluateNode(node, scope, simulate);\n      };\n    }\n\n    return v.apply(f);\n  });\n  simulate.varBank.get(\"map\").delayEvalParams = true;\n  setFunctionDef(\"Map\", {\n    object: [simulate.varBank, VectorObject],\n    params: [\n      { name: \"Vector\" },\n      {\n        name: \"Function\",\n        implicitFunction: true,\n        injectedVariables: [\n          { name: \"x\" },\n          { name: \"key\" }\n        ]\n      }\n    ]\n  });\n  VectorObject[\"map\"] = simulate.varBank.get(\"map\");\n  simulate.coreBank.set(\"map\", simulate.varBank.get(\"map\"));\n\n  defineFunction(simulate, \"Sample\", { object: [simulate.varBank, VectorObject], params: [{ name: \"Vector\", needVector: true }, { name: \"Sample Size\", noUnits: true, noVector: true }, { name: \"Repeat\", noVector: true, allowBoolean: true, defaultVal: false }] }, (x) => {\n    let v = toNum(x[0]);\n    let count = toNum(x[1]).value;\n    if (count === 0) {\n      return new Vector([], simulate);\n    }\n\n    let length = v.length();\n    let repeat = x[2] && trueValue(toNum(x[2]));\n\n    if (length === 0) {\n      throw new ModelError(\"Sample() requires a non-empty vector.\", {\n        code: 6011\n      });\n    }\n\n    if (count < 0) {\n      throw new ModelError(\"Sample size in Sample() must be greater than or equal to 0.\", {\n        code: 6081\n      });\n    }\n\n    let res = [];\n    if (repeat) {\n      for (let i = 0; i < count; i++) {\n        res.push(v.items[Math.floor(Rand(simulate) * length)]);\n      }\n    } else {\n      if (length < count) {\n        throw new ModelError(\"Vector for Sample() is too small for the given sample size.\", {\n          code: 6012\n        });\n      }\n\n      let shuffled = v.items.slice();\n      for (let i = 0; i < count; i++) {\n        res.push(shuffled.splice(Math.floor(Rand(simulate) * shuffled.length), 1)[0]);\n      }\n    }\n\n    return new Vector(res, simulate);\n  });\n\n  defineFunction(simulate, \"IndexOf\", { object: [simulate.varBank, VectorObject], params: [{ name: \"Haystack\", needVector: true }, { name: \"Needle\", allowBoolean: true, allowString: true }] }, (x) => {\n\n    let v = x[1];\n\n    if (v instanceof Vector) {\n      let res = [];\n      for (let i = 0; i < v.items.length; i++) {\n        res.push(findElement(v.items[i], x[0]));\n      }\n      return new Vector(res, simulate);\n    } else {\n      return findElement(v, x[0]);\n    }\n  });\n\n  defineFunction(simulate, \"Contains\", { object: [simulate.varBank, VectorObject], params: [\n    { name: \"Haystack\", needVector: true },\n    { name: \"Needle\", allowBoolean: true, noVector: true, allowString: true }\n  ] }, (x) => {\n    if (eq(\n      new Material(0),\n      simulate.coreBank.get(\"indexof\")([new Vector(flatten(x[0]).items, simulate), x[1]])\n    )) {\n      return false;\n    } else {\n      return true;\n    }\n  });\n\n  defineFunction(simulate, \"Collapse\", {\n    params: [{ name: \"Source\", needVector: true }, { name: \"Target\", noVector: false }],\n    complete: false\n  }, (x) => {\n    return toNum(x[0]).collapseDimensions(toNum(x[1]));\n  });\n\n  function findElement(needle, haystack) {\n    for (let i = 0; i < haystack.length(); i++) {\n      if (eq(needle, haystack.items[i])) {\n        return new Material(i + 1);\n      }\n    }\n    return new Material(0);\n  }\n\n  simulate.varBank.set(\"filter\", (x) => {\n    testArgumentsSize(x, \"Filter\", 2, 2);\n\n    let v;\n    if (x[0].node instanceof Vector) {\n      v = x[0].node;\n    } else if (x[0] instanceof Vector) {\n      v = x[0];\n    } else {\n      v = evaluateNode(x[0].node, x[0].scope, simulate);\n    }\n\n    if (v instanceof SPrimitive) {\n      v = toNum(v);\n    }\n    if (!(v instanceof Vector)) {\n      throw new ModelError(\"Filter() requires a vector as its first argument.\", {\n        code: 6013\n      });\n    }\n    v = v.fullClone();\n\n    let t = simulate.coreBank.get(\"map\")(x);\n    return simulate.coreBank.get(\"select\")([v, t]);\n  });\n  simulate.varBank.get(\"filter\").delayEvalParams = true;\n  setFunctionDef(\"Filter\", {\n    object: [simulate.varBank, VectorObject],\n    params: [\n      { name: \"Vector\" },\n      {\n        name: \"Function\",\n        implicitFunction: true,\n        injectedVariables: [\n          { name: \"x\" },\n          { name: \"key\" }\n        ]\n      }\n    ]\n  });\n  VectorObject[\"filter\"] = simulate.varBank.get(\"filter\");\n  simulate.coreBank.set(\"filter\", simulate.varBank.get(\"filter\"));\n\n  simulate.varBank.set(\"join\", (x) => {\n    let res = [];\n    let names = [];\n    let hasNames = false;\n    for (let i = 0; i < x.length; i++) {\n      let y = x[i];\n\n      if (y instanceof SPrimitive) {\n        y = toNum(y);\n      }\n\n      if (y instanceof Vector) {\n        res = res.concat(y.items);\n        if (y.names) {\n          names = names.concat(y.names);\n          hasNames = true;\n        } else {\n          for (let j = 0; j < y.items.length; j++) {\n            names.push(undefined);\n          }\n        }\n      } else {\n        res.push(y);\n        names.push(undefined);\n      }\n    }\n    return new Vector(res, simulate, hasNames ? names : undefined);\n  });\n  simulate.coreBank.set(\"join\", simulate.varBank.get(\"join\"));\n  setFunctionDef(\"Join\", {\n    allowEmpty: true,\n    param: { name: \"Items...\" }\n  });\n\n  simulate.varBank.set(\"repeat\", (x) => {\n    testArgumentsSize(x, \"Repeat\", 2, 2);\n    let items = toNum(evaluateNode(x[1].node, x[1].scope, simulate));\n    let count = items;\n    if (items instanceof Vector) {\n      if (items.names && items.names.length) {\n        throw new ModelError(`If a repeat count is a vector, it can't have names. Got, <i>${items}</i>.`, {\n          code: 6070\n        });\n      }\n\n      let innerItems = items.items;\n      if (innerItems.find(x => !(typeof x === \"string\" || x instanceof String))) {\n        throw new ModelError(`If a repeat count is a vector, it must consist of all strings. Got, <i>${items}</i>.`, {\n          code: 6071\n        });\n      }\n\n      if (new Set(innerItems).size !== innerItems.length) {\n        throw new ModelError(`If a repeat count is a vector, it must contain unique strings. Got, <i>${items}</i>.`, {\n          code: 6072\n        });\n      }\n\n      count = items.items.length;\n    } else if (items instanceof Material) {\n      if (items.units && !items.units.isUnitless()) {\n        throw new ModelError(`Repeat count must be unitless. Got, <i>${items}</i>.`, {\n          code: 6073\n        });\n      }\n\n      if (items.value < 0) {\n        throw new ModelError(`Repeat count must be a non-negative. Got, <i>${items.value}</i>.`, {\n          code: 6075\n        });\n      }\n    } else {\n      throw new ModelError(`Repeat count must be a Number or Vector. Got, <i>${items}</i>.`, {\n        code: 6074\n      });\n    }\n\n    let res = [];\n\n    /** @type {Array} */\n    let scopeItems = [\n      [\"x\", null],\n      [PARENT_SYMBOL, x[1].scope],\n      [\"key\", null]\n    ];\n    let scope = new Map(scopeItems);\n    for (let i = 0; i < count; i++) {\n      if (items instanceof Vector) {\n        scope.set(\"key\", items.items[i]);\n      }\n      scope.set(\"x\", new Material(i + 1));\n      res.push(evaluateNode(x[0].node, scope, simulate));\n    }\n\n    return new Vector(res, simulate, items instanceof Vector ? items.items.slice() : undefined);\n  });\n  simulate.varBank.get(\"repeat\").delayEvalParams = true;\n  setFunctionDef(\"Repeat\", {\n    params: [\n      {\n        name: \"Expression\",\n        implicitFunction: true,\n        injectedVariables: [\n          { name: \"x\" },\n          { name: \"key\" }\n        ]\n      },\n      {\n        name: \"Times\"\n      }\n    ]\n  });\n  simulate.coreBank.set(\"repeat\", simulate.varBank.get(\"repeat\"));\n\n  defineFunction(simulate, \"Select\", { params: [{ name: \"Haystack\", needVector: true }, { name: \"Indexes\", noUnits: true }] }, (x) => {\n    if (x[1] instanceof Vector) {\n      let v = toNum(x[1]);\n      let isBoolean = true;\n      for (let i = 0; i < v.length(); i++) {\n        if (v.items[i] instanceof Material) {\n          isBoolean = false;\n          break;\n        }\n      }\n      if (isBoolean === true) {\n        let res = [];\n        let names = x[0].names ? /** @type {string[]} */ ([]) : undefined;\n        if (v.length() !== x[0].length()) {\n          throw new ModelError(\"Length of vector must be equal for boolean selection.\", {\n            code: 6014\n          });\n        }\n        for (let i = 0; i < v.length(); i++) {\n          if (trueValue(v.items[i])) {\n            res.push(x[0].items[i]);\n\n            if (names) {\n              names.push(x[0].names[i]);\n            }\n          }\n        }\n        return new Vector(res, simulate, names);\n      } else {\n        let res = [];\n        let names = x[0].names ? /** @type {string[]} */ ([]) : undefined;\n        for (let i = 0; i < v.length(); i++) {\n          let q = v.items[i].value;\n          if (q <= 0 || q > x[0].length()) {\n            let msg = \"Selected element out of range.\";\n\n            if (q === 0) {\n              msg += \" Vector indexes are 1-based, so the first element is selected with 1.\";\n            }\n\n\n            throw new ModelError(msg, {\n              code: 6015\n            });\n          } else if (Math.floor(q) !== q) {\n            throw new ModelError(\"Selected element must be an integer.\", {\n              code: 6015\n            });\n          }\n          res.push(x[0].items[q - 1]);\n\n          if (names) {\n            names.push(x[0].names[q - 1]);\n          }\n        }\n        return new Vector(res, simulate, names);\n      }\n    } else {\n      if (Math.floor(x[1].value) !== x[1].value) {\n        throw new ModelError(\"Selected element must be an integer.\", {\n          code: 6016\n        });\n      } else if (x[1].value > 0 && x[1].value <= x[0].length()) {\n        return x[0].items[x[1].value - 1];\n      } else {\n        let msg = \"Selected element out of range.\";\n\n        if (x[1].value === 0) {\n          msg += \" Vector indexes are 1-based, so the first element is selected with 1.\";\n        }\n\n        throw new ModelError(msg, {\n          code: 6016\n        });\n      }\n    }\n  });\n\n  defineFunction(simulate, \"Reverse\", {\n    allowEmpty: true, param: { name: \"Items...\" }, prep: function (x) {\n      return simulate.coreBank.get(\"join\")(x);\n    }\n  }, (x) => {\n    return new Vector(x.items.slice().reverse(), simulate, x.names ? x.names.slice().reverse() : undefined);\n  });\n  defineFunction(simulate, \"Reverse\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"reverse\")(x);\n  });\n\n  defineFunction(simulate, \"Sort\", {\n    allowEmpty: true, param: { name: \"Items...\" }, prep: function (x) {\n      return toNum(simulate.coreBank.get(\"join\")(x));\n    }\n  },\n  /**\n     * @param {Vector} x\n     * @returns\n     */\n  (x) => {\n    let res = x.stackApply((x) => {\n      let items = [];\n      for (let i = 0; i < x.items.length; i++) {\n        items.push({ item: x.items[i], name: x.names ? x.names[i] : undefined });\n      }\n\n      let res = items.sort((a, b) => {\n        if (lessThan(a.item, b.item)) {\n          return -1;\n        }\n        if (greaterThan(a.item, b.item)) {\n          return 1;\n        }\n        return 0;\n      });\n\n\n      let names = x.names ? /** @type {string[]} */ ([]) : undefined;\n      items = [];\n\n      for (let i = 0; i < res.length; i++) {\n        items.push(res[i].item);\n        if (names) {\n          names.push(/** @type {string} */ (res[i].name));\n        }\n      }\n\n      return new Vector(items, simulate, names);\n    });\n\n    return res;\n  });\n  defineFunction(simulate, \"Sort\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"sort\")(x);\n  });\n\n  defineFunction(simulate, \"Unique\", {\n    allowEmpty: true, param: { name: \"Items...\", allowBoolean: true }, prep: function (x) {\n      return toNum(simulate.coreBank.get(\"join\")(x));\n    }\n  }, (x) => {\n    if (!x.items.length) {\n      return new Vector([], simulate);\n    }\n\n    let res = [];\n    let names = x.names ? /** @type {string[]} */ ([]) : undefined;\n\n    for (let i = 0; i < x.items.length; i++) {\n      let found = false;\n\n      for (let j = 0; j < res.length; j++) {\n        if (strictEquals(x.items[i], res[j])) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        res.push(x.items[i]);\n        if (names) {\n          names.push(x.names[i]);\n        }\n      }\n    }\n\n    return new Vector(res, simulate, names);\n  });\n  defineFunction(simulate, \"Unique\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"unique\")(x);\n  });\n\n\n  defineFunction(simulate, \"Union\", { object: [simulate.varBank, VectorObject], params: [{ name: \"Vector 1\", needVector: true }, { name: \"Vector 2\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"unique\")(simulate.coreBank.get(\"join\")(x).items);\n  });\n\n  defineFunction(simulate, \"Intersection\", { object: [simulate.varBank, VectorObject], params: [{ name: \"Vector 1\", needVector: true }, { name: \"Vector 2\", needVector: true }] }, (x) => {\n    let v1 = x[0];\n    let v2 = x[1];\n\n    let res = [];\n\n    for (let i = 0; i < v1.items.length; i++) {\n      for (let j = 0; j < v2.items.length; j++) {\n        if (strictEquals(v1.items[i], v2.items[j])) {\n          res.push(v1.items[i]);\n          break;\n        }\n      }\n    }\n    return simulate.coreBank.get(\"unique\")(res);\n  });\n\n\n  defineFunction(simulate, \"Difference\", { object: [simulate.varBank, VectorObject], params: [{ name: \"Vector 1\", needVector: true }, { name: \"Vector 2\", needVector: true }] }, (x) => {\n    let v1 = x[0];\n    let v2 = x[1];\n\n    let res = [];\n\n    for (let i = 0; i < v1.items.length; i++) {\n      let found = false;\n      for (let j = 0; j < v2.items.length; j++) {\n        if (strictEquals(v1.items[i], v2.items[j])) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        res.push(v1.items[i]);\n      }\n    }\n    for (let i = 0; i < v2.items.length; i++) {\n      let found = false;\n      for (let j = 0; j < v1.items.length; j++) {\n        if (strictEquals(v2.items[i], v1.items[j])) {\n          found = true;\n          break;\n        }\n      }\n      if (!found) {\n        res.push(v2.items[i]);\n      }\n    }\n\n    return simulate.coreBank.get(\"unique\")(res);\n  });\n\n  defineFunction(simulate, \"Factorial\", { params: [{ name: \"Number\", noUnits: true, leafNeedNum: true }], recurse: true }, (x) => {\n    return new Material(factorial(toNum(x[0]).value));\n  });\n\n  defineFunction(simulate, \"Max\", { param: { name: \"Items...\" }, prep: joinVector }, (x) => {\n\n    let res = x.stackApply((v) => {\n      let x = v.items;\n      if (x.length > 0) {\n        let max = x[0];\n        for (let i = 1; i < x.length; i++) {\n          if (greaterThan(x[i], max)) {\n            max = x[i];\n          }\n        }\n        return max;\n      } else {\n        throw new ModelError(\"You must have at least one element to calculate a max.\", {\n          code: 6017\n        });\n      }\n    });\n\n    return res;\n  });\n  defineFunction(simulate, \"Max\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"max\")(x);\n  });\n\n  function joinVector(x, notToNum, skip) {\n    if (!notToNum) {\n      for (let i = 0; i < x.length; i++) {\n        x[i] = toNum(x[i]);\n      }\n    }\n    if (x.length === 1 && x[0] instanceof Vector) {\n      if (skip) {\n        return x[0];\n      } else {\n        return simulate.coreBank.get(\"flatten\")([x[0]]);\n      }\n    } else {\n      return new Vector(scalarsToVectors(x), simulate);\n    }\n  }\n  function joinArray(x) {\n    for (let i = 0; i < x.length; i++) {\n      if (x[i].toNum) {\n        x[i] = toNum(x[i]);\n      }\n    }\n    if (x.length === 1 && x[0] instanceof Vector) {\n      return simulate.coreBank.get(\"flatten\")([toNum(x[0])]).items;\n    }\n    return joinVector(x, undefined, true).items;\n  }\n  function scalarsToVectors(x) {\n    let needVector = false;\n    let vec;\n\n    for (let i = 0; i < x.length; i++) {\n      if (x[i] instanceof Vector) {\n        vec = x[i];\n        needVector = true;\n        break;\n      }\n    }\n\n    if (needVector) {\n      for (let i = 0; i < x.length; i++) {\n        if (!(x[i] instanceof Vector)) {\n          x[i] = replicateVectorStructure(vec, x[i]);\n        }\n      }\n    }\n\n    return x;\n  }\n  function replicateVectorStructure(vec, val) {\n    let v = vec.fullClone();\n    for (let i = 0; i < v.items.length; i++) {\n      if (v.items[i] instanceof Vector) {\n        v.items[i] = replicateVectorStructure(v.items[i], val);\n      } else {\n        v.items[i] = val;\n      }\n    }\n    return v;\n  }\n\n  defineFunction(simulate, \"Lookup\", { params: [{ name: \"Value\", noVector: true }, { name: \"Value Vector\", needVector: true }, { name: \"Results Vector\", needVector: true }] }, (x) => {\n    let v = toNum(x[0]);\n    let xVec = toNum(x[1]);\n    let yVec = toNum(x[2]);\n\n    if (xVec.items.length !== yVec.items.length) {\n      throw new ModelError(\"The <i>value</i> and <i>results</i> vectors must be the same length\", {\n        code: 6018\n      });\n    }\n\n    if (xVec.items.length < 1) {\n      throw new ModelError(\"You must have at least one element in your vectors\", {\n        code: 6019\n      });\n    }\n\n    let vec = [];\n    for (let i = 0; i < xVec.items.length; i++) {\n      vec.push({ x: xVec.items[i], y: yVec.items[i] });\n    }\n\n    vec.sort((a, b) => {\n      if (greaterThan(a.x, b.x)) {\n        return 1;\n      } else if (lessThan(a.x, b.x)) {\n        return -1;\n      } else {\n        return 0;\n      }\n    });\n\n    for (let i = 0; i < vec.length; i++) {\n      if (eq(vec[i].x, v)) {\n        return vec[i].y.fullClone();\n      } else if (greaterThan(vec[i].x, v)) {\n        if (i === 0) {\n          return vec[i].y.fullClone();\n        }\n\n        let dist = minus(vec[i].x, vec[i - 1].x);\n        let distLower = minus(v, vec[i - 1].x);\n        let distUpper = minus(vec[i].x, v);\n        let fLower = div(distUpper, dist);\n        let fUpper = div(distLower, dist);\n        return plus(mult(vec[i - 1].y, fLower), mult(vec[i].y, fUpper));\n      }\n    }\n\n    return vec[vec.length - 1].y.fullClone();\n  });\n\n  defineFunction(simulate, \"Fill\", { object: [simulate.varBank, VectorObject], params: [{ name: \"Vector\", needVector: true }, { name: \"Value\", allowBoolean: true, allowString: true }] }, (x) => {\n    return replicateVectorStructure(x[0], x[1]);\n  });\n\n  defineFunction(simulate, \"Min\", { param: { name: \"Items...\" }, prep: joinVector },\n    /**\n     * @param {Vector} x\n     * @returns\n     */\n    (x) => {\n      let res = x.stackApply((v) => {\n        let x = v.items;\n        if (x.length > 0) {\n          let min = x[0];\n          for (let i = 1; i < x.length; i++) {\n            if (lessThan(x[i], min)) {\n              min = x[i];\n            }\n          }\n          return min;\n\n        } else {\n          throw new ModelError(\"You must have at least one element to calculate a min.\", {\n            code: 6020\n          });\n        }\n      });\n\n      return res;\n    });\n  defineFunction(simulate, \"Min\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"min\")(x);\n  });\n  defineFunction(simulate, \"Mean\", { param: { name: \"Items...\" }, prep: joinArray },\n    /**\n     * @param {any[]} x\n     * @returns\n     */\n    (x) => {\n      let sum = x[0];\n      for (let i = 1; i < x.length; i++) {\n        sum = plus(sum, x[i]);\n      }\n      return div(sum, new Material(x.length));\n    });\n  defineFunction(simulate, \"Mean\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"mean\")(x);\n  });\n  defineFunction(simulate, \"Sum\", { param: { name: \"Items...\" }, prep: joinArray },\n    /**\n     * @param {any[]} x\n     * @returns\n     */\n    (x) => {\n      let sum = x[0];\n\n      for (let i = 1; i < x.length; i++) {\n        sum = plus(sum, x[i]);\n      }\n\n      return sum;\n    });\n  defineFunction(simulate, \"Sum\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"sum\")(x);\n  });\n  defineFunction(simulate, \"Product\", { param: { name: \"Items...\" }, prep: joinArray }, (x) => {\n    let total = x[0];\n    for (let i = 1; i < x.length; i++) {\n      total = mult(total, x[i]);\n    }\n    return total;\n  });\n  defineFunction(simulate, \"Product\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"product\")(x);\n  });\n  defineFunction(simulate, \"Median\", { param: { name: \"Items...\" }, prep: joinVector }, (x) => {\n    let res = x.stackApply((v) => {\n      /** @type {Material[]} */\n      let x = simulate.coreBank.get(\"sort\")([v]).items;\n      if (x.length > 0) {\n        if (Math.floor((x.length - 1) / 2) === (x.length - 1) / 2) {\n          return x[(x.length - 1) / 2];\n        } else {\n          return div(plus(x[Math.floor((x.length - 1) / 2)], x[Math.ceil((x.length - 1) / 2)]), new Material(2));\n        }\n      } else {\n        throw new ModelError(\"You must have at least one element to calculate a median.\", {\n          code: 6021\n        });\n      }\n    });\n    return res;\n  });\n  defineFunction(simulate, \"Median\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"median\")(x);\n  });\n  defineFunction(simulate, \"StdDev\", { param: { name: \"Items...\" }, prep: joinVector }, (x) => {\n    let res = x.stackApply((v) => {\n      let x = v.items;\n      if (x.length > 1) {\n\n        let mean = simulate.coreBank.get(\"mean\")(x);\n        let sum = power(minus(x[0], mean), new Material(2));\n\n        for (let i = 1; i < x.length; i++) {\n          sum = plus(sum, power(minus(x[i], mean), new Material(2)));\n        }\n        let r = power(div(sum, new Material(x.length - 1)), new Material(0.5));\n\n        return r;\n      } else {\n        throw new ModelError(\"You must have at least two elements to calculate the standard deviation.\", {\n          code: 6022\n        });\n      }\n    });\n    return res;\n  });\n  defineFunction(simulate, \"StdDev\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"stddev\")(x);\n  });\n  defineFunction(simulate, \"Correlation\", { params: [{ name: \"Vector 1\", needVector: true }, { name: \"Vector 2\", needVector: true }] }, (x) => {\n    let v1 = toNum(x[0]);\n    let v2 = toNum(x[1]);\n\n    if (v1.length() <= 1) {\n      throw new ModelError(\"You must have at least two elements in your vectors to calculate their correlation.\", {\n        code: 6023\n      });\n    }\n    if (v1.length() !== v2.length()) {\n      throw new ModelError(\"The vectors for Correlation() must be of the same size.\", {\n        code: 6024\n      });\n    }\n\n\n    let v1Mean = simulate.coreBank.get(\"mean\")([v1]);\n    let v2Mean = simulate.coreBank.get(\"mean\")([v2]);\n\n    let v1StdDev = simulate.coreBank.get(\"stddev\")([v1]);\n    let v2StdDev = simulate.coreBank.get(\"stddev\")([v2]);\n\n    if (v1StdDev.value === 0 || v2StdDev.value === 0) {\n      return new Material(0);\n    }\n\n    return div(simulate.coreBank.get(\"sum\")([mult(minus(v1.clone(), v1Mean), minus(v2.clone(), v2Mean))]), mult(minus(simulate.coreBank.get(\"count\")([v1]), new Material(1)), mult(v1StdDev, v2StdDev)));\n  });\n  simulate.varBank.set(\"count\", (x) => {\n    x = simulate.coreBank.get(\"join\")(x).items;\n    return new Material(x.length);\n  });\n  simulate.coreBank.set(\"count\", simulate.varBank.get(\"count\"));\n  setFunctionDef(\"Count\", {\n    allowEmpty: true,\n    param: { name: \"Items...\" }\n  });\n\n  simulate.varBank.set(\"flatten\", (x) => {\n    let res = flatten(simulate.coreBank.get(\"join\")(x));\n    return new Vector(res.items, simulate, res.hasName ? res.names : undefined);\n  });\n  simulate.coreBank.set(\"flatten\", simulate.varBank.get(\"flatten\"));\n  setFunctionDef(\"Flatten\", {\n    allowEmpty: true,\n    param: { name: \"Items...\" }\n  });\n\n  defineFunction(simulate, \"Keys\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    if (!x[0].names) {\n      return new Vector([], simulate);\n    }\n    return new Vector(x[0].names.filter(x => x !== undefined).map(x => stringify(x, simulate)), simulate);\n  });\n  defineFunction(simulate, \"Values\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return new Vector(x[0].items, simulate);\n  });\n  defineFunction(simulate, \"Length\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return new Material(x[0].items.length);\n  });\n  defineFunction(simulate, \"Count\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return new Material(x[0].items.length);\n  });\n  defineFunction(simulate, \"Flatten\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }] }, (x) => {\n    return simulate.coreBank.get(\"flatten\")(x);\n  });\n\n  /**\n   * @param {Vector} x\n   * @returns\n   */\n  function flatten(x) {\n    let res = [];\n    let names = [];\n    let hasName = undefined;\n\n    for (let i = 0; i < x.length(); i++) {\n      if (x.items[i] instanceof Vector) {\n        let z = flatten(x.items[i]);\n        res = res.concat(z.items);\n        names = names.concat(z.names);\n        hasName = hasName || z.hasName;\n      } else {\n        res.push(x.items[i]);\n        if (x.names) {\n          names.push(x.names[i]);\n          hasName = true;\n        } else {\n          names.push(undefined);\n        }\n      }\n    }\n    return { items: res, names: names, hasName: hasName };\n  }\n\n\n  /* Statistics */\n\n  defineFunction(simulate, \"CDFNormal\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Mean\", defaultVal: 0, noUnits: true, noVector: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let mu = x[1] ? toNum(x[1]).value : 0;\n    let sd = x[2] ? toNum(x[2]).value : 1;\n\n    if (sd < 0) {\n      throw new ModelError(\"Standard Deviation must not be negative.\", {\n        code: 6076\n      });\n    }\n\n    return new Material(jStat.normal.cdf(val, mu, sd));\n  });\n\n  defineFunction(simulate, \"PDFNormal\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Mean\", defaultVal: 0, noUnits: true, noVector: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let mu = x[1] ? toNum(x[1]).value : 0;\n    let sd = x[2] ? toNum(x[2]).value : 1;\n\n    if (sd < 0) {\n      throw new ModelError(\"Standard Deviation must not be negative.\", {\n        code: 6076\n      });\n    }\n\n    return new Material(jStat.normal.pdf(val, mu, sd));\n  });\n\n  defineFunction(simulate, \"InvNormal\", { params: [{ name: \"p\", noUnits: true, noVector: true }, { name: \"Mean\", defaultVal: 0, noUnits: true, noVector: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0 || val > 1) {\n      throw new ModelError(\"<i>p</i> is a probability and must be between 0 and 1 inclusive.\", {\n        code: 6025\n      });\n    }\n    let mu = x[1] ? toNum(x[1]).value : 0;\n    let sd = x[2] ? toNum(x[2]).value : 1;\n\n    if (sd < 0) {\n      throw new ModelError(\"Standard Deviation must not be negative.\", {\n        code: 6076\n      });\n    }\n\n    return new Material(jStat.normal.inv(val, mu, sd));\n  });\n\n  defineFunction(simulate, \"CDFLogNormal\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Mean\", defaultVal: 0, noUnits: true, noVector: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let mu = x[1] ? toNum(x[1]).value : 0;\n    let sd = x[2] ? toNum(x[2]).value : 1;\n\n    if (sd < 0) {\n      throw new ModelError(\"Standard Deviation must not be negative.\", {\n        code: 6076\n      });\n    }\n\n    return new Material(jStat.lognormal.cdf(val, mu, sd));\n  });\n\n  defineFunction(simulate, \"PDFLogNormal\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Mean\", defaultVal: 0, noUnits: true, noVector: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let mu = x[1] ? toNum(x[1]).value : 0;\n    let sd = x[2] ? toNum(x[2]).value : 1;\n\n    if (sd < 0) {\n      throw new ModelError(\"Standard Deviation must not be negative.\", {\n        code: 6076\n      });\n    }\n\n    return new Material(jStat.lognormal.pdf(val, mu, sd));\n  });\n\n  defineFunction(simulate, \"InvLogNormal\", { params: [{ name: \"p\", noUnits: true, noVector: true }, { name: \"Mean\", defaultVal: 0, noUnits: true, noVector: true }, { name: \"Standard Deviation\", defaultVal: 1, noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0 || val > 1) {\n      throw new ModelError(\"<i>p</i> is a probability and must be between 0 and 1 inclusive.\", {\n        code: 6026\n      });\n    }\n    let mu = x[1] ? toNum(x[1]).value : 0;\n    let sd = x[2] ? toNum(x[2]).value : 1;\n\n    if (sd < 0) {\n      throw new ModelError(\"Standard Deviation must not be negative.\", {\n        code: 6076\n      });\n    }\n\n    return new Material(jStat.lognormal.inv(val, mu, sd));\n  });\n\n  defineFunction(simulate, \"CDFt\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let dof = toNum(x[1]).value;\n    if (dof <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6027\n      });\n    }\n\n    return new Material(jStat.studentt.cdf(val, dof));\n  });\n\n  defineFunction(simulate, \"PDFt\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let dof = toNum(x[1]).value;\n    if (dof <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6028\n      });\n    }\n\n    return new Material(jStat.studentt.pdf(val, dof));\n  });\n\n  defineFunction(simulate, \"Invt\", { params: [{ name: \"p\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0 || val > 1) {\n      throw new ModelError(\"<i>p</i> is a probability and must be between 0 and 1 inclusive.\", {\n        code: 6029\n      });\n    }\n    let dof = toNum(x[1]).value;\n    if (dof <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6030\n      });\n    }\n\n    return new Material(jStat.studentt.inv(val, dof));\n  });\n\n  defineFunction(simulate, \"CDFF\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom 1\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom 2\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let dof1 = toNum(x[1]).value;\n    if (dof1 <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6031\n      });\n    }\n    let dof2 = toNum(x[2]).value;\n    if (dof2 <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6032\n      });\n    }\n\n    return new Material(jStat.centralF.cdf(val, dof1, dof2));\n  });\n\n  defineFunction(simulate, \"PDFF\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom 1\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom 2\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let dof1 = toNum(x[1]).value;\n    if (dof1 <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom 1</i> must be greater than 0.\", {\n        code: 6033\n      });\n    }\n    let dof2 = toNum(x[2]).value;\n    if (dof2 <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom 2</i> must be greater than 0.\", {\n        code: 6034\n      });\n    }\n\n    return new Material(jStat.centralF.pdf(val, dof1, dof2));\n  });\n\n  defineFunction(simulate, \"InvF\", { params: [{ name: \"p\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom 1\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom 2\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0 || val > 1) {\n      throw new ModelError(\"<i>p</i> is a probability and must be between 0 and 1 inclusive.\", {\n        code: 6035\n      });\n    }\n    let dof1 = toNum(x[1]).value;\n    if (dof1 <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom 1</i> must be greater than 0.\", {\n        code: 6036\n      });\n    }\n    let dof2 = toNum(x[2]).value;\n    if (dof2 <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6037\n      });\n    }\n\n    return new Material(jStat.centralF.inv(val, dof1, dof2));\n  });\n\n  defineFunction(simulate, \"CDFChiSquared\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let dof = toNum(x[1]).value;\n    if (dof <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6038\n      });\n    }\n\n    return new Material(jStat.chisquare.cdf(val, dof));\n  });\n\n  defineFunction(simulate, \"PDFChiSquared\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let dof = toNum(x[1]).value;\n    if (dof <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6039\n      });\n    }\n\n    return new Material(jStat.chisquare.pdf(val, dof));\n  });\n\n  defineFunction(simulate, \"InvChiSquared\", { params: [{ name: \"p\", noUnits: true, noVector: true }, { name: \"Degrees of Freedom\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0 || val > 1) {\n      throw new ModelError(\"<i>p</i> is a probability and must be between 0 and 1 inclusive.\", {\n        code: 6040\n      });\n    }\n    let dof = toNum(x[1]).value;\n    if (dof <= 0) {\n      throw new ModelError(\"<i>Degrees of Freedom</i> must be greater than 0.\", {\n        code: 6041\n      });\n    }\n\n    return new Material(jStat.chisquare.inv(val, dof));\n  });\n\n\n  defineFunction(simulate, \"CDFExponential\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Rate\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let rate = toNum(x[1]).value;\n    if (rate <= 0) {\n      throw new ModelError(\"<i>Rate</i> must be greater than 0.\", {\n        code: 6042\n      });\n    }\n\n    return new Material(jStat.exponential.cdf(val, rate));\n  });\n\n  defineFunction(simulate, \"PDFExponential\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Rate\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let rate = toNum(x[1]).value;\n    if (rate <= 0) {\n      throw new ModelError(\"<i>Rate</i> must be greater than 0.\", {\n        code: 6043\n      });\n    }\n\n    return new Material(jStat.exponential.pdf(val, rate));\n  });\n\n  defineFunction(simulate, \"InvExponential\", { params: [{ name: \"p\", noUnits: true, noVector: true }, { name: \"Rate\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    if (val < 0 || val > 1) {\n      throw new ModelError(\"<i>p</i> is a probability and must be between 0 and 1 inclusive.\", {\n        code: 6044\n      });\n    }\n    let rate = toNum(x[1]).value;\n    if (rate <= 0) {\n      throw new ModelError(\"<i>Rate</i> must be greater than 0.\", {\n        code: 6045\n      });\n    }\n\n    return new Material(jStat.exponential.inv(val, rate));\n  });\n\n  defineFunction(simulate, \"CDFPoisson\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Lambda\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let Lambda = toNum(x[1]).value;\n    if (Lambda < 0) {\n      throw new ModelError(\"<i>Lambda</i> must be greater than or equal to 0.\", {\n        code: 6046\n      });\n    }\n\n    return new Material(jStat.poisson.cdf(val, Lambda));\n  });\n\n  defineFunction(simulate, \"PMFPoisson\", { params: [{ name: \"x\", noUnits: true, noVector: true }, { name: \"Lambda\", noUnits: true, noVector: true }] }, (x) => {\n    let val = toNum(x[0]).value;\n    let Lambda = toNum(x[1]).value;\n    if (Lambda < 0) {\n      throw new ModelError(\"<i>Lambda</i> must be greater than or equal to 0.\", {\n        code: 6047\n      });\n    }\n\n    return new Material(jStat.poisson.pdf(val, Lambda));\n  });\n\n\n\n  /* End Statistics */\n\n\n\n  defineFunction(simulate, \"SetRandSeed\", { params: [{ name: \"Seed Number\", noUnits: true, noVector: true }] }, (x) => {\n    simulate.random = SeedRandom.seedrandom(toNum(x[0]).value);\n    return stringify(\"Random Seed Set\", simulate);\n  });\n\n  defineFunction(simulate, \"Alert\", { params: [{ name: \"Message\", allowString: true, allowBoolean: true }] }, (x) => {\n    if (typeof alert === \"undefined\") {\n      throw new ModelError(\"Alert() is not implemented on this platform.\", {\n        code: 6048\n      });\n    }\n\n    alert(x[0]);\n    return new Material(1);\n  });\n\n  defineFunction(simulate, \"Console\", { params: [{ name: \"Message\", allowString: true, allowBoolean: true }], complete: false }, (x) => {\n    console.log(x[0]);\n    return new Material(1);\n  });\n\n  defineFunction(simulate, \"Prompt\", { params: [{ name: \"Message\", allowString: true, allowBoolean: true }, { name: \"Default\", defaultVal: \"''\", allowString: true, allowBoolean: true }] }, (x) => {\n    if (typeof prompt === \"undefined\") {\n      throw new ModelError(\"Prompt() is not implemented on this platform.\", {\n        code: 6049\n      });\n    }\n\n    let y = x[1];\n\n    if (y instanceof Material && !y.units) {\n      y = y.value;\n    }\n\n    let result = prompt(x[0], y);\n\n    if (result === null) {\n      return new Material(0);\n    } else if (parseFloat(result).toString() === result) {\n      return new Material(parseFloat(result));\n    } else {\n      return stringify(result, simulate);\n    }\n  });\n\n  defineFunction(simulate, \"Confirm\", { params: [{ name: \"Message\", allowString: true, allowBoolean: true }] }, (x) => {\n\n    if (typeof confirm === \"undefined\") {\n      throw new ModelError(\"Confirm() is not implemented on this platform.\", {\n        code: 6050\n      });\n    }\n\n\n    return confirm(x[0]);\n  });\n\n  defineFunction(simulate, \"Parse\", { object: StringObject, params: [{ name: \"String\", allowString: true }] }, (x) => {\n    let res = parseFloat(x[0]);\n\n    if (isNaN(res)) {\n      throw new ModelError(`\"${x[0]}\" is not a number.`, {\n        code: 6091\n      });\n    }\n\n    return new Material(res);\n  });\n\n  defineFunction(simulate, \"Split\", { object: StringObject, params: [{ name: \"String\", needString: true }, { name: \"Splitter\", needString: true }] }, (x) => {\n    return stringify(new Vector(x[0].split(x[1]), simulate), simulate);\n  });\n\n  defineFunction(simulate, \"Join\", { object: VectorObject, params: [{ name: \"Vector\", needVector: true }, { name: \"Joiner\", needString: true }] }, (x) => {\n    return stringify(x[0].items.join(x[1]), simulate);\n  });\n\n  defineFunction(simulate, \"Trim\", { object: StringObject, params: [{ name: \"String\", needString: true }], recurse: true }, (x) => {\n    return stringify(x[0].trim(), simulate);\n  });\n\n  defineFunction(simulate, \"Range\", { object: StringObject, params: [{ name: \"String\", needString: true }, { name: \"Indexes\", noUnits: true }] }, (x) => {\n    function validateStringRangeIndex(index) {\n      if (!Number.isInteger(index)) {\n        throw new ModelError(`Range() indexes must be integers, got ${index}.`, {\n          code: 6083\n        });\n      }\n      if (index < 1 || index > x[0].length) {\n        throw new ModelError(`Range() index out of range, must be between 1 and ${x[0].length}. Got ${index}.`, {\n          code: 6084\n        });\n      }\n      return index;\n    }\n\n    if (x[1] instanceof Vector) {\n      let res = \"\";\n      for (let i = 0; i < x[1].items.length; i++) {\n        res += x[0].charAt(validateStringRangeIndex(toNum(x[1].items[i]).value) - 1);\n      }\n      return stringify(res, simulate);\n    } else {\n      return stringify(x[0].charAt(validateStringRangeIndex(toNum(x[1]).value) - 1), simulate);\n    }\n  });\n\n  defineFunction(simulate, \"Length\", { object: StringObject, params: [{ name: \"String\", needString: true }] }, (x) => {\n    return new Material(x[0].length);\n  });\n\n  defineFunction(simulate, \"IndexOf\", { object: StringObject, params: [{ name: \"Haystack\", needString: true }, { name: \"Needle\", needString: true }] }, (x) => {\n    return new Material(x[0].indexOf(x[1]) + 1);\n  });\n\n  defineFunction(simulate, \"Contains\", { object: StringObject, params: [{ name: \"Haystack\", needString: true }, { name: \"Needle\", needString: true }] }, (x) => {\n    return !eq(StringObject[\"indexof\"](x), new Material(0));\n  });\n\n  defineFunction(simulate, \"Lowercase\", { object: StringObject, params: [{ name: \"String\", needString: true }] }, (x) => {\n    return stringify(x[0].toLowerCase(), simulate);\n  });\n\n  defineFunction(simulate, \"Uppercase\", { object: StringObject, params: [{ name: \"String\", needString: true }] }, (x) => {\n    return stringify(x[0].toUpperCase(), simulate);\n  });\n\n  simulate.coreBank.set(\"stringbase\", makeObjectBase(StringObject, simulate));\n  simulate.varBank.set(\"stringbase\", simulate.coreBank.get(\"stringbase\"));\n  simulate.coreBank.set(\"vectorbase\", makeObjectBase(VectorObject, simulate));\n  simulate.varBank.set(\"vectorbase\", simulate.coreBank.get(\"vectorbase\"));\n}\n\n\n/**\n * @param {*} x\n * @param {import(\"../Simulator\").Simulator} simulate\n *\n * @returns\n */\nexport function makeObjectBase(x, simulate) {\n  let names = Object.keys(x);\n  let items = [];\n  for (let name of names) {\n    items.push(objectizeFunction(x[name]));\n  }\n  let vec = new Vector(items, simulate, names);\n  vec.parent = undefined;\n  return vec;\n}\n\n\n/**\n * @typedef {Object} DefineFunctionParam\n * @property {string} name\n * @property {any=} defaultVal\n * @property {boolean=} noUnits\n * @property {boolean=} noVector\n * @property {boolean=} needVector\n * @property {boolean=} needNum\n * @property {boolean=} leafNeedNum\n * @property {boolean=} vectorize\n * @property {boolean=} allowBoolean\n * @property {boolean=} allowString\n * @property {boolean=} needString\n * @property {boolean=} needPrimitive\n * @property {boolean=} allowOptionalPrimitive\n * @property {boolean=} needAgent\n * @property {boolean=} needAgents\n * @property {boolean=} needPopulation\n * @property {boolean=} implicitFunction\n * @property {{ name: string }[]=} injectedVariables\n * @property {boolean=} silentDefault - don't show defaultVal in function signature, don't show the parameter at all unless the user specifies it\n */\n\n\n/**\n * @callback DefineFunctionPrep\n * @param {any[]} args\n * @returns {any}\n */\n\n/**\n * @typedef {{ param: DefineFunctionParam, allowEmpty?: boolean, prep?: DefineFunctionPrep, object?: any, complete?: boolean }|{ params: DefineFunctionParam[], recurse?: boolean, prep?: DefineFunctionPrep, object?: any, complete?: boolean }} DefineFunctionDefinition\n */\n\n\n/** @typedef {Map<string, {name: string, standardFnName: string, objectFnName: string, definition: DefineFunctionDefinition }>} FunctionDefItem */\n\nexport let functionDefs = {\n  topLevel: /** @type {FunctionDefItem} */ (new Map()),\n  string: /** @type {FunctionDefItem} */ (new Map()),\n  vector: /** @type {FunctionDefItem} */ (new Map()),\n  primitive: /** @type {FunctionDefItem} */ (new Map()),\n  agent: /** @type {FunctionDefItem} */ (new Map())\n};\n\n/**\n * @param {DefineFunctionDefinition} definition\n * @returns\n */\nfunction bucketsForDefinition(definition) {\n  const buckets = new Set();\n\n  const targets = !definition.object\n    ? [null]\n    : Array.isArray(definition.object)\n      ? definition.object\n      : [definition.object];\n\n  for (const target of targets) {\n    if (target == null) {\n      buckets.add(\"topLevel\");\n    } else if (target instanceof Map) {\n      buckets.add(\"topLevel\");\n    } else {\n      buckets.add(target._object_type);\n    }\n  }\n  return buckets;\n}\n\n\n/**\n * @param {string} name\n * @param {DefineFunctionDefinition} definition\n */\nexport function setFunctionDef(name, definition) {\n  let standardFnName;\n  let objectFnName;\n\n  if (\"params\" in definition) {\n    standardFnName = name + \"(\" + definition.params.map((x) => {\n      return x.name + (\"defaultVal\" in x ? \"=\" + x.defaultVal.toString() : \"\");\n    }).join(\", \") + \")\";\n    objectFnName = name + \"(\" + definition.params.slice(1).map((x) => {\n      return x.name + (\"defaultVal\" in x ? \"=\" + x.defaultVal.toString() : \"\");\n    }).join(\", \") + \")\";\n  } else {\n    let paramName = definition.param.name;\n    standardFnName = name + \"(\" + paramName + \")\";\n    objectFnName = name + \"(\" + paramName + \")\";\n  }\n\n  const res = {\n    name,\n    standardFnName,\n    objectFnName,\n    definition\n  };\n\n  const key = name.toLowerCase();\n  for (const bucket of bucketsForDefinition(definition)) {\n    functionDefs[bucket].set(key, res);\n  }\n\n  return res;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {string} name\n * @param {DefineFunctionDefinition} definition\n * @param {function} fn\n */\nexport function defineFunction(simulate, name, definition, fn) {\n  let def = setFunctionDef(name, definition);\n\n  const arr = \"params\" in definition;\n\n  let vectorized = [];\n\n\n  let requiredLength = undefined;\n  if (arr) {\n    requiredLength = definition.params.length;\n    for (let i = 0; i < definition.params.length; i++) {\n      if (\"defaultVal\" in definition.params[i]) {\n        requiredLength = i;\n        break;\n      }\n    }\n\n    for (let i = 0; i < definition.params.length; i++) {\n      if (definition.params[i].vectorize) {\n        vectorized.push(i);\n        if (definition.params[i].noVector) {\n          throw new ModelError(`Cannot have a non-vector vectorized parameter. Function '${name}', parameter '${definition.params[i].name}'.`, {\n            code: 6051\n          });\n        }\n      }\n    }\n  }\n\n\n\n\n  let f = function (x, id, _ls, config = {}) {\n    let fnName;\n    if (config.isObjectCaller) {\n      // e.g. [test].x()\n      fnName = def.objectFnName;\n    } else {\n      // e.g. x([test])\n      fnName = def.standardFnName;\n    }\n\n    if (definition.prep) {\n      x = definition.prep(x);\n    }\n\n    if (arr) {\n      if ((x.length > definition.params.length || x.length < requiredLength)) {\n        throw new ModelError(`Wrong number of parameters for ${fnName}.`, {\n          code: 6052\n        });\n      }\n    } else {\n      if (!x.length && !definition.allowEmpty) {\n        throw new ModelError(`At least one parameter required for ${name}().`, {\n          code: 6053\n        });\n      }\n    }\n\n    for (let i = 0; i < x.length; i++) {\n      let config = arr ? definition.params[i] : definition.param;\n\n      function simplify(param) {\n        if (param instanceof UserFunction) {\n          return simplify(param.fn([]));\n        }\n        if (!config.needPrimitive && !config.allowOptionalPrimitive && !config.needAgent && !config.needPopulation) {\n          if (param instanceof SPrimitive && !(param instanceof SPopulation)) {\n            return simplify(toNum(param));\n          }\n        }\n        return param;\n      }\n      x[i] = simplify(x[i]);\n\n      if (config.noUnits) {\n        let unitCheck = (z) => {\n          if (z && (toNum(z) instanceof Material) && toNum(z).units && !toNum(z).units.isUnitless()) {\n            throw new ModelError(`${fnName} does not accept units for the parameter '${config.name}'. Got units of <i>${toNum(z).units.toString()}</i>`, {\n              code: 6054\n            });\n          }\n        };\n        if (x[i] instanceof Vector) {\n          x[i].recurseEach(unitCheck);\n        } else {\n          unitCheck(x[i]);\n        }\n      }\n      if (config.noVector && x[i] instanceof Vector) {\n        throw new ModelError(`${fnName} does not accept vectors for the parameter '${config.name}'.`, {\n          code: 6055\n        });\n      }\n      if (config.vectorize && x[i] instanceof Vector && !x[i].names) {\n        throw new ModelError(`${fnName} does not accepted non-named vectors for the parameter '${config.name}'.`, {\n          code: 6056\n        });\n      }\n      if (config.needVector) {\n        if (x[i] instanceof SPrimitive) {\n          x[i] = toNum(x[i]);\n        }\n        if (!(x[i] instanceof Vector)) {\n          throw new ModelError(`${fnName} requires a vector for the parameter '${config.name}'.`, {\n            code: 6057\n          });\n        }\n      }\n      if (config.needNum) {\n        if (x[i] instanceof SPrimitive) {\n          x[i] = toNum(x[i]);\n        }\n        if (!(x[i] instanceof Material)) {\n          throw new ModelError(`${fnName} requires a number for the parameter '${config.name}'.`, {\n            code: 6058\n          });\n        }\n      }\n      if (config.needPrimitive && !(x[i] instanceof SPrimitive)) {\n        throw new ModelError(`${fnName} requires a primitive for the parameter '${config.name}'.`, {\n          code: 6059\n        });\n      }\n      if (!config.allowBoolean && typeof x[i] === \"boolean\") {\n        throw new ModelError(`${fnName} does not accept boolean values for the parameter '${config.name}'.`, {\n          code: 6060\n        });\n      }\n      if (config.needAgent && !(x[i] instanceof SAgent)) {\n        x[i] = agent(x[i], simulate);\n      }\n      if (config.needString) {\n        if (!(typeof x[i] === \"string\" || x[i] instanceof String)) {\n          throw new ModelError(`${fnName} requires a string for the parameter '${config.name}'.`, {\n            code: 6061\n          });\n        }\n      }\n      if (!config.allowString && !config.needString\n        && (typeof x[i] === \"string\" || x[i] instanceof String)) {\n        throw new ModelError(`${fnName} does not accept string values for the parameter '${config.name}'.`, {\n          code: 6062\n        });\n      }\n      if (config.needAgents && !(x[i] instanceof SPopulation)) {\n        x[i] = agents(x[i]);\n      }\n      if (config.needPopulation && !(x[i] instanceof Vector)) {\n        x[i] = getPopulation(x[i], simulate);\n      }\n    }\n    let q;\n    if (arr && definition.recurse) {\n      q = toNum(x[0]);\n      if (definition.params[0] && definition.params[0].leafNeedNum) {\n        if (!(q instanceof Vector)) {\n          if (!(q instanceof Material)) {\n            throw new ModelError(`${fnName} requires a number for the parameter '${definition.params[0].name}'.`, {\n              code: 6058\n            });\n          }\n        }\n      }\n    }\n    if (arr && definition.recurse && q instanceof Vector) {\n      return q.cloneApply((z) => {\n        if (!(z instanceof Vector) && definition.params[0] && definition.params[0].leafNeedNum) {\n          if (!(z instanceof Material)) {\n            throw new ModelError(`${fnName} requires a number for the parameter '${definition.params[0].name}'.`, {\n              code: 6058\n            });\n          }\n        }\n        return f([z].concat(x.slice(1)), id);\n      });\n    } else if (arr && vectorized.length > 0) {\n      // Auto-vectorize the inner function\n\n      let base = undefined, baseI = -1;\n      for (let i = 0; i < vectorized.length; i++) {\n        if (x[vectorized[i]]) {\n          let v = toNum(x[vectorized[i]]);\n          if (v instanceof Vector && v.namesLC) {\n            if (!base) {\n              base = v;\n              baseI = vectorized[i];\n            } else {\n              if (!base.keysMatch(v.namesLC)) {\n                throw new ModelError(`Vector keys do not match between parameters '${definition.params[baseI].name}' and '${definition.params[vectorized[i]].name}' in ${fnName}.`, {\n                  code: 6064\n                });\n              }\n            }\n          }\n        }\n      }\n\n      if (!base) {\n        // Nothing is vectorized, we can behave normally\n        return fn(x, id);\n      } else {\n        // We need to vectorize\n        let keys = base.namesLC;\n        let res = [];\n        for (let i = 0; i < keys.length; i++) {\n          let newX = [];\n          for (let j = 0; j < x.length; j++) {\n            if (vectorized.indexOf(j) === -1) {\n              newX.push(x[j]);\n            } else {\n              let v = toNum(x[j]);\n              if (v instanceof Vector && v.namesLC) {\n                newX.push(v.select([keys[i]]));\n              } else {\n                newX.push(v);\n              }\n\n            }\n          }\n          let z = fn(newX, id);\n          if (z instanceof Vector) {\n            if (!base.keysMatch(z.namesLC)) {\n              throw new ModelError(`Vector keys do not match between parameter '${definition.params[baseI].name}' and calculation result.`, {\n                code: 6065\n              });\n            }\n\n            res.push(z.select([keys[i]]));\n          } else {\n            res.push(z);\n          }\n        }\n        return new Vector(res, simulate, keys);\n      }\n\n\n    } else {\n      return fn(x, id);\n    }\n  };\n\n  if (!definition.object) {\n    simulate.varBank.set(name.toLowerCase(), f);\n    simulate.coreBank.set(name.toLowerCase(), f);\n  } else {\n    if (definition.object instanceof Array) {\n      for (let i = 0; i < definition.object.length; i++) {\n        if (definition.object[i] instanceof Map) {\n          if (definition.object[i] === simulate.varBank) {\n            simulate.coreBank.set(name.toLowerCase(), f);\n          }\n          definition.object[i].set(name.toLowerCase(), f);\n        } else {\n          definition.object[i][name.toLowerCase()] = f;\n\n        }\n      }\n    } else {\n      if (definition.object instanceof Map) {\n        definition.object.set(name.toLowerCase(), f);\n      } else {\n        definition.object[name.toLowerCase()] = f;\n      }\n    }\n  }\n\n  if (arr && definition.recurse) {\n    VectorObject[name.toLowerCase()] = f;\n  }\n}\n\n\nfunction objectizeFunction(fn) {\n  let f = function (x, fingerprint, lastSelf) {\n    if (!lastSelf) {\n      throw new ModelError(\"Object function not used on object\", {\n        code: 6066\n      });\n    }\n    return fn([lastSelf].concat(x), fingerprint, lastSelf, {\n      isObjectCaller: true\n    });\n  };\n  f.delayEvalParams = fn.delayEvalParams;\n  return f;\n}\n\n\n/**\n * @param {number} x\n * @returns {number}\n */\nfunction factorial(x) {\n  if (Math.round(x) !== x) {\n    throw new ModelError(\"The factorial() function only accepts integers.\", {\n      code: 6067\n    });\n  } else if (x < 0) {\n    throw new ModelError(\"The factorial() function is only defined for integers 0 or larger.\", {\n      code: 6068\n    });\n  }\n  if (x > 1) {\n    return x * factorial(x - 1);\n  } else {\n    return 1;\n  }\n}\n\n\nexport function testArgumentsSize(x, name, min, max) {\n  if (x.length < min || x.length > max) {\n    throw new ModelError(`Wrong number of parameters for ${name}().`, {\n      code: 6069\n    });\n  }\n}\n", "src/formula/Material.js": "import { convertUnits, UnitStore } from \"./Units.js\";\nimport { fn } from \"../CalcMap.js\";\nimport { ModelError } from \"./ModelError.js\";\nimport { PrimitiveStore } from \"./Formula.js\";\n\n\nexport class Material {\n  /**\n   * @param {number} value\n   * @param {import(\"./Units\").UnitStore=} units\n   * @param {boolean=} explicitUnits\n   */\n  constructor(value, units, explicitUnits=true) {\n    /** @type {number} */\n    this.value = value;\n    /** @type {import(\"./Units\").UnitStore|undefined} */\n    this.units = units;\n    /** @type {boolean} */\n    this.explicitUnits = explicitUnits;\n  }\n\n  /**\n   * @returns {Material}\n   */\n  toNum() {\n    return this;\n  }\n\n  toString() {\n    if (this.units && !this.units.isUnitless()) {\n      return \"{\" + this.value + \" \" + this.units.toStringShort() + \"}\";\n    } else {\n      return this.value + \"\";\n    }\n  }\n\n  fullClone() {\n    return new Material(this.value, this.units, this.explicitUnits);\n  }\n\n  /**\n   * @param {import(\"./Units\").UnitStore} newUnits\n   *\n   * @returns {Material}\n   */\n  forceUnits(newUnits) {\n    if (!this.units) {\n      this.units = newUnits;\n    } else {\n      let scale = convertUnits(this.units, newUnits);\n      if (scale === 0) {\n        unitAlert(this.units, newUnits, \"conversion of units\");\n      } else {\n        this.value = fn[\"*\"](this.value, scale);\n        this.units = newUnits;\n      }\n    }\n\n    return this;\n  }\n}\n\n\n/**\n * Find a unit shared by all materials. Or null if they are all unitless.\n *\n * @param {Material[]} materials\n * @returns {{ units: import(\"./Units\").UnitStore|null, explicitUnits: boolean }}\n */\nexport function findSharedUnits(materials) {\n  if (!materials.length) {\n    return { units: null, explicitUnits: true };\n  }\n\n  let shared = materials[0].units;\n  let explicitUnits = materials[0].explicitUnits;\n\n  if (!shared || shared.isUnitless()) {\n    for (let i = 1; i < materials.length; i++) {\n      let m = materials[i];\n      if (m.units && !m.units.isUnitless()) {\n        throw new ModelError(`Incompatible units between ${m.units.toString()} and unitless.`, {\n          code: 5023\n        });\n      }\n    }\n  } else {\n    for (let i = 1; i < materials.length; i++) {\n      let m = materials[i];\n      let units = m && m.units;\n      let scale = convertUnits(units, shared);\n      if (scale === 0) {\n        throw new ModelError(`Incompatible units between ${units ? units.toString() : \"unitless\"} and ${shared.toString()}.`, {\n          code: 5023\n        });\n      }\n      if (scale !== 1 || !m.explicitUnits) {\n        explicitUnits = false;\n      }\n    }\n  }\n\n  return { units: shared, explicitUnits };\n}\n\n\n/** @typedef {\"MATERIAL\"|\"VECTOR\"|\"PRIMITIVE\"|null} OperandType */\n\n/**\n * @param {Material|UnitStore} lhs\n * @param {Material|UnitStore} rhs\n * @param {string} type\n * @param {string=} operator\n * @param {import(\"./Formula\").TreeNode=} lhsNode\n * @param {import(\"./Formula\").TreeNode=} rhsNode\n */\nexport function unitAlert(lhs, rhs, type, operator, lhsNode, rhsNode) {\n  if (lhs instanceof UnitStore && rhs instanceof UnitStore) {\n    throw new ModelError(`Incompatible units for the ${type} of ${((lhs && !lhs.isUnitless()) ? lhs.toString() : \"unitless\")} and ${((rhs && !rhs.isUnitless()) ? rhs.toString() : \"unitless\")}.`, {\n      code: 5000\n    });\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n    let lhsUnits = lhs.units;\n    let rhsUnits = rhs.units;\n    let msg = `Incompatible units for the ${type} of ${((lhsUnits && !lhsUnits.isUnitless()) ? lhsUnits.toString() : \"unitless\")} and ${((rhsUnits && !rhsUnits.isUnitless()) ? rhsUnits.toString() : \"unitless\")}.`;\n\n    let formatMat = (mat) => {\n      if (mat.units && !mat.units.isUnitless()) {\n        return `{${mat.value} ${mat.units.toStringShort()}}`;\n      } else {\n        return mat.value;\n      }\n    };\n\n    msg += `<br/><br/>Attempted ${type}: <b>${formatMat(lhs)} ${operator.replace(\"<\", \"&lt;\").replace(\">\", \"&gt;\")} ${formatMat(rhs)}</b>`;\n\n    if (!lhsUnits) {\n      if (lhsNode instanceof Material) {\n        let lhsSuggested = lhs.fullClone();\n        lhsSuggested.units = rhsUnits;\n        msg += `<br/><br/>Consider replacing <b>${formatMat(lhs)}</b> with <b>${formatMat(lhsSuggested)}</b>.`;\n      } else if (lhsNode instanceof PrimitiveStore) {\n        msg += \"<br/><br/>Consider setting the units of <b>[\" + lhsNode.primitive.dna.name + \"]</b> to <b>\" + rhsUnits.toStringShort() + \"</b>.\";\n      }\n    }\n\n    if (!rhsUnits) {\n      if (rhsNode instanceof Material) {\n        let rhsSuggested = rhs.fullClone();\n        rhsSuggested.units = lhsUnits;\n        msg += `<br/><br/>Consider replacing <b>${formatMat(rhs)}</b> with <b>${formatMat(rhsSuggested)}</b>.`;\n      } else if (rhsNode instanceof PrimitiveStore) {\n        msg += \"<br/><br/>Consider setting the units of <b>[\" + rhsNode.primitive.dna.name + \"]</b> to <b>\" + lhsUnits.toStringShort() + \"</b>.\";\n      }\n    }\n\n    throw new ModelError(msg, {\n      code: 5000\n    });\n  }\n}\n\n", "src/formula/Formula.js": "import { Material, unitAlert } from \"./Material.js\";\nimport { convertUnits } from \"./Units.js\";\nimport { SAgent, SPopulation, SPrimitive } from \"../Primitives.js\";\nimport { fn } from \"../CalcMap.js\";\nimport { stringify, selectFromMatrix, selectFromVector } from \"./Utilities.js\";\nimport { Vector } from \"./Vector.js\";\nimport { createFunctions as generalCreateFunctions } from \"./CalcFunctions.js\";\nimport { createFunctions as modelerCreateFunctions } from \"../Functions.js\";\nimport { ModelError } from \"./ModelError.js\";\nimport {\n  BailErrorStrategy,\n  CharStream,\n  CommonTokenStream,\n  PredictionMode,\n  ParseCancellationException,\n  Token\n} from \"../../vendor/antlr4ng-all.js\";\nimport { FormulaLexer } from \"./grammar/FormulaLexer.js\";\nimport { FormulaParser } from \"./grammar/FormulaParser.js\";\nimport { sanitizeText } from \"../Utilities.js\";\nimport { DUPLICATE_PRIMITIVE_NAMES } from \"../Modeler.js\";\n\n\n/** @typedef {import(\"../SharedTypes.js\").ValueType} ValueType */\n\nexport const PARENT_SYMBOL = Symbol(\"-parent\");\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nexport function bootCalc(simulate) {\n  simulate.coreBank = new Map();\n  simulate.coreBank.set(PARENT_SYMBOL, null);\n\n\n  simulate.varBank = new Map();\n  simulate.varBank.set(PARENT_SYMBOL, null);\n  simulate.varBank.set(\"e\", new Material(Math.E));\n  simulate.varBank.set(\"pi\", new Material(Math.PI));\n  simulate.varBank.set(\"phi\", new Material(1.61803399));\n\n  generalCreateFunctions(simulate);\n  modelerCreateFunctions(simulate);\n}\n\n/**\n * @param {any} node\n * @param {number} ruleIndex\n * @returns {boolean}\n */\nfunction isRule(node, ruleIndex) {\n  return !!node && typeof node === \"object\" && node.ruleIndex === ruleIndex;\n}\n\nfunction getInnerBlock(node, parser, source) {\n  let innerBlock = node.children.find(x => isRule(x, FormulaParser.RULE_innerBlock));\n  if (!innerBlock || !innerBlock.children) {\n    return new TreeNode(\"\", \"LINES\", {\n      line: node.start.line,\n      source\n    });\n  }\n\n  return convertToObject(innerBlock, parser, source);\n}\n\n\n\nexport class PrimitiveStore {\n  /**\n   * @param {any} primitive\n   * @param {string} type\n   */\n  constructor(primitive, type) {\n    this.primitive = primitive;\n    this.type = type; // \"value\", \"totalValue\", \"object\"\n  }\n}\n\n\n/**\n * @template {any} T\n * @param {T} x\n * @returns {T extends Vector ? Vector : (T extends Material ? Material : (T extends SPrimitive ? Material : any))}\n */\nexport function toNum(x) {\n  if (x instanceof Material || x instanceof SPrimitive || x instanceof Vector || x instanceof UserFunction || x instanceof SPopulation) {\n    return /** @type {any} */ (x.toNum());\n  }\n\n  if (x instanceof Function) {\n    return x([]);\n  }\n\n  return /** @type {any} */ (x.valueOf());\n}\n\n\nexport class UserFunction {\n  constructor() {\n    this.localScope = undefined;\n    this.defaults = undefined;\n    this.fn = undefined;\n  }\n\n  toNum() {\n    return this.fn([]);\n  }\n}\n\n\nexport let StringObject = Object.create(null);\nObject.defineProperty(StringObject, \"_object_type\", {\n  value: \"string\",\n  enumerable: false,\n  configurable: false,\n  writable: false\n});\n\n\nexport let VectorObject = Object.create(null);\nObject.defineProperty(VectorObject, \"_object_type\", {\n  value: \"vector\",\n  enumerable: false,\n  configurable: false,\n  writable: false\n});\n\n\n\n/**\n * Returns a snippet of the input string around the error position. E.g. \"...bc xy...\"\n *\n * @param {string} input\n * @param {number} line\n * @param {number} column\n * @returns\n */\nfunction getErrorSnippet(input, line, column) {\n  const PADDING_CHARS = 4;\n\n  const lines = input.split(\"\\n\");\n\n  if (line < 1 || line > lines.length) {\n    return null;\n  }\n\n  const errorLine = lines[line - 1];\n  const start = Math.max(0, column - PADDING_CHARS);\n  const end = Math.min(errorLine.length, column + PADDING_CHARS);\n  const prefix = start > 0 ? \"...\" : \"\";\n  const suffix = end < errorLine.length ? \"...\" : \"\";\n\n  return sanitizeText(prefix + errorLine.substring(start, end) + suffix);\n}\n\n\n// cached parse trees, makes subsequent simulations faster\nconst PARSED_TREE_CACHE = new Map();\nconst PARSED_TREE_CACHE_MAX = 4000;\n\n\n/**\n * @param {string} input\n * @param {string} source\n * @param {import(\"../Simulator\").Simulator} simulate\n * @returns\n */\nexport function createTree(input, source, simulate) {\n  simulate.evaluatingPosition = {\n    line: 1,\n    source\n  };\n\n  let cacheKey = source + \"\\0\" + input;\n  let cached = PARSED_TREE_CACHE.get(cacheKey);\n  if (cached) {\n    return cached.cloneStructure();\n  }\n\n  const chars = CharStream.fromString(input);\n  const lexer = new FormulaLexer(chars);\n  lexer.removeErrorListeners();\n  lexer.addErrorListener({\n    syntaxError: (recognizer, offendingSymbol, line, column, msg, err) => {\n      simulate.evaluatingPosition.line = line;\n      let snippet = getErrorSnippet(input, line, column);\n\n      if (snippet !== null) {\n        snippet = ` at \"${snippet}\"`;\n      } else {\n        snippet = \"\";\n      }\n\n      throw new ModelError(`Invalid equation syntax${snippet}`, {\n        code: 9000\n      });\n    },\n    reportAmbiguity: () => {},\n    reportAttemptingFullContext: () => {},\n    reportContextSensitivity: () => {}\n  });\n  const tokens = new CommonTokenStream(lexer);\n\n  const parser = new FormulaParser(tokens);\n  parser.interpreter.predictionMode = PredictionMode.SLL;\n  // @ts-ignore\n  parser.errorHandler = new BailErrorStrategy();\n\n  parser.removeErrorListeners();\n  parser.addErrorListener({\n    syntaxError: (recognizer, offendingSymbol, line, column, msg, err) => {\n      simulate.evaluatingPosition.line = line;\n      throw new ModelError(`Invalid equation syntax at \"${getErrorSnippet(input, line, column)}\"`, {\n        code: 9000\n      });\n    },\n    reportAttemptingFullContext: (...args) => {\n      // console.log(\"reportAttemptingFullContext\", args);\n    },\n    reportAmbiguity: (...args) => {\n      // console.log(\"reportAmbiguity\", args);\n    },\n    reportContextSensitivity: (...args) => {\n      // console.log(\"reportContextSensitivity\", args);\n    }\n  });\n  try {\n    const parsedTree = parser.lines();\n    removeWhitespaceTokens(parsedTree);\n\n    let tree = convertToObject(parsedTree, parser, source);\n    if (PARSED_TREE_CACHE.size >= PARSED_TREE_CACHE_MAX) {\n      // Evict the oldest entry. Map iteration is insertion order.\n      let oldest = PARSED_TREE_CACHE.keys().next().value;\n      PARSED_TREE_CACHE.delete(oldest);\n    }\n\n    PARSED_TREE_CACHE.set(cacheKey, tree);\n    return tree.cloneStructure();\n  } catch (err) {\n    if (err instanceof ModelError) {\n      throw err;\n    }\n\n    if (err instanceof ParseCancellationException) {\n      let ctx = err.cause.ctx.stop || err.cause.ctx.start;\n      throw new ModelError(`Invalid equation syntax at \"${getErrorSnippet(input, ctx.line, ctx.column)}\"`, { code: 9000 });\n    }\n\n    throw err;\n  }\n}\n\nfunction removeWhitespaceTokens(node) {\n  if (node.children) {\n    node.children = node.children.filter(x => {\n      if (x.symbol?.type === FormulaLexer.R_ || x.symbol?.type === FormulaLexer.R__) {\n        return false;\n      }\n      removeWhitespaceTokens(x);\n      return true;\n    });\n  }\n}\n\n\n/**\n * @param {Object} root\n * @param {Map} nodeBase\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nexport function trimTree(root, nodeBase, simulate) {\n  return trimNode(root, nodeBase, simulate);\n}\n\n\n/**\n * @param {Object} root\n * @param {Map} varBank\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nexport function evaluateTree(root, varBank, simulate) {\n  simulate.evaluatingPosition = {\n    line: null,\n    source: null\n  };\n  try {\n    return evaluateNode(root, varBank, simulate);\n  } catch (err) {\n    if (err.returnVal) {\n      return err.data;\n    } else {\n      throw err;\n    }\n  }\n}\n\n\n\nexport class TreeNode {\n  /**\n   * @param {string} text\n   * @param {string} typeName\n   * @param {{ line: number, source: string }} position\n   * @param {any[]=} children\n   */\n  constructor(text, typeName, position, children = []) {\n    this.origText = text;\n\n    this.text = text.toLowerCase();\n\n    this.typeName = typeName;\n\n    this.position = position;\n\n    this.children = children;\n\n    /** @type {string} */\n    this.functionFingerprint = null;\n\n    /** @type {boolean} */\n    this.delayEvalParams = null;\n  }\n\n  cloneStructure() {\n    let res = new TreeNode(this.origText, this.typeName, this.position);\n    res.children = this.children.map(child => {\n      if (child instanceof TreeNode) {\n        return child.cloneStructure();\n      }\n      console.error(this, child);\n      throw new TypeError(\"Unknown structure clone type\");\n    });\n    return res;\n  }\n}\n\n/**\n * @param {Partial<import(\"antlr4ng\").ParserRuleContext>} node\n * @param {function(Partial<import(\"antlr4ng\").ParseTree>):TreeNode} fn\n * @param {*} parser\n * @param {string} source\n * @returns\n */\nfunction flatChildrenToTreeRight(node, fn, parser, source) {\n  let children = node.children.slice();\n  let isFirst = true;\n  while (children.length > 1) {\n    let right = children.pop();\n    let operator = children.pop();\n    let left = children.pop();\n    let current = fn(operator);\n    current.children = [convertToObject(left, parser, source), isFirst ? convertToObject(right, parser, source) : right];\n    // @ts-ignore\n    children.push(current);\n    isFirst = false;\n  }\n  return children[0];\n}\n\n\n/**\n * @param {Partial<import(\"antlr4ng\").ParserRuleContext>} node\n * @param {function(Partial<import(\"antlr4ng\").ParseTree>):TreeNode} fn\n * @param {*} parser\n * @param {string} source\n * @returns\n */\nfunction flatChildrenToTreeLeft(node, fn, parser, source) {\n  let children = node.children.slice();\n  let isFirst = true;\n  while (children.length > 1) {\n    let left = children.shift();\n    let operator = children.shift();\n    let right = children.shift();\n    let current = fn(operator);\n    current.children = [isFirst ? convertToObject(left, parser, source) : left, convertToObject(right, parser, source) ];\n    // @ts-ignore\n    children.unshift(current);\n    isFirst = false;\n  }\n  return children[0];\n}\n\n\nfunction convertSimpleTerminalNode(node, source, fallbackLine) {\n  // @ts-ignore\n  const symbol = node?.symbol;\n  if (!symbol) {\n    return null;\n  }\n\n  const type = symbol.type;\n  const text = symbol.text;\n\n  if (type === FormulaLexer.BOOL) {\n    return new TreeNode(text, text.toLowerCase() === \"true\" ? \"TRUE\" : \"FALSE\", {\n      line: symbol.line,\n      source\n    });\n  }\n\n  if (type === FormulaLexer.STRING) {\n    return new TreeNode(text, \"STRING\", {\n      line: symbol.line,\n      source\n    });\n  }\n\n  if (type === FormulaLexer.IDENT) {\n    return new TreeNode(text, \"IDENT\", {\n      line: symbol.line,\n      source\n    });\n  }\n\n  if (type === FormulaLexer.PRIMITIVE) {\n    return new TreeNode(text, \"PRIMITIVE\", {\n      line: symbol.line || fallbackLine,\n      source\n    });\n  }\n\n  if (type === FormulaLexer.MULT) {\n    return new TreeNode(text, \"MULT\", {\n      line: symbol.line,\n      source\n    });\n  }\n\n  return null;\n}\n\n/**\n * @param {any} node\n * @param {object} parser\n * @param {string} source\n * @returns\n */\nfunction convertToObject(node, parser, source) {\n  // @ts-ignore\n  let ruleIndex = node.ruleIndex;\n\n  if (ruleIndex === FormulaParser.RULE_lines) {\n    let current = new TreeNode(\"\", \"LINES\", {\n      line: node.start.line,\n      source\n    });\n    let children = node.children;\n    for (let i = 0; i < children.length; i++) {\n      let type = children[i].symbol?.type;\n      if (type === Token.EOF) {\n        continue;\n      }\n      if (type === FormulaLexer.NEWLINES) {\n        continue;\n      }\n      current.children.push(convertToObject(children[i], parser, source));\n\n      if (!current.position?.line && current.children[current.children.length - 1].position?.line) {\n        current.position = current.children[current.children.length - 1].position;\n      }\n    }\n\n    return current;\n  } else if (ruleIndex === FormulaParser.RULE_multiplicativeExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, (op) => {\n        // @ts-ignore\n        let type = op.symbol.type;\n        return new TreeNode(\"\", type === FormulaLexer.MULT ? \"MULT\" : (type === FormulaLexer.DIV ? \"DIV\" : \"MOD\"), {\n          // @ts-ignore\n          line: (op.start || op.symbol).line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_number) {\n    return new TreeNode(node.getText(), \"FLOAT\", {\n      line: node.start.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_value) {\n    const child = node.children[0];\n    const simple = convertSimpleTerminalNode(child, source, node.start.line);\n    if (simple) {\n      return simple;\n    }\n    return convertToObject(child, parser, source);\n\n  } else if (ruleIndex === FormulaParser.RULE_symbolRef) {\n    return new TreeNode(node.children[0].symbol.text, \"IDENT\", {\n      line: node.start.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_typeRef) {\n    return new TreeNode(node.children[0].symbol.text, \"IDENT\", {\n      line: node.start.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_primitiveRef) {\n    return new TreeNode(node.children[0].symbol.text, \"PRIMITIVE\", {\n      line: node.start.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_memberSymbolRef) {\n    let token = node.children[0];\n    let simple = convertSimpleTerminalNode(token, source, node.start.line);\n    if (simple) {\n      return simple;\n    }\n    throw new ModelError(\"Unknown invalid equation member syntax\", {\n      code: 9002\n    });\n\n  // boolean lexer\n  // @ts-ignore\n  } else if (node.symbol?.type === FormulaLexer.BOOL) {\n    return new TreeNode(\"\", node.symbol.text.toLowerCase() === \"true\" ? \"TRUE\" : \"FALSE\", {\n      // @ts-ignore\n      line: node.symbol.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_returnExp) {\n    let expr = null;\n    for (let i = 0; i < node.children.length; i++) {\n      if (isRule(node.children[i], FormulaParser.RULE_logicalExpression)) {\n        expr = node.children[i];\n        break;\n      }\n    }\n\n    if (!expr) {\n      throw new ModelError(\"Invalid return expression syntax\", {\n        code: 9002\n      });\n    }\n\n    let current = new TreeNode(\"return\", \"RETURN\", {\n      line: node.start.line,\n      source\n    }, [convertToObject(expr, parser, source)]);\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_throwExp) {\n    let current = new TreeNode(\"\", \"THROW\", {\n      line: node.start.line,\n      source\n    }, [convertToObject(node.children[1], parser, source)]);\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_additiveExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, (op) => {\n        // @ts-ignore\n        let type = op.symbol.type;\n        // @ts-ignore\n        return new TreeNode(op.symbol.text, type === FormulaLexer.PLUS ? \"PLUS\" : \"MINUS\", {\n          // @ts-ignore\n          line: (op.start || op.symbol).line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_powerExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeRight(node, () => {\n        return new TreeNode(\"\", \"POWER\", {\n          line: node.start.line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unaryOrNegate) {\n    if (node.children.length > 1) {\n      let current = new TreeNode(\"\", \"NEGATE\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[1], parser, source)];\n      return current;\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_arrayExpression) {\n    if (node.children.length > 1) {\n      let current = new TreeNode(\"\", \"RANGE\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[0], parser, source), convertToObject(node.children[2], parser, source)];\n      if (node.children.length > 3) {\n        current.children.push(convertToObject(node.children[4], parser, source));\n      }\n      return current;\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unaryExpression) {\n    if (node.children.length > 1) {\n      let current = new TreeNode(\"\", \"NOT\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[1], parser, source)];\n      return current;\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_booleanXORExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, () => {\n        return new TreeNode(\"\", \"XOR\", {\n          line: node.start.line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_equalityExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, (op) => {\n        // @ts-ignore\n        let type = op.symbol.type;\n        return new TreeNode(\"\", type === FormulaLexer.EQUALS ? \"EQUALS\" : \"NOTEQUALS\", {\n          // @ts-ignore\n          line: (op.start || op.symbol).line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_relationalExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, (op) => {\n        // @ts-ignore\n        let type = op.symbol.type;\n        return new TreeNode(\"\", type === FormulaLexer.LT ? \"LT\" : (type === FormulaLexer.GT ? \"GT\" : (type === FormulaLexer.LTEQ ? \"LTEQ\" : \"GTEQ\")), {\n          // @ts-ignore\n          line: (op.start || op.symbol).line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_logicalExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, () => {\n        return new TreeNode(\"\", \"OR\", {\n          line: node.start.line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_booleanAndExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, () => {\n        return new TreeNode(\"\", \"AND\", {\n          line: node.start.line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_negnumber) {\n    return new TreeNode(node.getText(), \"FLOAT\", {\n      line: node.start.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_negationExpression) {\n    if (node.children.length > 1) {\n      let current = new TreeNode(\"\", \"NEGATE\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[1], parser, source)];\n      return current;\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_anonFunctionDef) {\n    let current = new TreeNode(\"\", \"ANONFUNCTION\", {\n      line: node.start.line,\n      source\n    });\n    let params = new TreeNode(\"\", \"PARAMS\", {\n      line: node.start.line,\n      source\n    });\n    let defaults = new TreeNode(\"\", \"DEFAULTS\", {\n      line: node.start.line,\n      source\n    });\n    params.children = [];\n    defaults.children = [];\n\n    for (let i = 2; i < node.children.length; i++) {\n      let type = node.children[i].symbol?.type;\n      if (type === FormulaLexer.RPAREN) {\n        break;\n      }\n      if (type === FormulaLexer.COMMA) {\n        continue;\n      }\n      params.children.push(new TreeNode(node.children[i].symbol.text, \"IDENT\", {\n        line: node.start.line,\n        source\n      }));\n      if (node.children[i + 1].symbol?.type === FormulaLexer.EQUALS) {\n        defaults.children.push(convertToObject(node.children[i + 2], parser, source));\n        i += 2;\n      }\n    }\n\n    current.children = [params, defaults];\n    if (isRule(node.children[node.children.length - 1], FormulaParser.RULE_expression)) {\n      current.children.push(convertToObject(node.children[node.children.length - 1], parser, source));\n    } else {\n      current.children.push(getInnerBlock(node, parser, source));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_functionDef) {\n    let current = new TreeNode(\"\", \"FUNCTION\", {\n      line: node.start.line,\n      source\n    });\n    let params = new TreeNode(\"\", \"PARAMS\", {\n      line: node.start.line,\n      source\n    });\n    let defaults = new TreeNode(\"\", \"DEFAULTS\", {\n      line: node.start.line,\n      source\n    });\n    params.children.push(new TreeNode(node.children[1].symbol.text, \"IDENT\", {\n      line: node.start.line,\n      source\n    }));\n\n    for (let i = 3; i < node.children.length; i++) {\n      let type = node.children[i].symbol?.type;\n      if (type === FormulaLexer.RPAREN) {\n        break;\n      }\n      if (type === FormulaLexer.COMMA) {\n        continue;\n      }\n      params.children.push(new TreeNode(node.children[i].symbol.text, \"IDENT\", {\n        line: node.start.line,\n        source\n      }));\n      if (node.children[i + 1].symbol?.type === FormulaLexer.EQUALS) {\n        defaults.children.push(convertToObject(node.children[i + 2], parser, source));\n        i += 2;\n      }\n    }\n    current.children = [params, defaults, getInnerBlock(node, parser, source)];\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_innerBlock) {\n    let current = new TreeNode(\"\", \"LINES\", {\n      line: node.start.line,\n      source\n    });\n    for (let i = 0; i < node.children?.length; i++) {\n      if (node.children[i].symbol?.type === FormulaLexer.NEWLINES) {\n        continue;\n      }\n      current.children.push(convertToObject(node.children[i], parser, source));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_newObject) {\n    let current = new TreeNode(\"\", \"NEW\", {\n      line: node.start.line,\n      source\n    });\n    current.children = [convertToObject(node.children[1], parser, source)];\n    if (node.children.length > 2) {\n      current.children.push(convertToObject(node.children[2], parser, source));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_whileLoop) {\n    let current = new TreeNode(\"\", \"WHILE\", {\n      line: node.start.line,\n      source\n    });\n    current.children = [\n      convertToObject(node.children[1], parser, source),\n      getInnerBlock(node, parser, source)\n    ];\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_forLoop) {\n    let current = new TreeNode(\"\", \"FOR\", {\n      line: node.start.line,\n      source\n    });\n    current.children = [\n      new TreeNode(node.children[1].symbol.text, \"IDENT\", {\n        line: node.start.line,\n        source\n      }),\n      new TreeNode(\"\", \"PARAMS\", {\n        line: node.start.line,\n        source\n      },\n      node.children\n        .filter(x => isRule(x, FormulaParser.RULE_logicalExpression))\n        .map(x => convertToObject(x, parser, source))),\n      getInnerBlock(node, parser, source)\n    ];\n\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_forInLoop) {\n    let current = new TreeNode(\"\", \"FORIN\", {\n      line: node.start.line,\n      source\n    });\n    current.children = [\n      new TreeNode(node.children[1].symbol.text, \"IDENT\", {\n        line: node.start.line,\n        source\n      }),\n      convertToObject(node.children[3], parser, source),\n      getInnerBlock(node, parser, source)\n    ];\n\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_ifThenElse) {\n    let current = new TreeNode(\"\", \"IFTHENELSE\", {\n      line: node.start.line,\n      source\n    });\n\n    let innerBlocks = [];\n    // @ts-ignore\n    let potentialInnerBlocks = node.children.filter(x => (\n      isRule(x, FormulaParser.RULE_innerBlock) ||\n      x.symbol?.type === FormulaLexer.ELSESTATEMENT ||\n      x.symbol?.type === FormulaLexer.ENDPREFIX ||\n      x.symbol?.type === FormulaLexer.ENDBLOCK\n    ));\n    let hadBlock = false;\n    for (let i = 0; i < potentialInnerBlocks.length; i++) {\n      if (isRule(potentialInnerBlocks[i], FormulaParser.RULE_innerBlock)) {\n        hadBlock = true;\n        innerBlocks.push(convertToObject(potentialInnerBlocks[i], parser, source));\n      } else {\n        if (!hadBlock) {\n          innerBlocks.push(new TreeNode(\"\", \"LINES\", {\n            line: node.start.line,\n            source\n          }));\n        }\n        hadBlock = false;\n      }\n    }\n\n    current.children = [\n      new TreeNode(\"\", \"PARAMS\", {\n        line: node.start.line,\n        source\n      },\n      node.children\n        .filter(x => isRule(x, FormulaParser.RULE_logicalExpression))\n        .map(x => convertToObject(x, parser, source))),\n      new TreeNode(\"\", \"PARAMS\", {\n        line: node.start.line,\n        source\n      },\n      innerBlocks)\n    ];\n\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_tryCatch) {\n    let current = new TreeNode(\"\", \"TRYCATCH\", {\n      line: node.start.line,\n      source\n    });\n\n    let innerBlocks = [];\n    // @ts-ignore\n    let potentialInnerBlocks = node.children.filter(x => (\n      isRule(x, FormulaParser.RULE_innerBlock) ||\n      x.symbol?.type === FormulaLexer.CATCHSTATEMENT ||\n      x.symbol?.type === FormulaLexer.ENDPREFIX ||\n      x.symbol?.type === FormulaLexer.ENDBLOCK\n    ));\n    let hadBlock = false;\n    for (let i = 0; i < potentialInnerBlocks.length; i++) {\n      if (isRule(potentialInnerBlocks[i], FormulaParser.RULE_innerBlock)) {\n        hadBlock = true;\n        innerBlocks.push(convertToObject(potentialInnerBlocks[i], parser, source));\n      } else {\n        if (!hadBlock) {\n          innerBlocks.push(new TreeNode(\"\", \"LINES\", {\n            line: node.start.line,\n            source\n          }));\n        }\n        hadBlock = false;\n      }\n    }\n\n    current.children = innerBlocks;\n\n    let identNode = node.children.find(x => x.symbol?.type === FormulaLexer.IDENT);\n    // @ts-ignore\n    current.children.push(new TreeNode(identNode.symbol.text, \"IDENT\", {\n      line: node.start.line,\n      source\n    }));\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_assignment) {\n    if (node.children[1].symbol?.type === FormulaLexer.LPAREN) {\n      let current = new TreeNode(\"\", \"FUNCTION\", {\n        line: node.start.line,\n        source\n      });\n      let params = new TreeNode(\"\", \"PARAMS\", {\n        line: node.start.line,\n        source\n      });\n      let defaults = new TreeNode(\"\", \"DEFAULTS\", {\n        line: node.start.line,\n        source\n      });\n      params.children.push(new TreeNode(node.children[0].symbol.text, \"IDENT\", {\n        line: node.start.line,\n        source\n      }));\n\n      for (let i = 2; i < node.children.length; i++) {\n        if (node.children[i].symbol?.type === FormulaLexer.ASSIGN) {\n          break;\n        }\n        if (\n          node.children[i].symbol?.type === FormulaLexer.COMMA ||\n          node.children[i].symbol?.type === FormulaLexer.RPAREN\n        ) {\n          continue;\n        }\n        params.children.push(new TreeNode(node.children[i].symbol.text, \"IDENT\", {\n          line: node.start.line,\n          source\n        }));\n        if (node.children[i + 1].symbol?.type === FormulaLexer.EQUALS) {\n          defaults.children.push(convertToObject(node.children[i + 2], parser, source));\n          i += 2;\n        }\n      }\n      current.children = [params, defaults, convertToObject(node.children[node.children.length - 1], parser, source)];\n      return current;\n    } else {\n      let current = new TreeNode(\"\", \"ASSIGN\", {\n        line: node.start.line,\n        source\n      });\n      for (let i = 0; i < node.children.length; i++) {\n        if (\n          node.children[i].symbol?.type === FormulaLexer.COMMA ||\n          node.children[i].symbol?.type === FormulaLexer.ASSIGN\n        ) {\n          continue;\n        }\n        current.children.push(convertToObject(node.children[i], parser, source));\n      }\n      return current;\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_assigned) {\n    let current = new TreeNode(\"\", \"ASSIGNED\", {\n      line: node.start.line,\n      source\n    });\n    current.children = [\n      new TreeNode(node.children[0].symbol.text, \"IDENT\", {\n        line: node.start.line,\n        source\n      })\n    ];\n    for (let i = 1; i < node.children.length; i++) {\n      current.children.push(convertToObject(node.children[i], parser, source));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_string) {\n    return new TreeNode(node.children[0].symbol.text, \"STRING\", {\n      line: node.start.line,\n      source\n    });\n\n  } else if (ruleIndex === FormulaParser.RULE_innerPrimaryExpression) {\n    let current = new TreeNode(\"\", \"INNER\", {\n      line: node.start.line,\n      source\n    });\n    if (isRule(node.children[0], FormulaParser.RULE_selectionExpression)) {\n      let selectionExpression = /** @type {any} */ (node.children[0]);\n      current.children.push(convertToObject(selectionExpression.children[0], parser, source));\n      for (let i = 1; i < selectionExpression.children.length; i++) {\n        current.children.push(convertToObject(selectionExpression.children[i], parser, source));\n      }\n    } else {\n      for (let i = 0; i < node.children.length; i++) {\n        current.children.push(convertToObject(node.children[i], parser, source));\n      }\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_primaryExpression) {\n    if (node.children[0].symbol?.type === FormulaLexer.LPAREN) {\n      return convertToObject(node.children[1], parser, source);\n    }\n    return convertToObject(node.children[0], parser, source);\n\n  } else if (ruleIndex === FormulaParser.RULE_selector) {\n    let current = new TreeNode(\"\", \"SELECTOR\", {\n      line: node.start.line,\n      source\n    });\n    if (isRule(node.children[0], FormulaParser.RULE_minarray)) {\n      let minArray = /** @type {any} */ (node.children[0]);\n      for (let i = 1; i < minArray.children.length - 1; i++) {\n        if (minArray.children[i].symbol?.type === FormulaLexer.COMMA) {\n          continue;\n        }\n        if (minArray.children[i].symbol?.type === FormulaLexer.MULT) {\n          current.children.push(new TreeNode(minArray.children[i].symbol.text, \"MULT\", {\n            line: minArray.children[i].symbol.line,\n            source\n          }));\n          continue;\n        }\n\n        current.children.push(convertToObject(minArray.children[i], parser, source));\n      }\n    } else {\n      current.children = [convertToObject(node.children[0], parser, source)];\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_dotselector) {\n    let current = new TreeNode(\"\", \"DOTSELECTOR\", {\n      line: node.start.line,\n      source\n    });\n    for (let i = 0; i < node.children.length; i++) {\n      if (node.children[i].symbol?.type === FormulaLexer.DOT) {\n        continue;\n      }\n      current.children.push(convertToObject(node.children[i], parser, source));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_arrayName) {\n    let token = node.children[0];\n    const simple = convertSimpleTerminalNode(token, source, node.start.line);\n    if (simple) {\n      return simple;\n    }\n    throw new Error(\"Invalid type - arrayName\");\n\n  } else if (ruleIndex === FormulaParser.RULE_funCall) {\n    let current = new TreeNode(\"\", \"FUNCALL\", {\n      line: node.start.line,\n      source\n    });\n    for (let i = 1; i < node.children.length - 1; i++) {\n      if (node.children[i].symbol?.type === FormulaLexer.COMMA) {\n        continue;\n      }\n      current.children.push(convertToObject(node.children[i], parser, source));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_material) {\n    let current = new TreeNode(node.getText(), \"MATERIAL\", {\n      line: node.start.line,\n      source\n    });\n    current.children = [convertToObject(node.children[2], parser, source), convertToObject(node.children[1], parser, source)];\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_unitMultiplicativeExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, () => {\n        return new TreeNode(\"\", \"PER\", {\n          line: node.start.line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unitInnerMultiplicativeExpression) {\n    if (node.children.length > 1) {\n      return flatChildrenToTreeLeft(node, (op) => {\n        let token = /** @type {{ symbol: { type: number }, start?: { line?: number } }} */ (op);\n        let type = token.symbol.type;\n        return new TreeNode(\"\", type === FormulaLexer.MULT ? \"MULT\" : \"DIV\", {\n          line: token.start?.line,\n          source\n        });\n      }, parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unitPowerExpression) {\n    if (node.children.length > 1) {\n      let children = /** @type {any} */ (node.children.slice());\n      let isFirst = true;\n      while (children.length > 1) {\n        let left = children.shift();\n        let operator = children.shift();\n        let minus;\n        let right;\n        let minusOrRight = children.shift();\n        if (minusOrRight.symbol?.type === FormulaLexer.MINUS) {\n          minus = minusOrRight;\n          right = children.pop();\n        } else {\n          right = minusOrRight;\n        }\n        let current = new TreeNode(\"\", \"POW\", {\n          // @ts-ignore\n          line: (operator.start || operator.symbol).line,\n          source\n        });\n        current.children = [isFirst ? convertToObject(left, parser, source) : left, new TreeNode(right.symbol.text, \"FLOAT\", {\n          line: right.symbol.line,\n          source\n        })];\n        if (minus) {\n          current.children.splice(1, 0, new TreeNode(\"\", \"MINUS\", {\n            // @ts-ignore\n            line: (minus.start || minus.symbol).line,\n            source\n          }));\n        }\n        children.push(current);\n        isFirst = false;\n      }\n      return children[0];\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unitClump) {\n    if (node.children[0].symbol?.type === FormulaLexer.INTEGER) {\n      let current = new TreeNode(\"\", \"UNITCLUMP\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[2], parser, source), new TreeNode(\"\", \"NEGATE\", {\n        line: node.start.line,\n        source\n      })];\n      for (let i = 3; i < node.children.length; i++) {\n        if (node.children[i].symbol?.type === FormulaLexer.CUBED) {\n          current.children.push(new TreeNode(\"\", \"CUBED\", {\n            line: node.start.line,\n            source\n          }));\n        } else if (node.children[i].symbol?.type === FormulaLexer.SQUARED) {\n          current.children.push(new TreeNode(\"\", \"SQUARED\", {\n            line: node.start.line,\n            source\n          }));\n        }\n      }\n      return current;\n    } else {\n      let current = new TreeNode(\"\", \"UNITCLUMP\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[0], parser, source)];\n\n      for (let i = 1; i < node.children.length; i++) {\n        if (node.children[i].symbol?.type === FormulaLexer.CUBED) {\n          current.children.push(new TreeNode(\"\", \"CUBED\", {\n            line: node.start.line,\n            source\n          }));\n        } else if (node.children[i].symbol?.type === FormulaLexer.SQUARED) {\n          current.children.push(new TreeNode(\"\", \"SQUARED\", {\n            line: node.start.line,\n            source\n          }));\n        }\n      }\n      return current;\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unit) {\n    if (node.children[0].symbol?.type === FormulaLexer.LPAREN) {\n      let current = new TreeNode(\"\", \"UNITCLUMP\", {\n        line: node.start.line,\n        source\n      });\n      current.children = [convertToObject(node.children[1], parser, source)];\n      return current;\n    } else {\n      return convertToObject(node.children[0], parser, source);\n    }\n\n  } else if (ruleIndex === FormulaParser.RULE_unitRef) {\n    let current = new TreeNode(\"\", \"UNIT\", {\n      line: node.start.line,\n      source\n    });\n    for (let i = 0; i < node.children.length; i++) {\n      let token = node.children[i];\n      // @ts-ignore\n      let symbol = token.symbol;\n      if (!symbol) {\n        continue;\n      }\n      current.children.push(new TreeNode(symbol.text, \"IDENT\", {\n        line: symbol.line,\n        source\n      }));\n    }\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_array) {\n    let current = new TreeNode(\"\", \"ARRAY\", {\n      line: node.start.line,\n      source\n    });\n    for (let i = 1; i < node.children.length - 1; i++) {\n      if (\n        node.children[i].symbol?.type === FormulaLexer.LCURL ||\n        node.children[i].symbol?.type === FormulaLexer.COMMA ||\n        node.children[i].symbol?.type === FormulaLexer.NEWLINES ||\n        node.children[i].symbol?.type === FormulaLexer.RCURL ||\n        node.children[i].symbol?.type === FormulaLexer.LARR ||\n        node.children[i].symbol?.type === FormulaLexer.RARR\n      ) {\n        continue;\n      }\n      if (isRule(node.children[i], FormulaParser.RULE_label)) {\n        current.children.push(convertToObject(node.children[i], parser, source));\n      } else {\n        current.children.push(new TreeNode(\"\", \"LABEL\", {\n          line: node.start.line,\n          source\n        }, [convertToObject(node.children[i], parser, source)]));\n      }\n    }\n\n    return current;\n\n  } else if (ruleIndex === FormulaParser.RULE_label) {\n    let current = new TreeNode(node.getText(), \"LABEL\", {\n      line: node.start.line,\n      source\n    });\n    let children = node.children.slice();\n    children = children.filter(child => child.symbol?.type !== FormulaLexer.NEWLINES);\n    if (children.length === 1) {\n      current.children = [convertToObject(children[0], parser, source)];\n    } else {\n      current.children = [convertToObject(children[2], parser, source), convertToObject(children[0], parser, source)];\n    }\n    return current;\n  }\n\n  if (node.children.length === 1) {\n    return convertToObject(node.children[0], parser, source);\n  }\n\n  throw new ModelError(\"Unknown invalid equation syntax\", {\n    code: 9002\n  });\n}\n\n\nlet funcEvalMap = Object.create(null);\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"LINES\"] = function (node, scope, simulate) {\n  if (!node.children.length) {\n    return new Material(0);\n  }\n\n  let response;\n  for (let child of node.children) {\n    if (child.text === \"return\") {\n      // eslint-disable-next-line\n      throw { returnVal: true, data: evaluateNode(child.children[0], scope, simulate) };\n    } else {\n      response = evaluateNode(child, scope, simulate);\n    }\n  }\n  return response;\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"NEGATE\"] = function (node, scope, simulate) {\n  return negate(toNum(evaluateNode(node.children[0], scope, simulate)));\n};\n\n/**\n * @template {Material|Vector} T\n *\n * @param {T} x\n *\n * @returns {T extends Vector ? Vector : Material}\n */\nexport function negate(x) {\n  if (x instanceof Vector) {\n    return /** @type {any} */ (x.cloneApply(negate));\n  } else if (x instanceof Material) {\n    return /** @type {any} */ (new Material(fn[\"-\"](x.value), x.units));\n  }\n\n\n  if (typeof x === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7001\n    });\n  }\n  if (x instanceof String || typeof x === \"string\") {\n    throw new ModelError(\"Cannot convert Strings to Numbers.\", {\n      code: 7002\n    });\n  }\n  if (x instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7003\n    });\n  }\n\n  throw new ModelError(\"Invalid type - negate\", {\n    code: 7004\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"AND\"] = function (node, scope, simulate) {\n  return funAnd(toNum(evaluateNode(node.children[0], scope, simulate)), toNum(evaluateNode(node.children[1], scope, simulate)));\n};\n\nfunction funAnd(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, funAnd, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, funAnd, true);\n  }\n\n  return trueValue(lhs) && trueValue(rhs);\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"OR\"] = function (node, scope, simulate) {\n  return funOr(toNum(evaluateNode(node.children[0], scope, simulate)), toNum(evaluateNode(node.children[1], scope, simulate)));\n};\n\nfunction funOr(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, funOr, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, funOr, true);\n  }\n\n  return trueValue(lhs) || trueValue(rhs);\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"XOR\"] = function (node, scope, simulate) {\n  return funXor(toNum(evaluateNode(node.children[0], scope, simulate)), toNum(evaluateNode(node.children[1], scope, simulate)));\n};\n\nfunction funXor(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, funXor, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, funXor, true);\n  }\n\n  return (trueValue(lhs) || trueValue(rhs)) && !(trueValue(lhs) && trueValue(rhs));\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"NOT\"] = function (node, scope, simulate) {\n  return fNot(toNum(evaluateNode(node.children[0], scope, simulate)));\n};\n\nexport function fNot(x) {\n  if (x instanceof Vector) {\n    return x.cloneApply(fNot);\n  }\n\n  return !trueValue(x);\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"NOTEQUALS\"] = function (node, scope, simulate) {\n  return neq(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1]\n  );\n};\n\n/**\n * @param {ValueType|string|number} lhs\n * @param {ValueType|string|number} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n *\n * @returns {boolean}\n */\nexport function neq(lhs, rhs, lhsNode, rhsNode) {\n  if ((typeof lhs === \"boolean\" && !(rhs instanceof Vector)) || (typeof rhs === \"boolean\" && !(lhs instanceof Vector))) {\n    return trueValue(lhs) !== trueValue(rhs);\n  }\n  if (((lhs instanceof String || typeof lhs === \"string\") && !(rhs instanceof Vector)) || ((rhs instanceof String || typeof rhs === \"string\") && !(lhs instanceof Vector))) {\n    return (\"\" + lhs).toLowerCase() !== (\"\" + rhs).toLowerCase();\n  }\n\n\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, neq, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, neq, true);\n  }\n\n  if (!(lhs instanceof Material) || !(rhs instanceof Material)) {\n    return lhs !== rhs;\n  }\n\n  let scale = 1;\n  if (lhs.units !== rhs.units) {\n    scale = convertUnits(rhs.units, lhs.units);\n    if (scale === 0) {\n      unitAlert(lhs, rhs, \"inequality comparison\", \"<>\", lhsNode, rhsNode);\n    }\n  }\n\n  return !fn[\"=\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](rhs.value, scale));\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"EQUALS\"] = function (node, scope, simulate) {\n  return eq(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1],\n    true);\n};\n\n\n/**\n * @param {ValueType|string|number} lhs\n * @param {ValueType|string|number} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n * @param {boolean=} allowVectorReturn\n * @returns {boolean}\n */\nexport function eq(lhs, rhs, lhsNode, rhsNode, allowVectorReturn=false) {\n  if ((typeof lhs === \"boolean\" && !(rhs instanceof Vector)) || (typeof rhs === \"boolean\" && !(lhs instanceof Vector))) {\n    return trueValue(lhs) === trueValue(rhs);\n  }\n  if (((typeof lhs === \"string\" || lhs instanceof String) && !(rhs instanceof Vector)) || ((typeof rhs === \"string\" || rhs instanceof String) && !(lhs instanceof Vector))) {\n    return (\"\" + lhs).toLowerCase() === (\"\" + rhs).toLowerCase();\n  }\n\n\n  if (allowVectorReturn) {\n    if (lhs instanceof Vector) {\n      return lhs.cloneCombine(rhs, (a, b) => eq(a, b, undefined, undefined, true), false);\n    } else if (rhs instanceof Vector) {\n      return rhs.cloneCombine(lhs, (a, b) => eq(a, b, undefined, undefined, true), true);\n    }\n  } else {\n    if (lhs instanceof Vector || rhs instanceof Vector) {\n      if (lhs instanceof Vector && rhs instanceof Vector) {\n        return lhs.equals(rhs);\n      }\n      return false;\n    }\n  }\n\n  if (!(lhs instanceof Material) || !(rhs instanceof Material)) {\n    return lhs === rhs;\n  }\n\n  let scale = 1;\n  if (lhs.units !== rhs.units) {\n    scale = convertUnits(rhs.units, lhs.units);\n    if (scale === 0) {\n      unitAlert(lhs, rhs, \"equality comparison\", \"=\", lhsNode, rhsNode);\n    }\n  }\n\n\n  return fn[\"=\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](rhs.value, scale));\n}\n\nfunction comparisonValid(lhs, rhs) {\n  if (lhs instanceof String || typeof lhs === \"string\" || rhs instanceof String || typeof rhs === \"string\") {\n    throw new ModelError(\"Cannot use Strings in logical inequality comparisons.\", {\n      code: 7005\n    });\n  }\n  if (lhs instanceof Boolean || typeof lhs === \"boolean\" || rhs instanceof Boolean || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot use Booleans in logical inequality comparisons.\", {\n      code: 7006\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot use Agents in logical inequality comparisons.\", {\n      code: 7007\n    });\n  }\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"LT\"] = function (node, scope, simulate) {\n  return lessThan(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1]\n  );\n};\n\n/**\n * @param {ValueType} lhs\n * @param {ValueType} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n *\n * @returns {boolean}\n */\nexport function lessThan(lhs, rhs, lhsNode, rhsNode) {\n  comparisonValid(lhs, rhs);\n\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, lessThan, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, lessThan, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n\n    let scale = 1;\n    if (lhs.units !== rhs.units) {\n      scale = convertUnits(rhs.units, lhs.units);\n      if (scale === 0) {\n        unitAlert(lhs, rhs, \"comparison\", \"<\", lhsNode, rhsNode);\n      }\n    }\n\n    return fn[\"<\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](scale, rhs.value));\n  }\n\n  throw new ModelError(\"Invalid type - lessThan\", {\n    code: 7008\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"LTEQ\"] = function (node, scope, simulate) {\n  return lessThanEq(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1]\n  );\n};\n\n/**\n * @param {ValueType} lhs\n * @param {ValueType} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n *\n * @returns {boolean}\n */\nexport function lessThanEq(lhs, rhs, lhsNode, rhsNode) {\n  comparisonValid(lhs, rhs);\n\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, lessThanEq, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, lessThanEq, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n\n\n    let scale = 1;\n    if (lhs.units !== rhs.units) {\n      scale = convertUnits(rhs.units, lhs.units);\n      if (scale === 0) {\n        unitAlert(lhs, rhs, \"comparison\", \"<=\", lhsNode, rhsNode);\n      }\n    }\n\n    return fn[\"<=\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](scale, rhs.value));\n  }\n\n  throw new ModelError(\"Invalid type - lessThanEq\", {\n    code: 7009\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"GT\"] = function (node, scope, simulate) {\n  return greaterThan(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1]\n  );\n};\n\n/**\n * @param {ValueType} lhs\n * @param {ValueType} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n * @returns {boolean}\n */\nexport function greaterThan(lhs, rhs, lhsNode, rhsNode) {\n  comparisonValid(lhs, rhs);\n\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, greaterThan, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, greaterThan, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n\n    let scale = 1;\n    if (lhs.units !== rhs.units) {\n      scale = convertUnits(rhs.units, lhs.units);\n      if (scale === 0) {\n        unitAlert(lhs, rhs, \"comparison\", \">\", lhsNode, rhsNode);\n      }\n    }\n\n    return fn[\">\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](scale, rhs.value));\n  }\n\n  throw new ModelError(\"Invalid type - greaterThan\", {\n    code: 7010\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"GTEQ\"] = function (node, scope, simulate) {\n  return greaterThanEq(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1]\n  );\n};\n\n/**\n * @param {ValueType} lhs\n * @param {ValueType} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n * @returns {boolean}\n */\nexport function greaterThanEq(lhs, rhs, lhsNode, rhsNode) {\n  comparisonValid(lhs, rhs);\n\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, greaterThanEq, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, greaterThanEq, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n\n    let scale = 1;\n    if (lhs.units !== rhs.units) {\n      scale = convertUnits(rhs.units, lhs.units);\n      if (scale === 0) {\n        unitAlert(lhs, rhs, \"comparison\", \">=\", lhsNode, rhsNode);\n      }\n    }\n\n    return fn[\">=\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](scale, rhs.value));\n  }\n\n  throw new ModelError(\"Invalid type - greaterThanEq\", {\n    code: 7011\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"PLUS\"] = function (node, scope, simulate) {\n  return plus(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1],\n    simulate\n  );\n};\n\n\n/**\n * @template {Material|Vector|String} L\n * @template {Material|Vector|String} R\n *\n * @param {L} lhs\n * @param {R} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n * @param {import(\"../Simulator\").Simulator=} simulate\n *\n * @returns {L extends Vector ? Vector : (R extends Vector ? Vector : (L extends string ? string: (R extends string ? string : Material)))}\n */\nexport function plus(lhs, rhs, lhsNode, rhsNode, simulate) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, (a, b) => plus(a, b, lhsNode, rhsNode, simulate), false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, (a, b) => plus(a, b, lhsNode, rhsNode, simulate), true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n\n    let explicitUnits = true;\n    let scale = 1;\n    if (lhs.units !== rhs.units) {\n      scale = convertUnits(rhs.units, lhs.units);\n      if (scale === 0) {\n        unitAlert(lhs, rhs, \"addition\", \"+\", lhsNode, rhsNode);\n      } else if (scale !== 1) {\n        explicitUnits = false;\n      }\n    }\n\n    return /** @type {any} */ (new Material(\n      fn[\"+\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](rhs.value, scale)),\n      lhs.units,\n      explicitUnits && lhs.explicitUnits && rhs.explicitUnits\n    ));\n  }\n\n\n  if (typeof lhs === \"boolean\" || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7012\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7013\n    });\n  }\n  if (typeof lhs === \"string\" || lhs instanceof String || typeof rhs === \"string\" || rhs instanceof String) {\n    let s = lhs.toString() + rhs.toString();\n    if (!simulate) {\n      throw new ModelError(\"Attempted to concatenate in an invalid context.\", {\n        code: 7014\n      });\n    }\n    return /** @type {any} */ (stringify(s, simulate));\n  }\n\n  throw new ModelError(\"Invalid type - plus\", {\n    code: 7014\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"MINUS\"] = function (node, scope, simulate) {\n  return minus(\n    toNum(evaluateNode(node.children[0], scope, simulate)),\n    toNum(evaluateNode(node.children[1], scope, simulate)),\n    node.children[0],\n    node.children[1]\n  );\n};\n\n\n\n/**\n * @template {Material|Vector} L\n * @template {Material|Vector} R\n *\n * @param {L} lhs\n * @param {R} rhs\n * @param {TreeNode=} lhsNode\n * @param {TreeNode=} rhsNode\n *\n * @returns {L extends Vector ? Vector : (R extends Vector ? Vector : Material)}\n */\nexport function minus(lhs, rhs, lhsNode, rhsNode) {\n\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, minus, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, minus, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n\n    let explicitUnits = true;\n    let scale = 1;\n    if (lhs.units !== rhs.units) {\n      scale = convertUnits(rhs.units, lhs.units);\n      if (scale === 0) {\n        unitAlert(lhs, rhs, \"subtraction\", \"-\", lhsNode, rhsNode);\n      } else if (scale !== 1) {\n        explicitUnits = false;\n      }\n    }\n\n\n    return /** @type {any} */ (new Material(\n      fn[\"-\"](lhs.value, scale === 1 ? rhs.value : fn[\"*\"](rhs.value, scale)),\n      lhs.units,\n      explicitUnits && lhs.explicitUnits && rhs.explicitUnits\n    ));\n  }\n\n\n  if (typeof lhs === \"boolean\" || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7015\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7016\n    });\n  }\n  if (typeof lhs === \"string\" || lhs instanceof String || typeof rhs === \"string\" || rhs instanceof String) {\n    throw new ModelError(\"Cannot convert Strings to Numbers.\", {\n      code: 7017\n    });\n  }\n\n\n  throw new ModelError(\"Invalid type - minus\", {\n    code: 7018\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"MULT\"] = function (node, scope, simulate) {\n  return mult(toNum(evaluateNode(node.children[0], scope, simulate)), toNum(evaluateNode(node.children[1], scope, simulate)));\n};\n\n/**\n * @template {Material|Vector} L\n * @template {Material|Vector} R\n *\n * @param {L} lhs\n * @param {R} rhs\n *\n * @returns {L extends Vector ? Vector : (R extends Vector ? Vector : Material)}\n */\nexport function mult(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, mult, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, mult, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n    let x = fn[\"*\"](lhs.value, rhs.value);\n\n    if (lhs.units && rhs.units) {\n      let [scale, newUnits, explicit] = lhs.units.multiply(rhs.units, true);\n      if (scale === 1) {\n        return /** @type {any} */ (new Material(\n          x,\n          newUnits,\n          explicit && lhs.explicitUnits && rhs.explicitUnits\n        ));\n      } else {\n        return /** @type {any} */ (new Material(\n          fn[\"*\"](x, scale),\n          newUnits,\n          explicit && lhs.explicitUnits && rhs.explicitUnits\n        ));\n      }\n    } else if (lhs.units) {\n      return /** @type {any} */ (new Material(x, lhs.units));\n    } else if (rhs.units) {\n      return /** @type {any} */ (new Material(x, rhs.units));\n    }\n\n    return /** @type {any} */ (new Material(x));\n  }\n\n  if (typeof lhs === \"boolean\" || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7019\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7020\n    });\n  }\n  if (typeof lhs === \"string\" || lhs instanceof String || typeof rhs === \"string\" || rhs instanceof String) {\n    throw new ModelError(\"Cannot convert Strings to Numbers.\", {\n      code: 7021\n    });\n  }\n\n\n  throw new ModelError(\"Invalid type - mult\", {\n    code: 7022\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"DIV\"] = function (node, scope, simulate) {\n  return div(toNum(evaluateNode(node.children[0], scope, simulate)), toNum(evaluateNode(node.children[1], scope, simulate)));\n};\n\n/**\n * @template {Material|Vector} L\n * @template {Material|Vector} R\n *\n * @param {L} lhs\n * @param {R} rhs\n *\n * @returns {L extends Vector ? Vector : (R extends Vector ? Vector : Material)}\n */\nexport function div(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, div, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, div, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n    let x = fn[\"/\"](lhs.value, rhs.value);\n\n    if (lhs.units && rhs.units) {\n      let [scale, newUnits, explicit] = lhs.units.multiply(rhs.units, false);\n      if (scale === 1) {\n        return /** @type {any} */ (new Material(\n          x,\n          newUnits,\n          explicit && lhs.explicitUnits && rhs.explicitUnits\n        ));\n      } else {\n        return /** @type {any} */ (new Material(\n          fn[\"*\"](x, scale),\n          newUnits,\n          explicit && lhs.explicitUnits && rhs.explicitUnits\n        ));\n      }\n    } else if (lhs.units) {\n      return /** @type {any} */ (new Material(x, lhs.units));\n    } else if (rhs.units) {\n      return /** @type {any} */ (new Material(x, rhs.units.power(-1)));\n    }\n\n    return /** @type {any} */ (new Material(x));\n  }\n\n  if (typeof lhs === \"boolean\" || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7023\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7024\n    });\n  }\n  if (typeof lhs === \"string\" || lhs instanceof String || typeof rhs === \"string\" || rhs instanceof String) {\n    throw new ModelError(\"Cannot convert Strings to Numbers.\", {\n      code: 7025\n    });\n  }\n\n  throw new ModelError(\"Invalid type - div\", {\n    code: 7026\n  });\n}\n\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"POWER\"] = function (node, scope, simulate) {\n  if (node.children.length === 1) {\n    return evaluateNode(node.children[0], scope, simulate);\n  }\n\n  let rhs = toNum(evaluateNode(node.children[node.children.length - 1], scope, simulate));\n\n  for (let j = node.children.length - 1; j > 0; j--) {\n    let lhs = toNum(evaluateNode(node.children[j - 1], scope, simulate));\n    if (rhs instanceof Vector || !rhs.units) {\n      rhs = power(lhs, rhs);\n    } else {\n      throw new ModelError(\"Exponents may not have units.\", {\n        code: 7027\n      });\n    }\n  }\n\n  return rhs;\n};\n\n\n/**\n * @template {Material|Vector} L\n * @template {Material|Vector} R\n *\n * @param {L} lhs\n * @param {R} rhs\n *\n * @returns {L extends Vector ? Vector : (R extends Vector ? Vector : Material)}\n */\nexport function power(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, power, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, power, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n    let x = lhs.value;\n    let y = rhs.value;\n    if (x < 0 && y !== Math.round(y)) {\n      throw new ModelError(`Cannot take a negative number (${x}) to a fractional power (${y}).`, {\n        code: 7028\n      });\n    }\n    return /** @type {any} */ (new Material(fn.expt(x, y), lhs.units ? lhs.units.power(y) : undefined));\n  }\n\n  if (typeof lhs === \"boolean\" || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7029\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7030\n    });\n  }\n  if (typeof lhs === \"string\" || lhs instanceof String || typeof rhs === \"string\" || rhs instanceof String) {\n    throw new ModelError(\"Cannot convert Strings to Numbers.\", {\n      code: 7031\n    });\n  }\n\n\n  throw new ModelError(\"Invalid type - power\", {\n    code: 7032\n  });\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"MOD\"] = function (node, scope, simulate) {\n  return doMod(toNum(evaluateNode(node.children[0], scope, simulate)), toNum(evaluateNode(node.children[1], scope, simulate)));\n};\n\n/**\n * @template {Material|Vector} L\n * @template {Material|Vector} R\n *\n * @param {L} lhs\n * @param {R} rhs\n *\n * @returns {L extends Vector ? Vector : (R extends Vector ? Vector : Material)}\n */\nexport function doMod(lhs, rhs) {\n  if (lhs instanceof Vector) {\n    return lhs.cloneCombine(rhs, doMod, false);\n  } else if (rhs instanceof Vector) {\n    return rhs.cloneCombine(lhs, doMod, true);\n  } else if (lhs instanceof Material && rhs instanceof Material) {\n    if (!rhs.units) {\n      return /** @type {any} */ (new Material(fn.mod(lhs.value, rhs.value), lhs.units));\n    } else {\n      throw new ModelError(\"The right hand side of \\\"mod\\\" may not have units.\", {\n        code: 7033\n      });\n    }\n  }\n\n  if (typeof lhs === \"boolean\" || typeof rhs === \"boolean\") {\n    throw new ModelError(\"Cannot convert Booleans to Numbers.\", {\n      code: 7034\n    });\n  }\n  if (lhs instanceof SAgent || rhs instanceof SAgent) {\n    throw new ModelError(\"Cannot convert Agents to Numbers.\", {\n      code: 7035\n    });\n  }\n  if (typeof lhs === \"string\" || lhs instanceof String || typeof rhs === \"string\" || rhs instanceof String) {\n    throw new ModelError(\"Cannot convert Strings to Numbers.\", {\n      code: 7036\n    });\n  }\n\n\n  throw new ModelError(\"Invalid type - mod\", {\n    code: 7037\n  });\n}\n\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"IDENT\"] = function (node, scope, simulate) {\n  let varName = node.text;\n\n  while (!scope.has(varName)) {\n    let parent = scope.get(PARENT_SYMBOL);\n    if (!parent) {\n      throw new ModelError(`The variable or function \"${node.origText}\" does not exist.`, {\n        code: 7038\n      });\n    }\n    scope = parent;\n  }\n\n  let v = scope.get(varName);\n\n  if (v instanceof TreeNode && v.typeName === \"ARRAY\") {\n    v = evaluateNode(v, scope, simulate);\n  }\n  if (v.fullClone && !(v instanceof Vector)) {\n    return v.fullClone();\n  } else {\n    return v;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"NEW\"] = function (node, scope, simulate) {\n  let base = evaluateNode(node.children[0], scope, simulate);\n  if (base instanceof Vector) {\n    let n = new Vector([], simulate, undefined, base);\n    let constructor;\n    let r;\n    try {\n      r = selectFromVector(base, simulate, \"constructor\");\n      constructor = r.data;\n    } catch (err) {\n      // pass\n    }\n\n    if (!constructor) {\n      if (node.children.length === 2 && node.children[1].children.length > 0) {\n        throw new ModelError(`No constructor available for '${node.children[0].text}'.`, {\n          code: 7039\n        });\n      }\n    } else {\n      if (node.children.length === 2) {\n        callFunction(constructor, node.children[1], simulate, scope, n, r.parent);\n      } else {\n        callFunction(constructor, { children: [] }, simulate, scope, n, r.parent);\n      }\n    }\n    return n;\n  } else {\n    throw new ModelError(\"'New' can only be use to create instances of Vectors.\", {\n      code: 7040\n    });\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"INNER\"] = function (node, scope, simulate) {\n  let base = evaluateNode(node.children[0], scope, simulate);\n\n  if (node.children.length === 2 && node.children[1].typeName === \"FUNCALL\") {\n    return callFunction(base, node.children[1], simulate, scope);\n  }\n\n  let lastSelf; // for \"self\" binding\n  let lastBase; // for \"self\" binding\n\n  if (scope.get(\"self\") && node.children[0].text === \"parent\") {\n    lastSelf = scope.get(\"self\");\n  } else if (!(base instanceof Function || base instanceof UserFunction)) {\n    lastSelf = base;\n  }\n\n  for (let i = 1; i < node.children.length; i++) {\n    if (node.children[i].typeName === \"SELECTOR\") {\n      if (node.children[i].children[0].typeName === \"DOTSELECTOR\") {\n\n        for (let j = 0; j < node.children[i].children[0].children.length; j++) {\n          let res = [];\n          if (node.children[i].children[0].children[j].text) {\n            res.push(node.children[i].children[0].children[j].text);\n          } else {\n            res.push(node.children[i].children[0].children[j].valueOf());\n          }\n          try {\n            base = selectFromMatrix(base, simulate, res);\n          } catch (err) {\n            if (base instanceof SPrimitive && !(base instanceof SAgent)) {\n              base = toNum(base);\n              j--;\n            } else {\n              throw err;\n            }\n          }\n\n          if (!(base instanceof Function || base instanceof UserFunction)) {\n            lastSelf = base;\n            lastBase = base;\n          }\n        }\n\n      } else {\n\n        if (base instanceof SPrimitive) {\n          base = toNum(base);\n\n          if (!(base instanceof Function || base instanceof UserFunction)) {\n            lastSelf = base;\n            lastBase = base;\n          }\n        }\n\n\n        try {\n          base = selectFromMatrix(base, simulate, createMatrixSelector(node.children[i], scope, 0, simulate));\n        } catch (err) {\n          if (base instanceof SPrimitive) {\n            base = toNum(base);\n            i--;\n          } else {\n            throw err;\n          }\n        }\n\n        if (!(base instanceof Function || base instanceof UserFunction)) {\n          lastSelf = base;\n          lastBase = base;\n        }\n      }\n\n\n    } else { // \"FUNCALL\"\n      base = callFunction(base, node.children[i], simulate, scope, lastSelf, lastBase);\n\n      if (!(base instanceof Function || base instanceof UserFunction)) {\n        lastSelf = base;\n        lastBase = base;\n      }\n    }\n  }\n  return base;\n};\n\nlet fingerprintCounter = 0;\n\n/**\n *\n * @param {*} base\n * @param {any} node\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {Map} scope\n * @param {*} lastSelf\n * @param {*} lastBase\n * @returns\n */\nfunction callFunction(base, node, simulate, scope, lastSelf, lastBase) {\n  if (typeof base !== \"function\" && !(base instanceof UserFunction)) {\n    throw new ModelError(\"Trying to call a non-function.\", {\n      code: 7041\n    });\n  }\n\n  let vals = [];\n  let fingerprint = \"\";\n  if (node instanceof Array) {\n    vals = node;\n  } else {\n    if (!node.functionFingerprint) {\n      node.functionFingerprint = \"FINGERPRINT-\" + (fingerprintCounter++);\n    }\n    fingerprint = node.functionFingerprint;\n\n    if (base.delayEvalParams) {\n      // don't evaluate params right away. needed for IfThenElse and short circuiting\n      for (let j = 0; j < node.children.length; j++) {\n        vals.push({ node: node.children[j], scope: scope });\n      }\n    } else {\n      for (let j = 0; j < node.children.length; j++) {\n        let item = evaluateNode(node.children[j], scope, simulate);\n        if (item.fullClone && !(item instanceof Vector)) {\n          item = item.fullClone();\n        }\n        vals.push(item);\n      }\n    }\n  }\n\n  let fn;\n  if (base.fn) {\n    fn = base.fn; // user defined function\n  } else {\n    node.delayEvalParams = base.delayEvalParams;\n    fn = base; // built-in\n  }\n\n  let oldPosition = simulate.evaluatingPosition;\n\n  let x = fn(vals, fingerprint, lastSelf, lastBase);\n\n  simulate.evaluatingPosition = oldPosition;\n\n  return x;\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {*} offset\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfunction createMatrixSelector(node, scope, offset, simulate) {\n  let selector = [];\n  offset = offset || 0;\n  for (let i = offset; i < node.children.length; i++) {\n    let child = node.children[i];\n    if (child.typeName === \"MULT\") {\n      selector.push(\"*\");\n    } else {\n      let x = evaluateNode(node.children[i], scope, simulate);\n      if (typeof x === \"function\" || x instanceof UserFunction) {\n        let fn;\n        if (typeof x === \"function\") {\n          fn = x;\n        } else {\n          fn = x.fn;\n        }\n        (function (f) {\n          selector.push((x) => {\n            if (!x[0].stackApply) {\n              throw new ModelError(\"Can't apply function across elements of non-vector.\", {\n                code: 7042\n              });\n            }\n\n            return x[0].stackApply((x) => {\n              return f([x]);\n            });\n          });\n        })(fn);\n      } else {\n        selector.push(toNum(x));\n      }\n    }\n  }\n  return selector;\n}\n\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"ARRAY\"] = function (node, scope, simulate) {\n\n  if (node.children.length === 1 && node.children[0] instanceof Vector) {\n    return node.children[0].fullClone(); // pre calculated vector\n  }\n\n  let vals = [];\n  let names = [];\n  let hasName = false;\n  for (let i = 0; i < node.children.length; i++) {\n    vals.push(evaluateNode(node.children[i].children[0], scope, simulate));\n    if (node.children[i].children.length > 1) {\n      if (node.children[i].children[1].text) {\n        names.push(node.children[i].children[1].origText);\n      } else {\n        names.push(node.children[i].children[1].valueOf());\n      }\n      hasName = true;\n    } else {\n      names.push(undefined);\n    }\n  }\n  return new Vector(vals, simulate, hasName ? names : undefined);\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"RANGE\"] = function (node, scope, simulate) {\n  if (node.children.length === 1) {\n    return evaluateNode(node.children[0], scope, simulate);\n  }\n  let vals = [];\n  let start = toNum(evaluateNode(node.children[0], scope, simulate));\n  let end = toNum(evaluateNode(node.children[node.children.length - 1], scope, simulate));\n\n  if (!(start instanceof Material) || !(end instanceof Material)) {\n    throw new ModelError(\"Range elements must be numbers.\", {\n      code: 7043\n    });\n  }\n\n  vals.push(start.fullClone());\n  if (start.units !== end.units) {\n    let scale = convertUnits(start.units, end.units);\n    if (scale !== 1) {\n      throw new ModelError(\"Units on both sides of ':' must be equal.\", {\n        code: 7044\n      });\n    }\n  }\n\n  /** @type {Material} */\n  let step = node.children.length === 2 ? new Material(1, start.units) : toNum(evaluateNode(node.children[1], scope, simulate));\n\n  if (!(step instanceof Material)) {\n    throw new ModelError(\"Range elements must be numbers.\", {\n      code: 7045\n    });\n  }\n\n  if (eq(start, end)) {\n    // pass\n  } else if (lessThan(start, end)) {\n    if (step.value <= 0) {\n      throw new ModelError(`Step size must be positive to range from ${start} to ${end}, got ${step.value}`, {\n        code: 7046\n      });\n    }\n\n    let it = plus(start, step);\n    while (lessThanEq(it, end)) {\n      vals.push(it);\n      it = plus(it, step);\n    }\n  } else if (greaterThan(start, end)) {\n    if (node.children.length === 2) {\n      step = negate(step);\n    } else {\n      if (step.value >= 0) {\n        throw new ModelError(`Step size must be negative to range from ${start} to ${end}, got ${step.value}`, {\n          code: 7046\n        });\n      }\n    }\n\n    let it = plus(start, step);\n    while (greaterThanEq(it, end)) {\n      vals.push(it);\n      it = plus(it, step);\n    }\n  }\n\n  return new Vector(vals, simulate);\n};\n\n/**\n * @param {*} varName\n * @param {*} varNames\n * @param {*} varDefaults\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfunction makeFunctionCall(varName, varNames, varDefaults, node, scope, simulate) {\n\n  let fn = new UserFunction();\n\n  fn.localScope = Object.create(null);\n  fn.localScope[\"nVars\"] = varNames.length;\n  for (let i = 0; i < varNames.length; i++) {\n    fn.localScope[i + \"\"] = varNames[i];\n  }\n  fn.defaults = varDefaults;\n\n  fn.fn = function (x, fingerPrint, lastSelf, lastBase) {\n    let minLength = x.length;\n    for (let i = 0; i < x.length; i++) {\n      if (x[i].optional) {\n        minLength--;\n      }\n    }\n    if (fn.localScope[\"nVars\"] - fn.defaults.length > x.length || minLength > fn.localScope[\"nVars\"]) {\n      let names = [];\n      for (let i = 0; i < fn.localScope[\"nVars\"]; i++) {\n        if (fn.defaults.length - (fn.localScope[\"nVars\"] - i) > -1) {\n          names.push(fn.localScope[i + \"\"] + \"=\" + fn.defaults[fn.defaults.length - (fn.localScope[\"nVars\"] - i)]);\n        } else {\n          names.push(fn.localScope[i + \"\"]);\n        }\n      }\n\n      throw new ModelError(\"Wrong number of parameters for \" + varName + \"(\" + names.join(\", \") + \").\", {\n        code: 7049\n      });\n    }\n    /** @type {Map<PARENT_SYMBOL|string, any>} */\n    let localScope = new Map([\n      [PARENT_SYMBOL, scope]\n    ]);\n\n    for (let i = 0; i < x.length; i++) {\n      localScope.set(fn.localScope[i + \"\"], x[i]);\n    }\n    for (let i = x.length; i < fn.localScope[\"nVars\"]; i++) {\n      localScope.set(fn.localScope[i + \"\"], fn.defaults[fn.defaults.length - (fn.localScope[\"nVars\"] - i)]);\n    }\n\n\n    if (lastSelf) {\n      if (!localScope.has(\"self\")) {\n        localScope.set(\"self\", lastSelf);\n      }\n    }\n    if (lastBase) {\n      if (lastBase.parent) {\n        localScope.set(\"parent\", lastBase.parent);\n      }\n    }\n\n    try {\n      return evaluateNode(node, localScope, simulate);\n    } catch (err) {\n      if (err.returnVal) {\n        return err.data;\n      } else {\n        throw err;\n      }\n    }\n  };\n\n  return fn;\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"THROW\"] = function (node, scope, simulate) {\n  throw new ModelError(evaluateNode(node.children[0], scope, simulate), {\n    code: 10000\n  });\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"TRYCATCH\"] = function (node, scope, simulate) {\n  try {\n    return evaluateNode(node.children[0], scope, simulate);\n  } catch (err) {\n\n    /** @type {Map} */\n    let localScope = new Map([[ PARENT_SYMBOL, scope ]]);\n    if (err instanceof ModelError) {\n      localScope.set(node.children[2].text, stringify(err.message, simulate));\n    } else {\n      localScope.set(node.children[2].text, stringify(\"An error has occurred.\", simulate));\n    }\n    return evaluateNode(node.children[1], localScope, simulate);\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"WHILE\"] = function (node, scope, simulate) {\n  let lastResult = new Material(0);\n\n  let innerScope = new Map([[ PARENT_SYMBOL, scope ]]);\n  while (trueValue(toNum(evaluateNode(node.children[0], scope, simulate)))) {\n    lastResult = evaluateNode(node.children[1], innerScope, simulate);\n  }\n  return lastResult;\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"IFTHENELSE\"] = function (node, scope, simulate) {\n\n  let innerScope = new Map([[ PARENT_SYMBOL, scope ]]);\n  let i;\n  for (i = 0; i < node.children[0].children.length; i++) {\n    if (trueValue(toNum(evaluateNode(node.children[0].children[i], scope, simulate)))) {\n      return evaluateNode(node.children[1].children[i], innerScope, simulate);\n    }\n  }\n  if (node.children[0].children.length !== node.children[1].children.length) {\n    return evaluateNode(node.children[1].children[i], innerScope, simulate);\n  }\n\n  return new Material(0);\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"FORIN\"] = function (node, scope, simulate) {\n  let lastResult = new Material(0);\n  let id = node.children[0].text;\n\n\n  let innerScope = new Map([[ PARENT_SYMBOL, scope ]]);\n  let vec = evaluateNode(node.children[1], scope, simulate);\n  if (!(vec instanceof Vector)) {\n    throw new ModelError(\"The in argument of a For-In loop must be a vector.\", {\n      code: 7050\n    });\n  }\n  for (let i = 0; i < vec.items.length; i++) {\n    innerScope.set(id, vec.items[i]);\n    lastResult = evaluateNode(node.children[2], innerScope, simulate);\n  }\n  return lastResult;\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"FOR\"] = function (node, scope, simulate) {\n  let lastResult = new Material(0);\n  let id = node.children[0].text;\n  let start = toNum(evaluateNode(node.children[1].children[0], scope, simulate));\n  if (!(start instanceof Material)) {\n    throw new ModelError(\"The start value of a For loop must be a number.\", {\n      code: 7068\n    });\n  }\n\n  let by = new Material(1, start.units);\n\n  if (node.children[1].children.length === 3) {\n    by = toNum(evaluateNode(node.children[1].children[2], scope, simulate));\n  }\n  if (!(by instanceof Material)) {\n    throw new ModelError(\"The step size of a For loop must be a number.\", {\n      code: 7069\n    });\n  }\n  if (by.value === 0) {\n    throw new ModelError(\"The step size of a For loop must not be 0.\", {\n      code: 7070\n    });\n  }\n  /** @type {Map} */\n  let innerScope = new Map([[ PARENT_SYMBOL, scope ]]);\n\n  innerScope.set(id, start);\n  let compare = by.value > 0 ? lessThanEq : greaterThanEq;\n  while (true) {\n    let end = toNum(evaluateNode(node.children[1].children[1], scope, simulate));\n    if (!(end instanceof Material)) {\n      throw new ModelError(\"The end value of a For loop must be a number.\", {\n        code: 7071\n      });\n    }\n    if (!compare(innerScope.get(id), end, node.children[1].children[0], node.children[1].children[1])) {\n      break;\n    }\n    lastResult = evaluateNode(node.children[2], innerScope, simulate);\n    innerScope.set(id, plus(innerScope.get(id), by));\n  }\n  return lastResult;\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"FUNCTION\"] = function (node, scope, simulate) {\n  let id = node.children[0].children[0].text;\n\n  functionGenerator(id, node.children[0], node.children[1], node.children[2], scope, simulate);\n\n  return `\"${id}\" defined`;\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"ANONFUNCTION\"] = function (node, scope, simulate) {\n  return functionGenerator(null, node.children[0], node.children[1], node.children[2], scope, simulate);\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"ASSIGN\"] = function (node, scope, simulate) {\n  let items = node.children.length - 1;\n  let x = evaluateNode(node.children[node.children.length - 1], scope, simulate);\n  if (items > 1 && (!(x instanceof Vector) || x.items.length < items)) {\n    throw new ModelError(\"Too few elements returned for assignment.\", {\n      code: 7051\n    });\n  }\n  for (let i = 0; i < items; i++) {\n    if (node.children[i] instanceof PrimitiveStore) {\n      if (items === 1) {\n        node.children[i].primitive.setValue(x);\n      } else {\n        node.children[i].primitive.setValue(x.items[i]);\n      }\n    } else {\n      let varName = node.children[i].children[0].text;\n      let selector;\n      if (node.children[i].children.length > 1) {\n        selector = createSelector(node.children[i].children[1], scope, simulate);\n      }\n\n      let origScope = scope;\n      while (scope.get(PARENT_SYMBOL) !== null) {\n        if (scope.has(varName)) {\n          break;\n        }\n        scope = scope.get(PARENT_SYMBOL);\n      }\n      if (scope.get(PARENT_SYMBOL) === null && !scope.has(varName)) {\n        scope = origScope;\n      }\n\n      let v;\n      if (items === 1) {\n        v = x;\n      } else {\n        v = x.items[i];\n      }\n      if (node.children[i].children.length === 1) {\n        scope.set(varName,  v);\n      } else {\n        if (scope.has(varName)) {\n          selectFromMatrix(scope.get(varName), simulate, selector, v);\n        } else {\n          throw new ModelError(`The variable '${node.children[i].children[0].origText}' does not exist.`, {\n            code: 7052\n          });\n        }\n      }\n    }\n  }\n  if (items > 1) {\n    return new Vector(x.items.slice(0, items), simulate);\n  } else {\n    return x;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfunction createSelector(node, scope, simulate) {\n  if (node.children[0].typeName === \"DOTSELECTOR\") {\n    let res = [];\n    for (let i = 0; i < node.children[0].children.length; i++) {\n      if (node.children[0].children[i].text) {\n        res.push(node.children[0].children[i].text);\n      } else {\n        res.push(node.children[0].children[i].valueOf());\n      }\n    }\n    return res;\n  } else {\n    return createMatrixSelector(node, scope, 0, simulate);\n  }\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfuncEvalMap[\"MATERIAL\"] = function (node, scope, simulate) {\n  let v = toNum(evaluateNode(node.children[0], scope, simulate));\n  if (v.units) {\n    throw new ModelError(\"Cannot create material where numeric part itself has units.\", {\n      code: 7053\n    });\n  }\n  return new Material(v.value, node.children[1]);\n};\n\n/**\n * @param {string} varName\n * @param {TreeNode} paramNames\n * @param {*} paramDefaults\n * @param {*} code\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfunction functionGenerator(varName, paramNames, paramDefaults, code, scope, simulate) {\n  let varNames = [];\n  let varDefaults = [];\n  for (let i = varName === null ? 0 : 1; i < paramNames.children.length; i++) {\n    varNames.push(paramNames.children[i].text);\n  }\n\n  for (let i = 0; i < paramDefaults.children.length; i++) {\n    varDefaults.push(paramDefaults.children[i]);\n  }\n  if (varName === null) {\n    return makeFunctionCall(\"Function\", varNames, varDefaults, code, scope, simulate);\n  } else {\n    scope.set(varName, makeFunctionCall(varName, varNames, varDefaults, code, scope, simulate));\n  }\n}\n\nlet unitEvalMap = Object.create(null);\n\nunitEvalMap[\"MULT\"] = function (node) {\n  return evaluateUnits(node.children[0]).concat(evaluateUnits(node.children[1]));\n};\n\nunitEvalMap[\"POW\"] = function (node) {\n  let rhsMult = 1;\n  let rhsLoc = 1;\n  let lhsLoc = 0;\n\n  if (node.children.length === 3 + lhsLoc) {\n    rhsMult = rhsMult * -1;\n    rhsLoc++;\n  }\n  let lhs = evaluateUnits(node.children[lhsLoc]);\n  let rhs = evaluateUnits(node.children[rhsLoc]) * rhsMult;\n\n  if (lhs instanceof Array) {\n    for (let i = 0; i < lhs.length; i++) {\n      lhs[i].exponent = lhs[i].exponent * rhs;\n    }\n    return lhs;\n  } else {\n    return Math.pow(lhs, rhs);\n  }\n};\n\nunitEvalMap[\"DIV\"] = function (node) {\n  let lhs = evaluateUnits(node.children[0]);\n  let rhs = evaluateUnits(node.children[1]);\n  for (let i = 0; i < rhs.length; i++) {\n    rhs[i].exponent = rhs[i].exponent * -1;\n  }\n  return lhs.concat(rhs);\n};\n\nunitEvalMap[\"PER\"] = unitEvalMap[\"DIV\"];\n\nunitEvalMap[\"UNIT\"] = function (node) {\n  let unitName = \"\";\n  for (let i = 0; i < node.children.length; i++) {\n    unitName = unitName + node.children[i].text;\n    if (i < node.children.length - 1) {\n      unitName = unitName + \" \";\n    }\n  }\n  return [{\n    id: unitName,\n    exponent: 1\n  }];\n};\n\nunitEvalMap[\"UNITCLUMP\"] = function (node) {\n  let x = evaluateUnits(node.children[0]);\n  if (node.children.length > 1) {\n    for (let i = 1; i < node.children.length; i++) {\n      if (node.children[i].typeName === \"NEGATE\") {\n        for (let j = 0; j < x.length; j++) {\n          x[j].exponent = x[j].exponent * -1;\n        }\n      } else if (node.children[i].typeName === \"SQUARED\") {\n        for (let j = 0; j < x.length; j++) {\n          x[j].exponent = x[j].exponent * 2;\n        }\n      } else if (node.children[i].typeName === \"CUBED\") {\n        for (let j = 0; j < x.length; j++) {\n          x[j].exponent = x[j].exponent * 3;\n        }\n      }\n    }\n  }\n  return x;\n};\n\nunitEvalMap[\"INTEGER\"] = function (node) {\n  return parseInt(node.text, 10);\n};\n\nunitEvalMap[\"FLOAT\"] = function (node) {\n  return parseFloat(node.text);\n};\n\nfunction evaluateUnits(node) {\n  if (node instanceof Material) {\n    return node.value;\n  }\n\n  return unitEvalMap[node.typeName](node);\n}\n\n/**\n * @param {*} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nexport function evaluateNode(node, scope, simulate) {\n  if (node instanceof TreeNode) {\n    simulate.evaluatingPosition = node.position || simulate.evaluatingPosition;\n\n    return funcEvalMap[node.typeName](node, scope, simulate);\n  } else if (node instanceof PrimitiveStore) {\n    if (node.type === \"totalValue\") {\n      if (!node.primitive.totalContents) {\n        throw new ModelError(\"You can only use the double-bracket notation for total conveyor contents on Stock primitives.\", {\n          code: 7054\n        });\n      }\n      return node.primitive.totalContents();\n    } else if (node.type === \"object\") {\n      return node.primitive;\n    }\n  } else {\n    return node;\n  }\n}\n\nlet trimEvalMap = Object.create(null);\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"POWER\"] = function (node, scope, simulate) {\n  if (node.children.length === 1) {\n    return trimNode(node.children[0], scope, simulate);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    for (let i = 0; i < node.children.length; i++) {\n      n.children.push(trimNode(node.children[i], scope, simulate));\n    }\n    return n;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"INNER\"] = function (node, scope, simulate) {\n  if (node.children.length === 1) {\n    return trimNode(node.children[0], scope, simulate);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    for (let i = 0; i < node.children.length; i++) {\n      n.children.push(trimNode(node.children[i], scope, simulate));\n    }\n    return n;\n  }\n};\n\ntrimEvalMap[\"RANGE\"] = trimEvalMap[\"POWER\"];\ntrimEvalMap[\"TRUE\"] = function () {\n  return true;\n};\ntrimEvalMap[\"FALSE\"] = function () {\n  return false;\n};\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"STRING\"] = function (node, scope, simulate) {\n  let sub = node.origText.slice(1, node.origText.length - 1);\n  let s;\n  if (node.origText[0] === \"\\\"\") {\n    s = sub.replace(/\\\\(.)/g, (match, ch) => {\n      switch (ch) {\n      case \"\\\\\": return \"\\\\\";\n      case \"\\\"\": return \"\\\"\";\n      case \"'\": return \"'\";\n      case \"t\": return \"\\t\";\n      case \"b\": return \"\\b\";\n      case \"f\": return \"\\f\";\n      case \"n\": return \"\\n\";\n      case \"r\": return \"\\r\";\n      default:\n        // unknown, leave as-is\n        return match;\n      }\n    });\n  } else {\n    s = sub;\n  }\n  // eslint-disable-next-line\n  s = new String(s);\n  // @ts-ignore\n  s.vector = new Vector([], simulate, [], simulate.coreBank.get(\"stringbase\"));\n  return s;\n};\ntrimEvalMap[\"INTEGER\"] = function (node) {\n  return new Material(+node.text);\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"MATERIAL\"] = function (node, scope, simulate) {\n  let x = trimNode(node.children[1], scope, simulate);\n  let units = evaluateUnits(node.children[0]);\n  let exponents = [], names = [];\n  for (let i = 0; i < units.length; i++) {\n    let j = names.indexOf(units[i].id);\n    if (j === -1) {\n      exponents.push(units[i].exponent);\n      names.push(units[i].id);\n    } else {\n      exponents[j] = exponents[j] + units[i].exponent;\n    }\n  }\n  if (x instanceof Material) {\n    if (x.units) {\n      throw new ModelError(\"Cannot create material where numeric part itself has units.\", {\n        code: 7055\n      });\n    }\n    return new Material(x.value, simulate.unitManager.getUnitStore(names, exponents, true));\n  } else {\n    let m = new TreeNode(node.origText, \"MATERIAL\", node.position);\n    m.children = [x, simulate.unitManager.getUnitStore(names, exponents, true)];\n    return m;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"MULT\"] = function (node, scope, simulate) {\n\n  if (!node.children.length) {\n    return \"*\";\n  }\n\n  let lhs = trimNode(node.children[0], scope, simulate);\n  let rhs = trimNode(node.children[1], scope, simulate);\n  if (isConst(lhs) && isConst(rhs)) {\n    return mult(lhs, rhs);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    n.children = [lhs, rhs];\n    return n;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"DIV\"] = function (node, scope, simulate) {\n  let lhs = trimNode(node.children[0], scope, simulate);\n  let rhs = trimNode(node.children[1], scope, simulate);\n  if (isConst(lhs) && isConst(rhs)) {\n    return div(lhs, rhs);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    n.children = [lhs, rhs];\n    return n;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"PLUS\"] = function (node, scope, simulate) {\n  let lhs = trimNode(node.children[0], scope, simulate);\n  let rhs = trimNode(node.children[1], scope, simulate);\n  if (isConst(lhs) && isConst(rhs)) {\n    return plus(lhs, rhs, lhs, rhs, simulate);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    n.children = [lhs, rhs];\n    return n;\n  }\n};\n\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"MINUS\"] = function (node, scope, simulate) {\n  let lhs = trimNode(node.children[0], scope, simulate);\n  let rhs = trimNode(node.children[1], scope, simulate);\n  if (isConst(lhs) && isConst(rhs)) {\n    return minus(lhs, rhs, lhs, rhs);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    n.children = [lhs, rhs];\n    return n;\n  }\n};\n\ntrimEvalMap[\"FLOAT\"] = trimEvalMap[\"INTEGER\"];\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n */\ntrimEvalMap[\"PRIMITIVE\"] = function (node, scope) {\n  let res;\n  if (node.text.slice(0, 2) === \"[[\") {\n    res = new PrimitiveStore(scope.get(node.text.slice(2, node.text.length - 2)), \"totalValue\");\n  } else {\n    res = new PrimitiveStore(scope.get(node.text.slice(1, node.text.length - 1)), \"object\");\n  }\n  if (res.primitive === undefined) {\n    throw new ModelError(`The primitive <i>${sanitizeText(node.origText)}</i> could not be found.`, {\n      code: 7056\n    });\n  }\n  if (res.primitive === DUPLICATE_PRIMITIVE_NAMES) {\n    throw new ModelError(`The primitive name <i>${sanitizeText(node.origText)}</i> is ambiguous and could refer to multiple primitives.`, {\n      code: 7067\n    });\n  }\n  return res;\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"NEGATE\"] = function (node, scope, simulate) {\n  if (!node.children.length) {\n    return new TreeNode(node.origText, node.typeName, node.position);\n  }\n  let x = trimNode(node.children[0], scope, simulate);\n  if (isConst(x)) {\n    return negate(x);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    n.children = [x];\n    return n;\n  }\n};\n\n/**\n * @param {TreeNode} node\n * @param {Map} scope\n * @param {import(\"../Simulator\").Simulator} simulate\n */\ntrimEvalMap[\"ARRAY\"] = function (node, scope, simulate) {\n  let n = new TreeNode(node.origText, node.typeName, node.position);\n  let vals = [];\n  let names = [];\n  let hasName = false;\n  for (let i = 0; i < node.children.length; i++) {\n    n.children.push(trimNode(node.children[i], scope, simulate));\n    vals.push(n.children[i].children[0]);\n    if (n.children[i].children.length > 1) {\n      if (n.children[i].children[1].text) {\n        names.push(n.children[i].children[1].origText);\n      } else {\n        names.push(n.children[i].children[1].valueOf());\n      }\n      hasName = true;\n    } else {\n      names.push(undefined);\n    }\n  }\n\n  let allConst = true;\n  for (let i = 0; i < vals.length; i++) {\n    if (!isConst(vals[i])) {\n      allConst = false;\n      break;\n    }\n  }\n\n  if (allConst) {\n    n.children = [new Vector(vals, simulate, hasName ? names : undefined)];\n  }\n  return n;\n};\n\nfunction isConst(x) {\n  if (x instanceof Material || typeof x === \"string\" || x instanceof String || typeof x === \"boolean\" || x instanceof Vector) {\n    return true;\n  }\n  return false;\n}\n\n/**\n * @param {TreeNode} node\n * @param {Map} primitives\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nfunction trimNode(node, primitives, simulate) {\n  if (node.typeName in trimEvalMap) {\n    simulate.evaluatingPosition = node.position || simulate.evaluatingPosition;\n    return trimEvalMap[node.typeName](node, primitives, simulate);\n  } else {\n    let n = new TreeNode(node.origText, node.typeName, node.position);\n    for (let i = 0; i < node.children.length; i++) {\n      n.children.push(trimNode(node.children[i], primitives, simulate));\n    }\n    return n;\n  }\n}\n\n\nexport function trueValue(q) {\n  if (typeof q === \"boolean\") {\n    return q;\n  } else if (q instanceof Material) {\n    return neq(q.value, 0);\n  } else if (q instanceof Vector) {\n    throw new ModelError(\"Cannot convert a Vector to a boolean.\", {\n      code: 7057\n    });\n  } else if (typeof q === \"string\" || q instanceof String) {\n    throw new ModelError(\"Cannot convert a String to a boolean.\", {\n      code: 7058\n    });\n  } else {\n    throw new ModelError(\"Only numbers can be used in place of booleans.\", {\n      code: 7059\n    });\n  }\n}\n", "src/formula/Units.js": "import { sanitizeText } from \"../Utilities.js\";\nimport { fn } from \"../CalcMap.js\";\n\n\n\n/**\n * @param {string[]} names\n * @param {number[]} exponents\n *\n * @returns\n */\nfunction sortAndCollapseUnits(names, exponents) {\n  if (names.length <= 1) {\n    if (names.length === 1) {\n      names[0] = names[0].toLowerCase();\n    }\n  } else {\n    let sorter = [];\n    for (let i = 0; i < names.length; i++) {\n      sorter.push({\n        name: names[i].toLowerCase(),\n        exponent: exponents[i]\n      });\n    }\n    sorter.sort((a, b) => {\n      return a.name.localeCompare(b.name);\n    });\n    names = [];\n    exponents = [];\n    for (let i = 0; i < sorter.length; i++) {\n      names.push(sorter[i].name);\n      exponents.push(sorter[i].exponent);\n    }\n    for (let i = 0; i < names.length; i++) {\n      for (let j = i + 1; j < names.length; j++) {\n        if (names[i] === names[j]) {\n          exponents[i] = exponents[i] + exponents[j];\n\n          names.splice(j, 1);\n          exponents.splice(j, 1);\n\n          j--;\n        }\n      }\n\n      if (exponents[i] === 0) {\n        names.splice(i, 1);\n        exponents.splice(i, 1);\n        i--;\n      }\n    }\n  }\n\n  return { names: names, exponents: exponents };\n}\n\n\n\n/**\n * @param {string[]} names\n * @param {number[]} exponents\n *\n * @returns {string}\n */\nfunction getUnitsId(names, exponents) {\n  return names.join(\",\") + exponents.join(\",\");\n}\n\n\nexport class UnitStore {\n  /**\n   * @param {UnitManager} manager\n   * @param {string[]} names\n   * @param {number[]} exponents\n   */\n  constructor(manager, names, exponents) {\n    this.manager = manager;\n\n    this.names = names;\n\n    this.exponents = exponents;\n\n\n    /** @type {number} */\n    this.toBase = null;\n\n    /** @type {UnitStore} */\n    this.baseUnits = null;\n\n    /** @type {Map<UnitStore, [number, UnitStore, boolean]>} */\n    this.multiples = new Map();\n    /** @type {Map<UnitStore, [number, UnitStore, boolean]>} */\n    this.divisions = new Map();\n\n    this.id = getUnitsId(this.names, this.exponents);\n  }\n\n  isUnitless() {\n    return !this.exponents.find(x => x !== 0);\n  }\n\n  /**\n   * Also check if the units would simplify to unitless.\n   *\n   * @returns\n   */\n  isDeepUnitless() {\n    if (this.isUnitless()) {\n      return true;\n    }\n\n    this.addBase();\n\n    return !this.baseUnits.exponents.find(x => x !== 0);\n  }\n\n  addBase() {\n    if (this.toBase !== null) {\n      return;\n    }\n\n    this.toBase = 1;\n\n\n    let names = this.names.slice();\n    let exponents = this.exponents.slice();\n\n    let modified = true;\n    while (modified) {\n      modified = false;\n\n      for (let i = names.length - 1; i >= 0; i--) {\n        let u = this.manager.findSource(names[i]);\n        if (u !== null && !(u.target.names.length === 1 && u.target.names[0] === names[i])) {\n          this.toBase = fn[\"*\"](this.toBase, fn.expt(u.scale, exponents[i]));\n          names = names.concat(u.target.names);\n          names.splice(i, 1);\n          let exp = exponents[i];\n          exponents = exponents.concat(u.target.exponents.map((x) => {\n            return x * exp;\n          }));\n          exponents.splice(i, 1);\n          modified = true;\n          break;\n        }\n      }\n    }\n\n    let x = sortAndCollapseUnits(names, exponents);\n\n    this.baseUnits = this.manager.getUnitStore(x.names, x.exponents, false, true);\n  }\n\n  /**\n   * @param {number} exponent\n   * @returns {UnitStore}\n   */\n  power(exponent) {\n    let names = this.names.slice();\n    let exponents = this.exponents.slice();\n    for (let i = 0; i < exponents.length; i++) {\n      exponents[i] = exponents[i] * exponent;\n    }\n    return this.manager.getUnitStore(names, exponents);\n  }\n\n  /**\n   * @returns {string}\n   */\n  toStringShort() {\n    let den = [];\n    let num = [];\n    let s = \"\";\n    for (let i = 0; i < this.names.length; i++) {\n      if (this.exponents[i] > 0) {\n        num.push({ name: this.names[i], exponent: this.exponents[i] });\n      } else if (this.exponents[i] < 0) {\n        den.push({ name: this.names[i], exponent: -this.exponents[i] });\n      }\n    }\n    if (num.length > 0) {\n      s = num.map(x => x.name + (x.exponent !== 1 ? \"^\" + x.exponent : \"\")).join(\"*\");\n    } else {\n      s = \"1\";\n    }\n    if (den.length > 0) {\n      s = s + \"/\" + den.map(x => x.name + (x.exponent !== 1 ? \"^\" + x.exponent : \"\")).join(\"*\");\n    }\n\n    return s;\n  }\n\n  /**\n   * @param {UnitStore} rhs\n   * @param {boolean} multiplication (false if division)\n   *\n   * @returns {[number, UnitStore, boolean]}\n   */\n  multiply(rhs, multiplication) {\n    let exponent = multiplication ? 1 : -1;\n    let cache = multiplication ? this.multiples : this.divisions;\n\n\n    if (!cache.has(rhs)) {\n      let lhsUnits = /** @type {UnitStore} */ (this);\n      let rhsUnits = rhs;\n\n      let lhsNames = null;\n      let lhsExponents = null;\n      let rhsNames = null;\n      let rhsExponents = null;\n      for (let i = 0; i < (lhsNames || lhsUnits.names).length; i++) {\n        let j = (rhsNames || rhsUnits.names).indexOf((lhsNames || lhsUnits.names)[i]);\n        if (j > -1 && (lhsExponents || lhsUnits.exponents)[i] === (-exponent) * (rhsExponents || rhsUnits.exponents)[j]) {\n          if (!lhsNames) {\n            lhsNames = lhsUnits.names.slice();\n            lhsExponents = lhsUnits.exponents.slice();\n            rhsNames = rhsUnits.names.slice();\n            rhsExponents = rhsUnits.exponents.slice();\n          }\n          lhsNames.splice(i, 1);\n          lhsExponents.splice(i, 1);\n          rhsNames.splice(j, 1);\n          rhsExponents.splice(j, 1);\n          i--;\n        }\n      }\n\n      if (lhsNames) {\n        lhsUnits = lhsUnits.manager.getUnitStore(lhsNames, lhsExponents);\n        rhsUnits = rhsUnits.manager.getUnitStore(rhsNames, rhsExponents);\n      }\n\n      if (!lhsUnits && !rhsUnits) {\n        cache.set(rhs, [1, undefined, true]);\n        return cache.get(rhs);\n      } else if (!lhsUnits) {\n        cache.set(rhs, [1, multiplication ? rhsUnits : rhsUnits.power(-1), true]);\n        return cache.get(rhs);\n      } else if (!rhsUnits) {\n        cache.set(rhs, [1, lhsUnits, true]);\n        return cache.get(rhs);\n      }\n\n      if (lhsUnits.toBase === null) {\n        lhsUnits.addBase();\n      }\n      if (rhsUnits.toBase === null) {\n        rhsUnits.addBase();\n      }\n\n\n      let lhsBaseUnits = lhsUnits.baseUnits.names;\n      let rhsBaseUnits = rhsUnits.baseUnits.names;\n      // check if there is any overlap\n      let overlap = false;\n      for (let i = 0; i < lhsBaseUnits.length; i++) {\n        if (rhsBaseUnits.includes(lhsBaseUnits[i])) {\n          overlap = true;\n          break;\n        }\n      }\n\n      if (!overlap) {\n        let newUnits = lhsUnits.manager.getUnitStore(\n          lhsUnits.names.concat(rhsUnits.names),\n          lhsUnits.exponents.concat(multiplication ? rhsUnits.exponents : rhsUnits.exponents.map(x => -x))\n        );\n        cache.set(rhs, [1, newUnits, true]);\n        return cache.get(rhs);\n      }\n\n\n\n      let names;\n      let exponents;\n      if (lhsUnits.baseUnits) {\n        names = lhsUnits.baseUnits.names.slice();\n        exponents = lhsUnits.baseUnits.exponents.slice();\n\n\n        if (rhsUnits.baseUnits) {\n          for (let i = 0; i < rhsUnits.baseUnits.names.length; i++) {\n            let j = names.indexOf(rhsUnits.baseUnits.names[i]);\n            if (j !== -1) {\n              exponents[j] = exponents[j] + rhsUnits.baseUnits.exponents[i] * exponent;\n            } else {\n              let found = false;\n              for (let k = 0; k < names.length; k++) {\n                if (rhsUnits.baseUnits.names[i] < names[k]) {\n                  names.splice(k, 0, rhsUnits.baseUnits.names[i]);\n                  exponents.splice(k, 0, rhsUnits.baseUnits.exponents[i] * exponent);\n                  found = true;\n                  break;\n                }\n              }\n              if (!found) {\n                names.push(rhsUnits.baseUnits.names[i]);\n                exponents.push(rhsUnits.baseUnits.exponents[i] * exponent);\n              }\n            }\n          }\n\n          for (let i = exponents.length - 1; i >= 0; i--) {\n            if (exponents[i] === 0) {\n              exponents.splice(i, 1);\n              names.splice(i, 1);\n            }\n          }\n        }\n      } else {\n        names = rhsUnits.baseUnits.names.slice();\n        exponents = rhsUnits.baseUnits.exponents.slice();\n      }\n      let newUnits = this.manager.getUnitStore(names, exponents);\n      cache.set(rhs, [\n        multiplication ? fn[\"*\"](lhsUnits.toBase, rhsUnits.toBase) : fn[\"/\"](lhsUnits.toBase, rhsUnits.toBase),\n        newUnits,\n        !newUnits\n      ]);\n    }\n\n    return cache.get(rhs);\n  }\n\n  /**\n   * @returns {string}\n   */\n  toString() {\n    let n = \"\",\n      den = \"\";\n    let numItems = 0,\n      denItems = 0;\n    for (let i = 0; i < this.names.length; i++) {\n      if (this.names[i] !== \"\") {\n        let item = \"<span class=\\\"unit\\\">\" + sanitizeText(toTitleCase(this.names[i])) + \"</span>\";\n        if (this.exponents[i] !== 1 && this.exponents[i] !== -1) {\n          item = item + \"<span class='markup'>^</span><sup>\" + Math.abs(this.exponents[i]) + \"</sup>\";\n        }\n        if (this.exponents[i] > 0) {\n          if (numItems > 0) {\n            n = n + \"<span class='markup'>*</span>\";\n          }\n          n = n + item;\n          numItems = numItems + 1;\n        } else {\n          if (denItems > 0) {\n            den = den + \"<span class='markup'>*</span>\";\n          }\n          den = den + item;\n          denItems = denItems + 1;\n        }\n      }\n    }\n\n\n    if (n === \"\") {\n      n = \"Unitless\";\n    }\n    if (den === \"\") {\n      return \"<div class=\\\"units\\\">\" + n + \"</div>\";\n    } else {\n      if (n === \"Unitless\") {\n        n = \"1\";\n      }\n      return \"<span class=\\\"units\\\">\" + n + \"<hr/><span class='markup'>/(</span>\" + den + \"<span class='markup'>)</span></span>\";\n    }\n  }\n\n}\n\n\n\nconst titleCaseReg = /\\w\\S*/g;\n/**\n * @param {string} txt\n *\n * @returns {string}\n */\nfunction titleCaseFunc(txt) {\n  return txt[0].toUpperCase() + txt.slice(1).toLowerCase();\n}\n\n\n/**\n * @param {string} str\n *\n * @returns {string}\n */\nfunction toTitleCase(str) {\n  return str.replace(titleCaseReg, titleCaseFunc);\n}\n\n\n/**\n * @param {UnitStore} source\n * @param {UnitStore} target\n * @param {boolean=} allowUnitApplication\n *\n * @returns {number}\n */\nexport function convertUnits(source, target, allowUnitApplication = false) {\n  if (source === target) {\n    return 1;\n  }\n\n  let sourceUnitless = !source || source.isUnitless();\n  let targetUnitless = !target || target.isUnitless();\n\n  if (sourceUnitless && targetUnitless) {\n    return 1;\n  }\n\n  if (!sourceUnitless && targetUnitless) {\n    if (source.isDeepUnitless()) {\n      return source.toBase;\n    }\n\n    return 0;\n  }\n\n  if (sourceUnitless && !targetUnitless) {\n    if (allowUnitApplication) {\n      // we apply the target units onto the unitless source\n      return 1;\n    }\n\n    if (target.isDeepUnitless()) {\n      return fn[\"/\"](1, target.toBase);\n    }\n\n\n    return 0;\n  }\n\n  if (source.toBase === null) {\n    source.addBase();\n  }\n  if (target.toBase === null) {\n    target.addBase();\n  }\n\n  if (source.baseUnits !== target.baseUnits) {\n    return 0;\n  }\n\n  return fn[\"/\"](source.toBase, target.toBase);\n}\n\n\n/**\n * @typedef {object} UnitDefinition\n * @property {string=} sourceString\n * @property {RegExp=} source\n * @property {string=} targetString\n * @property {UnitStore=} target\n * @property {number} scale\n */\n\n/** @type {UnitDefinition[]} */\nconst DEFAULT_UNITS = [\n  {\n    \"source\": /^Degree$/i,\n    \"targetString\": \"Degrees\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Radians?$/i,\n    \"targetString\": \"Degrees\",\n    \"scale\": 180 / Math.PI\n  },\n  {\n    \"source\": /^Ampere$/i,\n    \"targetString\": \"Amperes\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Gram$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Second$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Meter$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Meters? ?Squared?|Squared? ?Meters?)$/i,\n    \"targetString\": \"Meters^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Centimeters? ?Squared?|Squared? ?Centimeters?)$/i,\n    \"targetString\": \"Centimeters^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Centimeters? ?Cubed?|Cubic ?Centimeters?)$/i,\n    \"targetString\": \"Centimeters^3\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Meters? Cubed?|Cubic ?Meters?)$/i,\n    \"targetString\": \"Meters^3\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Kilometers? ?Cubed?|Cubic ?Kilometers?)$/i,\n    \"targetString\": \"Kilometers^3\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Inches? Squared?|Squared? ?Inches?)$/i,\n    \"targetString\": \"Inches^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Miles? ?Squared?|Squared? ?Miles?)$/i,\n    \"targetString\": \"Miles^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Kilometers? Squared?|Squared? ?Kilometers?)$/i,\n    \"targetString\": \"Kilometers^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Acre? ?(Feet|Foot)$/i,\n    \"targetString\": \"Acres,Feet\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Meters? ?per ?Seconds?$/i,\n    \"targetString\": \"Meters,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Meters? ?per ?Seconds? ?Squared?$/i,\n    \"targetString\": \"Meters,Seconds^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Foot|Feet) ?per ?Seconds?$/i,\n    \"targetString\": \"Feet,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Foot|Feet) ?per ?Seconds? ?Squared?$/i,\n    \"targetString\": \"Feet,Seconds^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Miles? ?per ?Hours?$/i,\n    \"targetString\": \"Miles,Hours^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Miles? ?per ?Hours? ?Squared?$/i,\n    \"targetString\": \"Miles,Hours^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Kilometers? ?per ?Hours?$/i,\n    \"targetString\": \"Kilometers,Hours^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Kilometers? ?per ?Hours? ?Squared?$/i,\n    \"targetString\": \"Kilometers,Hours^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Liters? ?per ?Seconds?$/i,\n    \"targetString\": \"Liters,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Cubic ?Meters?|Meters? ?Cubed?) ?per ?Seconds?$/i,\n    \"targetString\": \"Meters^3,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Squared? ?Yards?|Yards? ?Squared?)$/i,\n    \"targetString\": \"Yards^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Squared? ?(Feet|Foot)|(Feet|Foot) ?Squared?)$/i,\n    \"targetString\": \"Feet^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Squared? Millimeters?|Millimeters? ?Squared?)$/i,\n    \"targetString\": \"Millimeters^2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^(Millimeters? ?Cubed?|Cubic ?Millimeters?)$/i,\n    \"targetString\": \"Millimeters^3\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Gallons? ?per ?Seconds?$/i,\n    \"targetString\": \"Gallons,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Gallons? ?per ?Minutes?$/i,\n    \"targetString\": \"Gallons,Minutes^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Pounds? ?per ?Seconds?$/i,\n    \"targetString\": \"Pounds,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Kilograms? ?per ?Seconds?$/i,\n    \"targetString\": \"Kilograms,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Seconds?$/i,\n    \"targetString\": \"Dollars,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Hours?$/i,\n    \"targetString\": \"Dollars,Hours^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Days?$/i,\n    \"targetString\": \"Dollars,Days^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Weeks?$/i,\n    \"targetString\": \"Dollars,Weeks^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Months?$/i,\n    \"targetString\": \"Dollars,Months^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Quarters?$/i,\n    \"targetString\": \"Dollars,Quarters^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Dollars? ?per ?Years?$/i,\n    \"targetString\": \"Dollars,Years^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Seconds?$/i,\n    \"targetString\": \"Euros,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Hours?$/i,\n    \"targetString\": \"Euros,Hours^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Days?$/i,\n    \"targetString\": \"Euros,Days^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Weeks?$/i,\n    \"targetString\": \"Euros,Weeks^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Months?$/i,\n    \"targetString\": \"Euros,Months^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Quarters?$/i,\n    \"targetString\": \"Euros,Quarters^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Euros? ?per ?Years?$/i,\n    \"targetString\": \"Euros,Years^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Centimeters?$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 0.01\n  },\n  {\n    \"source\": /^Millimeters?$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 0.001\n  },\n  {\n    \"source\": /^Kilometers?$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 1000\n  },\n  {\n    \"source\": /^Inch(es)?$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 0.0254\n  },\n  {\n    \"source\": /^(Foot|Feet)$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 0.3048\n  },\n  {\n    \"source\": /^Yards?$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 0.9144\n  },\n  {\n    \"source\": /^Miles?$/i,\n    \"targetString\": \"Meters\",\n    \"scale\": 1609.344\n  },\n  {\n    \"source\": /^Acres?$/i,\n    \"targetString\": \"Meters^2\",\n    \"scale\": 4046.85642\n  },\n  {\n    \"source\": /^Hectares?$/i,\n    \"targetString\": \"Meters^2\",\n    \"scale\": 10000\n  },\n  {\n    \"source\": /^Liters?$/i,\n    \"targetString\": \"Meters^3\",\n    \"scale\": 0.001\n  },\n  {\n    \"source\": /^Gallons?$/i,\n    \"targetString\": \"Meters^3\",\n    \"scale\": 0.003785\n  },\n  {\n    \"source\": /^Quarts?$/i,\n    \"targetString\": \"Meters^3\",\n    \"scale\": 0.000946\n  },\n  {\n    \"source\": /^Fluid ?Ounces?$/i,\n    \"targetString\": \"Meters^3\",\n    \"scale\": 0.00003\n  },\n  {\n    \"source\": /^Years?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 31536000\n  },\n  {\n    \"source\": /^Quarters?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 7884000\n  },\n  {\n    \"source\": /^Months?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 2628000\n  },\n  {\n    \"source\": /^Weeks?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 604800\n  },\n  {\n    \"source\": /^Days?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 86400\n  },\n  {\n    \"source\": /^Hours?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 3600\n  },\n  {\n    \"source\": /^Minutes?$/i,\n    \"targetString\": \"Seconds\",\n    \"scale\": 60\n  },\n  {\n    \"source\": /^Kilograms?$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 1000\n  },\n  {\n    \"source\": /^Milligrams?$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 0.001\n  },\n  {\n    \"source\": /^Ounces?$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 28.349523\n  },\n  {\n    \"source\": /^Pounds?$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 453.59237\n  },\n  {\n    \"source\": /^Tonnes?$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 1000000\n  },\n  {\n    \"source\": /^Tons?$/i,\n    \"targetString\": \"Grams\",\n    \"scale\": 907184.74\n  },\n  {\n    \"source\": /^Watts?$/i,\n    \"targetString\": \"Joules,Seconds^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Kilowatts?$/i,\n    \"targetString\": \"Watts\",\n    \"scale\": 1000\n  },\n  {\n    \"source\": /^Megawatts?$/i,\n    \"targetString\": \"Watts\",\n    \"scale\": 1000000\n  },\n  {\n    \"source\": /^Gigawatts?$/i,\n    \"targetString\": \"Watts\",\n    \"scale\": 1000000000\n  },\n  {\n    \"source\": /^Calories?$/i,\n    \"targetString\": \"Joules\",\n    \"scale\": 4.184\n  },\n  {\n    \"source\": /^Kilocalories?$/i,\n    \"targetString\": \"Joules\",\n    \"scale\": 4184\n  },\n  {\n    \"source\": /^(BTUs?|British ?Thermal ?units?)$/i,\n    \"targetString\": \"Joules\",\n    \"scale\": 1055.05585\n  },\n  {\n    \"source\": /^Kilojoules?$/i,\n    \"targetString\": \"Joules\",\n    \"scale\": 1000\n  },\n  {\n    \"source\": /^Joules?$/i,\n    \"targetString\": \"Newtons,Meters\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Coulombs?$/i,\n    \"targetString\": \"Amperes,Seconds\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Volts?$/i,\n    \"targetString\": \"Watts,Amperes^-1\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Millivolts?$/i,\n    \"targetString\": \"Volts\",\n    \"scale\": 0.001\n  },\n  {\n    \"source\": /^Kilovolts?$/i,\n    \"targetString\": \"Volts\",\n    \"scale\": 1000\n  },\n  {\n    \"source\": /^Newtons?$/i,\n    \"targetString\": \"Kilograms,Meters,Seconds^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Pounds? ?Force$/i,\n    \"targetString\": \"Pounds,Feet per Second Squared\",\n    \"scale\": 32.17405\n  },\n  {\n    \"source\": /^Atoms?$/i,\n    \"targetString\": \"Moles\",\n    \"scale\": 1 / 6.02214076e23\n  },\n  {\n    \"source\": /^Molecules?$/i,\n    \"targetString\": \"Moles\",\n    \"scale\": 1 / 6.02214076e23\n  },\n  {\n    \"source\": /^Farads?$/i,\n    \"targetString\": \"Joules,Volts^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Pascals?$/i,\n    \"targetString\": \"Newton,Meters^-2\",\n    \"scale\": 1\n  },\n  {\n    \"source\": /^Kilopascals?$/i,\n    \"targetString\": \"Pascals\",\n    \"scale\": 1000\n  },\n  {\n    \"source\": /^Bars?$/i,\n    \"targetString\": \"Pascals\",\n    \"scale\": 100000\n  },\n  {\n    \"source\": /^Atmospheres?$/i,\n    \"targetString\": \"Pascals\",\n    \"scale\": 101325\n  },\n  {\n    \"source\": /^Pounds? ?per ?Squared? ?Inch(es)?$/i,\n    \"targetString\": \"Pascals\",\n    \"scale\": 6894\n  }\n];\n\n\n\n\nexport class UnitManager {\n  constructor() {\n    /** @type {UnitDefinition[]} */\n    this.unitDefinitions = [];\n\n    /** @type {Object<string, UnitDefinition>} */\n    this.cachedUnits = Object.create(null);\n\n    /**\n     * @type {Object<string, UnitStore>}\n     */\n    this.unitsBank = Object.create(null);\n\n    this.addUnits(DEFAULT_UNITS);\n  }\n\n\n  /**\n   * @param {UnitDefinition[]} units\n   */\n  addUnits(units) {\n    for (let unit of units) {\n      if (!unit.source) {\n        unit.source = new RegExp(\"^\" + unit.sourceString + \"$\", \"i\");\n      }\n      if (!unit.target) {\n        unit.target = this.unitsFromString(unit.targetString.toLowerCase());\n      }\n    }\n\n    this.unitDefinitions = units.concat(this.unitDefinitions);\n  }\n\n\n  /**\n   * @param {string} name\n   *\n   * @returns {UnitDefinition}\n   */\n  findSource(name) {\n    if (!(name in this.cachedUnits)) {\n      this.cachedUnits[name] = null;\n\n      for (let i = this.unitDefinitions.length - 1; i >= 0; i--) {\n        if (this.unitDefinitions[i].source.test(name)) {\n          this.cachedUnits[name] = this.unitDefinitions[i];\n\n          break;\n        }\n      }\n    }\n\n\n    return this.cachedUnits[name];\n  }\n\n  /**\n   * @param {string[]} names\n   * @param {number[]} exponents\n   * @param {boolean=} checkNames\n   * @param {boolean=} alwaysReturn - units must be returned, when calling setBase\n   *\n   * @returns {UnitStore}\n   */\n  getUnitStore(names, exponents, checkNames = false, alwaysReturn = false) {\n    if (checkNames) {\n      let x = sortAndCollapseUnits(names, exponents);\n      names = x.names;\n      exponents = x.exponents;\n    }\n\n    if (!alwaysReturn && !names.length) {\n      return;\n    }\n\n    let id = getUnitsId(names, exponents);\n\n    if (!this.unitsBank[id]) {\n      this.unitsBank[id] = new UnitStore(this, names, exponents);\n    }\n\n    return this.unitsBank[id];\n  }\n\n\n  /**\n   * @param {string} expandString\n   *\n   * @returns {UnitStore}\n   */\n  unitsFromString(expandString) {\n    let names = [];\n    let exponents = [];\n    if (expandString) {\n      let expandItems = expandString.split(\",\");\n      for (let j = 0; j < expandItems.length; j++) {\n        names.push(expandItems[j].split(\"^\")[0]);\n        if (expandItems[j].indexOf(\"^\") !== -1) {\n          exponents.push(parseFloat(expandItems[j].split(\"^\")[1]));\n        } else {\n          exponents.push(1);\n        }\n      }\n    }\n    return this.getUnitStore(names, exponents, true);\n  }\n}\n\n", "src/formula/Vector.js": "import { toNum } from \"./Formula.js\";\nimport { Material } from \"./Material.js\";\nimport { ModelError } from \"./ModelError.js\";\nimport { selectFromMatrix, strictEquals } from \"./Utilities.js\";\n\n\n/** @typedef {import(\"../SharedTypes.js\").VectorElementType} VectorElementType */\n\n/**\n * Truncates to max length adding ellipsis if truncated. If text is only 2 or fewer characters longer than maxLength, it will not be truncated.\n *\n * @param {string} string\n * @param {number} maxLength\n */\nfunction truncate(string, maxLength) {\n  if (string.length > maxLength + 2) {\n    return string.substring(0, maxLength - 3) + \"...\";\n  }\n  return string;\n}\n\n/**\n * @param {string[]} thisNames\n * @param {string[]} keys\n *\n * @returns {boolean}\n */\nfunction keysMatch(thisNames, keys) {\n  if (!keys.includes(\"*\")) {\n    for (let i = 0; i < thisNames.length; i++) {\n      if (thisNames[i] !== \"*\") {\n        if (thisNames[i] === undefined) {\n          return false;\n        }\n        if (!keys.includes(thisNames[i])) {\n          return false;\n        }\n      }\n    }\n  }\n\n  if (!thisNames.includes(\"*\")) {\n    for (let i = 0; i < keys.length; i++) {\n      if (keys[i] !== \"*\") {\n        if (keys[i] === undefined) {\n          return false;\n        }\n        if (!thisNames.includes(keys[i])) {\n          return false;\n        }\n      }\n    }\n  }\n\n  return true;\n}\n\n\n/** @template {any} T */\nexport class Vector {\n  /**\n   * @param {T[]} items\n   * @param {import(\"../Simulator\").Simulator} simulate\n   * @param {string[]=} names\n   * @param {Vector=} parent\n   */\n  constructor(items, simulate, names, parent) {\n    this.simulate = simulate;\n\n    this.parent = parent ? parent : simulate.coreBank.get(\"vectorbase\");\n    this.items = items;\n    /** @type {string[]} */\n    this.names = names;\n    /** @type {string[]} */\n    this.namesLC = undefined;\n    /** @type {boolean} */\n    this.isNum = undefined;\n    /** @type {boolean} */\n    this.terminateApply = undefined;\n\n    if (names) {\n      this.namesLC = [];\n      for (let name of names) {\n        if (name) {\n          this.namesLC.push(name.toLowerCase());\n        } else {\n          this.namesLC.push(undefined);\n        }\n      }\n    }\n\n  }\n\n  toNum() {\n    if (this.isNum) {\n      return this;\n    }\n\n    let v = this.fullClone();\n    for (let i = 0; i < v.items.length; i++) {\n      v.items[i] = toNum(v.items[i]);\n    }\n    v.isNum = true;\n    return v;\n  }\n\n  /**\n   * @returns {string}\n   */\n  toString() {\n    let items = [];\n    for (let i = 0; i < this.items.length; i++) {\n      try {\n        let str = toNum(this.items[i]).toString();\n        if (this.names && this.names[i]) {\n          str = this.names[i] + \": \" + str;\n        }\n        items.push(str);\n      } catch (err) {\n        items.push(\"{Cannot convert value to string}\");\n      }\n    }\n    return \"{\" + items.join(\", \") + \"}\";\n  }\n\n  /**\n   * @returns {number}\n   */\n  length() {\n    return this.items.length;\n  }\n\n  cloneCombine(other, operation, rhs, noSwitch) {\n    return this.fullClone().combine(other, operation, rhs, noSwitch);\n  }\n\n  combine(other, operation, rhs, noSwitch) {\n    if (other instanceof Vector) {\n      if (this.length() !== other.length() && (!this.names || !other.names)) {\n        throw new ModelError(`Vectors must have equal length when combined. Got lengths of ${this.length()} and ${other.length()}.`, {\n          code: 2001\n        });\n      }\n    }\n\n    if (other instanceof Vector && (this.names && other.names)) {\n      if (!noSwitch && other.depth() > this.depth()) {\n        return other.combine(this, operation, !rhs);\n      }\n      if (!this.keysMatch(other.namesLC)) {\n        if (this.items[0] instanceof Vector) {\n          for (let i = 0; i < this.items.length; i++) {\n            /** @type {Vector} */ (this.items[i]).combine(other, operation, rhs, true);\n          }\n          return this;\n        } else {\n          throw new ModelError(`Keys do not match for vector operation. Got keys {${truncate(this.names.map(x => \"\\\"\" + x +\"\\\"\").join(\", \"), 36)}} and {${truncate(other.names.map(x => \"\\\"\" + x +\"\\\"\").join(\", \"), 36)}}.`, {\n            code: 2000\n          });\n        }\n      }\n    }\n\n    for (let i = 0; i < this.length(); i++) {\n      let x;\n      if (other instanceof Vector) {\n        if (this.names && other.names) {\n          let index = other.namesLC.indexOf(this.namesLC[i]);\n          if (this.names.length === 1 && this.names[0] === \"*\") {\n            index = -2;\n          }\n          if (index === -1) {\n            index = other.names.indexOf(\"*\");\n          }\n          if (index === -1) {\n            throw new ModelError(\"Mismatched keys for vector operation.\", {\n              code: 2002\n            });\n          }\n          if (index === -2) {\n            x = undefined;\n          } else {\n            x = other.items[index];\n          }\n        } else {\n          x = other.items[i];\n        }\n      } else {\n        x = other;\n      }\n      if (x !== undefined) {\n        if (rhs) {\n          this.items[i] = operation(x, this.items[i]);\n        } else {\n          this.items[i] = operation(this.items[i], x);\n        }\n      }\n    }\n\n    if (this.names && this.names.includes(\"*\") && other instanceof Vector && other.names) {\n      let starred = this.items[this.names.indexOf(\"*\")];\n      for (let i = 0; i < other.names.length; i++) {\n        if (other.names[i] && (!this.namesLC.includes(other.namesLC[i]))) {\n\n          if (rhs) {\n            this.items.push(operation(other.items[i], starred));\n          } else {\n            this.items.push(operation(starred, other.items[i]));\n          }\n          this.names.push(other.names[i]);\n          this.namesLC.push(other.namesLC[i]);\n        }\n      }\n    }\n\n    return this;\n  }\n\n  collapseDimensions(target) {\n    if (target instanceof Vector) {\n      if (this.depth() === target.depth()) {\n        return this;\n      } else {\n        let selector = [];\n        /** @type {Vector} */\n        let base = this;\n        let targetLevel = target;\n        for (let i = 0; i < this.depth(); i++) {\n          if (!(targetLevel instanceof Vector)) {\n            selector.push((x) => {\n              return this.simulate.coreBank.get(\"sum\")(x[0].items);\n            });\n            base = /** @type {Vector} */ (base.items[0]);\n          } else if ((base.namesLC === undefined && targetLevel.namesLC === undefined) || (base.namesLC !== undefined && targetLevel.namesLC !== undefined && keysMatch(base.namesLC, targetLevel.namesLC))) {\n            selector.push(\"*\");\n            base =  /** @type {Vector} */ (base.items[0]);\n            targetLevel =  /** @type {Vector} */ (targetLevel.items[0]);\n          } else {\n            selector.push((x) => {\n              return this.simulate.coreBank.get(\"sum\")(x[0].items);\n            });\n\n            base =  /** @type {Vector} */ (base.items[0]);\n          }\n        }\n        if (targetLevel.items) {\n          throw new ModelError(\"Keys do not match for vector collapsing.\", {\n            code: 2003\n          });\n        }\n        return selectFromMatrix(this, this.simulate, selector);\n      }\n    } else {\n      return this.simulate.coreBank.get(\"sum\")([this.simulate.coreBank.get(\"flatten\")([this])]);\n    }\n  }\n\n  /**\n   * @returns {number}\n   */\n  depth() {\n    if (!this.items.length) {\n      return 1;\n    }\n    let firstItem = this.items[0];\n    if (firstItem instanceof Vector) {\n      return firstItem.depth() + 1;\n    }\n    return 1;\n  }\n\n  /**\n   * @param {string[]} keys\n   */\n  keysMatch(keys) {\n    if (this.names && keys) {\n      return keysMatch(this.namesLC, keys);\n    }\n    return false;\n  }\n\n  /**\n   * @param {function} operation\n   * @returns\n   */\n  cloneApply(operation) {\n    return this.fullClone().apply(operation);\n  }\n\n  /**\n   * @param {function} operation\n   * @returns\n   */\n  apply(operation) {\n    for (let i = 0; i < this.items.length; i++) {\n      this.items[i] = operation(this.items[i], this.names ? this.names[i] : undefined);\n    }\n    return this;\n  }\n\n  /**\n   * @param {function(Vector): any} operation\n   *\n   * @returns {Vector}\n   */\n  stackApply(operation) {\n    if (this.depth() === 1) {\n      return operation(this);\n    }\n    let s = this.stack();\n\n    return s.recurseApply(operation);\n  }\n\n  /**\n   * @param {any[]=} selector\n   *\n   * @returns\n   */\n  stack(selector) {\n    let res = [];\n\n    selector = selector || [0];\n\n    let base = /** @type {Vector} */ (this.select(selector));\n\n\n    for (let i = 1; i < this.items.length; i++) {\n      selector[0] = i;\n      let alt = this.select(selector);\n      if (base instanceof Vector && alt instanceof Vector) {\n        if ((base.names && !alt.names) || (alt.names && !base.names)) {\n          throw new ModelError(\"Mismatched keys for vector collapsing.\", {\n            code: 2004\n          });\n        } else if (base.items.length !== alt.items.length) {\n          throw new ModelError(\"Vectors of unequal size.\", {\n            code: 2005\n          });\n        }\n      } else if (!(base instanceof Vector || alt instanceof Vector)) {\n        throw new ModelError(\"Mismatched keys for vector collapsing.\", {\n          code: 2006\n        });\n      }\n    }\n    selector[0] = 0;\n\n    selector.push(0);\n\n    for (let i = 0; i < base.items.length; i++) {\n      selector[selector.length - 1] = base.names ? base.namesLC[i] : i;\n\n      if (base.items[i] instanceof Vector) {\n        res.push(this.stack(selector.slice()));\n      } else {\n        let vecs = [];\n        for (let j = 0; j < this.items.length; j++) {\n          let newSelector = selector.slice();\n          newSelector[0] = j;\n\n          let item = this.select(newSelector);\n          if (item instanceof Vector) {\n            throw new ModelError(\"Number where vector expected in vector collapsing.\", {\n              code: 2007\n            });\n          }\n          vecs.push(item);\n        }\n        let v = new Vector(vecs, this.simulate);\n        v.terminateApply = true;\n        res.push(v);\n      }\n    }\n\n    return new Vector(res, this.simulate, base.names ? base.names.slice() : undefined);\n  }\n\n\n  select(selector) {\n    /** @type {VectorElementType} */\n    let b = this;\n\n    for (let s = 0; s < selector.length; s++) {\n      if (!(b instanceof Vector)) {\n        throw new ModelError(\"Number where vector expected in vector collapsing.\", {\n          code: 2008\n        });\n      }\n\n      if (selector[s] instanceof String || typeof selector[s] === \"string\") {\n        let ind = b.namesLC.indexOf(selector[s].valueOf());\n        if (ind === -1) {\n          throw new ModelError(\"Mismatched keys for vector collapsing.\", {\n            code: 2009\n          });\n        }\n        b = b.items[ind];\n      } else {\n        b = b.items[selector[s]];\n      }\n    }\n    return b;\n  }\n\n  /**\n   * @param {function} operation\n   *\n   * @returns {Vector}\n   */\n  recurseApply(operation) {\n    for (let i = 0; i < this.items.length; i++) {\n      let item = this.items[i];\n      if (item instanceof Vector && !item.terminateApply) {\n        this.items[i] = /** @type {any} */ (item.recurseApply(operation));\n      } else {\n        this.items[i] = operation(this.items[i]);\n      }\n    }\n    return this;\n  }\n\n\n  /**\n   * @param {function} operation\n   */\n  recurseEach(operation) {\n    for (let i = 0; i < this.items.length; i++) {\n      let item = this.items[i];\n      if (item instanceof Vector) {\n        item.recurseEach(operation);\n      } else {\n        operation(this.items[i]);\n      }\n    }\n  }\n\n\n\n\n  /**\n   * @returns {any[]}\n   */\n  fullNames() {\n    let firstElement = this.items[0];\n\n    if (firstElement instanceof Vector && firstElement.names) {\n      let subn = firstElement.fullNames();\n      let n = [];\n      for (let i = 0; i < this.names.length; i++) {\n        for (let j = 0; j < subn.length; j++) {\n          n.push([this.names[i]].concat(subn[j]));\n        }\n      }\n\n      return n;\n    } else {\n      return this.names.map(name => [name]);\n    }\n  }\n\n\n  /**\n   * @returns {Vector}\n   */\n  clone() {\n    let newItems = [];\n    for (let item of this.items) {\n      if (item instanceof Vector) {\n        newItems.push(item.clone());\n      } else {\n        newItems.push(item);\n      }\n    }\n    return new Vector(newItems, this.simulate, this.names ? this.names.slice() : undefined, this.parent);\n  }\n\n  /**\n   * @returns {Vector}\n   */\n  fullClone() {\n    let newItems = [];\n    for (let item of this.items) {\n      if (item instanceof Vector || item instanceof Material) {\n        newItems.push(item.fullClone());\n      } else {\n        newItems.push(item);\n      }\n    }\n    return new Vector(newItems, this.simulate, this.names ? this.names.slice() : undefined, this.parent);\n  }\n\n  /**\n   * @param {Vector} vec\n   *\n   * @returns {boolean}\n   */\n  equals(vec) {\n    if (this.length() !== vec.length()) {\n      return false;\n    }\n\n    for (let i = 0; i < this.items.length; i++) {\n      if (!strictEquals(this.items[i], vec.items[i])) {\n        return false;\n      }\n    }\n    return true;\n  }\n}\n\n", "src/formula/Utilities.js": "import { SAgent } from \"../Primitives.js\";\nimport { eq, toNum } from \"./Formula.js\";\nimport { Material } from \"./Material.js\";\nimport { ModelError } from \"./ModelError.js\";\nimport { Vector } from \"./Vector.js\";\n\n\n/**\n * @param {*} x\n * @param {import(\"../Simulator\").Simulator} simulate\n */\nexport function stringify(x, simulate) {\n  if (x instanceof Vector) {\n    return x.recurseApply((x) => stringify(x, simulate));\n  }\n  // eslint-disable-next-line\n  let res = new String(x);\n  // @ts-ignore\n  res.parent = simulate.coreBank.get(\"stringbase\");\n  return res;\n}\n\n\n\n/**\n * @param {*} mat\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {any[]} items\n * @param {*} fill\n */\nexport function selectFromMatrix(mat, simulate, items, fill) {\n\n  let selectorCount = items.length;\n\n  /**\n   * @param {any} m\n   * @returns {Vector}\n   */\n  function vectorize(m) {\n    if (!(m instanceof Vector)) {\n      if (items[0] === \"*\") {\n        if (m instanceof Material) {\n          throw new ModelError(\"Can't use * selector on a number.\", {\n            code: 3000\n          });\n        } else if (m instanceof Boolean || typeof m === \"boolean\") {\n          throw new ModelError(\"Can't use * selector on a boolean.\", {\n            code: 3001\n          });\n        } else if (m instanceof String || typeof m === \"string\") {\n          throw new ModelError(\"Can't use * selector on a string.\", {\n            code: 3002\n          });\n        } else {\n          throw new ModelError(\"Can't use * selector on an object.\", {\n            code: 3003\n          });\n        }\n      }\n      if (m.vector) {\n        m = m.vector;\n      } else if (m.parent) {\n        m = new Vector([], simulate, [], m.parent);\n      }\n    }\n    if (fill === undefined && m.fullClone) {\n      m = m.fullClone();\n    }\n    return m;\n  }\n\n\n  let m = vectorize(mat);\n\n  let root = selectFromVector(m, simulate, items.shift(), !items.length ? fill : undefined, fill !== undefined);\n  let children = [];\n  if (root.collapsed) {\n    children = [root.data];\n  } else {\n    if (!root.data.items) {\n      throw new ModelError(`No element available for selector ${selectorCount - items.length + 1}`, {\n        code: 3004\n      });\n    }\n    children = root.data.items;\n  }\n\n  while (items.length) {\n    let newChildren = [];\n    let selector = items.shift();\n    for (let i = 0; i < children.length; i++) {\n      if (!(children[i] instanceof Vector)) {\n        throw new ModelError(`No element available for selector ${selectorCount - items.length}`, {\n          code: 3005\n        });\n      }\n\n      let vec = selectFromVector(children[i], simulate, selector, !items.length ? fill : undefined);\n\n      if (vec.collapsed) {\n\n        if (fill === undefined) {\n          children[i].items = [vec.data];\n          children[i].names = [\"!!BREAKOUT DATA\"];\n        }\n\n        newChildren = newChildren.concat(vec.data);\n      } else {\n        newChildren = newChildren.concat(vec.data.items);\n\n        if (fill === undefined) {\n          children[i].items = vec.data.items;\n          children[i].names = vec.data.names;\n        }\n      }\n    }\n    children = newChildren;\n  }\n\n  return doBreakouts(root.data);\n}\n\n\nfunction doBreakouts(vec) {\n  if (!(vec instanceof Vector)) {\n    return vec;\n  }\n  if (vec.items.length === 1 && vec.names && vec.names[0] === \"!!BREAKOUT DATA\") {\n    return doBreakouts(vec.items[0]);\n  }\n  for (let i = 0; i < vec.items.length; i++) {\n    vec.items[i] = doBreakouts(vec.items[i]);\n  }\n  return vec;\n}\n\n\n/**\n * @param {Vector} vec\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {*} items\n * @param {*} fill\n * @param {boolean=} doNotClone\n */\nexport function selectFromVector(vec, simulate, items, fill, doNotClone) {\n  if (items === \"*\") {\n    return { data: vec };\n  } else if (typeof items === \"function\") {\n    return { data: items([vec]), collapsed: true };\n  } else if (items === \"parent\") {\n    if (vec.parent) {\n      return { data: doNotClone ? vec.parent : vec.parent.fullClone(), collapsed: true };\n    } else {\n      throw new ModelError(\"Vector does not have a parent.\", {\n        code: 3006\n      });\n    }\n  }\n\n  if (items instanceof Vector) {\n    let res = [];\n    /** @type {string[]} */\n    let names = vec.names ? [] : undefined;\n    for (let i = 0; i < items.items.length; i++) {\n      let v = items.items[i];\n      let shouldSelect = true;\n      if (typeof v === \"boolean\") {\n        if (v) {\n          v = new Material(i + 1);\n        } else {\n          shouldSelect = false;\n        }\n      }\n      if (shouldSelect) {\n        let r = selectElementFromVector(vec, v, fill);\n        res.push(r.value);\n        if (names) {\n          names.push(r.name);\n        }\n      }\n    }\n    return { collapsed: false, parent: vec, data: new Vector(res, simulate, names, vec.parent) };\n  } else {\n    return { collapsed: true, parent: vec, data: selectElementFromVector(vec, items, fill).value };\n  }\n}\n\n\n/**\n * @param {Vector} vec\n * @param {any} item\n * @param {any} fill\n *\n * @returns {any}\n */\nfunction selectElementFromVector(vec, item, fill) {\n  let name = undefined;\n  let value = undefined;\n\n  let index;\n\n\n  if (typeof item === \"string\" || item instanceof String) {\n    try {\n      if (fill === undefined) {\n        if (!vec.names) {\n          if (vec.parent) {\n            return selectElementFromVector(vec.parent, item, fill);\n          } else {\n            throw new ModelError(`Key '${item}' not in vector.`, {\n              code: 3007\n            });\n          }\n        }\n      }\n      if (vec.names) {\n        index = -1;\n        let lc = item.toLowerCase();\n        for (let i = 0; i < vec.names.length; i++) {\n          if (vec.names[i] && vec.names[i].toLowerCase() === lc) {\n            index = i;\n            break;\n          }\n        }\n        if (index < 0) {\n          index = vec.names.indexOf(\"*\");\n        }\n      }\n      if (index < 0 || index === undefined) {\n        if (fill === undefined) {\n          if (vec.parent) {\n            return selectElementFromVector(vec.parent, item, fill);\n          } else {\n            throw new ModelError(`Key '${item}' not in vector.`, {\n              code: 3008\n            });\n          }\n        } else {\n          index = item;\n        }\n\n      }\n    } catch (err) {\n      if (vec.parent) {\n        return selectElementFromVector(vec.parent, item, fill);\n      } else {\n        throw err;\n      }\n    }\n\n  } else {\n    index = parseFloat(toNum(item)) - 1;\n  }\n\n  if (index instanceof String || typeof index === \"string\") {\n    if (!vec.names) {\n      vec.names = [];\n      for (let i = 0; i < vec.items.length; i++) {\n        vec.names.push(undefined);\n      }\n    }\n    vec.items.push(fill);\n    vec.names.push(index.valueOf());\n    value = fill;\n    name = index;\n\n  } else {\n    if (index < 0 || !vec.items || index >= vec.items.length || index % 1 !== 0) {\n      throw new ModelError(\"Index \" + (1 + index) + \" is not in the vector.\", {\n        code: 3009\n      });\n    }\n    if (fill !== undefined) {\n      vec.items[index] = fill;\n    }\n    value = vec.items[index];\n    if (vec.names) {\n      name = vec.names[index];\n    }\n  }\n\n  return { name: name, value: value };\n}\n\n\nexport function strictEquals(a, b) {\n  if (a instanceof SAgent || b instanceof SAgent) {\n    if (a instanceof SAgent && b instanceof SAgent) {\n      if (a.instanceId === b.instanceId) {\n        return true;\n      }\n    }\n  } else if (a instanceof Vector || b instanceof Vector) {\n    if (a instanceof Vector && b instanceof Vector) {\n      if (a.equals(b)) {\n        return true;\n      }\n    }\n  } else if (eq(a, b)) {\n    return true;\n  }\n  return false;\n}\n\n", "src/formula/Rand.js": "import { ModelError } from \"./ModelError.js\";\nimport { jStat } from \"../../vendor/jstat/jstat.js\";\n\n\nexport class RandList {\n  /**\n   * @param {import(\"../Simulator\").Simulator} simulate\n   */\n  constructor(simulate) {\n    this.simulate = simulate;\n\n    /** @type {number[]} */\n    this.vals = [];\n  }\n\n  /**\n   * @param {number} i\n   *\n   * @returns {number}\n   */\n  get(i) {\n    if (i > this.vals.length - 1) {\n      for (let j = this.vals.length; j <= i; j++) {\n        if (this.simulate.random) {\n          this.vals.push(this.simulate.random());\n        } else {\n          this.vals.push(Math.random());\n        }\n      }\n    }\n    return this.vals[i];\n  }\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n *\n * @returns {number}\n */\nfunction getRandPos(simulate) {\n  return Math.floor((simulate.time().value - simulate.timeStart.value) / simulate.timeStep.value);\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number=} minVal\n * @param {number=} maxVal\n *\n * @return {number}\n */\nexport function Rand(simulate, minVal = null, maxVal = null) {\n  simulate.stochastic = true;\n\n  if (minVal !== null && minVal !== undefined) {\n    isNormalNumber(minVal, \"Rand\", \"Minimum\");\n    isNormalNumber(maxVal, \"Rand\", \"Maximum\");\n\n    return Rand(simulate) * (maxVal - minVal) + (0 + minVal);\n  }\n\n  if (simulate.RKOrder === 1) {\n    if (simulate.random) {\n      return simulate.random();\n    } else {\n      return Math.random();\n    }\n  }\n  let RandPos = getRandPos(simulate);\n  if (RandPos !== simulate.lastRandPos) {\n    simulate.randLoc = -1;\n    simulate.lastRandPos = RandPos;\n  }\n  while (simulate.previousRandLists.length <= RandPos) {\n    simulate.previousRandLists.push(new RandList(simulate));\n  }\n  simulate.randLoc = simulate.randLoc + 1;\n  return simulate.previousRandLists[RandPos].get(simulate.randLoc);\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number=} mu\n * @param {number=} sigma\n *\n * @returns {number}\n */\nexport function RandNormal(simulate, mu = null, sigma = null) {\n\n  if (mu === null) {\n    mu = 0;\n  }\n  if (sigma === null) {\n    sigma = 1;\n  }\n\n  isNormalNumber(mu, \"RandNormal\", \"mean\");\n  isNormalNumber(sigma, \"RandNormal\", \"standard deviation\");\n  if (sigma < 0) {\n    throw new ModelError(`<i>Standard deviation</i> for RandNormal() must be greater than or equal to 0; got ${sigma}.`, {\n      code: 4023\n    });\n  }\n\n\n  let z = Math.sqrt(-2 * Math.log1p(-Rand(simulate))) * Math.cos(Rand(simulate) * 2 * Math.PI);\n  return z * sigma + mu;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number=} lambda\n *\n * @returns {number}\n */\nexport function RandExp(simulate, lambda = null) {\n  if (lambda === null) {\n    lambda = 1;\n  }\n\n  if (lambda < 0) {\n    throw new ModelError(`Lambda for RandExp must be greater than or equal to 0; got ${lambda}.`, {\n      code: 4000\n    });\n  }\n\n  isNormalNumber(lambda, \"RandExp\", \"lambda\");\n\n  return -Math.log(Rand(simulate)) / lambda;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} mu\n * @param {number} sigma\n *\n * @returns {number}\n */\nexport function RandLognormal(simulate, mu, sigma) {\n  isNormalNumber(mu, \"RandLognormal\", \"mu\");\n  isNormalNumber(sigma, \"RandLognormal\", \"sigma\");\n\n\n  if (mu <= 0) {\n    throw new ModelError(`<i>Mean</i> for RandLognormal() must be greater than 0; got ${mu}.`, {\n      code: 4001\n    });\n  }\n  if (sigma <= 0) {\n    throw new ModelError(`<i>Standard deviation</i> for RandLognormal() must be greater than 0; got ${sigma}.`, {\n      code: 4002\n    });\n  }\n\n  const z = Math.log1p(Math.pow(sigma / mu, 2));\n\n  let lmu = Math.log(mu) - 0.5 * z;\n  let lsigma = Math.sqrt(z);\n\n  return Math.exp(RandNormal(simulate, lmu, lsigma));\n}\n\n\n/**\n * Based on:\n *   https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/random/src/distributions/distributions.c\n *\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} count\n * @param {number} probability\n *\n * @returns {number}\n */\nexport function RandBinomial(simulate, count, probability) {\n  isNormalNumber(count, \"RandBinomial\", \"count\");\n  isNormalNumber(probability, \"RandBinomial\", \"probability\");\n  if (count < 0) {\n    throw new ModelError(`<i>Count</i> for RandBinomial() must be greater than or equal to 0; got ${count}.`, {\n      code: 4003\n    });\n  }\n  if (probability < 0 || probability > 1) {\n    throw new ModelError(`<i>Probability</i> for RandBinomial() must be between 0 and 1 (inclusive); got ${probability}.`, {\n      code: 4004\n    });\n  }\n\n  if ((count === 0) || (probability === 0)) {\n    return 0;\n  }\n\n  if (probability <= 0.5) {\n    if (probability * count <= 30.0) {\n      return randomBinomialInversion(simulate, count, probability);\n    } else {\n      return randomBinomialBtpe(simulate, count, probability);\n    }\n  } else {\n    let q = 1.0 - probability;\n    if (q * count <= 30.0) {\n      return count - randomBinomialInversion(simulate, count, q);\n    } else {\n      return count - randomBinomialBtpe(simulate, count, q);\n    }\n  }\n}\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} n\n * @param {number} p\n */\nfunction randomBinomialBtpe(simulate, n, p) {\n  let r, q, fm, p1, xm, xl, xr, c, laml, lamr, p2, p3, p4;\n  let a, u, v, s, F, rho, t, A, nrq, x1, x2, f1, f2, z, z2, w, w2, x;\n  let m, y, k, i;\n\n\n  r = Math.min(p, 1.0 - p);\n  q = 1.0 - r;\n  fm = n * r + r;\n  m = Math.floor(fm);\n  p1 = Math.floor(2.195 * Math.sqrt(n * r * q) - 4.6 * q) + 0.5;\n  xm = m + 0.5;\n  xl = xm - p1;\n  xr = xm + p1;\n  c = 0.134 + 20.5 / (15.3 + m);\n  a = (fm - xl) / (fm - xl * r);\n  laml = a * (1.0 + a / 2.0);\n  a = (xr - fm) / (xr * q);\n  lamr = a * (1.0 + a / 2.0);\n  p2 = p1 * (1.0 + 2.0 * c);\n  p3 = p2 + c / laml;\n  p4 = p3 + c / lamr;\n\n\n\n  while (true) {\n    nrq = n * r * q;\n    u = Rand(simulate) * p4;\n    v = Rand(simulate);\n    if (!(u > p1)) {\n      y = Math.floor(xm - p1 * v + u);\n      break;\n    }\n\n\n    if (!(u > p2)) {\n      x = xl + (u - p1) / c;\n      v = v * c + 1.0 - Math.abs(m - x + 0.5) / p1;\n      if (v > 1.0) {\n        continue;\n      }\n      y = Math.floor(x);\n    } else if (!(u > p3)) {\n      y = Math.floor(xl + Math.log(v) / laml);\n      /* Reject if v==0.0 since previous cast is undefined */\n      if ((y < 0) || (v === 0.0)) {\n        continue;\n      }\n      v = v * (u - p2) * laml;\n    } else {\n      y = Math.floor(xr - Math.log(v) / lamr);\n      /* Reject if v==0.0 since previous cast is undefined */\n      if ((y > n) || (v === 0.0)) {\n        continue;\n      }\n      v = v * (u - p3) * lamr;\n    }\n\n    k = Math.abs(y - m);\n    if (!((k > 20) && (k < ((nrq) / 2.0 - 1)))) {\n      s = r / q;\n      a = s * (n + 1);\n      F = 1.0;\n      if (m < y) {\n        for (i = m + 1; i <= y; i++) {\n          F *= (a / i - s);\n        }\n      } else if (m > y) {\n        for (i = y + 1; i <= m; i++) {\n          F /= (a / i - s);\n        }\n      }\n      if (v > F) {\n        continue;\n      }\n      break;\n    } else {\n      rho =\n        (k / (nrq)) * ((k * (k / 3.0 + 0.625) + 0.16666666666666666) / nrq + 0.5);\n      t = -k * k / (2 * nrq);\n      /* log(0.0) ok here */\n      A = Math.log(v);\n      if (A < (t - rho)) {\n        break;\n      }\n      if (A > (t + rho)) {\n        continue;\n      }\n\n      x1 = y + 1;\n      f1 = m + 1;\n      z = n + 1 - m;\n      w = n - y + 1;\n      x2 = x1 * x1;\n      f2 = f1 * f1;\n      z2 = z * z;\n      w2 = w * w;\n      if (A > (xm * Math.log(f1 / x1) + (n - m + 0.5) * Math.log(z / w) +\n        (y - m) * Math.log(w * r / (x1 * q)) +\n        (13680. - (462. - (132. - (99. - 140. / f2) / f2) / f2) / f2) / f1 /\n        166320. +\n        (13680. - (462. - (132. - (99. - 140. / z2) / z2) / z2) / z2) / z /\n        166320. +\n        (13680. - (462. - (132. - (99. - 140. / x2) / x2) / x2) / x2) / x1 /\n        166320. +\n        (13680. - (462. - (132. - (99. - 140. / w2) / w2) / w2) / w2) / w /\n        166320.)) {\n        continue;\n      }\n    }\n  }\n\n  if (p > 0.5) {\n    y = n - y;\n  }\n\n  return y;\n}\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} n\n * @param {number} p\n */\nfunction randomBinomialInversion(simulate, n, p) {\n  let q, qn, np, px, U;\n  let X, bound;\n\n  q = 1.0 - p;\n  qn = Math.exp(n * Math.log1p(-p));\n  np = n * p;\n  bound = Math.min(n, np + 10.0 * Math.sqrt(np * q + 1));\n\n  X = 0;\n  px = qn;\n  U = Rand(simulate);\n  while (U > px) {\n    X++;\n    if (X > bound) {\n      X = 0;\n      px = qn;\n      U = Rand(simulate);\n    } else {\n      U -= px;\n      px = ((n - X + 1) * p * px) / (X * q);\n    }\n  }\n  return X;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} successes\n * @param {number} probability\n *\n * @returns {number}\n */\nexport function RandNegativeBinomial(simulate, successes, probability) {\n  isNormalNumber(successes, \"RandNegativeBinomial\", \"successes\");\n  isNormalNumber(probability, \"RandNegativeBinomial\", \"probability\");\n  if (successes < 0) {\n    throw new ModelError(`<i>Successes</i> for RandNegativeBinomial() must be greater than or equal to 0; got ${successes}.`, {\n      code: 4005\n    });\n  }\n  if (!Number.isInteger(successes)) {\n    throw new ModelError(`<i>Successes</i> for RandNegativeBinomial() must be an integer; got ${successes}.`, {\n      code: 4025\n    });\n  }\n  if (probability < 0 || probability > 1) {\n    throw new ModelError(`<i>Probability</i> for RandNegativeBinomial() must be between 0 and 1 (inclusive); got ${probability}.`, {\n      code: 4006\n    });\n  }\n\n  if (successes === 0) {\n    return 0;\n  }\n  if (probability === 1) {\n    return successes;\n  }\n  if (probability === 0) {\n    // Would never succeed\n    throw new ModelError(\"<i>Probability</i> for RandNegativeBinomial() cannot be 0 when <i>successes</i> > 0.\", {\n      code: 4021\n    });\n  }\n\n\n\n  let i = 0;\n  let s = 0;\n  while (s < successes) {\n    if (Rand(simulate) <= probability) {\n      s = s + 1;\n    }\n    i = i + 1;\n  }\n  return i;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} lambda\n *\n * @returns {number}\n */\nexport function RandPoisson(simulate, lambda) {\n  isNormalNumber(lambda, \"RandPoisson\", \"lambda\");\n  if (lambda < 0) {\n    throw new ModelError(`<i>Lambda</i> for RandPoisson() must be greater than or equal to 0; got ${lambda}.`, {\n      code: 4007\n    });\n  }\n\n\n  if (lambda < 50) {\n    // Slow method suitable for small lambda's\n    // https://en.wikipedia.org/wiki/Poisson_distribution#Generating_Poisson-distributed_random_variables\n    let L = Math.exp(-lambda);\n    let k = 0;\n    let p = 1;\n\n    while (true) {\n      k = k + 1;\n      p = p * Rand(simulate);\n      if (!(p > L)) {\n        break;\n      }\n    }\n    return k - 1;\n  } else {\n    // Approximation suitable for large lambda's\n    // https://www.johndcook.com/blog/2010/06/14/generating-poisson-random-values/\n    let c = 0.767 - 3.36 / lambda;\n    let beta = Math.PI / Math.sqrt(3.0 * lambda);\n    let alpha = beta * lambda;\n    let k = Math.log(c) - lambda - Math.log(beta);\n\n\n    while (true) {\n      let u = Rand(simulate);\n      let x = (alpha - Math.log((1.0 - u) / u)) / beta;\n      let n = Math.floor(x + 0.5);\n      if (n < 0) {\n        continue;\n      }\n      let v = Rand(simulate);\n      let y = alpha - beta * x;\n      let lhs = y + Math.log(v / Math.pow(1.0 + Math.exp(y), 2));\n      let rhs = k + n * Math.log(lambda) - jStat.gammaln(n + 1);\n      if (lhs <= rhs) {\n        return n;\n      }\n    }\n  }\n}\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} alpha\n * @param {number} beta\n *\n * @returns {number}\n */\nexport function RandGamma(simulate, alpha, beta) {\n  isNormalNumber(alpha, \"RandGamma\", \"alpha\");\n  isNormalNumber(beta, \"RandGamma\", \"beta\");\n\n  if (alpha <= 0) {\n    throw new ModelError(`<i>Alpha</i> (shape parameter) for RandGamma() must be greater than 0; got ${alpha}.`, {\n      code: 4008\n    });\n  }\n  if (beta <= 0) {\n    throw new ModelError(`<i>Beta</i> (scale parameter) for RandGamma() must be greater than 0; got ${beta}.`, {\n      code: 4009\n    });\n  }\n\n  // Marsaglia\u2013Tsang method for generating gamma distribution\n\n  function gammaShapeGe1(a) {\n    const d = a - 1 / 3;\n    const c = 1 / Math.sqrt(9 * d);\n\n    while (true) {\n      const z = RandNormal(simulate, 0, 1);\n      if (!Number.isFinite(z)) continue;\n\n      const t = 1 + c * z;\n      if (t <= 0) continue;\n\n      const v = t * t * t;\n      const u = Rand(simulate);\n      if (!(u > 0 && u < 1)) continue;\n\n      const z2 = z * z;\n      if (u < 1 - 0.0331 * z2 * z2) return d * v;\n\n      if (Math.log(u) < 0.5 * z2 + d * (1 - v + Math.log(v))) return d * v;\n    }\n  }\n\n  let x;\n  if (alpha >= 1) {\n    x = gammaShapeGe1(alpha);\n  } else {\n    const g = gammaShapeGe1(alpha + 1);\n    const u = Math.max(Rand(simulate), Number.EPSILON);\n    x = g * Math.pow(u, 1 / alpha);\n  }\n\n  return x * beta;\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} alpha\n * @param {number} beta\n *\n * @returns {number}\n */\nexport function RandBeta(simulate, alpha, beta) {\n  isNormalNumber(alpha, \"RandBeta\", \"alpha\");\n  isNormalNumber(beta, \"RandBeta\", \"beta\");\n\n  if (alpha <= 0) {\n    throw new ModelError(`<i>Alpha</i> for RandBeta() must be greater than 0; got ${alpha}.`, {\n      code: 4010\n    });\n  }\n  if (beta <= 0) {\n    throw new ModelError(`<i>Beta</i> for RandBeta() must be greater than 0; got ${beta}.`, {\n      code: 4011\n    });\n  }\n\n  let x = RandGamma(simulate, alpha, 1);\n  let y = RandGamma(simulate, beta, 1);\n  return x / (x + y);\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number} minimum\n * @param {number} maximum\n * @param {number} peak\n *\n * @returns {number}\n */\nexport function RandTriangular(simulate, minimum, maximum, peak) {\n  isNormalNumber(minimum, \"RandTriangular\", \"minimum\");\n  isNormalNumber(maximum, \"RandTriangular\", \"maximum\");\n  isNormalNumber(peak, \"RandTriangular\", \"peak\");\n\n  let a = 0 + minimum;\n  let b = 0 + maximum;\n  let c = 0 + peak;\n\n  if (a === b) {\n    throw new ModelError(\"Maximum can't equal the minimum for the triangular distribution.\", {\n      code: 4012\n    });\n  }\n\n  if (a > b) {\n    throw new ModelError(\"Maximum must be greater than the minimum for the triangular distribution.\", {\n      code: 4012\n    });\n  }\n\n  if (c < a || c > b) {\n    throw new ModelError(\"The peak must be within the maximum and minimum for the triangular distribution.\", {\n      code: 4013\n    });\n  }\n\n  let fc = (c - a) / (b - a);\n\n  let u = Rand(simulate);\n\n  if (u < fc) {\n    return a + Math.sqrt(u * (b - a) * (c - a));\n  } else {\n    return b - Math.sqrt((1 - u) * (b - a) * (b - c));\n  }\n}\n\n\n/**\n * @param {import(\"../Simulator\").Simulator} simulate\n * @param {number[]} x\n * @param {number[]} y\n *\n * @returns {number}\n */\nexport function RandDist(simulate, x, y) {\n  if (x.length !== y.length) {\n    throw new ModelError(\"The lengths of the 'x' and 'y' vectors must be the same.\", {\n      code: 4014\n    });\n  }\n  if (x.length < 2) {\n    throw new ModelError(\"There must be at least 2 points in a distribution to generate a random number.\", {\n      code: 4015\n    });\n  }\n  for (let i = 0; i < x.length; i++) {\n    isNormalNumber(x[i], \"RandDist\", \"x\");\n    isNormalNumber(y[i], \"RandDist\", \"y\");\n    if (y[i] < 0) {\n      throw new ModelError(\"The y values of RandDist cannot be negative.\", {\n        code: 4016\n      });\n    }\n    if (i > 0 && x[i] < x[i - 1]) {\n      throw new ModelError(\"The x values of RandDist must not decrease.\", {\n        code: 4022\n      });\n    }\n  }\n\n  let area = 0;\n  for (let i = 0; i < x.length - 1; i++) {\n    area += (x[i + 1] - x[i]) * (y[i + 1] + y[i]) / 2;\n  }\n  if (area === 0) {\n    throw new ModelError(\"The area of the distribution in RandDist cannot be 0.\", {\n      code: 4017\n    });\n  }\n\n  let a = area * Rand(simulate);\n  area = 0;\n  for (let i = 0; i < x.length - 1; i++) {\n    let nextArea = (x[i + 1] - x[i]) * (y[i + 1] + y[i]) / 2;\n    if (a >= area && a <= area + nextArea) {\n      let neededArea = a - area;\n      let slope = (y[i + 1] - y[i]) / (x[i + 1] - x[i]);\n      let dist;\n      if (slope === 0) {\n        dist = neededArea / y[i];\n      } else {\n        dist = (-y[i] + Math.sqrt(Math.pow(y[i], 2) + 2 * slope * neededArea)) / slope;\n      }\n\n      return x[i] + dist;\n    }\n    area += nextArea;\n  }\n\n}\n\n\n/**\n * @param {number} x\n * @param {string} name\n * @param {string} v\n */\nfunction isNormalNumber(x, name, v) {\n  if (x === null) {\n    throw new ModelError(`The <i>${v}</i> passed to ${name}() was not a number.`, {\n      code: 4018\n    });\n  }\n\n  if (isNaN(x)) {\n    throw new ModelError(`The <i>${v}</i> passed to ${name}() was not a number.`, {\n      code: 4018\n    });\n  }\n\n  if (!isFinite(x)) {\n    throw new ModelError(`The <i>${v}</i> passed to ${name}() must not be infinite.`, {\n      code: 4019\n    });\n  }\n\n  if (x > 1e+15) {\n    // randBinomial fails at a count of around 1e26. Let's add a reasonable maximum to all these\n    // functions\n    throw new ModelError(`The <i>${v}</i> passed to ${name}() must not be greater than 1e15 (got ${x}).`, {\n      code: 4020\n    });\n  }\n}\n", "src/formula/ModelError.js": "\n/** @typedef {import(\"../SharedTypes.js\").GraphNode} GraphNode */\n\nexport class ModelError extends Error {\n  /**\n   * @param {string} message\n   * @param {{ source?: string, primitive?: import('../api/Blocks.js').Primitive|import('../Primitives').SPrimitive|GraphNode, showEditor?: boolean, line?: number, details?: string, code: number }} config\n   */\n  constructor(message, config) {\n    super(message);\n    this.name = \"ModelError\";\n    this.primitive = config.primitive;\n    this.showEditor = config.showEditor;\n    this.source = config.source;\n    this.line = config.line;\n    this.details = config.details;\n    this.code = config.code;\n  }\n}", "src/api/Results.js": "import { Vector } from \"../formula/Vector.js\";\n\n\nexport class Results {\n  /**\n   * @param {import(\"../Simulator\").ResultsType} data\n   * @param {Object<string, string>} nameIdMapping\n   */\n  constructor(data, nameIdMapping) {\n    this._data = data;\n    this._nameIdMapping = nameIdMapping;\n    this.timeUnits = data.timeUnits;\n\n    for (let i = 0; i < this._data.data.length; i++) {\n      let current = this._data.data[i];\n      for (let key in current) {\n        current[key] = simplifyResults(current[key]);\n      }\n    }\n  }\n\n  times() {\n    return this._data.times.slice();\n  }\n\n  /**\n   * @param {import(\"./Blocks\").Primitive[]=} primitives\n   */\n  table(primitives) {\n    if (primitives) {\n      let series = primitives.map(x => ({ primitive: x, series: this.series(x) }));\n      let times = this.times();\n\n      let res = [];\n      for (let i = 0; i < times.length; i++) {\n        let data = {\n          _time: times[i],\n        };\n        for (let item of series) {\n          data[item.primitive.name] = item.series[i];\n        }\n        res.push(data);\n      }\n\n      return res;\n    } else {\n      let res = [];\n      for (let i = 0; i < this._data.data.length; i++) {\n        let data = {};\n        data._time = this._data.times[i];\n\n        let current = this._data.data[i];\n        for (let id in current) {\n          data[this._nameIdMapping[id]] = current[id];\n        }\n        res.push(data);\n      }\n      return res;\n    }\n  }\n\n  /**\n   * @param {import(\"./Blocks\").Primitive} primitive\n   */\n  series(primitive) {\n    return this._data.value(primitive._node).slice();\n  }\n\n  /**\n   * @param {import(\"./Blocks\").Primitive} primitive\n   * @param {number=} time - if omitted, the last available value\n   */\n  value(primitive, time = null) {\n    if (!primitive?._node) {\n      throw new Error(\"Expected a primitive when calling Results.value(), got: \" + primitive);\n    }\n\n    let series = this.series(primitive);\n    if (time === null) {\n      return series[series.length - 1];\n    }\n\n    let times = this.times();\n\n    let index = times.indexOf(time);\n    if (index === -1) {\n      throw new Error(\"Could not find time: \" + time + \". Available options are: \" + JSON.stringify(times));\n    }\n\n    return series[index];\n  }\n}\n\n\nfunction simplifyResults(x) {\n  if (x instanceof Vector) {\n    if (x.names) {\n      let res = {};\n      for (let i = 0; i < x.names.length; i++) {\n        res[x.names[i]] = simplifyResults(x.items[i]);\n      }\n      return res;\n    } else {\n      return x.items.map(simplifyResults);\n    }\n  }\n\n  return x;\n}", "src/api/SimulationError.js": "export class SimulationError extends Error {\n  /**\n   * @param {string} message\n   * @param {{ source?: string, primitive?: any, line?: number, code: number }} config\n   */\n  constructor(message, config) {\n    super(message);\n\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, SimulationError);\n    }\n\n    this.name = \"SimulationError\";\n\n\n    this.source = config.source;\n    this.primitive = config.primitive;\n    this.line = config.line;\n    this.code = config.code;\n\n    // Don't print these on the console\n    Object.defineProperty(this, \"code\", { enumerable: false });\n    Object.defineProperty(this, \"primitive\", { enumerable: false });\n  }\n\n}\n", "src/api/Blocks.js": "import { ModelError } from \"../formula/ModelError.js\";\nimport { isTrue } from \"../Utilities.js\";\n\n\n/** @typedef {import(\"../SharedTypes.js\").TriggerType} TriggerType */\n/** @typedef {import(\"../SharedTypes.js\").StockTypeType} StockTypeType */\n/** @typedef {import(\"../SharedTypes.js\").PlacementType} PlacementType */\n/** @typedef {import(\"../SharedTypes.js\").NetworkType} NetworkType */\n\n/**\n * @typedef {string|number} Value\n */\n\n\n/**\n * @typedef {object} NeighborhoodEntry\n * @property {Primitive} item\n * @property {string} type\n * @property {boolean=} linkHidden\n * @property {string=} name\n */\n\n\n\n/**\n * @typedef {object} PrimitiveConfig\n * @property {string=} name\n * @property {string=} note\n */\n\n\n\nexport class Primitive {\n  /**\n   * @param {import(\"../ModelNode\").ModelNode} node\n   * @param {PrimitiveConfig} config\n   */\n  constructor(node, config) {\n    this._node = node;\n\n    /** @type {import(\"./Model\").Model} */\n    this.model = null;\n\n    for (let key in config) {\n      if (key in this) {\n        this[key] = config[key];\n      } else {\n        throw new Error(\"Unknown property: \" + key);\n      }\n    }\n  }\n\n\n  delete() {\n    let connectors = this.model.find(node => node instanceof Flow || node instanceof Transition || node instanceof Link);\n\n    let x = this._node;\n    if (x.parent.children.includes(x)) {\n      x.parent.children.splice(x.parent.children.indexOf(x), 1);\n    }\n\n    connectors.forEach((c) => {\n      if (c._node.source === x) {\n        c._node.source = null;\n        if (c._node.target && c._node.target.parent !== c._node.parent) {\n          c.parent = /** @type {Container} */ (c._node.target.parent.primitive(this.model));\n        }\n      }\n      if (c._node.target === x) {\n        c._node.target = null;\n        if (c._node.source && c._node.source.parent !== c._node.parent) {\n          c.parent =  /** @type {Container} */ (c._node.source.parent.primitive(this.model));\n        }\n      }\n    });\n  }\n\n\n  /**\n   * @return {Container}\n   */\n  get parent() {\n    let p = this._node.parent;\n    if ((p.value && p.value.nodeName === \"root\") || p.id === \"1\") {\n      return null;\n    } else {\n      return /** @type {Container} */ (p.primitive(this.model));\n    }\n  }\n\n  /**\n   * @param {Container} parent\n   */\n  set parent(parent) {\n    let p;\n    if (parent === null) {\n      p = this.model._graph.children[0].children[0];\n    } else {\n      p = parent._node;\n    }\n\n    if (this._node.parent.children.includes(this._node)) {\n      this._node.parent.children.splice(this._node.parent.children.indexOf(this._node), 1);\n    }\n\n    p.addChild(this._node);\n  }\n\n  /**\n   * @param {function(Container):boolean} selector\n   *\n   * @returns {Container}\n   */\n  getParent(selector) {\n    let parent = this.parent;\n    if (!parent) {\n      return null;\n    }\n\n    if (selector(parent)) {\n      return parent;\n    }\n\n    return parent.getParent(selector);\n  }\n\n  isInAgent() {\n    return !!this.getParent(x => x instanceof Agent);\n  }\n\n  neighbors() {\n    /** @type {NeighborhoodEntry[]} */\n    let neighbors = [];\n\n    let flows = this.model.findFlows();\n    let links = this.model.findLinks();\n    if (this instanceof Flow || this instanceof Link || this instanceof Transition) {\n      if (this.start) {\n        neighbors.push({\n          item: this.start,\n          type: \"direct\"\n        });\n      }\n      if (this.end) {\n        neighbors.push({\n          item: this.end,\n          type: \"direct\"\n        });\n      }\n    }\n    if (this instanceof Population) {\n      if (this.agentBase) {\n        neighbors = neighbors.concat(getAgentItems(this));\n      }\n    }\n\n\n    if (this instanceof Stock) {\n      for (let i = 0; i < flows.length; i++) {\n        if (flows[i].start === this) {\n          neighbors.push({\n            item: flows[i],\n            type: \"direct\",\n            linkHidden: true\n          });\n        }\n        if (flows[i].end === this) {\n          neighbors.push({\n            item: flows[i],\n            type: \"direct\",\n            linkHidden: true\n          });\n        }\n      }\n    }\n\n    for (let i = 0; i < links.length; i++) {\n      if (links[i].start === this && links[i].end) {\n        let linkHidden = !links[i].biDirectional;\n        neighbors.push({\n          item: links[i].end,\n          type: \"direct\",\n          linkHidden: linkHidden\n        });\n\n        neighbors = neighbors.concat(getAgentItems(links[i].end, linkHidden));\n      }\n      if (links[i].end === this && links[i].start && !(links[i].start.isInAgent() && !this.isInAgent())) {\n        neighbors.push({\n          item: links[i].start,\n          type: \"direct\"\n        });\n        neighbors = neighbors.concat(getAgentItems(links[i].start));\n      }\n    }\n\n\n\n    let res = [];\n    let seen = new Map();\n\n\n    // Remove duplicated elements\n    for (let i = 0; i < neighbors.length; i++) {\n      let n = neighbors[i];\n      if (n.linkHidden) {\n\n        continue;\n      }\n      let key = n.type + \" - \" + n.item.id;\n      let existing = seen.get(key);\n      if (existing) {\n        if (existing.linkHidden && !n.linkHidden) {\n          existing.linkHidden = false;\n        }\n        continue;\n      }\n      if ((n.item instanceof ValuedPrimitive) || (n.item instanceof Population)) {\n        seen.set(key, n);\n        res.push(n);\n      }\n\n    }\n    return res;\n\n    /**\n     * @param {Primitive} agent\n     * @param {boolean=} linkHidden\n     * @returns {NeighborhoodEntry[]}\n     */\n    function getAgentItems(agent, linkHidden) {\n      /** @type {NeighborhoodEntry[]} */\n      let res = [];\n      if ((agent instanceof Population) && agent.agentBase) {\n        let items = agent.agentBase.children();\n        items.forEach((x) => {\n          if (x instanceof ValuedPrimitive) {\n            res.push({\n              item: x,\n              type: \"agent\",\n              linkHidden: linkHidden,\n              name: x.name\n            });\n          }\n        });\n      }\n\n      res.sort((a, b) => {\n        if (a.name === b.name) {\n          return 0;\n        } else if (a.name > b.name) {\n          return 1;\n        } else {\n          return -1;\n        }\n      });\n\n      return res;\n    }\n  }\n\n\n\n  /**\n   * @return {string}\n   */\n  get id() {\n    return this._node.id;\n  }\n\n\n  /**\n   * @return {PrimitiveConfig[\"name\"]}\n   */\n  get name() {\n    return this._node.getAttribute(\"name\");\n  }\n\n  /**\n   * @param {PrimitiveConfig[\"name\"]} value\n   */\n  set name(value) {\n    this._node.setAttribute(\"name\", value);\n  }\n\n  /**\n   * @return {PrimitiveConfig[\"note\"]}\n   */\n  get note() {\n    return this._node.getAttribute(\"Note\");\n  }\n\n  /**\n   * @param {PrimitiveConfig[\"note\"]} value\n   */\n  set note(value) {\n    this._node.setAttribute(\"Note\", value);\n  }\n}\n\n\n\n/**\n * @typedef {object} ValuedConfig\n * @property {{max?: number, min?: number}=} constraints\n * @property {string=} units\n * @property {boolean=} external\n */\n\n\n\nexport class ValuedPrimitive extends Primitive {\n  /**\n   * @return {ValuedConfig[\"units\"]}\n   */\n  get units() {\n    return this._node.getAttribute(\"Units\");\n  }\n\n  /**\n   * @param {ValuedConfig[\"units\"]} value\n   */\n  set units(value) {\n    this._node.setAttribute(\"Units\", value);\n  }\n\n  /**\n   * @return {ValuedConfig[\"constraints\"]}\n   */\n  get constraints() {\n    let res = {};\n    if (isTrue(this._node.getAttribute(\"MinConstraintUsed\"))) {\n      res.min = +this._node.getAttribute(\"MinConstraint\");\n    }\n    if (isTrue(this._node.getAttribute(\"MaxConstraintUsed\"))) {\n      res.max = +this._node.getAttribute(\"MaxConstraint\");\n    }\n    return res;\n  }\n\n  /**\n   * @param {ValuedConfig[\"constraints\"]} constraints\n   */\n  set constraints(constraints) {\n    this._node.setAttribute(\"MinConstraint\", constraints.min);\n    this._node.setAttribute(\"MinConstraintUsed\", \"min\" in constraints);\n    this._node.setAttribute(\"MaxConstraint\", constraints.max);\n    this._node.setAttribute(\"MaxConstraintUsed\", \"max\" in constraints);\n  }\n\n\n  /**\n   * @return {ValuedConfig[\"external\"]}\n   */\n  get external() {\n    return isTrue(this._node.getAttribute(\"ShowSlider\"));\n  }\n\n  /**\n   * @param {ValuedConfig[\"external\"]} value\n   */\n  set external(value) {\n    this._node.setAttribute(\"ShowSlider\", value);\n  }\n}\n\n\n\n/**\n * @typedef {object} StockConfig\n * @property {Value=} initial\n * @property {StockTypeType=} type\n * @property {boolean=} nonNegative\n * @property {Value=} delay\n */\n\nexport class Stock extends ValuedPrimitive {\n  /**\n   * @return {string}\n   */\n  get initial() {\n    return this._node.getAttribute(\"InitialValue\") || \"\";\n  }\n\n  /**\n   * @param {StockConfig[\"initial\"]} value\n   */\n  set initial(value) {\n    this._node.setAttribute(\"InitialValue\", \"\" + value);\n  }\n\n  /**\n   * @return {StockConfig[\"type\"]}\n   */\n  get type() {\n    return /** @type {any} */ (this._node.getAttribute(\"StockMode\"));\n  }\n\n  /**\n   * @param {StockConfig[\"type\"]} value\n   */\n  set type(value) {\n    this._node.setAttribute(\"StockMode\", \"\" + value);\n  }\n\n  /**\n   * @return {string}\n   */\n  get delay() {\n    return this._node.getAttribute(\"Delay\");\n  }\n\n  /**\n   * @param {StockConfig[\"delay\"]} value\n   */\n  set delay(value) {\n    this._node.setAttribute(\"Delay\", \"\" + value);\n  }\n\n  /**\n   * @return {StockConfig[\"nonNegative\"]}\n   */\n  get nonNegative() {\n    return isTrue(this._node.getAttribute(\"NonNegative\"));\n  }\n\n  /**\n   * @param {StockConfig[\"nonNegative\"]} value\n   */\n  set nonNegative(value) {\n    this._node.setAttribute(\"NonNegative\", value);\n  }\n}\n\n\n/**\n * @typedef {object} VariableConfig\n * @property {Value=} value\n */\n\nexport class Variable extends ValuedPrimitive {\n  /**\n   * @return {string}\n   */\n  get value() {\n    return this._node.getAttribute(\"Equation\") || \"\";\n  }\n\n  /**\n   * @param {VariableConfig[\"value\"]} value\n   */\n  set value(value) {\n    this._node.setAttribute(\"Equation\", \"\" + value);\n  }\n}\n\n\n/**\n * @typedef {object} ConverterConfig\n * @property {\"Discrete\"|\"Linear\"=} interpolation\n * @property {\"Time\"|ValuedPrimitive=} input\n * @property {{x: number, y: number}[]=} values\n */\n\nexport class Converter extends ValuedPrimitive {\n  /**\n   * @return {ConverterConfig[\"interpolation\"]}\n   */\n  get interpolation() {\n    return /** @type {any} */ (this._node.getAttribute(\"Interpolation\"));\n  }\n\n  /**\n   * @param {ConverterConfig[\"interpolation\"]} value\n   */\n  set interpolation(value) {\n    this._node.setAttribute(\"Interpolation\", value);\n  }\n\n\n  /**\n   * @return {ConverterConfig[\"values\"]}\n   */\n  get values() {\n    return this._node.getAttribute(\"Data\").split(\";\").map(row => {\n      let parts = row.split(\",\");\n      if (parts.length !== 2) {\n        throw new ModelError(`Converter data point should have the form \"x, y\", got \"${row}\"`, {\n          primitive: this,\n          code: 2100\n        });\n      }\n\n\n      let res = {\n        x: +parts[0],\n        y: +parts[1]\n      };\n\n      if (isNaN(res.x) || isNaN(res.y)) {\n        throw new ModelError(`Converter has invalid data \"${row}\"`, {\n          primitive: this,\n          showEditor: true,\n          code: 2101\n        });\n      }\n\n      return res;\n    });\n  }\n\n  /**\n   * @param {ConverterConfig[\"values\"]} value\n   */\n  set values(value) {\n    this._node.setAttribute(\"Data\", value.map(x => x.x + \",\" + x.y).join(\";\"));\n  }\n\n\n  /**\n   * @return {ConverterConfig[\"input\"]}\n   */\n  get input() {\n    let v = this._node.getAttribute(\"Source\");\n\n    if (v === \"Time\") {\n      return v;\n    }\n\n    let p = null;\n    try {\n      p = this.model.getId(v);\n    } catch (_err) {\n      // the source does not exist, return null;\n    }\n\n\n    return /** @type {ValuedPrimitive} */ (p);\n  }\n\n  /**\n   * @param {ConverterConfig[\"input\"]} value\n   */\n  set input(value) {\n    this._node.setAttribute(\"Source\", value === \"Time\" ? value : value.id);\n  }\n\n}\n\n\n/**\n * @typedef {object} FlowConfig\n * @property {Value=} rate\n * @property {Stock|null=} start\n * @property {Stock|null=} end\n * @property {boolean=} nonNegative\n */\n\nexport class Flow extends ValuedPrimitive {\n  /**\n   * @return {string}\n   */\n  get rate() {\n    return this._node.getAttribute(\"FlowRate\") || \"\";\n  }\n\n  /**\n   * @param {FlowConfig[\"rate\"]} value\n   */\n  set rate(value) {\n    this._node.setAttribute(\"FlowRate\", \"\" + value);\n  }\n\n  /**\n   * @return {FlowConfig[\"start\"]}\n   */\n  get start() {\n    return /** @type {Stock} */ (this._node.source ? this._node.source.primitive(this.model) : null);\n  }\n\n  /**\n   * @param {FlowConfig[\"start\"]} node\n   */\n  set start(node) {\n    this._node.source = node._node;\n  }\n\n  /**\n   * @return {FlowConfig[\"end\"]}\n   */\n  get end() {\n    return /** @type {Stock} */ (this._node.target ? this._node.target.primitive(this.model) : null);\n  }\n\n  /**\n   * @param {FlowConfig[\"end\"]} node\n   */\n  set end(node) {\n    this._node.target = node._node;\n  }\n\n  /**\n   * @return {FlowConfig[\"nonNegative\"]}\n   */\n  get nonNegative() {\n    return isTrue(this._node.getAttribute(\"OnlyPositive\"));\n  }\n\n  /**\n   * @param {FlowConfig[\"nonNegative\"]} value\n   */\n  set nonNegative(value) {\n    this._node.setAttribute(\"OnlyPositive\", value);\n  }\n}\n\n\n/**\n * @typedef {object} LinkConfig\n * @property {boolean=} biDirectional\n * @property {Primitive|null=} start\n * @property {Primitive|null=} end\n */\n\nexport class Link extends Primitive {\n  /**\n   * @return {LinkConfig[\"biDirectional\"]}\n   */\n  get biDirectional() {\n    return isTrue(this._node.getAttribute(\"BiDirectional\"));\n  }\n\n  /**\n   * @param {LinkConfig[\"biDirectional\"]} value\n   */\n  set biDirectional(value) {\n    this._node.setAttribute(\"BiDirectional\", value);\n  }\n\n  /**\n   * @return {LinkConfig[\"start\"]}\n   */\n  get start() {\n    return this._node.source ? this._node.source.primitive(this.model) : null;\n  }\n\n  /**\n   * @param {LinkConfig[\"start\"]} node\n   */\n  set start(node) {\n    this._node.source = node._node;\n  }\n\n  /**\n   * @return {LinkConfig[\"end\"]}\n   */\n  get end() {\n    return this._node.target ? this._node.target.primitive(this.model) : null;\n  }\n\n  /**\n   * @param {LinkConfig[\"end\"]} node\n   */\n  set end(node) {\n    this._node.target = node._node;\n  }\n}\n\n\n/**\n * @typedef {object} StateConfig\n * @property {string|boolean=} startActive\n * @property {Value=} residency\n */\n\nexport class State extends ValuedPrimitive {\n  /**\n   * @return {StateConfig[\"startActive\"]}\n   */\n  get startActive() {\n    return this._node.getAttribute(\"Active\");\n  }\n\n  /**\n   * @param {StateConfig[\"startActive\"]} value\n   */\n  set startActive(value) {\n    this._node.setAttribute(\"Active\", value);\n  }\n\n  /**\n   * @return {string}\n   */\n  get residency() {\n    return this._node.getAttribute(\"Residency\");\n  }\n\n  /**\n   * @param {StateConfig[\"residency\"]} value\n   */\n  set residency(value) {\n    this._node.setAttribute(\"Residency\", value);\n  }\n}\n\n\n\n/**\n * @typedef {object} TransitionConfig\n * @property {Value=} value\n * @property {State|null=} start\n * @property {State|null=} end\n * @property {boolean=} recalculate\n * @property {boolean=} repeat\n * @property {TriggerType=} trigger\n */\n\nexport class Transition extends ValuedPrimitive {\n  /**\n   * @return {TransitionConfig[\"value\"]}\n   */\n  get value() {\n    return this._node.getAttribute(\"Value\") || \"\";\n  }\n\n  /**\n   * @param {TransitionConfig[\"value\"]} value\n   */\n  set value(value) {\n    this._node.setAttribute(\"Value\", \"\" + value);\n  }\n\n\n  /**\n   * @return {TransitionConfig[\"start\"]}\n   */\n  get start() {\n    return /** @type {State} */ (this._node.source ? this._node.source.primitive(this.model) : null);\n  }\n\n  /**\n   * @param {TransitionConfig[\"start\"]} node\n   */\n  set start(node) {\n    this._node.source = node._node;\n  }\n\n\n  /**\n   * @return {TransitionConfig[\"end\"]}\n   */\n  get end() {\n    return /** @type {State} */ (this._node.target ? this._node.target.primitive(this.model) : null);\n  }\n\n  /**\n   * @param {TransitionConfig[\"end\"]} node\n   */\n  set end(node) {\n    this._node.target = node._node;\n  }\n\n\n  /**\n   * @return {TransitionConfig[\"recalculate\"]}\n   */\n  get recalculate() {\n    return isTrue(this._node.getAttribute(\"Recalculate\"));\n  }\n\n  /**\n   * @param {TransitionConfig[\"recalculate\"]} value\n   */\n  set recalculate(value) {\n    this._node.setAttribute(\"Recalculate\", value);\n  }\n\n\n  /**\n   * @return {TransitionConfig[\"repeat\"]}\n   */\n  get repeat() {\n    return isTrue(this._node.getAttribute(\"Repeat\"));\n  }\n\n  /**\n   * @param {TransitionConfig[\"repeat\"]} value\n   */\n  set repeat(value) {\n    this._node.setAttribute(\"Repeat\", value);\n  }\n\n\n  /**\n   * @return {TransitionConfig[\"trigger\"]}\n   */\n  get trigger() {\n    return /** @type {any} */ (this._node.getAttribute(\"Trigger\"));\n  }\n\n  /**\n   * @param {TransitionConfig[\"trigger\"]} value\n   */\n  set trigger(value) {\n    this._node.setAttribute(\"Trigger\", value);\n  }\n}\n\n\n/**\n * @typedef {object} ActionConfig\n * @property {Value=} value\n * @property {boolean=} recalculate\n * @property {boolean=} repeat\n * @property {TriggerType=} trigger\n * @property {string=} action\n */\n\nexport class Action extends Primitive {\n  /**\n   * @return {string}\n   */\n  get value() {\n    return this._node.getAttribute(\"Value\") || \"\";\n  }\n\n  /**\n   * @param {ActionConfig[\"value\"]} value\n   */\n  set value(value) {\n    this._node.setAttribute(\"Value\", \"\" + value);\n  }\n\n\n  /**\n   * @return {ActionConfig[\"action\"]}\n   */\n  get action() {\n    return this._node.getAttribute(\"Action\");\n  }\n\n  /**\n     * @param {ActionConfig[\"action\"]} value\n     */\n  set action(value) {\n    this._node.setAttribute(\"Action\", \"\" + value);\n  }\n\n\n  /**\n   * @return {ActionConfig[\"recalculate\"]}\n   */\n  get recalculate() {\n    return isTrue(this._node.getAttribute(\"Recalculate\"));\n  }\n\n  /**\n   * @param {ActionConfig[\"recalculate\"]} value\n   */\n  set recalculate(value) {\n    this._node.setAttribute(\"Recalculate\", value);\n  }\n\n\n  /**\n   * @return {ActionConfig[\"repeat\"]}\n   */\n  get repeat() {\n    return isTrue(this._node.getAttribute(\"Repeat\"));\n  }\n\n  /**\n   * @param {ActionConfig[\"repeat\"]} value\n   */\n  set repeat(value) {\n    this._node.setAttribute(\"Repeat\", value);\n  }\n\n\n  /**\n   * @return {ActionConfig[\"trigger\"]}\n   */\n  get trigger() {\n    return /** @type {any} */ (this._node.getAttribute(\"Trigger\"));\n  }\n\n  /**\n   * @param {ActionConfig[\"trigger\"]} value\n   */\n  set trigger(value) {\n    this._node.setAttribute(\"Trigger\", value);\n  }\n}\n\n\n/**\n * @typedef {object} PopulationConfig\n * @property {Agent=} agentBase\n * @property {number=} populationSize\n * @property {string=} geoUnits\n * @property {Value=} geoWidth\n * @property {Value=} geoHeight\n * @property {boolean=} geoWrapAround\n * @property {PlacementType=} geoPlacementType\n * @property {string=} geoPlacementFunction\n * @property {NetworkType=} networkType\n * @property {string=} networkFunction\n */\n\nexport class Population extends Primitive {\n  /**\n   * @return {PopulationConfig[\"agentBase\"]}\n   */\n  get agentBase() {\n    let targetId = this._node.getAttribute(\"Agent\");\n\n    if (!targetId) {\n      return null;\n    }\n\n    let base = null;\n    try {\n      base = this.model.getId(targetId);\n    } catch (_err) {\n      // the source does not exist, return null;\n    }\n\n    return /** @type {Agent} */ (base);\n  }\n\n  /**\n   * @param {PopulationConfig[\"agentBase\"]} value\n   */\n  set agentBase(value) {\n    this._node.setAttribute(\"Agent\", value.id);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"populationSize\"]}\n   */\n  get populationSize() {\n    return +this._node.getAttribute(\"Size\");\n  }\n\n  /**\n   * @param {PopulationConfig[\"populationSize\"]} value\n   */\n  set populationSize(value) {\n    this._node.setAttribute(\"Size\", value);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"geoUnits\"]}\n   */\n  get geoUnits() {\n    return this._node.getAttribute(\"GeoDimUnits\");\n  }\n\n  /**\n   * @param {PopulationConfig[\"geoUnits\"]} value\n   */\n  set geoUnits(value) {\n    this._node.setAttribute(\"GeoDimUnits\", value);\n  }\n\n\n  /**\n   * @return {string}\n   */\n  get geoWidth() {\n    return this._node.getAttribute(\"GeoWidth\");\n  }\n\n  /**\n   * @param {PopulationConfig[\"geoWidth\"]} value\n   */\n  set geoWidth(value) {\n    this._node.setAttribute(\"GeoWidth\", value);\n  }\n\n\n  /**\n   * @return {string}\n   */\n  get geoHeight() {\n    return this._node.getAttribute(\"GeoHeight\");\n  }\n\n  /**\n   * @param {PopulationConfig[\"geoHeight\"]} value\n   */\n  set geoHeight(value) {\n    this._node.setAttribute(\"GeoHeight\", value);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"geoWrapAround\"]}\n   */\n  get geoWrapAround() {\n    return isTrue(this._node.getAttribute(\"GeoWrap\"));\n  }\n\n  /**\n   * @param {PopulationConfig[\"geoWrapAround\"]} value\n   */\n  set geoWrapAround(value) {\n    this._node.setAttribute(\"GeoWrap\", value);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"geoPlacementType\"]}\n   */\n  get geoPlacementType() {\n    return /** @type {any} */ (this._node.getAttribute(\"Placement\"));\n  }\n\n  /**\n   * @param {PopulationConfig[\"geoPlacementType\"]} value\n   */\n  set geoPlacementType(value) {\n    this._node.setAttribute(\"Placement\", value);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"geoPlacementFunction\"]}\n   */\n  get geoPlacementFunction() {\n    return this._node.getAttribute(\"PlacementFunction\");\n  }\n\n  /**\n   * @param {PopulationConfig[\"geoPlacementFunction\"]} value\n   */\n  set geoPlacementFunction(value) {\n    this._node.setAttribute(\"PlacementFunction\", value);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"networkType\"]}\n   */\n  get networkType() {\n    return /** @type {any} */ (this._node.getAttribute(\"Network\"));\n  }\n\n  /**\n   * @param {PopulationConfig[\"networkType\"]} value\n   */\n  set networkType(value) {\n    this._node.setAttribute(\"Network\", value);\n  }\n\n\n  /**\n   * @return {PopulationConfig[\"networkFunction\"]}\n   */\n  get networkFunction() {\n    return this._node.getAttribute(\"NetworkFunction\");\n  }\n\n  /**\n   * @param {PopulationConfig[\"networkFunction\"]} value\n   */\n  set networkFunction(value) {\n    this._node.setAttribute(\"NetworkFunction\", value);\n  }\n}\n\n\n/**\n * @typedef {object} ContainerConfig\n * @property {boolean=} frozen\n * @property {{ enabled: boolean, algorithm: import(\"./Model\").AlgorithmType, timeStep: number}=} customTimeSettings\n */\n\nexport class Container extends Primitive {\n  children(recursive = true) {\n    let children = this._node.children ? this._node.children.map(x => x.primitive(this.model)) : [];\n\n    if (recursive) {\n      let childrenLength = children.length;\n      for (let i = 0; i < childrenLength; i++) {\n        let child = children[i];\n        if (child instanceof Container) {\n          children = children.concat(child.children(recursive));\n        }\n      }\n    }\n\n    return children;\n  }\n\n  /**\n   * @param {PrimitiveConfig & ValuedConfig & StockConfig} config\n   */\n  Stock(config = {}) {\n    let stock = this.model.Stock(config);\n    stock.parent = this;\n    return stock;\n  }\n\n  /**\n   * @param {PrimitiveConfig & ValuedConfig & VariableConfig} config\n   */\n  Variable(config = {}) {\n    let variable = this.model.Variable(config);\n    variable.parent = this;\n    return variable;\n  }\n\n  /**\n   * @param {PrimitiveConfig & ValuedConfig & ConverterConfig} config\n   */\n  Converter(config = {}) {\n    let converter = this.model.Converter(config);\n    converter.parent = this;\n    return converter;\n  }\n\n  /**\n   * @param {PrimitiveConfig & StateConfig} config\n   */\n  State(config = {}) {\n    let state = this.model.State(config);\n    state.parent = this;\n    return state;\n  }\n\n  /**\n   * @param {PrimitiveConfig & ActionConfig} config\n   */\n  Action(config = {}) {\n    let action = this.model.Action(config);\n    action.parent = this;\n    return action;\n  }\n\n  /**\n   * @param {PrimitiveConfig & PopulationConfig} config\n   */\n  Population(config = {}) {\n    let population = this.model.Population(config);\n    population.parent = this;\n    return population;\n  }\n\n  /**\n   * @param {Stock|null} start\n   * @param {Stock|null} end\n   * @param {(PrimitiveConfig & ValuedConfig & FlowConfig)=} config\n   */\n  Flow(start, end, config = {}) {\n    let flow = this.model.Flow(start, end, config);\n    flow.parent = this;\n    return flow;\n  }\n\n  /**\n   * @param {State|null} start\n   * @param {State|null} end\n   * @param {(PrimitiveConfig & TransitionConfig)=} config\n   */\n  Transition(start, end, config = {}) {\n    let transition = this.model.Transition(start, end, config);\n    transition.parent = this;\n    return transition;\n  }\n\n  /**\n   * @param {Primitive|null} start\n   * @param {Primitive|null} end\n   * @param {(PrimitiveConfig & LinkConfig)=} config\n   */\n  Link(start, end, config = {}) {\n    let link = this.model.Link(start, end, config);\n    link.parent = this;\n    return link;\n  }\n\n\n  /**\n   * @return {ContainerConfig[\"frozen\"]}\n   */\n  get frozen() {\n    return isTrue(this._node.getAttribute(\"Frozen\"));\n  }\n\n  /**\n   * @param {ContainerConfig[\"frozen\"]} value\n   */\n  set frozen(value) {\n    this._node.setAttribute(\"Frozen\", value);\n  }\n\n  /**\n   * @return {ContainerConfig[\"customTimeSettings\"]}\n   */\n  get customTimeSettings() {\n    let value = JSON.parse(this._node.getAttribute(\"Solver\") || \"{}\");\n    if (value.algorithm === \"RK1\") {\n      value.algorithm = \"Euler\";\n    }\n    return value;\n  }\n\n  /**\n   * @param {ContainerConfig[\"customTimeSettings\"]} value\n   */\n  set customTimeSettings(value) {\n    /** @type {any} */\n    let newValue = Object.assign({}, value);\n    if (newValue.algorithm === \"Euler\") {\n      newValue.algorithm = \"RK1\";\n    }\n    this._node.setAttribute(\"Solver\", JSON.stringify(newValue));\n  }\n}\n\n\n/**\n * @typedef {object} FolderConfig\n */\n\nexport class Folder extends Container {\n\n}\n\n\n/**\n * @typedef {object} AgentConfig\n * @property {string=} agentParent\n */\n\n\nexport class Agent extends Container {\n  /**\n   * @return {AgentConfig[\"agentParent\"]}\n   */\n  get agentParent() {\n    return this._node.getAttribute(\"AgentBase\");\n  }\n\n  /**\n   * @param {AgentConfig[\"agentParent\"]} value\n   */\n  set agentParent(value) {\n    this._node.setAttribute(\"AgentBase\", value);\n  }\n}", "src/api/Model.js": "import { ModelNode, modelNodeClone, primitives } from \"../ModelNode.js\";\nimport { runSimulation } from \"../Modeler.js\";\nimport { nodeBase } from \"../Constants.js\";\n\nimport { Primitive, Stock, Variable, Converter, State, Action, Population, Flow, Transition, Link, Agent, Folder } from \"./Blocks.js\";\nimport { Results } from \"./Results.js\";\nimport { SimulationError } from \"./SimulationError.js\";\nimport { createModelJSON, loadModelJSON } from \"./import_export/ModelJSON/ModelJSON.js\";\nimport { loadInsightMaker } from \"./import_export/InsightMaker/InsightMaker.js\";\nimport { Simulator } from \"../Simulator.js\";\nimport { trimTree, createTree } from \"../formula/Formula.js\";\nimport { ModelError } from \"../formula/ModelError.js\";\nexport { Primitive, Stock, Variable, Converter, State, Action, Population, Flow, Transition, Link, Agent, Folder, createModelJSON as toModelJSON, loadModelJSON, loadInsightMaker };\n\n\n/**\n * @typedef {{ name: string, target: string, scale: number}[]} CustomUnitsType\n */\n\n\n/**\n * @typedef {\"Euler\"|\"RK4\"} AlgorithmType\n */\n\n\n/**\n * @typedef {object} ModelConfig\n * @property {function} primitiveFn\n * @property {number} timeStart\n * @property {number} timeLength\n * @property {number} timeStep\n * @property {number=} timePause\n * @property {AlgorithmType} algorithm\n * @property {\"Seconds\"|\"Minutes\"|\"Hours\"|\"Days\"|\"Weeks\"|\"Months\"|\"Years\"} timeUnits\n */\n\n/**\n * @typedef {Partial<ModelConfig>} ModelConfigOptions\n */\n\n\n\n\n/**\n * @param {Model} model\n */\nexport function removeModelGhosts(model) {\n  /** @type {(Flow|Transition|Link)[]} */\n  let connectors = model.findLinks();\n  connectors = connectors.concat(model.findFlows()).concat(model.findTransitions());\n\n  let items = model.find();\n  /**  @type {Object<string, Primitive>} */\n  let idMapping = {};\n  for (let item of items) {\n    idMapping[item.id] = item;\n  }\n\n  for (let connector of connectors) {\n    if (connector._node.source && connector._node.source.value.nodeName === \"Ghost\") {\n      let item = idMapping[connector._node.source.getAttribute(\"Source\")];\n      if (item) {\n        connector._node.source = item._node;\n      } else {\n        // may not exist for instance in the case of connecting to a <Picture/>\n        connector.delete();\n      }\n    }\n    if (connector._node.target && connector._node.target.value.nodeName === \"Ghost\") {\n      let item = idMapping[connector._node.target.getAttribute(\"Source\")];\n      if (item) {\n        connector._node.target = item._node;\n      } else {\n        connector.delete();\n      }\n    }\n  }\n}\n\n\nexport class Model {\n  /**\n   * @param {ModelConfigOptions=} config\n   */\n  constructor(config = {}) {\n    /** @type {string} */\n    this.name = null;\n    /** @type {string} */\n    this.description = null;\n    this.visualizations = [];\n    this.scenarios = [];\n\n    this._graph = new ModelNode();\n    this._graph.id = \"1\";\n    this._graph.addChild(new ModelNode());\n    this._graph.children[0].addChild(new ModelNode());\n\n    this.settings = this._createNode(\"setting\");\n\n    this.p = config.primitiveFn || primitives;\n\n\n    for (let key in excludeKeys(config, [\"primitiveFn\"])) {\n      if (key in this) {\n        this[key] = config[key];\n      } else {\n        throw new Error(\"Unknown model property: \" + key);\n      }\n    }\n  }\n\n  /**\n   * @param {string} type\n   */\n  _createNode(type) {\n    let parent = this._graph.children[0].children[0];\n    let node = modelNodeClone(nodeBase[type], parent);\n    parent.addChild(node);\n\n    return node;\n  }\n\n  /**\n   * @param {string} type\n   * @param {Primitive} alpha\n   * @param {Primitive} omega\n   */\n  _createConnector(type, alpha, omega) {\n    let parent = this._graph.children[0].children[0];\n\n    if (alpha) {\n      parent = alpha._node.parent;\n    }\n    if (omega) {\n      parent = omega._node.parent;\n    }\n    let edge = modelNodeClone(nodeBase[type], parent);\n    parent.addChild(edge);\n\n    if (alpha) {\n      edge.source = alpha._node;\n    } else {\n      edge.source = null;\n    }\n    if (omega) {\n      edge.target = omega._node;\n    } else {\n      edge.target = null;\n    }\n\n    return edge;\n  }\n\n  /**\n   * Checks the model for some static errors (e.g syntax errors). The model is not run and runtime errors are not checked.\n   *\n   * The function returns an array of errors found.\n   *\n   * @returns {ModelError[]}\n   */\n  check() {\n    let simulate = new Simulator();\n    let errors = [];\n\n\n    /**\n     * @param {Primitive} p\n     * @param {string} eq\n     * @returns\n     */\n    function equationCheck(p, eq) {\n      let tree;\n      // check for syntax errors\n      try {\n        tree = createTree(eq, \"_\", simulate);\n      } catch (e) {\n        e.primitive = p;\n        errors.push(e);\n        return;\n      }\n\n      // check that we have all the primitives connected\n      let neighbors = p.neighbors();\n      let flaggedMissing = new Set();\n      try {\n        // @ts-ignore\n        trimTree(tree, {\n          get: (name) => {\n            if (!flaggedMissing.has(name)) {\n              if (!neighbors.find(x => x.item.name.toLowerCase() === name.toLowerCase())) {\n                flaggedMissing.add(name.toLowerCase());\n                errors.push(new ModelError(\"Attempted to reference [\" + name + \"] but it was not linked.\", {\n                  primitive: p,\n                  code: 9912,\n                  details: name\n                }));\n              }\n            }\n            return null;\n          }\n        }, simulate);\n      } catch (e) {\n        return e;\n      }\n\n      return null;\n    }\n\n\n\n    let stocks = this.findStocks();\n    for (let stock of stocks) {\n      equationCheck(stock, stock.initial);\n    }\n\n    let flows = this.findFlows();\n    for (let flow of flows) {\n      equationCheck(flow, flow.rate);\n    }\n\n    let variables = this.findVariables();\n    for (let variable of variables) {\n      equationCheck(variable, variable.value);\n    }\n\n    let states = this.findStates();\n    for (let state of states) {\n      equationCheck(state, \"\" + state.startActive);\n    }\n\n    let transitions = this.findTransitions();\n    for (let transition of transitions) {\n      equationCheck(transition, \"\" + transition.value);\n    }\n\n    let populations = this.findPopulations();\n    for (let population of populations) {\n      equationCheck(population, \"\" + population.networkFunction);\n\n      equationCheck(population, \"\" + population.geoPlacementFunction);\n\n      equationCheck(population, \"\" + population.populationSize);\n\n    }\n\n    return errors;\n  }\n\n\n  /**\n   * Async simulation mode. Allows for pausing the simulation and adjusting\n   * values. Returns a promise that resolves with the results or rejects\n   * with an error.\n   *\n   * @param {object} options\n   * @param {function({ results: Results, time: number, setValue: function(Primitive, any) })=} options.onStep - async function that will be awaited each time step prior to simulation resuming, use setValue() to adjust values.\n   *\n   * @returns {Promise<Results, { error: string, errorCode: number, errorPrimitive: Primitive, errorPrimitiveName: string, errorPrimitiveId: string}|Error>}\n   */\n  async simulateAsync(options = {}) {\n    if (\"onPause\" in options) {\n      throw new Error(\"onPause has been replaced by onStep which is called each time step.\");\n    }\n\n    return new Promise((resolve, reject) => {\n      /** @type {import(\"../Modeler.js\").SimulationConfigType} */\n      let config = {\n        silent: true,\n        model: this\n      };\n\n      if (options.onStep) {\n        config.pauseEachTimeStep = true;\n        config.onPause = async (results) => {\n          let items = this.find();\n          /** @type {Object<string, string>} */\n          let nameIdMapping = {};\n          for (let item of items) {\n            nameIdMapping[item.id] = item.name;\n          }\n\n          try {\n            await options.onStep({\n              results: new Results(results, nameIdMapping),\n              time: results.times.at(-1),\n              setValue: (primitive, value) => {\n                results.setValue(primitive._node, value);\n              }\n            });\n          } catch (e) {\n            reject(e);\n            return;\n          }\n\n          results.resume();\n        };\n      }\n\n      config.onSuccess = (results) => {\n        let items = this.find();\n        /** @type {Object<string, string>} */\n        let nameIdMapping = {};\n        for (let item of items) {\n          nameIdMapping[item.id] = item.name;\n        }\n\n        resolve(new Results(results, nameIdMapping));\n      };\n\n      config.onError = (results) => {\n        let ep = results.errorPrimitive ? this.get(p => p.id === results.errorPrimitive.id) : null;\n        let e = {\n          error: results.error,\n          errorCode: results.errorCode\n        };\n        if (ep) {\n          e.errorPrimitiveName = ep.name;\n          e.errorPrimitiveId = ep.id;\n          Object.defineProperty(e, \"errorPrimitive\", {\n            value: ep,\n            enumerable: false // so we don't get massive errors\n          });\n        }\n        reject(e);\n      };\n\n\n      runSimulation(config);\n    });\n  }\n\n\n  simulate() {\n    let config = {\n      silent: true,\n      model: this\n    };\n\n    let results = runSimulation(config);\n    if (results.error) {\n      let config = {\n        code: results.errorCode\n      };\n      if (results.errorPrimitive) {\n        config.primitive = this.get(p => p.id === results.errorPrimitive.id);\n      }\n      config.line = results.errorLine;\n      config.source = results.errorSource;\n\n      throw new SimulationError(results.error, config);\n    }\n\n    let items = this.find();\n    /** @type {Object<string, string>} */\n    let nameIdMapping = {};\n    for (let item of items) {\n      nameIdMapping[item.id] = item.name;\n    }\n\n    return new Results(results, nameIdMapping);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ValuedConfig & import(\"./Blocks.js\").StockConfig} config\n   *\n   * @return {Stock}\n   */\n  Stock(config = {}) {\n    let stock = /** @type {Stock} */ (this._createNode(\"stock\").primitive(this, excludeKeys(config, [\"name\"])));\n    stock.name = config.name || \"New Stock\";\n    stock.model = this;\n    return stock;\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ValuedConfig & import(\"./Blocks.js\").VariableConfig} config\n   *\n   * @return {Variable}\n   */\n  Variable(config = {}) {\n    let variable = this._createNode(\"variable\").primitive(this, excludeKeys(config, [\"name\"]));\n    variable.name = config.name || \"New Variable\";\n    variable.model = this;\n    return /** @type {Variable} */ (variable);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ValuedConfig & import(\"./Blocks.js\").ConverterConfig} config\n   *\n   * @return {Converter}\n   */\n  Converter(config = {}) {\n    let converter = this._createNode(\"converter\").primitive(this, excludeKeys(config, [\"name\"]));\n    converter.name = config.name || \"New Converter\";\n    converter.model = this;\n    return /** @type {Converter} */ (converter);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").StateConfig} config\n   *\n   * @return {State}\n   */\n  State(config = {}) {\n    let state = this._createNode(\"state\").primitive(this, excludeKeys(config, [\"name\"]));\n    state.name = config.name || \"New State\";\n    state.model = this;\n    return /** @type {State} */ (state);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ActionConfig} config\n   *\n   * @return {Action}\n   */\n  Action(config = {}) {\n    let action = this._createNode(\"action\").primitive(this, excludeKeys(config, [\"name\"]));\n    action.name = config.name || \"New Action\";\n    action.model = this;\n    return /** @type {Action} */ (action);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").PopulationConfig} config\n   *\n   * @return {Population}\n   */\n  Population(config = {}) {\n    let population = this._createNode(\"agents\").primitive(this, excludeKeys(config, [\"name\"]));\n    population.name = config.name || \"New Population\";\n    population.model = this;\n    return /** @type {Population} */ (population);\n  }\n\n  /**\n   * @param {Stock|null} start\n   * @param {Stock|null} end\n   * @param {(import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ValuedConfig & import(\"./Blocks.js\").FlowConfig)=} config\n   *\n   * @return {Flow}\n   */\n  Flow(start, end, config = {}) {\n    let flow = this._createConnector(\"flow\", start || config.start || null, end || config.end || null).primitive(this, excludeKeys(config, [\"name\", \"start\", \"end\"]));\n    flow.name = config.name || \"New Flow\";\n    flow.model = this;\n    return /** @type {Flow} */ (flow);\n  }\n\n  /**\n   * @param {State|null} start\n   * @param {State|null} end\n   * @param {(import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").TransitionConfig)=} config\n   *\n   * @return {Transition}\n   */\n  Transition(start, end, config = {}) {\n    let transition = this._createConnector(\"transition\", start || config.start || null, end || config.end || null).primitive(this, excludeKeys(config, [\"name\", \"start\", \"end\"]));\n    transition.name = config.name || \"New Transition\";\n    transition.model = this;\n    return /** @type {Transition} */ (transition);\n  }\n\n  /**\n   * @param {Primitive|null} start\n   * @param {Primitive|null} end\n   * @param {(import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").LinkConfig)=} config\n   *\n   * @return {Link}\n   */\n  Link(start, end, config = {}) {\n    let link = this._createConnector(\"link\", start || config.start || null, end || config.end || null).primitive(this, excludeKeys(config, [\"name\", \"start\", \"end\"]));\n    link.name = config.name || \"Link\";\n    link.model = this;\n    return /** @type {Link} */ (link);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ContainerConfig & import(\"./Blocks.js\").AgentConfig} config\n   *\n   * @return {Agent}\n   */\n  Agent(config = {}) {\n    let agentCell = this._createNode(\"folder\");\n    // must be set before primitive() is called\n    agentCell.setAttribute(\"Type\", \"Agent\");\n    let agent = agentCell.primitive(this, excludeKeys(config, [\"name\"]));\n    agent.name = config.name || \"New Agent\";\n    agent.model = this;\n    return /** @type {Agent} */ (agent);\n  }\n\n  /**\n   * @param {import(\"./Blocks.js\").PrimitiveConfig & import(\"./Blocks.js\").ContainerConfig & import(\"./Blocks.js\").FolderConfig} config\n   *\n   * @return {Folder}\n   */\n  Folder(config = {}) {\n    let folder = this._createNode(\"folder\").primitive(this, excludeKeys(config, [\"name\"]));\n    folder.name = config.name || \"New Folder\";\n    folder.model = this;\n    folder._node.setAttribute(\"Type\", \"None\");\n    return /** @type {Folder} */ (folder);\n  }\n\n  /**\n   * @param {string} id\n   *\n   * @return {Primitive}\n   */\n  getId(id) {\n    return this.get((item) => item.id === id, \"getId\");\n  }\n\n\n  /**\n   * @param {function(Primitive):boolean} selector\n   * @param {string} fn\n   *\n   * @return {Primitive}\n   */\n  get(selector, fn = \"get\") {\n    let items = this.p(this._graph);\n    let found = items.find(x => x.primitive() && selector(x.primitive()));\n    if (!found) {\n      throw new Error(`No matching primitive found for ${fn}()`);\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Link):boolean} selector\n   *\n   * @return {Link}\n   */\n  getLink(selector) {\n    let items = this.p(this._graph, \"Link\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getLink()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Flow):boolean} selector\n   *\n   * @return {Flow}\n   */\n  getFlow(selector) {\n    let items = this.p(this._graph, \"Flow\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getFlow()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Transition):boolean} selector\n   *\n   * @return {Transition}\n   */\n  getTransition(selector) {\n    let items = this.p(this._graph, \"Transition\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getTransition()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Stock):boolean} selector\n   *\n   * @return {Stock}\n   */\n  getStock(selector) {\n    let items = this.p(this._graph, \"Stock\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getStock()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Variable):boolean} selector\n   *\n   * @return {Variable}\n   */\n  getVariable(selector) {\n    let items = this.p(this._graph, \"Variable\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getVariable()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Converter):boolean} selector\n   *\n   * @return {Converter}\n   */\n  getConverter(selector) {\n    let items = this.p(this._graph, \"Converter\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getConverter()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(State):boolean} selector\n   *\n   * @return {State}\n   */\n  getState(selector) {\n    let items = this.p(this._graph, \"State\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getState()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Action):boolean} selector\n   *\n   * @return {Action}\n   */\n  getAction(selector) {\n    let items = this.p(this._graph, \"Action\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getAction()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Population):boolean} selector\n   *\n   * @return {Population}\n   */\n  getPopulation(selector) {\n    let items = this.p(this._graph, \"Agents\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getPopulation()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Folder):boolean} selector\n   *\n   * @return {Folder}\n   */\n  getFolder(selector) {\n    let items = this.p(this._graph, \"Folder\").filter(x => x.getAttribute(\"Type\") !== \"Agent\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getFolder()\");\n    }\n    return found.primitive();\n  }\n\n  /**\n   * @param {function(Agent):boolean} selector\n   *\n   * @return {Agent}\n   */\n  getAgent(selector) {\n    let items = this.p(this._graph, \"Folder\").filter(x => x.getAttribute(\"Type\") === \"Agent\");\n\n    let found = items.find(x => selector(x.primitive()));\n\n    if (!found) {\n      throw new Error(\"No matching primitive found for getAgent()\");\n    }\n    return found.primitive();\n  }\n\n\n\n  /**\n   * @param {function(Primitive):boolean=} selector\n   *\n   * @return {Primitive[]}\n   */\n  find(selector = (() => true)) {\n    let items = this.p(this._graph);\n    return items.filter(x => x.primitive() && selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Link):boolean=} selector\n   *\n   * @return {Link[]}\n   */\n  findLinks(selector = (() => true)) {\n    let items = this.p(this._graph, \"Link\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Flow):boolean=} selector\n   *\n   * @return {Flow[]}\n   */\n  findFlows(selector = (() => true)) {\n    let items = this.p(this._graph, \"Flow\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Transition):boolean=} selector\n   *\n   * @return {Transition[]}\n   */\n  findTransitions(selector = (() => true)) {\n    let items = this.p(this._graph, \"Transition\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Stock):boolean=} selector\n   *\n   * @return {Stock[]}\n   */\n  findStocks(selector = (() => true)) {\n    let items = this.p(this._graph, \"Stock\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Variable):boolean=} selector\n   *\n   * @return {Variable[]}\n   */\n  findVariables(selector = (() => true)) {\n    let items = this.p(this._graph, \"Variable\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Converter):boolean=} selector\n   *\n   * @return {Converter[]}\n   */\n  findConverters(selector = (() => true)) {\n    let items = this.p(this._graph, \"Converter\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(State):boolean=} selector\n   *\n   * @return {State[]}\n   */\n  findStates(selector = (() => true)) {\n    let items = this.p(this._graph, \"State\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Action):boolean=} selector\n   *\n   * @return {Action[]}\n   */\n  findActions(selector = (() => true)) {\n    let items = this.p(this._graph, \"Action\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Population):boolean=} selector\n   *\n   * @return {Population[]}\n   */\n  findPopulations(selector = (() => true)) {\n    let items = this.p(this._graph, \"Agents\");\n\n    return items.filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Folder):boolean=} selector\n   *\n   * @return {Folder[]}\n   */\n  findFolders(selector = (() => true)) {\n    let items = this.p(this._graph, \"Folder\");\n\n    return items.filter(x => x.getAttribute(\"Type\") !== \"Agent\").filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n  /**\n   * @param {function(Agent):boolean=} selector\n   *\n   * @return {Agent[]}\n   */\n  findAgents(selector = (() => true)) {\n    let items = this.p(this._graph, \"Folder\");\n\n    return items.filter(x => x.getAttribute(\"Type\") === \"Agent\").filter(x => selector(x.primitive())).map(x => x.primitive());\n  }\n\n\n\n  /**\n   * @return {ModelConfig[\"timeStart\"]}\n   */\n  get timeStart() {\n    return +this.settings.getAttribute(\"TimeStart\");\n  }\n\n  /**\n   * @param {ModelConfig[\"timeStart\"]} value\n   */\n  set timeStart(value) {\n    this.settings.setAttribute(\"TimeStart\", value);\n  }\n\n\n  /**\n   * @return {ModelConfig[\"timeLength\"]}\n   */\n  get timeLength() {\n    return +this.settings.getAttribute(\"TimeLength\");\n  }\n\n  /**\n   * @param {ModelConfig[\"timeLength\"]} value\n   */\n  set timeLength(value) {\n    this.settings.setAttribute(\"TimeLength\", value);\n  }\n\n\n  /**\n   * @return {ModelConfig[\"timePause\"]}\n   */\n  get timePause() {\n    return +this.settings.getAttribute(\"TimePause\");\n  }\n\n  /**\n   * @param {ModelConfig[\"timePause\"]} value\n   */\n  set timePause(value) {\n    this.settings.setAttribute(\"TimePause\", value);\n  }\n\n\n  /**\n   * @return {ModelConfig[\"timeStep\"]}\n   */\n  get timeStep() {\n    return +this.settings.getAttribute(\"TimeStep\");\n  }\n\n  /**\n   * @param {ModelConfig[\"timeStep\"]} value\n   */\n  set timeStep(value) {\n    this.settings.setAttribute(\"TimeStep\", value);\n  }\n\n\n  /**\n   * @return {ModelConfig[\"timeUnits\"]}\n   */\n  get timeUnits() {\n    return /** @type {any} */ (this.settings.getAttribute(\"TimeUnits\"));\n  }\n\n  /**\n   * @param {ModelConfig[\"timeUnits\"]} value\n   */\n  set timeUnits(value) {\n    this.settings.setAttribute(\"TimeUnits\", value);\n  }\n\n\n  /**\n   * @return {ModelConfig[\"algorithm\"]}\n   */\n  get algorithm() {\n    let value = /** @type {any} */ (this.settings.getAttribute(\"SolutionAlgorithm\"));\n    if (value === \"RK1\") {\n      return \"Euler\";\n    }\n    return value;\n  }\n\n  /**\n   * @param {ModelConfig[\"algorithm\"]} value\n   */\n  set algorithm(value) {\n    let usedValue;\n    if (value === \"Euler\") {\n      usedValue = \"RK1\";\n    } else {\n      usedValue = value;\n    }\n    this.settings.setAttribute(\"SolutionAlgorithm\", usedValue);\n  }\n\n\n  /**\n   * @return {string}\n   */\n  get globals() {\n    return this.settings.getAttribute(\"Macros\") || \"\";\n  }\n\n  /**\n   * @param {string} value\n   */\n  set globals(value) {\n    this.settings.setAttribute(\"Macros\", value);\n  }\n\n\n  /**\n   * @return {CustomUnitsType}\n   */\n  get customUnits() {\n    return (this.settings.getAttribute(\"Units\") || \"\").split(\"\\n\").filter(x => !!x).map(unit => {\n      let parts = unit.split(\"<>\");\n      return {\n        name: parts[0],\n        scale: +parts[1],\n        target: parts[2]\n      };\n    });\n  }\n\n  /**\n   * @param {CustomUnitsType} value\n   */\n  set customUnits(value) {\n    this.settings.setAttribute(\"Units\", value.map(unit => unit.name + \"<>\" + unit.scale + \"<>\" + unit.target).join(\"\\n\"));\n  }\n}\n\n\n/**\n * @param {object} obj\n * @param {string[]} keys\n */\nfunction excludeKeys(obj, keys) {\n  let newObj = {};\n  for (let key in obj) {\n    if (!keys.includes(key)) {\n      newObj[key] = obj[key];\n    }\n  }\n  return newObj;\n}\n\n", "src/api/import_export/ModelJSON/ModelJSON.js": "import { isTrue } from \"../../../Utilities.js\";\nimport { Model } from \"../../Model.js\";\n\n\n/** @typedef {import(\"../../../SharedTypes.js\").GraphNode} GraphNode */\n\nconst TIME_UNITS = [\"SECONDS\", \"MINUTES\", \"HOURS\", \"DAYS\", \"WEEKS\", \"MONTHS\", \"YEARS\"];\n\n\n/**\n * Validates that an object only has the allowedKeys. Keys that aren't\n * on the list but start with \"_\" are ignored.\n *\n * @param {string} label\n * @param {object} object\n * @param {Object<string, string|string[]>} allowed\n * @param {string[]} errors\n *\n * @return {boolean} - true if there were no errors\n */\nfunction validateKeys(label, object, allowed, errors) {\n  let startErrorsLength = errors.length;\n\n  let keys = Object.keys(object);\n\n  for (let key of keys) {\n    if (key[0] === \"_\") {\n      continue;\n    }\n\n    if (!(key in allowed)) {\n      errors.push(`Invalid property \"${key}\" found in ${label}. Allowed properties are: ${Object.keys(allowed).map(k => `\"${k}\"`).join(\", \")}.`);\n      continue;\n    } else {\n      let type = allowed[key];\n      if (type === \"string\") {\n        if (object[key] === null && (key === \"from\" || key === \"to\")) {\n          // allow from/to to be null for connectors\n          continue;\n        }\n        if (typeof object[key] !== \"string\") {\n          errors.push(`Property \"${key}\" requires a string value. Got: ${object[key]}`);\n        }\n      } else if (type === \"number\") {\n        if (typeof object[key] !== \"number\") {\n          errors.push(`Property \"${key}\" requires a number value. Got: ${object[key]}`);\n        }\n      } else if (type === \"boolean\") {\n        if (typeof object[key] !== \"boolean\") {\n          errors.push(`Property \"${key}\" requires a boolean value. Got: ${object[key]}`);\n        }\n      } else if (type === \"equation\") {\n        if (typeof object[key] !== \"number\" && typeof object[key] !== \"boolean\" && typeof object[key] !== \"string\") {\n          errors.push(`Invalid value given for \"${key}\". Got: ${object[key]}`);\n        }\n      } else if (type === \"array\") {\n        if (!Array.isArray(object[key])) {\n          errors.push(`Property \"${key}\" requires an array value. Got: ${object[key]}`);\n        }\n      } else if (type === \"point\") {\n        if (!Array.isArray(object[key])) {\n          errors.push(`Property \"${key}\" requires an [x, y] value. Got: ${JSON.stringify(object[key])}`);\n        } else {\n          if (object[key].length !== 2 || typeof object[key][0] !== \"number\" || typeof object[key][1] !== \"number\") {\n            errors.push(`Property \"${key}\" requires an [x, y] value. Got: ${JSON.stringify(object[key])}`);\n          }\n        }\n      } else if (type === \"object\") {\n        if ((typeof object[key] !== \"object\") || object[key] === null || Array.isArray(object[key])) {\n          errors.push(`Property \"${key}\" requires an object value. Got: ${JSON.stringify(object[key])}`);\n        }\n      } else if (Array.isArray(type)) {\n        validateEnum(key, object[key], type, errors);\n      } else {\n        throw new Error(`Unknown type \"${type}\" in validateKeys.`);\n      }\n    }\n  }\n\n  if (startErrorsLength === errors.length) {\n    // no errors were added\n    return true;\n  }\n\n  return false;\n}\n\n\n/**\n * @param {string} label\n * @param {string} value\n * @param {string[]} allowedValues\n * @param {string[]} errors\n */\nfunction validateEnum(label, value, allowedValues, errors) {\n  if (value === undefined || value === null) {\n    return;\n  }\n\n  if (typeof value !== \"string\") {\n    errors.push(`Invalid value \"${value}\" given for \"${label}\". Allowed values are ${allowedValues.map(k => `\"${k}\"`).join(\", \")}`);\n    return;\n  }\n\n  if (value[0] === \"_\") {\n    return;\n  }\n\n  if (!allowedValues.includes(value)) {\n    errors.push(`Invalid value \"${value}\" given for \"${label}\". Allowed values are ${allowedValues.map(k => `\"${k}\"`).join(\", \")}`);\n  }\n}\n\n\n/**\n *\n * @param {object} object\n * @param {string[]} errors\n */\nfunction validateModel(object, errors) {\n  let noErrors = validateKeys(\n    \"the model\",\n    object,\n    {\n      \"name\": \"string\",\n      \"description\": \"string\",\n      \"file_notes\": \"string\",\n      \"engine\": [\"SIMULATION_PACKAGE\"],\n      \"simulation\": \"object\",\n      \"elements\": \"array\",\n      \"visualizations\": \"array\",\n      \"scenarios\": \"array\",\n      \"engine_settings\": \"object\"\n    },\n    errors\n  );\n\n  if (!noErrors) {\n    return;\n  }\n\n  if (object.simulation) {\n    validateKeys(\n      \"the simulation\",\n      object.simulation,\n      {\n        \"algorithm\": [\"RK1\", \"RK4\"],\n        \"time_start\": \"number\",\n        \"time_length\": \"number\",\n        \"time_step\": \"number\",\n        \"time_units\": TIME_UNITS\n      }, errors);\n  }\n\n  if (object.engine_settings) {\n    validateKeys(\n      \"the engine_settings\",\n      object.engine_settings,\n      {\n        \"units\": \"array\",\n        \"globals\": \"string\"\n      }, errors);\n\n\n    if (object.engine_settings.units && Array.isArray(object.engine_settings.units)) {\n      for (let unit of object.engine_settings.units) {\n        validateKeys(\n          \"a unit\",\n          unit,\n          {\n            \"name\": \"string\",\n            \"base\": \"string\",\n            \"factor\": \"number\"\n          }, errors);\n      }\n    }\n  }\n\n  if (object.visualizations) {\n    for (let visualization of object.visualizations) {\n      validateKeys(\n        \"a visualization\",\n        visualization,\n        {\n          \"type\": [\"TIME_SERIES\", \"TABLE\"],\n          \"name\": \"string\",\n          \"elements\": \"array\"\n        }, errors);\n\n      if (!visualization.elements) {\n        errors.push(\"Visualizations require an arrays of element names\");\n      } else {\n        if (Array.isArray(visualization.elements)) {\n          for (let el of visualization.elements) {\n            if (typeof el !== \"string\") {\n              errors.push(\"Visualizations' element names must be strings. Got \" + el);\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (object.scenarios) {\n    for (let scenario of object.scenarios) {\n      if (!scenario || typeof scenario !== \"object\" || Array.isArray(scenario)) {\n        errors.push(`Scenarios must be objects. Got: ${JSON.stringify(scenario)}`);\n        continue;\n      }\n\n      validateKeys(\n        \"a scenario\",\n        scenario,\n        {\n          \"name\": \"string\",\n          \"description\": \"string\",\n          \"values\": \"object\"\n        }, errors);\n      if (!(\"values\" in scenario)) {\n        errors.push(\"Scenarios require a values object.\");\n      }\n      if (scenario.values) {\n        for (let key in scenario.values) {\n          let val = scenario.values[key];\n          if (typeof val !== \"number\" && typeof val !== \"string\" && typeof val !== \"boolean\") {\n            errors.push(`Scenario value for \"${key}\" must be a number, string, or boolean. Got: ${val}`);\n          }\n        }\n      }\n    }\n  }\n\n\n\n\n  if (!object.elements) {\n    errors.push(\"You must have an array of elements\");\n  } else {\n    for (let element of object.elements) {\n      let allowedBase = {\n        \"type\": [\"STOCK\", \"VARIABLE\", \"CONVERTER\", \"STATE\", \"FLOW\", \"LINK\", \"TRANSITION\"],\n        \"name\": \"string\",\n        \"description\": \"string\",\n        \"behavior\": \"object\",\n        \"display\": \"object\"\n      };\n      /** @type {Object<string, string|string[]>} */\n      let allowedBehavior = {\n\n      };\n      /** @type {Object<string, string|string[]>} */\n      let allowedDisplay = {\n        symbol: \"string\"\n      };\n\n      function assignProperties(base, behavior, display) {\n        Object.assign(allowedBase, base);\n        Object.assign(allowedBehavior, behavior);\n        Object.assign(allowedDisplay, display);\n      }\n\n      if (element.type === \"STOCK\") {\n        assignProperties(\n          {},\n          {\n            initial_value: \"equation\",\n            non_negative: \"boolean\",\n            units: \"string\"\n          }, {\n            coordinates: \"point\",\n            size: \"point\",\n            interactive: \"boolean\",\n            interactive_min: \"number\",\n            interactive_max: \"number\"\n          });\n      } else if (element.type === \"VARIABLE\") {\n        assignProperties(\n          {},\n          {\n            value: \"equation\",\n            units: \"string\"\n          }, {\n            coordinates: \"point\",\n            size: \"point\",\n            interactive: \"boolean\",\n            interactive_min: \"number\",\n            interactive_max: \"number\"\n          });\n      } else if (element.type === \"STATE\") {\n        assignProperties(\n          {},\n          {\n            initial_value: \"equation\"\n          }, {\n            coordinates: \"point\",\n            size: \"point\",\n            interactive: \"boolean\"\n          });\n      } else if (element.type === \"CONVERTER\") {\n        assignProperties(\n          {},\n          {\n            input: [\"TIME\", \"ELEMENT\"],\n            input_element: \"string\",\n            interpolation: [\"NONE\", \"LINEAR\"],\n            data: \"array\",\n            units: \"string\"\n          }, {\n            coordinates: \"point\",\n            size: \"point\"\n          });\n      } else if (element.type === \"FLOW\") {\n        assignProperties(\n          {\n            to: \"string\",\n            from: \"string\"\n          },\n          {\n            value: \"equation\",\n            non_negative: \"boolean\",\n            units: \"string\",\n          }, {\n            to_coordinates: \"point\",\n            from_coordinates: \"point\",\n            interactive: \"boolean\",\n            interactive_min: \"number\",\n            interactive_max: \"number\"\n          });\n      } else if (element.type === \"TRANSITION\") {\n        assignProperties(\n          {\n            to: \"string\",\n            from: \"string\"\n          }, {\n            value: \"equation\",\n            trigger: [\"PROBABILITY\", \"TIMEOUT\", \"CONDITION\"]\n          }, {\n            to_coordinates: \"point\",\n            from_coordinates: \"point\",\n            interactive: \"boolean\",\n            interactive_min: \"number\",\n            interactive_max: \"number\"\n          });\n      } else if (element.type === \"LINK\") {\n        assignProperties(\n          {\n            to: \"string\",\n            from: \"string\"\n          }, {\n            polarity: [\"NEUTRAL\", \"POSITIVE\", \"NEGATIVE\"]\n          }, {\n            to_coordinates: \"point\",\n            from_coordinates: \"point\"\n          });\n      }\n\n      if (validateKeys(\"an element\", element, allowedBase, errors)) {\n        if (element.behavior) {\n          validateKeys(\"an element's \\\"behavior\\\"\", element.behavior, allowedBehavior, errors);\n        }\n        if (element.display) {\n          validateKeys(\"an element's \\\"display\\\"\", element.display, allowedDisplay, errors);\n        }\n      }\n    }\n  }\n}\n\n\n\n\n/**\n * @param {string} units\n */\nfunction mapTimeUnits(units) {\n  const uc = (units || \"\").toUpperCase();\n\n  if (TIME_UNITS.includes(uc)) {\n    return uc;\n  }\n\n  return \"DAYS\";\n}\n\n\n/**\n * @param {string} val\n * @returns\n */\nfunction toNumberOrString(val) {\n  if (val == null) return \"\";\n\n  const trimmed = val.trim();\n  const parsed = parseFloat(trimmed);\n\n  if (!isNaN(parsed) && /^[+-]?\\d+(\\.\\d+)?$/.test(trimmed)) {\n    return parsed;\n  }\n\n  return trimmed;\n}\n\n\n/**\n * @param {GraphNode} node\n * @param {{x: number, y: number}} coordinates\n */\nfunction shiftGeometry(node, coordinates) {\n  let newCoords = { x: coordinates.x, y: coordinates.y };\n  let p = node.parent;\n\n  while (p && p.geometry) {\n    newCoords.x += p.geometry.x;\n    newCoords.y += p.geometry.y;\n    p = p.parent;\n  }\n\n  newCoords.x = Math.round(newCoords.x);\n  newCoords.y = Math.round(newCoords.y);\n\n  return newCoords;\n}\n\n\n\n/**\n * @type {Object<string, function(GraphNode, Model):object>}\n */\nlet processors = {\n  base: (element) => {\n    let el = {\n      name: element.getAttribute(\"name\"),\n    };\n\n    if (element.value.nodeName === \"Link\" && el.name === \"Link\") {\n      // \"Link\" isn't shown in the UI on Links, so we remove it from the JSON\n      delete el.name;\n    }\n\n    if (element.getAttribute(\"Note\")) {\n      el.description = element.getAttribute(\"Note\");\n    }\n\n    let interactive = isTrue(element.getAttribute(\"ShowSlider\"));\n\n    if (interactive) {\n      el.display = {\n        interactive: true\n      };\n    }\n\n    let symbol = element.getAttribute(\"Image\");\n    if (symbol && symbol.startsWith(\"emoji:\")) {\n      el.display = el.display || {};\n      el.display.symbol = symbol.slice(6);\n    }\n\n    return el;\n  },\n  // mixins\n  node: (element) => {\n    let c = shiftGeometry(element, element.geometry);\n    return {\n      display: {\n        coordinates: [c.x, c.y],\n        size: [element.geometry.width, element.geometry.height]\n      }\n    };\n  },\n  connector: (element) => {\n    let base = {\n      from: element.source ? element.source.getAttribute(\"name\") : null,\n      to: element.target ? element.target.getAttribute(\"name\") : null,\n    };\n\n\n    if (!element.source || !element.target) {\n      let display = {};\n\n      if (!element.source && element.geometry.sourcePoint) {\n        let c = shiftGeometry(element, element.geometry.sourcePoint);\n        display.from_coordinates = [c.x, c.y];\n        base.display = display;\n      }\n\n      if (!element.target && element.geometry.targetPoint) {\n        let c = shiftGeometry(element, element.geometry.targetPoint);\n        display.to_coordinates = [c.x, c.y];\n        base.display = display;\n      }\n    }\n\n    return base;\n  },\n  scalarInteractive: (element) => {\n    let shouldShowSlider = isTrue(element.getAttribute(\"ShowSlider\"));\n\n    if (!shouldShowSlider) {\n      return null;\n    }\n\n    return {\n      display: {\n        interactive_min: +element.getAttribute(\"SliderMin\"),\n        interactive_max: +element.getAttribute(\"SliderMax\")\n      }\n    };\n  },\n  units: (element) => {\n    let units = element.getAttribute(\"Units\");\n    if (units && units.toLowerCase() !== \"unitless\" && units !== \"1\") {\n      return {\n        behavior: {\n          units\n        }\n      };\n    }\n  },\n  // types\n  Stock: (element) => {\n    let el = {\n      type: \"STOCK\",\n      behavior: {\n        initial_value: toNumberOrString(element.getAttribute(\"InitialValue\"))\n      },\n    };\n    if (isTrue(element.getAttribute(\"NonNegative\"))) {\n      el.behavior.non_negative = true;\n    }\n    return el;\n  },\n  Flow: (element) => {\n    let el = {\n      type: \"FLOW\",\n      behavior: {\n        value: toNumberOrString(element.getAttribute(\"FlowRate\")),\n      },\n    };\n\n    if (isTrue(element.getAttribute(\"OnlyPositive\"))) {\n      el.behavior.non_negative = true;\n    }\n    return el;\n  },\n  Variable: (element) => {\n    let res = {\n      type: \"VARIABLE\"\n    };\n\n    let eq = element.getAttribute(\"Equation\");\n\n    if (eq !== undefined && eq !== \"\") {\n      res.behavior = {\n        value: toNumberOrString(eq),\n      };\n    }\n    return res;\n  },\n  Converter: (element, model) => {\n    let rawData = element.getAttribute(\"Data\") || \"\";\n    let pairs = [];\n    rawData.split(\";\").forEach(token => {\n      let t = token.trim();\n      if (!t) return;\n      let match = t.split(\",\").map(x => x.trim());\n      if (match.length === 2) {\n        let inVal = parseFloat(match[0]);\n        let outVal = parseFloat(match[1]);\n        if (!isNaN(inVal) && !isNaN(outVal)) {\n          pairs.push([inVal, outVal]);\n        } else {\n          console.warn(`Invalid data pair in Converter: \"${t}\". Expected format \"input,output\".`);\n        }\n      } else if (match.length) {\n        console.warn(`Invalid data pair in Converter: \"${t}\". Expected format \"input,output\".`);\n      }\n    });\n\n    /** @type {string} */\n    let sourceAttr = element.getAttribute(\"Source\") || \"\";\n    let source = \"ELEMENT\";\n    let sourceElement = \"\";\n    if (sourceAttr === \"Time\") {\n      source = \"TIME\";\n    } else {\n      let el = model.getId(sourceAttr);\n      sourceElement = el ? el._node.getAttribute(\"name\") : \"\";\n    }\n\n    let interpolation = element.getAttribute(\"Interpolation\");\n\n    let el = {\n      type: \"CONVERTER\",\n      behavior: {\n        input: source,\n        interpolation: interpolation === \"Linear\" ? \"LINEAR\" : \"NONE\",\n        data: pairs,\n      },\n    };\n\n    if (source === \"ELEMENT\") {\n      el.behavior.input_element = sourceElement;\n    }\n\n    return el;\n  },\n  State: (element) => {\n    return {\n      type: \"STATE\",\n      behavior: {\n        initial_value: isTrue(element.getAttribute(\"Active\")),\n      },\n    };\n  },\n  Transition: (element) => {\n    let trigger = element.getAttribute(\"Trigger\");\n    if (trigger === \"Probability\") {\n      trigger = \"PROBABILITY\";\n    } else if (trigger === \"Condition\") {\n      trigger = \"CONDITION\";\n    } else if (trigger === \"Timeout\") {\n      trigger = \"TIMEOUT\";\n    } else {\n      console.warn(`Unknown trigger type in Transition: \"${trigger}\". Expected \"Probability\", \"Condition\", or \"Timeout\".`);\n    }\n\n    return {\n      type: \"TRANSITION\",\n      behavior: {\n        trigger,\n        value: toNumberOrString(element.getAttribute(\"Value\"))\n      },\n    };\n  },\n  Link: (element) => {\n    let el = {\n      type: \"LINK\"\n    };\n\n    let style = element.style;\n\n    if (style?.includes?.(\"END_ANNOTATION=+\")) {\n      el.behavior = {\n        polarity: \"POSITIVE\"\n      };\n    } else if (style?.includes?.(\"END_ANNOTATION=-\")) {\n      el.behavior = {\n        polarity: \"NEGATIVE\"\n      };\n    }\n\n\n    return el;\n  },\n};\n\n\n\n\n\n/**\n * @param {Model} model\n * @param {string} id\n */\nfunction idToName(model, id) {\n  try {\n    let primitive = model.getId(id);\n    return primitive.name;\n  } catch (e) {\n    // if the primitive with the given id doesn't exist, return null\n    return null;\n  }\n}\n\n\n/**\n * Converts a Model object into a JSON string following the ModelJSON specification.\n *\n * @param {Model} model\n * @returns {object} The ModleJSON object representing the model.\n */\nexport function createModelJSON(model) {\n  const fileNotes = [];\n\n  const mySetting = model.settings;\n  const sim = {\n    algorithm: mySetting.getAttribute(\"SolutionAlgorithm\") === \"RK1\" ? \"RK1\" : \"RK4\",\n    time_start: parseFloat(mySetting.getAttribute(\"TimeStart\") || \"0\"),\n    time_length: parseFloat(mySetting.getAttribute(\"TimeLength\") || \"10\"),\n    time_step: parseFloat(mySetting.getAttribute(\"TimeStep\") || \"1\"),\n    time_units: mapTimeUnits(mySetting.getAttribute(\"TimeUnits\"))\n  };\n\n\n  /** @type {Object<string, object>} */\n  let nameMap = Object.create(null);\n  const elements = [];\n\n  function doProcessors(types, node) {\n    /** @type {any} */\n    let element = {};\n    for (let type of types) {\n      if (processors[type]) {\n        let data = processors[type](node._node, node.model);\n        if (data) {\n          // merge data into element, objects with the same key will also be merged\n          for (let key in data) {\n            if (key in element) {\n              if (key === \"behavior\" && type[0].toUpperCase() === type[0]) {\n                // the type specific behavior properties should be first\n                element[key] = { ...data[key], ...element[key] };\n              } else {\n                element[key] = { ...element[key], ...data[key] };\n              }\n\n            } else {\n              element[key] = data[key];\n            }\n          }\n        }\n      }\n    }\n\n    // for cleanup\n    let finalElement = {\n      type: element.type\n    };\n\n    if (element.name) {\n      finalElement.name = element.name;\n    }\n\n    if (element.description) {\n      finalElement.description = element.description;\n    }\n\n    Object.assign(finalElement, element);\n\n    elements.push(finalElement);\n\n    if (\"name\" in element) {\n      if (element.type !== \"LINK\" && nameMap[element.name.toLowerCase()]) {\n        throw new Error(`Duplicate primitive name: ${element.name}. Primitives other than links must have unique names in ModelJSON.`);\n      }\n\n      nameMap[element.name.toLowerCase()] = finalElement;\n    }\n  }\n\n  let items = model.find();\n  items.forEach(item => {\n    switch (item._node.value.nodeName) {\n    case \"Stock\":\n      return doProcessors([\"base\", \"scalarInteractive\", \"node\", \"units\", \"Stock\"], item);\n    case \"Flow\":\n      return doProcessors([\"base\", \"scalarInteractive\", \"connector\", \"units\", \"Flow\"], item);\n    case \"Variable\":\n      return doProcessors([\"base\", \"scalarInteractive\", \"node\", \"units\", \"Variable\"], item);\n    case \"Converter\":\n      return doProcessors([\"base\", \"node\", \"units\", \"Converter\"], item);\n    case \"State\":\n      return doProcessors([\"base\", \"node\", \"State\"], item);\n    case \"Transition\":\n      return doProcessors([\"base\", \"connector\", \"Transition\"], item);\n    case \"Link\":\n      return doProcessors([\"base\", \"connector\", \"Link\"], item);\n    case \"Text\":\n      return;\n    case \"Picture\":\n      return;\n    case \"Display\":\n      return;\n    case \"Setting\":\n      return;\n    case \"Ghost\":\n      return;\n    case \"Folder\":\n      return;\n    default:\n      fileNotes.push(`Skipped primitive: ${item._node.getAttribute(\"name\") || \"Unnamed\"}`);\n    }\n  });\n\n\n\n  // Construct JSON\n  const modelJSON = {\n    engine: \"SIMULATION_PACKAGE\",\n  };\n\n  if (fileNotes.length) {\n    modelJSON.file_notes = fileNotes.join(\"\\n\") || undefined;\n  }\n\n  if (model.name) {\n    modelJSON.name = model.name;\n  }\n  if (model.description) {\n    modelJSON.description = model.description;\n  }\n\n  modelJSON.simulation = sim;\n  modelJSON.elements = elements;\n\n  let engineSettings = {};\n\n  let customUnits = model.customUnits;\n  if (customUnits.length) {\n    engineSettings.units = customUnits.map(u => {\n      let o = {\n        name: u.name,\n      };\n\n      if (u.target?.trim()) {\n        o.base = u.target;\n        o.factor = u.scale;\n      }\n\n      return o;\n    });\n  }\n\n  if (model.globals?.trim()) {\n    engineSettings.globals = model.globals;\n  }\n\n  if (Object.keys(engineSettings).length) {\n    modelJSON.engine_settings = engineSettings;\n  }\n\n\n  let visualizations = [];\n  model.visualizations.forEach(display => {\n    if (display.type === \"Time Series\" || display.type === \"Tabular\" || display.type === \"Scatterplot\") {\n      let viz = {\n        name: display.name,\n      };\n      if (display.type === \"Scatterplot\" || display.type === \"Time Series\") {\n        viz.type = \"TIME_SERIES\";\n      } else if (display.type === \"Tabular\") {\n        viz.type = \"TABLE\";\n      }\n      viz.elements = display.primitives.map(id => idToName(model, id)).filter(n => !!n);\n\n      if (viz.elements.length) {\n        visualizations.push(viz);\n      }\n    }\n  });\n\n  if (visualizations.length) {\n    modelJSON.visualizations = visualizations;\n  }\n\n  let scenarios = model.scenarios.map(scenario => {\n    let sc = {\n      name: scenario.name,\n      values: Object.fromEntries(Object.entries(scenario.primitives).map(([id, value]) => {\n        return [idToName(model, id), value];\n      }))\n    };\n    if (scenario.note) {\n      sc.description = scenario.note;\n    }\n    return sc;\n  });\n  if (scenarios.length) {\n    modelJSON.scenarios = scenarios;\n  }\n\n\n  return modelJSON;\n}\n\n\n\n/**\n * Loads a ModelJSON string into a new Model instance.\n *\n * @param {object} data\n * @returns {Model} A new Model object reflecting the parsed ModelJSON.\n */\nexport function loadModelJSON(data) {\n  if (!data || !(data instanceof Object)) {\n    throwModelJSONError([\"ModelJSON data is not an object.\"]);\n  }\n\n\n  /** @type {string[]} */\n  let errors = [];\n\n\n  validateModel(data, errors);\n\n\n  const model = new Model();\n\n\n  if (data.name) {\n    model.name = data.name;\n  }\n  if (data.description) {\n    model.description = data.description;\n  }\n  const sim = data.simulation || {};\n\n  model.algorithm = sim.algorithm === \"RK1\" ? \"Euler\" : \"RK4\";\n  model.timeStart = sim.time_start ?? 0;\n  model.timeLength = sim.time_length ?? 10;\n  model.timeStep = sim.time_step ?? 1;\n  let units = sim.time_units;\n  if (!units) {\n    // default units to years\n    model.timeUnits = \"Years\";\n  } else if (TIME_UNITS.includes(units)) {\n    model.timeUnits = units.charAt(0) + units.slice(1).toLowerCase();\n  }\n\n\n  const elements = Array.isArray(data.elements) ? data.elements.slice() : [];\n\n  const TYPE_ORDER = {\n    \"STOCK\": 1,\n    \"VARIABLE\": 1,\n    \"STATE\": 1,\n    \"FLOW\": 3,\n    \"TRANSITION\": 3,\n    \"CONVERTER\": 4,\n    \"LINK\": 5\n  };\n\n  elements.sort((a, b) => (TYPE_ORDER[a.type] || 99) - (TYPE_ORDER[b.type] || 99));\n\n  const nameMap = Object.create(null);\n  /** @type {Object<string, {id: string, defaultValue: any}>} */\n  const interactiveDefaults = Object.create(null);\n\n  // We need to run this after everything is created\n  // converters by depend on other converters.\n  let converterFns = [];\n\n  /** @type {number} */\n  let elementIndex = -1;\n  for (const el of elements) {\n    elementIndex++;\n\n    const { type, name, description, behavior = {}, display = {} } = el;\n\n    let newPrimitive = null;\n\n    /**\n     * @param {import(\"../../Blocks\").Primitive} prim\n     */\n    function setGeometry(prim) {\n      const [x, y] = display.coordinates || [0, 0];\n      const [w, h] = display.size || [100, 60];\n\n\n      prim._node.geometry.x = x;\n      prim._node.geometry.y = y;\n      prim._node.geometry.width = w;\n      prim._node.geometry.height = h;\n    }\n\n\n    switch (type) {\n    case \"STOCK\": {\n      newPrimitive = model.Stock({\n        name,\n        initial: behavior.initial_value ?? \"0\",\n        nonNegative: !!behavior.non_negative\n      });\n\n      if (behavior.units) {\n        newPrimitive._node.setAttribute(\"Units\", behavior.units);\n      }\n      setGeometry(newPrimitive);\n      break;\n    }\n\n    case \"VARIABLE\": {\n      newPrimitive = model.Variable({\n        name,\n        value: behavior.value ?? \"\"\n      });\n      if (behavior.units) {\n        newPrimitive._node.setAttribute(\"Units\", behavior.units);\n      }\n      setGeometry(newPrimitive);\n      break;\n    }\n\n    case \"STATE\": {\n      newPrimitive = model.State({\n        name,\n        startActive: behavior.initial_value ?? false\n      });\n      setGeometry(newPrimitive);\n      break;\n    }\n\n    case \"CONVERTER\": {\n\n      let values = [];\n      if (behavior.data) {\n        for (let row of behavior.data) {\n          if (!Array.isArray(row) || row.length!== 2) {\n            errors.push(\"Converter data should be an array of [x, y] pairs, got a row of : \" + row);\n            continue;\n          }\n          values.push({ x: row[0], y: row[1] });\n        }\n      }\n      const interp = (behavior.interpolation === \"LINEAR\") ? \"Linear\" : \"None\";\n\n      newPrimitive = model.Converter({\n        name,\n        values\n      });\n\n      setGeometry(newPrimitive);\n\n      newPrimitive._node.setAttribute(\"Source\", \"Time\");\n      newPrimitive._node.setAttribute(\"Interpolation\", interp);\n      if (behavior.units) {\n        newPrimitive._node.setAttribute(\"Units\", behavior.units);\n      }\n\n      if (behavior.input === \"ELEMENT\") {\n        if (!behavior.input_element) {\n          errors.push(`Converter input element is missing for \"${name}\".`);\n        } else{\n          converterFns.push(() => {\n            if (behavior.input_element.toLowerCase() in nameMap) {\n              let el = nameMap[behavior.input_element.toLowerCase()];\n              // check that there is a link between the converter and the input element\n              let connected = !!model.findLinks((l) => l.start === el && l.end === newPrimitive).length;\n\n              if (!connected) {\n                errors.push(`Converter input element \"${behavior.input_element}\" is not connected to the converter \"${name}\".`);\n              } else {\n                newPrimitive._node.setAttribute(\"Source\", el.id);\n              }\n            } else {\n              errors.push(`Converter input element \"${behavior.input_element}\" not found.`);\n            }\n          });\n        }\n      }\n\n      break;\n    }\n\n    case \"FLOW\": {\n      const fromName = el.from || null;\n      const toName = el.to || null;\n      if (fromName && !(fromName.toLowerCase() in nameMap)) {\n        errors.push(`Flow \"from\" element \"${fromName}\" not found.`);\n      }\n      if (toName && !(toName.toLowerCase() in nameMap)) {\n        errors.push(`Flow \"to\" element \"${toName}\" not found.`);\n      }\n      const fromPrim = fromName ? nameMap[fromName.toLowerCase()] : null;\n      const toPrim = toName ? nameMap[toName.toLowerCase()] : null;\n\n      newPrimitive = model.Flow(fromPrim, toPrim, {\n        name,\n        rate: behavior.value ?? \"0\",\n        nonNegative: !!behavior.non_negative\n      });\n\n      if (!fromPrim && display.from_coordinates) {\n        newPrimitive._node.geometry.sourcePoint = {\n          x: display.from_coordinates[0],\n          y: display.from_coordinates[1]\n        };\n      }\n      if (!toPrim && display.to_coordinates) {\n        newPrimitive._node.geometry.targetPoint = {\n          x: display.to_coordinates[0],\n          y: display.to_coordinates[1]\n        };\n      }\n      if (behavior.units) {\n        newPrimitive._node.setAttribute(\"Units\", behavior.units);\n      }\n      break;\n    }\n\n    case \"TRANSITION\": {\n      const fromName = el.from || null;\n      const toName = el.to || null;\n      if (fromName && !(fromName.toLowerCase() in nameMap)) {\n        errors.push(`Transition \"from\" element \"${fromName}\" not found.`);\n      }\n      if (toName && !(toName.toLowerCase() in nameMap)) {\n        errors.push(`Transition \"to\" element \"${toName}\" not found.`);\n      }\n      const fromPrim = fromName ? nameMap[fromName.toLowerCase()] : null;\n      const toPrim = toName ? nameMap[toName.toLowerCase()] : null;\n\n      newPrimitive = model.Transition(fromPrim, toPrim, {\n        name,\n        value: behavior.value ?? \"\"\n      });\n\n      if (!fromPrim && display.from_coordinates) {\n        newPrimitive._node.geometry.sourcePoint = {\n          x: display.from_coordinates[0],\n          y: display.from_coordinates[1]\n        };\n      }\n      if (!toPrim && display.to_coordinates) {\n        newPrimitive._node.geometry.targetPoint = {\n          x: display.to_coordinates[0],\n          y: display.to_coordinates[1]\n        };\n      }\n\n      let trigVal = null;\n      if ((!behavior.trigger) || behavior.trigger === \"TIMEOUT\") {\n        // default to TIMEOUT\n        trigVal = \"Timeout\";\n      } else if (behavior.trigger === \"CONDITION\") {\n        trigVal = \"Condition\";\n      } else if (behavior.trigger === \"PROBABILITY\") {\n        trigVal = \"Probability\";\n      }\n\n      newPrimitive._node.setAttribute(\"Trigger\", trigVal);\n      break;\n    }\n\n    case \"LINK\": {\n      const fromName = el.from || null;\n      const toName = el.to || null;\n      if (fromName && !(fromName.toLowerCase() in nameMap)) {\n        errors.push(`Link \"from\" element \"${fromName}\" not found.`);\n      }\n      if (toName && !(toName.toLowerCase() in nameMap)) {\n        errors.push(`Link \"to\" element \"${toName}\" not found.`);\n      }\n      const fromPrim = fromName ? nameMap[fromName.toLowerCase()] : null;\n      const toPrim = toName ? nameMap[toName.toLowerCase()] : null;\n\n      newPrimitive = model.Link(fromPrim, toPrim, {\n        name\n      });\n\n      if (!fromPrim && display.from_coordinates) {\n        newPrimitive._node.geometry.sourcePoint = {\n          x: display.from_coordinates[0],\n          y: display.from_coordinates[1]\n        };\n      }\n      if (!toPrim && display.to_coordinates) {\n        newPrimitive._node.geometry.targetPoint = {\n          x: display.to_coordinates[0],\n          y: display.to_coordinates[1]\n        };\n      }\n\n      if (behavior.polarity === \"POSITIVE\") {\n        newPrimitive._node.style = \"END_ANNOTATION=+\";\n      } else if (behavior.polarity === \"NEGATIVE\") {\n        newPrimitive._node.style = \"END_ANNOTATION=-\";\n      }\n\n      break;\n    }\n\n    default:\n      let errorMessage = \"\";\n      if (type) {\n        errorMessage = `Unknown element type: ${type}. Expected \"STOCK\", \"VARIABLE\", \"STATE\", \"CONVERTER\", \"FLOW\", \"TRANSITION\", or \"LINK\".`;\n      } else {\n        errorMessage = `Element had no type: ${JSON.stringify(el)}.`;\n      }\n\n      errorMessage += ` At index ${elementIndex}.`;\n      errors.push(errorMessage);\n\n      break;\n    }\n\n    if (newPrimitive) {\n      if (description) {\n        newPrimitive._node.setAttribute(\"Note\", description);\n      }\n      if (display.interactive) {\n        newPrimitive._node.setAttribute(\"ShowSlider\", \"true\");\n        if (\"interactive_min\" in display) {\n          newPrimitive._node.setAttribute(\"SliderMin\", display.interactive_min);\n        }\n        if (\"interactive_max\" in display) {\n          newPrimitive._node.setAttribute(\"SliderMax\", display.interactive_max);\n        }\n        let defaultValue;\n        if (type === \"STOCK\") {\n          defaultValue = behavior.initial_value;\n        } else if (type === \"STATE\") {\n          defaultValue = behavior.initial_value;\n        } else {\n          defaultValue = behavior.value;\n        }\n        if (defaultValue !== undefined) {\n          interactiveDefaults[name.toLowerCase()] = { id: newPrimitive.id, defaultValue };\n        }\n      }\n      if (display.symbol) {\n        newPrimitive._node.setAttribute(\"Image\", `emoji:${display.symbol}`);\n      }\n\n      if (name && type !== \"LINK\") {\n        if (nameMap[name.toLowerCase()]) {\n          errors.push(`Duplicate element name: ${name}. Elements other than LINKS's must have unique names in ModelJSON. Names are case-insensitive.`);\n        }\n\n        nameMap[name.toLowerCase()] = newPrimitive;\n      }\n    }\n  }\n\n\n  for (const fn of converterFns) {\n    fn();\n  }\n\n\n  if (data.engine_settings?.units && Array.isArray(data.engine_settings.units)) {\n    model.customUnits = data.engine_settings.units.map(u => ({\n      name: u.name,\n      target: (\"base\" in u) ? u.base : \"\",\n      scale: (\"factor\" in u) ? u.factor : 1\n    }));\n  }\n\n  if (data.engine_settings?.globals) {\n    model.globals = data.engine_settings.globals;\n  }\n\n\n  if (Array.isArray(data.visualizations)) {\n    data.visualizations.forEach((viz) => {\n      const { type, name, elements = [] } = viz;\n      let dType = \"Time Series\";\n      if (type === \"TABLE\") {\n        dType = \"Tabular\";\n      }\n\n      const ids = elements\n        .map(nm => nameMap[nm.toLowerCase()] ? nameMap[nm.toLowerCase()].id : null)\n        .filter(id => !!id);\n\n      model.visualizations.push({\n        name,\n        type: dType,\n        primitives: ids\n      });\n    });\n  }\n\n  if (Array.isArray(data.scenarios)) {\n    data.scenarios.forEach((scenario) => {\n      const { name, values, description } = scenario;\n\n      if (!values || typeof values !== \"object\" || Array.isArray(values)) {\n        return;\n      }\n\n      let valuesLower = new Set(Object.keys(values).map(k => k.toLowerCase()));\n      let primitives = {};\n      for (const [name, value] of Object.entries(values)) {\n        let primitive = nameMap[name.toLowerCase()];\n        if (!primitive) {\n          errors.push(`Scenario value element \"${name}\" not found.`);\n          continue;\n        }\n\n        primitives[primitive.id] = value;\n      }\n\n      for (const [lowerName, entry] of Object.entries(interactiveDefaults)) {\n        if (!valuesLower.has(lowerName)) {\n          primitives[entry.id] = entry.defaultValue;\n        }\n      }\n\n      let s = { name, primitives };\n      if (description) {\n        s.note = description;\n      }\n      model.scenarios.push(s);\n    });\n  }\n\n  if (errors.length) {\n    throwModelJSONError(errors);\n  }\n\n  return model;\n}\n\n\nclass ModelJSONError extends Error {\n  constructor(message, errorList = []) {\n    super(message);\n    this.name = \"ModelJSONError\";\n    this.errors = errorList;\n  }\n}\n\n/**\n *\n * @param {string[]} errorList\n */\nfunction throwModelJSONError(errorList) {\n  const message = `Errors occurred while loading the ModelJSON:\\n\\n${errorList.map(e => \"- \" + e).join(\"\\n\")}`;\n  throw new ModelJSONError(message, errorList);\n}\n", "src/api/import_export/ModelJSON/ModelJSON.test.js": "import { loadModelJSON, createModelJSON } from \"./ModelJSON.js\";\nimport { readFileSync, readdirSync } from \"fs\";\nimport { join } from \"path\";\nimport { Model, toModelJSON } from \"../../Model.js\";\n// simulation package imports\nimport { fileURLToPath } from \"url\";\nimport { dirname } from \"path\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\ndescribe(\"ModelJSON samples\", () => {\n  let samplesDir = join(__dirname, \"samples\");\n  let jsonFiles = readdirSync(samplesDir).filter(file => file.endsWith(\".json\"));\n\n  jsonFiles.forEach(file => {\n    test(`should correctly process ${file}`, () => {\n      let filePath = join(samplesDir, file);\n      let originalJson = JSON.parse(readFileSync(filePath, \"utf8\"));\n\n      let loadedModel = loadModelJSON(originalJson);\n      expect(loadedModel).toBeTruthy();\n\n\n      loadedModel.simulate(); // no error\n\n      let exportedJson = createModelJSON(loadedModel);\n\n      // sort the elements array in each\n      originalJson.elements.sort((a, b) => (a.name || \"\").localeCompare(b.name || \"\"));\n      exportedJson.elements.sort((a, b) => (a.name || \"\").localeCompare(b.name || \"\"));\n\n      // CLD example does not have engine and simulation properties\n      if (!originalJson.engine) {\n        delete exportedJson.engine;\n      }\n      if (!originalJson.simulation) {\n        delete exportedJson.simulation;\n      }\n\n      expect(exportedJson).toEqual(originalJson);\n    });\n  });\n});\n\n\ntest(\"Links are case insensitive\", () => {\n  let model = loadModelJSON({\n    elements: [\n      {\n        type: \"VARIABLE\",\n        name: \"x\",\n        behavior: {\n          value: 2\n        }\n      },\n      {\n        type: \"VARIABLE\",\n        name: \"y\",\n        behavior: {\n          value: \"[x] * 3\"\n        }\n      },\n      {\n        type: \"LINK\",\n        from: \"x\",\n        to: \"y\"\n      }\n    ]\n  });\n\n  let res = model.simulate();\n  expect(res.value(model.get(z => z.name === \"y\"))).toBe(6);\n\n\n  model = loadModelJSON({\n    elements: [\n      {\n        type: \"VARIABLE\",\n        name: \"X\",\n        behavior: {\n          value: 2\n        }\n      },\n      {\n        type: \"VARIABLE\",\n        name: \"y\",\n        behavior: {\n          value: \"[x] * 3\"\n        }\n      },\n      {\n        type: \"LINK\",\n        from: \"x\",\n        to: \"y\"\n      }\n    ]\n  });\n\n  res = model.simulate();\n  expect(res.value(model.get(z => z.name === \"y\"))).toBe(6);\n\n\n\n\n  model = loadModelJSON({\n    elements: [\n      {\n        type: \"VARIABLE\",\n        name: \"x\",\n        behavior: {\n          value: 2\n        }\n      },\n      {\n        type: \"VARIABLE\",\n        name: \"y\",\n        behavior: {\n          value: \"[x] * 3\"\n        }\n      },\n      {\n        type: \"LINK\",\n        from: \"X\",\n        to: \"Y\"\n      }\n    ]\n  });\n\n  res = model.simulate();\n  expect(res.value(model.get(z => z.name === \"y\"))).toBe(6);\n\n});\n\n\ntest(\"Invalid ModelJSON\", () => {\n  expect(() => loadModelJSON({\n    elements: [\n      \"abc\"\n    ]\n  })).toThrow(\"Element had no type: \\\"abc\\\". At index 0.\");\n\n\n  expect(() => loadModelJSON({\n    elements: [\n      {type: \"CAT\"}\n    ]\n  })).toThrow(\"Unknown element type: CAT\");\n\n\n  expect(() => loadModelJSON({\n    engine_settings: {\n      globals: true\n    },\n    elements: [\n\n    ]\n  })).toThrow(\"requires a string value\");\n\n\n  expect(() => loadModelJSON({\n    engine_settings: {\n      units: true\n    },\n    elements: [\n\n    ]\n  })).toThrow(\"requires an array value\");\n\n\n  expect(() => loadModelJSON({\n    engine: \"INVALID\",\n    elements: [ ]\n  })).toThrow(\"Invalid value \\\"INVALID\\\" given for \\\"engine\\\"\");\n\n\n  try {\n    loadModelJSON({\n      engine: \"INVALID\",\n      elements: [ ]\n    });\n    expect(1).toBe(2); // should never reach here\n  } catch (e) {\n    expect(e.errors).toHaveLength(1);\n  }\n\n\n  try {\n    loadModelJSON({\n      engine: \"INVALID\",\n      elements: [ 1, 2, 3 ]\n    });\n    expect(1).toBe(2); // should never reach here\n  } catch (e) {\n    expect(e.errors).toHaveLength(4);\n  }\n\n\n  expect(() => loadModelJSON(\"hi\")).toThrow(\"not an object\");\n\n\n  // Converter data is well structured\n  expect(() => loadModelJSON({\n    elements: [\n      {type: \"CONVERTER\", behavior: { data: \"foo\" }}\n    ]\n  })).toThrow(\"Converter data should be an array\");\n\n  expect(() => loadModelJSON({\n    elements: [\n      {type: \"CONVERTER\", behavior: { data: [[1, 2, 3]] }}\n    ]\n  })).toThrow(\"Converter data should be an array\");\n\n\n  // unknown polarity\n  expect(() => loadModelJSON({\n    elements: [\n      {type: \"LINK\", behavior: { polarity: \"foo\" }}\n    ]\n  })).toThrow(\"Invalid value \\\"foo\\\" given for \\\"polarity\\\"\");\n\n\n  // error on unknown key\n\n  expect(() => loadModelJSON({\n    foo: \"abc\",\n    elements: []\n  })).toThrow(\"Invalid property \\\"foo\\\" found in the model.\");\n\n\n  // but \"_\" key's are ignored\n\n  expect(() => loadModelJSON({\n    \"_foo\": \"abc\",\n    elements: []\n  })).not.toThrow();\n\n\n  // error on non-object keys that should be objects\n\n  expect(() => loadModelJSON({\n    simulation: true,\n    elements: []\n  })).toThrow(/Property \"simulation\" requires an object value. Got: true/);\n\n\n  expect(() => loadModelJSON({\n    simulation: [1],\n    elements: []\n  })).toThrow(/Property \"simulation\" requires an object value. Got: \\[1\\]/);\n\n  expect(() => loadModelJSON({\n    elements: [\n      { type: \"VARIABLE\", name: \"a\", behavior: { value: 1 } }\n    ],\n    scenarios: [\n      { name: \"Missing values\" }\n    ]\n  })).toThrow(/Scenarios require a values object/);\n\n  expect(() => loadModelJSON({\n    elements: [\n      { type: \"VARIABLE\", name: \"a\", behavior: { value: 1 } }\n    ],\n    scenarios: [\n      { name: \"Unknown primitive\", values: { missing: 2 } }\n    ]\n  })).toThrow(/Scenario value element \"missing\" not found/);\n\n\n});\n\n\ntest(\"ModelJSON linkage errors\", () => {\n  // converter input does not exist\n  expect(() => loadModelJSON({\n    elements: [\n      {\n        type: \"CONVERTER\",\n        name: \"A\",\n        behavior: {\n          input: \"ELEMENT\",\n          input_element: \"foo\"\n        }\n      }\n    ]\n  })).toThrow(\"Converter input element \\\"foo\\\" not found.\");\n\n  // flow to/from does not exist\n  expect(() => loadModelJSON({\n    elements: [\n      {\n        type: \"FLOW\",\n        name: \"A\",\n        from: \"x\",\n        to: \"y\"\n      }\n    ]\n  })).toThrow(\"Flow \\\"from\\\" element \\\"x\\\" not found.\");\n\n});\n\n\ntest(\"Time units imported/exported correctly\", () => {\n  // simulation uses units like \"Months\"\n  // ModelJSON uses \"MONTHS\"\n\n  let inputJson = {\n    simulation: {\n      time_units: \"MONTHS\"\n    },\n    elements: [\n      {\n        type: \"VARIABLE\",\n        name: \"a\",\n        behavior: {\n          value: 10\n        }\n      }\n    ]\n  };\n\n  let model = loadModelJSON(inputJson);\n  expect(model.timeUnits).toBe(\"Months\");\n\n  const exported = createModelJSON(model);\n  expect(exported.simulation.time_units).toBe(\"MONTHS\");\n\n\n  // missing units default to year\n\n  delete inputJson.simulation.time_units;\n\n  model = loadModelJSON(inputJson);\n  expect(model.timeUnits).toBe(\"Years\");\n\n\n  // invalid units throw error\n\n  inputJson.simulation.time_units = \"foo\";\n\n  expect(() => loadModelJSON(inputJson)).toThrow(/foo/);\n});\n\n\nit(\"Duplicate names\", () => {\n  // importing ModelJSON\n\n  let inputJson = {\n    simulation: {\n      time_units: \"MONTHS\"\n    },\n    elements: [\n      {\n        type: \"VARIABLE\",\n        name: \"a\",\n        behavior: {\n          value: 10\n        }\n      },\n      {\n        type: \"VARIABLE\",\n        name: \"a\",\n        behavior: {\n          value: 10\n        }\n      }\n    ]\n  };\n\n\n  expect(() => loadModelJSON(inputJson)).toThrow(/unique/);\n\n\n  // exporting ModelJSON\n\n  let m = new Model();\n\n  m.Stock({\n    name: \"stock 1\"\n  });\n\n  m.Stock({\n    name: \"stock 1\"\n  });\n\n  expect(() => toModelJSON(m)).toThrow(/unique/);\n});\n\ntest(\"Algorithm imported/exported correctly\", () => {\n  // RK4\n  let model = loadModelJSON({\n    simulation: { algorithm: \"RK4\" },\n    elements: [\n      { type: \"VARIABLE\", name: \"a\", behavior: { value: 1 } }\n    ]\n  });\n  expect(model.algorithm).toBe(\"RK4\");\n  expect(createModelJSON(model).simulation.algorithm).toBe(\"RK4\");\n\n  // RK1 (Euler)\n  model = loadModelJSON({\n    simulation: { algorithm: \"RK1\" },\n    elements: [\n      { type: \"VARIABLE\", name: \"a\", behavior: { value: 1 } }\n    ]\n  });\n  expect(model.algorithm).toBe(\"Euler\");\n  expect(createModelJSON(model).simulation.algorithm).toBe(\"RK1\");\n});\n\n\nit(\"Converters referencing each other are imported correctly\", () => {\n  let inputJson = {\n    elements: [\n      {\n        type: \"CONVERTER\",\n        name: \"A\",\n        behavior: {\n          input: \"ELEMENT\",\n          input_element: \"B\",\n          data: [\n            [1, 2]\n          ]\n        }\n      },\n      {\n        type: \"CONVERTER\",\n        name: \"B\",\n        behavior: {\n          input: \"ELEMENT\",\n          input_element: \"A\",\n          data: [\n            [2, 3]\n          ]\n        }\n      },\n      {\n        type: \"LINK\",\n        from: \"A\",\n        to: \"B\",\n      },\n      {\n        type: \"LINK\",\n        from: \"B\",\n        to: \"A\",\n      }\n    ]\n  };\n\n  let model = loadModelJSON(inputJson);\n\n  expect(() => model.simulate()).toThrow(\"Circular equation loop identified including the primitives: A, B\");\n});", "src/api/import_export/InsightMaker/InsightMaker.test.js": "import { loadInsightMaker } from \"../../Model.js\";\n\n\ntest(\"Test loading Insight Maker\", () => {\n  let m = loadInsightMaker(`<InsightMakerModel>\n    <root>\n      <info id=\"0\">\n        <mxCell />\n      </info>\n      <mxCell id=\"1\" parent=\"0\" />\n      <Setting Note=\"\" Version=\"40\" TimeLength=\"40\" TimeStart=\"1\" TimeStep=\"1\" TimeUnits=\"Quarters\" Units=\"\" SolutionAlgorithm=\"RK1\" BackgroundColor=\"white\" Throttle=\"-1\" Macros=\"\" SensitivityPrimitives=\"\" SensitivityRuns=\"50\" SensitivityBounds=\"50, 80, 95, 100\" SensitivityShowRuns=\"false\" StyleSheet=\"{}\" id=\"2\">\n      <mxCell parent=\"1\" vertex=\"1\" visible=\"0\">\n        <mxGeometry x=\"20\" y=\"20\" width=\"80\" height=\"40\" as=\"geometry\" />\n      </mxCell>\n    </Setting>\n    </root>\n  </InsightMakerModel>\n  `);\n\n  m.simulate(); // no error\n});", "src/api/import_export/InsightMaker/InsightMaker.js": "import { DOMParser } from \"../../../../vendor/xmldom/dom-parser.js\";\nimport { ModelNode, primitives } from \"../../../ModelNode.js\";\nimport { Model, removeModelGhosts } from \"../../Model.js\";\n\n\n\n/**\n * @param {string} modelString\n *\n * @returns\n */\nexport function loadXML(modelString) {\n  let oParser = new DOMParser();\n  let data = oParser.parseFromString(modelString, \"text/xml\");\n  let graph = graphXMLToNodes(data);\n\n\n  graph.children[0].value = { nodeName: \"root\" };\n  graph.children[0].id = \"1\";\n\n  let connectors = primitives(/** @type {any} */(graph), [\"Flow\", \"Link\", \"Transition\"]);\n\n\n  let items = primitives(graph);\n  connectors.forEach((x) => {\n    x.source = null;\n    x.target = null;\n    items.forEach((i) => {\n      if (x.children[0].getAttribute(\"source\") && x.children[0].getAttribute(\"source\") === i.id) {\n        x.source = i;\n      }\n      if (x.children[0].getAttribute(\"target\") && x.children[0].getAttribute(\"target\") === i.id) {\n        x.target = i;\n      }\n    });\n  });\n\n  function cleanNode(x) {\n    if (x.children) {\n      let nodes = x.children.filter((c) => c.value.nodeName === \"mxCell\");\n\n      if (nodes.length > 0) {\n        if (nodes[0].getAttribute(\"parent\")) {\n          let parent = items.find(item => item.id === nodes[0].getAttribute(\"parent\"));\n          if (parent && parent.value.nodeName === \"Folder\") {\n            parent.addChild(x);\n          }\n        }\n      }\n\n      x.children = x.children.filter((c) => c.value.nodeName !== \"mxCell\");\n\n      for (let i = x.children.length - 1; i >= 0; i--) {\n        cleanNode(x.children[i]);\n      }\n    }\n  }\n\n  cleanNode(graph);\n\n\n  return graph;\n}\n\n\n\nfunction graphXMLToNodes(xml, parent) {\n  // Create the return object\n  let obj = new ModelNode();\n  obj.value = xml;\n  obj.parent = parent;\n\n  if (xml.nodeType === 1) { // element\n    // do attributes\n    if (xml.attributes.length > 0) {\n      for (let j = 0; j < xml.attributes.length; j++) {\n        let attribute = xml.attributes.item(j);\n        obj.attributes.set(attribute.nodeName, attribute.nodeValue);\n      }\n\n      obj.id = obj.attributes.get(\"id\");\n    }\n  } else if (xml.nodeType === 3) { // text\n    return null;\n  }\n\n  if (xml.hasChildNodes()) {\n    obj.children = [];\n    for (let i = 0; i < xml.childNodes.length; i++) {\n      let item = xml.childNodes.item(i);\n      let x = graphXMLToNodes(item, obj);\n      if (x) {\n        obj.addChild(x);\n      }\n    }\n  }\n\n  return obj;\n}\n\n\n\n/**\n * @param {string} xml - Insight Maker model XML string\n */\nexport function loadInsightMaker(xml) {\n  if (!xml) {\n    throw new Error(\"No Insight Maker model provided\");\n  }\n\n  if (!xml.includes(\"InsightMakerModel\")) {\n    throw new Error(\"Invalid Insight Maker model contents\");\n  }\n\n  let root = loadXML(xml);\n\n  let m = new Model();\n\n  m._graph = /** @type {any} */ (root);\n\n  primitives(m._graph).map(x => x.primitive(m));\n\n  m.settings = /** @type {any} */ (primitives(m._graph, \"Setting\")[0]);\n\n  removeModelGhosts(m);\n\n  return m;\n}", "src/api/import_export/ModelJSON/samples/population.json": "{\n    \"engine\": \"SIMULATION_PACKAGE\",\n    \"name\": \"Population Growth\",\n    \"simulation\": {\n        \"algorithm\": \"RK4\",\n        \"time_start\": 0,\n        \"time_length\": 20,\n        \"time_step\": 0.2,\n        \"time_units\": \"YEARS\"\n    },\n    \"elements\": [\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"Population\",\n            \"display\": {\n                \"coordinates\": [\n                    130,\n                    210\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": 1,\n                \"non_negative\": true\n            }\n        },\n        {\n            \"type\": \"CONVERTER\",\n            \"name\": \"Growth Rate\",\n            \"display\": {\n                \"coordinates\": [\n                    260,\n                    90\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            },\n            \"behavior\": {\n                \"input\": \"ELEMENT\",\n                \"interpolation\": \"LINEAR\",\n                \"data\": [\n                    [\n                        0,\n                        2\n                    ],\n                    [\n                        1500,\n                        1.07\n                    ],\n                    [\n                        3990,\n                        0.429\n                    ],\n                    [\n                        6780,\n                        0.125\n                    ],\n                    [\n                        10000,\n                        0\n                    ]\n                ],\n                \"input_element\": \"Population\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Flow\",\n            \"from\": null,\n            \"to\": \"Population\",\n            \"display\": {\n                \"from_coordinates\": [\n                    180,\n                    60\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"[Population] * [Growth Rate]\",\n                \"non_negative\": true\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Growth Rate\",\n            \"to\": \"Flow\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Population\",\n            \"to\": \"Growth Rate\"\n        }\n    ],\n    \"visualizations\": [\n        {\n            \"type\": \"TIME_SERIES\",\n            \"name\": \"Default Display\",\n            \"elements\": [\n                \"Population\"\n            ]\n        }\n    ]\n}", "src/api/import_export/ModelJSON/samples/cld.json": "{\n    \"elements\": [\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Population\",\n            \"display\": {\n                \"coordinates\": [\n                    140,\n                    100\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Births\",\n            \"display\": {\n                \"coordinates\": [\n                    90,\n                    280\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Carrying Capacity\",\n            \"display\": {\n                \"coordinates\": [\n                    480,\n                    60\n                ],\n                \"size\": [\n                    130,\n                    50\n                ]\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Deaths\",\n            \"display\": {\n                \"coordinates\": [\n                    430,\n                    180\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Population\",\n            \"to\": \"Deaths\",\n            \"behavior\": {\n                \"polarity\": \"POSITIVE\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Population\",\n            \"to\": \"Births\",\n            \"behavior\": {\n                \"polarity\": \"POSITIVE\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Net Growth\",\n            \"display\": {\n                \"coordinates\": [\n                    320,\n                    320\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Deaths\",\n            \"to\": \"Net Growth\",\n            \"behavior\": {\n                \"polarity\": \"NEGATIVE\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Carrying Capacity\",\n            \"to\": \"Deaths\",\n            \"behavior\": {\n                \"polarity\": \"NEGATIVE\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Births\",\n            \"to\": \"Net Growth\",\n            \"behavior\": {\n                \"polarity\": \"POSITIVE\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Net Growth\",\n            \"to\": \"Population\",\n            \"behavior\": {\n                \"polarity\": \"POSITIVE\"\n            }\n        }\n    ]\n}", "src/api/import_export/ModelJSON/samples/bathtub.json": "{\n    \"engine\": \"SIMULATION_PACKAGE\",\n    \"name\": \"Bathtub\",\n    \"simulation\": {\n        \"algorithm\": \"RK1\",\n        \"time_start\": 0,\n        \"time_length\": 20,\n        \"time_step\": 1,\n        \"time_units\": \"MINUTES\"\n    },\n    \"elements\": [\n        {\n            \"type\": \"STATE\",\n            \"name\": \"Is Filling\",\n            \"display\": {\n                \"coordinates\": [\n                    630,\n                    110\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": true\n            }\n        },\n        {\n            \"type\": \"STATE\",\n            \"name\": \"Is Bathing\",\n            \"display\": {\n                \"coordinates\": [\n                    630,\n                    230\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": false\n            }\n        },\n        {\n            \"type\": \"STATE\",\n            \"name\": \"Is Draining\",\n            \"display\": {\n                \"coordinates\": [\n                    630,\n                    350\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": false\n            }\n        },\n        {\n            \"type\": \"TRANSITION\",\n            \"name\": \"Done Filling\",\n            \"from\": \"Is Filling\",\n            \"to\": \"Is Bathing\",\n            \"behavior\": {\n                \"trigger\": \"TIMEOUT\",\n                \"value\": 5\n            }\n        },\n        {\n            \"type\": \"TRANSITION\",\n            \"name\": \"Bath Over\",\n            \"from\": \"Is Bathing\",\n            \"to\": \"Is Draining\",\n            \"behavior\": {\n                \"trigger\": \"TIMEOUT\",\n                \"value\": 5\n            }\n        },\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"Bathtub\",\n            \"description\": \"The bathtub starts empty.\",\n            \"display\": {\n                \"coordinates\": [\n                    390,\n                    220\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": 0,\n                \"non_negative\": true,\n                \"units\": \"Liters\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Filling\",\n            \"description\": \"Water fills at a rate of 10 liters per minute.\",\n            \"from\": null,\n            \"to\": \"Bathtub\",\n            \"display\": {\n                \"from_coordinates\": [\n                    440,\n                    90\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"IfThenElse([Is Filling], 10, 0)\",\n                \"non_negative\": true,\n                \"units\": \"Liters/Minute\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Draining\",\n            \"description\": \"Water drains at a rate of 20% per minute.\",\n            \"from\": \"Bathtub\",\n            \"to\": null,\n            \"display\": {\n                \"to_coordinates\": [\n                    440,\n                    400\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"IfThenElse([Is Draining], {0.2 1/Minute} * [Bathtub], 0)\",\n                \"non_negative\": true,\n                \"units\": \"Liters/Minute\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Is Filling\",\n            \"to\": \"Filling\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Is Draining\",\n            \"to\": \"Draining\"\n        }\n    ],\n    \"visualizations\": [\n        {\n            \"type\": \"TIME_SERIES\",\n            \"name\": \"Bathtub Volume\",\n            \"elements\": [\n                \"Bathtub\"\n            ]\n        },\n        {\n            \"type\": \"TIME_SERIES\",\n            \"name\": \"States\",\n            \"elements\": [\n                \"Is Filling\",\n                \"Is Bathing\",\n                \"Is Draining\"\n            ]\n        }\n    ]\n}", "src/api/import_export/ModelJSON/samples/disease.json": "{\n    \"engine\": \"SIMULATION_PACKAGE\",\n    \"simulation\": {\n        \"algorithm\": \"RK1\",\n        \"time_start\": 0,\n        \"time_length\": 20,\n        \"time_step\": 0.2,\n        \"time_units\": \"WEEKS\"\n    },\n    \"elements\": [\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"S\",\n            \"description\": \"Initial number of susceptible individuals.\",\n            \"behavior\": {\n                \"initial_value\": 100\n            },\n            \"display\": {\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 100,\n                \"coordinates\": [\n                    140,\n                    60\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            }\n        },\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"I\",\n            \"description\": \"Initial number of infected individuals.\",\n            \"behavior\": {\n                \"initial_value\": 3\n            },\n            \"display\": {\n                \"coordinates\": [\n                    140,\n                    190\n                ],\n                \"size\": [\n                    100,\n                    40\n                ],\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 100\n            }\n        },\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"R\",\n            \"description\": \"Initial number of recovered individuals.\",\n            \"behavior\": {\n                \"initial_value\": 0\n            },\n            \"display\": {\n                \"coordinates\": [\n                    140,\n                    310\n                ],\n                \"size\": [\n                    100,\n                    40\n                ],\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 100\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"\u03b3\",\n            \"behavior\": {\n                \"value\": 0.3\n            },\n            \"display\": {\n                \"coordinates\": [\n                    50,\n                    185\n                ],\n                \"size\": [\n                    50,\n                    50\n                ],\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 1\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"\u03b2\",\n            \"behavior\": {\n                \"value\": 0.01\n            },\n            \"display\": {\n                \"coordinates\": [\n                    50,\n                    40\n                ],\n                \"size\": [\n                    50,\n                    50\n                ],\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 0.05\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Infection\",\n            \"from\": \"S\",\n            \"to\": \"I\",\n            \"behavior\": {\n                \"value\": \"[\u03b2] * [S] * [I]\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Recovery\",\n            \"from\": \"I\",\n            \"to\": \"R\",\n            \"behavior\": {\n                \"value\": \"[\u03b3] * [I]\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"\u03b2\",\n            \"to\": \"Infection\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"\u03b3\",\n            \"to\": \"Recovery\"\n        }\n    ],\n    \"visualizations\": [\n        {\n            \"type\": \"TIME_SERIES\",\n            \"name\": \"Disease Spread\",\n            \"elements\": [\n                \"I\",\n                \"R\",\n                \"S\"\n            ]\n        }\n    ],\n    \"scenarios\": [\n        {\n            \"name\": \"Baseline\",\n            \"values\": {\n                \"S\": 100,\n                \"I\": 3,\n                \"R\": 0,\n                \"\u03b2\": 0.01,\n                \"\u03b3\": 0.3\n            }\n        },\n        {\n            \"name\": \"High Transmission\",\n            \"values\": {\n                \"S\": 100,\n                \"I\": 3,\n                \"R\": 0,\n                \"\u03b2\": 0.02,\n                \"\u03b3\": 0.3\n            }\n        },\n        {\n            \"name\": \"Mitigation\",\n            \"description\": \"Reduced transmission rate.\",\n            \"values\": {\n                \"S\": 100,\n                \"I\": 3,\n                \"R\": 0,\n                \"\u03b2\": 0.005,\n                \"\u03b3\": 0.3\n            }\n        }\n    ]\n}", "src/api/import_export/ModelJSON/samples/predator_prey.json": "{\n    \"engine\": \"SIMULATION_PACKAGE\",\n    \"name\": \"Predator Prey Model\",\n    \"description\": \"Version of the classic Lotka-Volterra model.\",\n    \"simulation\": {\n        \"algorithm\": \"RK4\",\n        \"time_start\": 2000,\n        \"time_length\": 50,\n        \"time_step\": 0.5,\n        \"time_units\": \"YEARS\"\n    },\n    \"elements\": [\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"Prey\",\n            \"behavior\": {\n                \"initial_value\": 400,\n                \"non_negative\": true,\n                \"units\": \"Prey\"\n            },\n            \"display\": {\n                \"symbol\": \"\ud83d\udc30\",\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 1000,\n                \"coordinates\": [\n                    135,\n                    214\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Prey Birth Rate\",\n            \"display\": {\n                \"coordinates\": [\n                    30,\n                    30\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            },\n            \"behavior\": {\n                \"value\": 0.25,\n                \"units\": \"1 / Years\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Prey Death Rate\",\n            \"display\": {\n                \"coordinates\": [\n                    285,\n                    371\n                ],\n                \"size\": [\n                    150,\n                    50\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"{0.005 1/(Predators * Years)} * [Predators]\",\n                \"units\": \"1 / Years\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Predator Birth Rate\",\n            \"display\": {\n                \"coordinates\": [\n                    300,\n                    50\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"{0.0002 1 / (Prey * Years)} * [Prey]\",\n                \"units\": \"1 / Years\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Predator Death Rate\",\n            \"display\": {\n                \"coordinates\": [\n                    637,\n                    340\n                ],\n                \"size\": [\n                    120,\n                    50\n                ]\n            },\n            \"behavior\": {\n                \"value\": 0.25,\n                \"units\": \"1 / Years\"\n            }\n        },\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"Predators\",\n            \"behavior\": {\n                \"initial_value\": 20,\n                \"non_negative\": true,\n                \"units\": \"Predators\"\n            },\n            \"display\": {\n                \"symbol\": \"\ud83e\udd8a\",\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 100,\n                \"coordinates\": [\n                    506,\n                    212\n                ],\n                \"size\": [\n                    100,\n                    40\n                ]\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Prey Births\",\n            \"from\": null,\n            \"to\": \"Prey\",\n            \"display\": {\n                \"from_coordinates\": [\n                    185,\n                    62\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"[Prey]*[Prey Birth Rate]\",\n                \"non_negative\": true,\n                \"units\": \"Prey / Years\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Prey Deaths\",\n            \"from\": \"Prey\",\n            \"to\": null,\n            \"display\": {\n                \"to_coordinates\": [\n                    185,\n                    422\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"[Prey]*[Prey Death Rate]\",\n                \"non_negative\": true,\n                \"units\": \"Prey / Years\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Predator Births\",\n            \"from\": null,\n            \"to\": \"Predators\",\n            \"display\": {\n                \"from_coordinates\": [\n                    556,\n                    60\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"[Predators]*[Predator Birth Rate]\",\n                \"non_negative\": true,\n                \"units\": \"Predators / Years\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Predator Deaths\",\n            \"from\": \"Predators\",\n            \"to\": null,\n            \"display\": {\n                \"to_coordinates\": [\n                    556,\n                    420\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"[Predator Death Rate]*[Predators]\",\n                \"non_negative\": true,\n                \"units\": \"Predators / Years\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Prey Birth Rate\",\n            \"to\": \"Prey Births\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Prey Death Rate\",\n            \"to\": \"Prey Deaths\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Predators\",\n            \"to\": \"Prey Death Rate\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Predator Death Rate\",\n            \"to\": \"Predator Deaths\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Predator Birth Rate\",\n            \"to\": \"Predator Births\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Prey\",\n            \"to\": \"Predator Birth Rate\"\n        }\n    ],\n    \"visualizations\": [\n        {\n            \"type\": \"TIME_SERIES\",\n            \"name\": \"Prey and Predators\",\n            \"elements\": [\n                \"Prey\",\n                \"Predators\"\n            ]\n        },\n        {\n            \"type\": \"TABLE\",\n            \"name\": \"Details Table\",\n            \"elements\": [\n                \"Predators\",\n                \"Prey\",\n                \"Predator Deaths\",\n                \"Predator Births\",\n                \"Prey Births\",\n                \"Prey Deaths\"\n            ]\n        }\n    ]\n}", "src/api/import_export/ModelJSON/samples/pendulum.json": "{\n    \"engine\": \"SIMULATION_PACKAGE\",\n    \"name\": \"Damped pendulum\",\n    \"description\": \"A simple damped pendulum model. Uses common SI units mapping to SIMULATION_PACKAGE built-in units.\",\n    \"simulation\": {\n        \"algorithm\": \"RK4\",\n        \"time_start\": 0,\n        \"time_length\": 10,\n        \"time_step\": 0.1,\n        \"time_units\": \"SECONDS\"\n    },\n    \"engine_settings\": {\n        \"globals\": \"# Acceleration due to gravity\\ng <- {9.81 m/s^2}\",\n        \"units\": [\n            {\n                \"name\": \"kg\",\n                \"base\": \"grams\",\n                \"factor\": 1000\n            },\n            {\n                \"name\": \"s\",\n                \"base\": \"seconds\",\n                \"factor\": 1\n            },\n            {\n                \"name\": \"m\",\n                \"base\": \"meters\",\n                \"factor\": 1\n            },\n            {\n                \"name\": \"rad\",\n                \"base\": \"radians\",\n                \"factor\": 1\n            }\n        ]\n    },\n    \"elements\": [\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"Angle\",\n            \"display\": {\n                \"coordinates\": [\n                    270,\n                    70\n                ],\n                \"size\": [\n                    120,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": 0.2,\n                \"units\": \"rad\"\n            }\n        },\n        {\n            \"type\": \"STOCK\",\n            \"name\": \"Angular Velocity\",\n            \"display\": {\n                \"coordinates\": [\n                    270,\n                    180\n                ],\n                \"size\": [\n                    120,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"initial_value\": 0,\n                \"units\": \"rad/s\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Mass\",\n            \"display\": {\n                \"interactive\": true,\n                \"interactive_min\": 0.1,\n                \"interactive_max\": 10,\n                \"coordinates\": [\n                    30,\n                    280\n                ],\n                \"size\": [\n                    80,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"value\": 1,\n                \"units\": \"kg\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Length\",\n            \"display\": {\n                \"interactive\": true,\n                \"interactive_min\": 0.1,\n                \"interactive_max\": 10,\n                \"coordinates\": [\n                    330,\n                    280\n                ],\n                \"size\": [\n                    80,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"value\": 1,\n                \"units\": \"m\"\n            }\n        },\n        {\n            \"type\": \"VARIABLE\",\n            \"name\": \"Damping Coefficient\",\n            \"display\": {\n                \"interactive\": true,\n                \"interactive_min\": 0,\n                \"interactive_max\": 1,\n                \"coordinates\": [\n                    70,\n                    380\n                ],\n                \"size\": [\n                    150,\n                    40\n                ]\n            },\n            \"behavior\": {\n                \"value\": 0.2,\n                \"units\": \"kg * m^2 / s\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Angle Rate\",\n            \"from\": null,\n            \"to\": \"Angle\",\n            \"display\": {\n                \"from_coordinates\": [\n                    110,\n                    90\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"[Angular Velocity]\",\n                \"units\": \"rad / s\"\n            }\n        },\n        {\n            \"type\": \"FLOW\",\n            \"name\": \"Angular Acceleration\",\n            \"from\": null,\n            \"to\": \"Angular Velocity\",\n            \"display\": {\n                \"from_coordinates\": [\n                    110,\n                    200\n                ]\n            },\n            \"behavior\": {\n                \"value\": \"-([Damping Coefficient]/([Mass]*[Length]^2))*[Angular Velocity] - (g /[Length])*sin([Angle]) * {1 radian}\",\n                \"units\": \"rad / s^2\"\n            }\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Angular Velocity\",\n            \"to\": \"Angle Rate\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Angle\",\n            \"to\": \"Angular Acceleration\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Mass\",\n            \"to\": \"Angular Acceleration\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Length\",\n            \"to\": \"Angular Acceleration\"\n        },\n        {\n            \"type\": \"LINK\",\n            \"from\": \"Damping Coefficient\",\n            \"to\": \"Angular Acceleration\"\n        }\n    ],\n    \"visualizations\": [\n        {\n            \"type\": \"TIME_SERIES\",\n            \"name\": \"Pendulum States\",\n            \"elements\": [\n                \"Angle\",\n                \"Angular Velocity\"\n            ]\n        }\n    ]\n}", "src/formula/grammar/Formula.g": "// Building:\n/*\nrm -f FormulaParser.ts FormulaParser.js FormulaLexer.ts FormulaLexer.js && \\\nantlr-ng -Dlanguage=TypeScript -v false -l false Formula.g && \\\nfor f in FormulaParser FormulaLexer; do\n  npx tsc \"$f.ts\" --noResolve --noCheck --module esnext --target esnext &&\n  sed -i '' $'1s|^|// eslint-disable\\\\\\n// @ts-nocheck\\\\\\n\\\\\\n|' \"$f.js\" &&\n  sed -i '' 's|antlr4ng|../../../vendor/antlr4ng-all.js|g' \"$f.js\"\ndone; \\\nrm -Rf .antlr\n*/\ngrammar Formula;\noptions\n{\n\tlanguage = JavaScript;\n\tcaseInsensitive = true;\n}\n\nCOMMENT: R_? '/*' .*? '*/' R_? -> channel(HIDDEN);\n\nLINE_COMMENT: R_? ('//' | '#') ~[\\r\\n]* R_? -> channel(HIDDEN);\n\nfragment SPACE: (' ' | '\\t' | '\\u000C');\n\nR__: SPACE* (NEWLINES SPACE*)+;\n\nR_: SPACE+;\n\n// Optional whitespace contains newlines: ((R__ | R_)*) Optional whitespace does not contain\n// newlines: ((R_)*) Note that using parser rules for these slows things down 5% or so\n\nNEWLINES: '\\n' | '\\r';\n\nWHILESTATEMENT: 'while';\n\nFORSTATEMENT: 'for';\n\nFROMSTATEMENT: 'from';\n\nINSTATEMENT: 'in';\n\nTOSTATEMENT: 'to';\n\nBYSTATEMENT: 'by';\n\nLOOPSTATEMENT: 'loop';\n\nIFSTATEMENT: 'if';\n\nTHENSTATEMENT: 'then';\n\nELSESTATEMENT: 'else';\n\nFUNCTIONSTATEMENT: 'function';\n\nENDPREFIX: 'end' SPACE+;\n\nENDBLOCK: 'end';\n\nRETURNSTATEMENT: 'return';\n\nNEWSTATEMENT: 'new';\n\nTRYSTATEMENT: 'try';\n\nCATCHSTATEMENT: 'catch';\n\nTHROWSTATEMENT: 'throw';\n\nLPAREN: '(';\nCOMMA: ',';\nRPAREN: ')';\nASSIGN: '<-';\nDOT: '.';\nCOLON: ':';\n\nOR: '||' | 'or';\nXOR: 'xor';\nAND: '&&' | 'and';\n\nEQUALS: '=' | '==';\nNOTEQUALS: '!=' | '<>';\n\nLT: '<';\nLTEQ: '<=';\nGT: '>';\nGTEQ: '>=';\n\nPLUS: '+';\nMINUS: '-';\n\nMULT: '*';\nDIV: '/';\nMOD: '%' | 'mod';\n\nPOW: '^';\n\nNOT: '!' | 'not';\n\nLARR: '\\u00AB' | '<<';\nRARR: '\\u00BB' | '>>';\n\nLCURL: '{';\nRCURL: '}';\n\nBOOL: 'true' | 'false';\n\nPER: 'per';\nSQUARED: 'squared';\nCUBED: 'cubed';\n\nLBRACKET: '[';\nRBRACKET: ']';\n\nIDENT: [\\p{L}] [\\p{L}\\p{N}_]*;\n\nPRIMITIVE:\n\tLBRACKET (~('[' | ']'))+? RBRACKET\n\t| LBRACKET LBRACKET (~('[' | ']'))+? RBRACKET RBRACKET;\n\nINTEGER: ('0' ..'9')+ ('e' ('+' | '-')? ('0' ..'9')*)?;\n\nFLOAT: (('0' ..'9')* '.' ('0' ..'9')+ | ('0' ..'9')+ '.') (\n\t\t'e' ('+' | '-')? ('0' ..'9')*\n\t)?;\n\n\nSTRING: '\\'' .*? '\\'' | '\"' ('\\\\\"' | ~'\"')* '\"';\n\nlines: ((R__ | R_)*) (\n\t\texpression (R__+ expression)* ((R__ | R_)*)\n\t)? EOF;\n\nexpression:\n\tassignment\n\t| logicalExpression\n\t| whileLoop\n\t| forLoop\n\t| forInLoop\n\t| ifThenElse\n\t| functionDef\n\t| returnExp\n\t| tryCatch\n\t| throwExp;\n\nreturnExp: RETURNSTATEMENT (R_*) logicalExpression;\n\ninnerBlock: ((R__ | R_)*) (\n\t\texpression (R__+ expression)* ((R__ | R_)*)\n\t)?;\n\nwhileLoop:\n\tWHILESTATEMENT (R_*) logicalExpression (R__ innerBlock) R__ ENDPREFIX LOOPSTATEMENT;\n\nforLoop:\n\tFORSTATEMENT R_ IDENT R_ FROMSTATEMENT (R_*) logicalExpression (\n\t\tR_*\n\t) TOSTATEMENT (R_*) logicalExpression (\n\t\t(R_*) BYSTATEMENT (R_*) logicalExpression\n\t)? (R__ innerBlock)? R__ ENDPREFIX LOOPSTATEMENT;\n\nforInLoop:\n\tFORSTATEMENT R_ IDENT R_ INSTATEMENT (R_*) logicalExpression (\n\t\tR__ innerBlock\n\t)? R__ ENDPREFIX LOOPSTATEMENT;\n\nifThenElse:\n\tIFSTATEMENT (R_*) logicalExpression ((R__ | R_)*) THENSTATEMENT? (\n\t\tR__ innerBlock\n\t)? (\n\t\tR__ ELSESTATEMENT R_ IFSTATEMENT (R_*) logicalExpression (\n\t\t\t(R__ | R_)*\n\t\t) THENSTATEMENT? (R__ innerBlock)?\n\t)* (R__ ELSESTATEMENT (R__ innerBlock)?)? R__ ENDPREFIX IFSTATEMENT;\n\nfunctionDef:\n\tFUNCTIONSTATEMENT R_ IDENT (R_*) LPAREN (\n\t\t(R_*) IDENT (\n\t\t\t(R_*) EQUALS (R_*) defaultValue\n\t\t\t| ((R_*) COMMA (R_*) IDENT)*\n\t\t) ((R_*) COMMA (R_*) IDENT (R_*) EQUALS (R_*) defaultValue)*\n\t)? (R_*) RPAREN (R__ innerBlock)? R__ ENDPREFIX FUNCTIONSTATEMENT;\n\ntryCatch:\n\tTRYSTATEMENT (R__ innerBlock)? R__ CATCHSTATEMENT R_ IDENT (\n\t\tR__ innerBlock\n\t)? R__ ENDPREFIX TRYSTATEMENT;\n\nthrowExp: THROWSTATEMENT R_ primaryExpression;\n\nanonFunctionDef:\n\tFUNCTIONSTATEMENT (R_*) LPAREN (\n\t\t(R_*) IDENT (\n\t\t\t(R_*) EQUALS (R_*) defaultValue\n\t\t\t| ((R_*) COMMA (R_*) IDENT)*\n\t\t) ((R_*) COMMA (R_*) IDENT (R_*) EQUALS (R_*) defaultValue)*\n\t)? (R_*) RPAREN (\n\t\t((R__ innerBlock)? R__ ENDPREFIX FUNCTIONSTATEMENT)\n\t\t| (R_*) expression\n\t);\n\nassignment:\n\tIDENT (R_*) LPAREN (\n\t\t(R_*) IDENT (\n\t\t\t(R_*) EQUALS (R_*) defaultValue\n\t\t\t| ((R_*) COMMA (R_*) IDENT)*\n\t\t) ((R_*) COMMA (R_*) IDENT (R_*) EQUALS (R_*) defaultValue)*\n\t)? (R_*) RPAREN (R_*) ASSIGN (R_*) logicalExpression\n\t| (primitiveRef | assigned) (\n\t\t(R_*) COMMA (R_*) (primitiveRef | assigned)\n\t)* (R_*) ASSIGN (R_*) logicalExpression;\n\nassigned: IDENT selector?;\n\nlogicalExpression:\n\tbooleanXORExpression ((R_*) OR (R_*) booleanXORExpression)*;\n\nbooleanXORExpression:\n\tbooleanAndExpression ((R_*) XOR (R_*) booleanAndExpression)*;\n\nbooleanAndExpression:\n\tequalityExpression ((R_*) AND (R_*) equalityExpression)*;\n\nequalityExpression:\n\trelationalExpression (\n\t\t(R_*) (EQUALS | NOTEQUALS) (R_*) relationalExpression\n\t)*;\n\nrelationalExpression:\n\tadditiveExpression (\n\t\t(R_*) (LT | LTEQ | GT | GTEQ) (R_*) additiveExpression\n\t)*;\n\nadditiveExpression:\n\tmultiplicativeExpression (\n\t\t(R_*) (PLUS | MINUS) (R_*) multiplicativeExpression\n\t)*;\n\nmultiplicativeExpression:\n\tarrayExpression (\n\t\t(R_*) (MULT | DIV | MOD) (R_*) arrayExpression\n\t)*;\n\narrayExpression:\n\tnegationExpression (COLON negationExpression)? (\n\t\tCOLON negationExpression\n\t)?;\n\nnegationExpression:\n\tMINUS (R_*) powerExpression\n\t| powerExpression;\n\npowerExpression:\n\tunaryExpression ((R_*) POW (R_*) unaryOrNegate)*;\n\nunaryOrNegate: MINUS (R_*) unaryExpression | unaryExpression;\n\nunaryExpression:\n\tNOT (R_*) innerPrimaryExpression\n\t| innerPrimaryExpression;\n\ninnerPrimaryExpression: selectionExpression;\n\nselectionExpression: primaryExpression (selector | funCall)*;\n\nfunCall:\n\tLPAREN (\n\t\t(R_*) logicalExpression (\n\t\t\t(R_*) COMMA (R_*) logicalExpression\n\t\t)*\n\t)? (R_*) RPAREN;\n\nprimaryExpression:\n\tLPAREN ((R__ | R_)*) logicalExpression ((R__ | R_)*) RPAREN\n\t| value;\n\nvalue:\n\tnumber\n\t| BOOL\n\t| string\n\t| material\n\t| symbolRef\n\t| primitiveRef\n\t| array\n\t| anonFunctionDef\n\t| newObject;\n\nsymbolRef: IDENT;\n\nmemberSymbolRef: IDENT | STRING | MULT;\n\nprimitiveRef: PRIMITIVE;\n\ntypeRef: IDENT;\n\nmaterial:\n\tLCURL (R_*) additiveExpression R_ unitMultiplicativeExpression (\n\t\tR_*\n\t) RCURL;\n\narray:\n\tLARR (\n\t\t((R__ | R_)*) label (\n\t\t\t((R__ | R_)*) COMMA ((R__ | R_)*) label\n\t\t)*\n\t)? ((R__ | R_)*) RARR\n\t| LCURL (\n\t\t((R__ | R_)*) label (\n\t\t\t((R__ | R_)*) COMMA ((R__ | R_)*) label\n\t\t)*\n\t)? ((R__ | R_)*) RCURL\n\t| LARR (\n\t\t((R__ | R_)*) logicalExpression (\n\t\t\t((R__ | R_)*) COMMA ((R__ | R_)*) logicalExpression\n\t\t)*\n\t)? ((R__ | R_)*) RARR\n\t| LCURL (\n\t\t((R__ | R_)*) logicalExpression (\n\t\t\t((R__ | R_)*) COMMA ((R__ | R_)*) logicalExpression\n\t\t)*\n\t)? ((R__ | R_)*) RCURL;\n\nnewObject: NEWSTATEMENT R_ typeRef funCall?;\n\ndefaultValue: negnumber | number | BOOL | string | array;\n\nselector: (minarray | dotselector);\n\nminarray:\n\tLARR (R_*) (logicalExpression | MULT) (\n\t\t(R_*) COMMA (R_*) (logicalExpression | MULT)\n\t)* (R_*) RARR\n\t| LCURL (R_*) (logicalExpression | MULT) (\n\t\t(R_*) COMMA (R_*) (logicalExpression | MULT)\n\t)* (R_*) RCURL;\n\ndotselector: (DOT memberSymbolRef)+;\n\narrayName: IDENT | STRING | MULT;\n\nlabel:\n\tarrayName ((R__ | R_)*) COLON ((R__ | R_)*) logicalExpression;\n\nnumber: INTEGER | FLOAT;\n\nnegnumber: MINUS number;\n\nstring: STRING;\n\nunitMultiplicativeExpression:\n\tunitInnerMultiplicativeExpression (\n\t\tR_ PER R_ unitInnerMultiplicativeExpression\n\t)*;\n\nunitInnerMultiplicativeExpression:\n\tunitClump ((R_*) (MULT | DIV) (R_*) unitClump)*;\n\nunitClump: (INTEGER (R_*) DIV) (R_*) unitPowerExpression (\n\t\tR_ CUBED\n\t)? (R_ SQUARED)?\n\t| unitPowerExpression (R_ CUBED)? (R_ SQUARED)?;\n\nunitPowerExpression:\n\tunit ((R_*) POW ((R_*) MINUS)? (R_*) (INTEGER | FLOAT))*;\n\nunit:\n\tunitRef\n\t| LPAREN (R_*) unitMultiplicativeExpression (R_*) RPAREN;\n\nunitRef: IDENT (R_ IDENT)*;\n", "src/formula/grammar/FormulaParser.js": "// eslint-disable\n// @ts-nocheck\n\nimport * as antlr from \"../../../vendor/antlr4ng-all.js\";\nexport class FormulaParser extends antlr.Parser {\n    static COMMENT = 1;\n    static LINE_COMMENT = 2;\n    static R__ = 3;\n    static R_ = 4;\n    static NEWLINES = 5;\n    static WHILESTATEMENT = 6;\n    static FORSTATEMENT = 7;\n    static FROMSTATEMENT = 8;\n    static INSTATEMENT = 9;\n    static TOSTATEMENT = 10;\n    static BYSTATEMENT = 11;\n    static LOOPSTATEMENT = 12;\n    static IFSTATEMENT = 13;\n    static THENSTATEMENT = 14;\n    static ELSESTATEMENT = 15;\n    static FUNCTIONSTATEMENT = 16;\n    static ENDPREFIX = 17;\n    static ENDBLOCK = 18;\n    static RETURNSTATEMENT = 19;\n    static NEWSTATEMENT = 20;\n    static TRYSTATEMENT = 21;\n    static CATCHSTATEMENT = 22;\n    static THROWSTATEMENT = 23;\n    static LPAREN = 24;\n    static COMMA = 25;\n    static RPAREN = 26;\n    static ASSIGN = 27;\n    static DOT = 28;\n    static COLON = 29;\n    static OR = 30;\n    static XOR = 31;\n    static AND = 32;\n    static EQUALS = 33;\n    static NOTEQUALS = 34;\n    static LT = 35;\n    static LTEQ = 36;\n    static GT = 37;\n    static GTEQ = 38;\n    static PLUS = 39;\n    static MINUS = 40;\n    static MULT = 41;\n    static DIV = 42;\n    static MOD = 43;\n    static POW = 44;\n    static NOT = 45;\n    static LARR = 46;\n    static RARR = 47;\n    static LCURL = 48;\n    static RCURL = 49;\n    static BOOL = 50;\n    static PER = 51;\n    static SQUARED = 52;\n    static CUBED = 53;\n    static LBRACKET = 54;\n    static RBRACKET = 55;\n    static IDENT = 56;\n    static PRIMITIVE = 57;\n    static INTEGER = 58;\n    static FLOAT = 59;\n    static STRING = 60;\n    static RULE_lines = 0;\n    static RULE_expression = 1;\n    static RULE_returnExp = 2;\n    static RULE_innerBlock = 3;\n    static RULE_whileLoop = 4;\n    static RULE_forLoop = 5;\n    static RULE_forInLoop = 6;\n    static RULE_ifThenElse = 7;\n    static RULE_functionDef = 8;\n    static RULE_tryCatch = 9;\n    static RULE_throwExp = 10;\n    static RULE_anonFunctionDef = 11;\n    static RULE_assignment = 12;\n    static RULE_assigned = 13;\n    static RULE_logicalExpression = 14;\n    static RULE_booleanXORExpression = 15;\n    static RULE_booleanAndExpression = 16;\n    static RULE_equalityExpression = 17;\n    static RULE_relationalExpression = 18;\n    static RULE_additiveExpression = 19;\n    static RULE_multiplicativeExpression = 20;\n    static RULE_arrayExpression = 21;\n    static RULE_negationExpression = 22;\n    static RULE_powerExpression = 23;\n    static RULE_unaryOrNegate = 24;\n    static RULE_unaryExpression = 25;\n    static RULE_innerPrimaryExpression = 26;\n    static RULE_selectionExpression = 27;\n    static RULE_funCall = 28;\n    static RULE_primaryExpression = 29;\n    static RULE_value = 30;\n    static RULE_symbolRef = 31;\n    static RULE_memberSymbolRef = 32;\n    static RULE_primitiveRef = 33;\n    static RULE_typeRef = 34;\n    static RULE_material = 35;\n    static RULE_array = 36;\n    static RULE_newObject = 37;\n    static RULE_defaultValue = 38;\n    static RULE_selector = 39;\n    static RULE_minarray = 40;\n    static RULE_dotselector = 41;\n    static RULE_arrayName = 42;\n    static RULE_label = 43;\n    static RULE_number = 44;\n    static RULE_negnumber = 45;\n    static RULE_string = 46;\n    static RULE_unitMultiplicativeExpression = 47;\n    static RULE_unitInnerMultiplicativeExpression = 48;\n    static RULE_unitClump = 49;\n    static RULE_unitPowerExpression = 50;\n    static RULE_unit = 51;\n    static RULE_unitRef = 52;\n    static literalNames = [\n        null, null, null, null, null, null, \"'while'\", \"'for'\", \"'from'\",\n        \"'in'\", \"'to'\", \"'by'\", \"'loop'\", \"'if'\", \"'then'\", \"'else'\", \"'function'\",\n        null, \"'end'\", \"'return'\", \"'new'\", \"'try'\", \"'catch'\", \"'throw'\",\n        \"'('\", \"','\", \"')'\", \"'<-'\", \"'.'\", \"':'\", null, \"'xor'\", null,\n        null, null, \"'<'\", \"'<='\", \"'>'\", \"'>='\", \"'+'\", \"'-'\", \"'*'\", \"'/'\",\n        null, \"'^'\", null, null, null, \"'{'\", \"'}'\", null, \"'per'\", \"'squared'\",\n        \"'cubed'\", \"'['\", \"']'\"\n    ];\n    static symbolicNames = [\n        null, \"COMMENT\", \"LINE_COMMENT\", \"R__\", \"R_\", \"NEWLINES\", \"WHILESTATEMENT\",\n        \"FORSTATEMENT\", \"FROMSTATEMENT\", \"INSTATEMENT\", \"TOSTATEMENT\", \"BYSTATEMENT\",\n        \"LOOPSTATEMENT\", \"IFSTATEMENT\", \"THENSTATEMENT\", \"ELSESTATEMENT\",\n        \"FUNCTIONSTATEMENT\", \"ENDPREFIX\", \"ENDBLOCK\", \"RETURNSTATEMENT\",\n        \"NEWSTATEMENT\", \"TRYSTATEMENT\", \"CATCHSTATEMENT\", \"THROWSTATEMENT\",\n        \"LPAREN\", \"COMMA\", \"RPAREN\", \"ASSIGN\", \"DOT\", \"COLON\", \"OR\", \"XOR\",\n        \"AND\", \"EQUALS\", \"NOTEQUALS\", \"LT\", \"LTEQ\", \"GT\", \"GTEQ\", \"PLUS\",\n        \"MINUS\", \"MULT\", \"DIV\", \"MOD\", \"POW\", \"NOT\", \"LARR\", \"RARR\", \"LCURL\",\n        \"RCURL\", \"BOOL\", \"PER\", \"SQUARED\", \"CUBED\", \"LBRACKET\", \"RBRACKET\",\n        \"IDENT\", \"PRIMITIVE\", \"INTEGER\", \"FLOAT\", \"STRING\"\n    ];\n    static ruleNames = [\n        \"lines\", \"expression\", \"returnExp\", \"innerBlock\", \"whileLoop\", \"forLoop\",\n        \"forInLoop\", \"ifThenElse\", \"functionDef\", \"tryCatch\", \"throwExp\",\n        \"anonFunctionDef\", \"assignment\", \"assigned\", \"logicalExpression\",\n        \"booleanXORExpression\", \"booleanAndExpression\", \"equalityExpression\",\n        \"relationalExpression\", \"additiveExpression\", \"multiplicativeExpression\",\n        \"arrayExpression\", \"negationExpression\", \"powerExpression\", \"unaryOrNegate\",\n        \"unaryExpression\", \"innerPrimaryExpression\", \"selectionExpression\",\n        \"funCall\", \"primaryExpression\", \"value\", \"symbolRef\", \"memberSymbolRef\",\n        \"primitiveRef\", \"typeRef\", \"material\", \"array\", \"newObject\", \"defaultValue\",\n        \"selector\", \"minarray\", \"dotselector\", \"arrayName\", \"label\", \"number\",\n        \"negnumber\", \"string\", \"unitMultiplicativeExpression\", \"unitInnerMultiplicativeExpression\",\n        \"unitClump\", \"unitPowerExpression\", \"unit\", \"unitRef\",\n    ];\n    get grammarFileName() { return \"Formula.g\"; }\n    get literalNames() { return FormulaParser.literalNames; }\n    get symbolicNames() { return FormulaParser.symbolicNames; }\n    get ruleNames() { return FormulaParser.ruleNames; }\n    get serializedATN() { return FormulaParser._serializedATN; }\n    createFailedPredicateException(predicate, message) {\n        return new antlr.FailedPredicateException(this, predicate, message);\n    }\n    constructor(input) {\n        super(input);\n        this.interpreter = new antlr.ParserATNSimulator(this, FormulaParser._ATN, FormulaParser.decisionsToDFA, new antlr.PredictionContextCache());\n    }\n    lines() {\n        let localContext = new LinesContext(this.context, this.state);\n        this.enterRule(localContext, 0, FormulaParser.RULE_lines);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                {\n                    this.state = 109;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 3 || _la === 4) {\n                        {\n                            {\n                                this.state = 106;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 3 || _la === 4)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                            }\n                        }\n                        this.state = 111;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 130;\n                this.errorHandler.sync(this);\n                _la = this.tokenStream.LA(1);\n                if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 28909760) !== 0) || ((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & 2032993) !== 0)) {\n                    {\n                        this.state = 112;\n                        this.expression();\n                        this.state = 121;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 2, this.context);\n                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                            if (alternative === 1) {\n                                {\n                                    {\n                                        this.state = 114;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        do {\n                                            {\n                                                {\n                                                    this.state = 113;\n                                                    this.match(FormulaParser.R__);\n                                                }\n                                            }\n                                            this.state = 116;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        } while (_la === 3);\n                                        this.state = 118;\n                                        this.expression();\n                                    }\n                                }\n                            }\n                            this.state = 123;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 2, this.context);\n                        }\n                        {\n                            this.state = 127;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 124;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 129;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                    }\n                }\n                this.state = 132;\n                this.match(FormulaParser.EOF);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    expression() {\n        let localContext = new ExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 2, FormulaParser.RULE_expression);\n        try {\n            this.state = 144;\n            this.errorHandler.sync(this);\n            switch (this.interpreter.adaptivePredict(this.tokenStream, 5, this.context)) {\n                case 1:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 134;\n                        this.assignment();\n                    }\n                    break;\n                case 2:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 135;\n                        this.logicalExpression();\n                    }\n                    break;\n                case 3:\n                    this.enterOuterAlt(localContext, 3);\n                    {\n                        this.state = 136;\n                        this.whileLoop();\n                    }\n                    break;\n                case 4:\n                    this.enterOuterAlt(localContext, 4);\n                    {\n                        this.state = 137;\n                        this.forLoop();\n                    }\n                    break;\n                case 5:\n                    this.enterOuterAlt(localContext, 5);\n                    {\n                        this.state = 138;\n                        this.forInLoop();\n                    }\n                    break;\n                case 6:\n                    this.enterOuterAlt(localContext, 6);\n                    {\n                        this.state = 139;\n                        this.ifThenElse();\n                    }\n                    break;\n                case 7:\n                    this.enterOuterAlt(localContext, 7);\n                    {\n                        this.state = 140;\n                        this.functionDef();\n                    }\n                    break;\n                case 8:\n                    this.enterOuterAlt(localContext, 8);\n                    {\n                        this.state = 141;\n                        this.returnExp();\n                    }\n                    break;\n                case 9:\n                    this.enterOuterAlt(localContext, 9);\n                    {\n                        this.state = 142;\n                        this.tryCatch();\n                    }\n                    break;\n                case 10:\n                    this.enterOuterAlt(localContext, 10);\n                    {\n                        this.state = 143;\n                        this.throwExp();\n                    }\n                    break;\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    returnExp() {\n        let localContext = new ReturnExpContext(this.context, this.state);\n        this.enterRule(localContext, 4, FormulaParser.RULE_returnExp);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 146;\n                this.match(FormulaParser.RETURNSTATEMENT);\n                {\n                    this.state = 150;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 147;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 152;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 153;\n                this.logicalExpression();\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    innerBlock() {\n        let localContext = new InnerBlockContext(this.context, this.state);\n        this.enterRule(localContext, 6, FormulaParser.RULE_innerBlock);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                {\n                    this.state = 158;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 7, this.context);\n                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                        if (alternative === 1) {\n                            {\n                                {\n                                    this.state = 155;\n                                    _la = this.tokenStream.LA(1);\n                                    if (!(_la === 3 || _la === 4)) {\n                                        this.errorHandler.recoverInline(this);\n                                    }\n                                    else {\n                                        this.errorHandler.reportMatch(this);\n                                        this.consume();\n                                    }\n                                }\n                            }\n                        }\n                        this.state = 160;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 7, this.context);\n                    }\n                }\n                this.state = 179;\n                this.errorHandler.sync(this);\n                _la = this.tokenStream.LA(1);\n                if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 28909760) !== 0) || ((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & 2032993) !== 0)) {\n                    {\n                        this.state = 161;\n                        this.expression();\n                        this.state = 170;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 9, this.context);\n                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                            if (alternative === 1) {\n                                {\n                                    {\n                                        this.state = 163;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        do {\n                                            {\n                                                {\n                                                    this.state = 162;\n                                                    this.match(FormulaParser.R__);\n                                                }\n                                            }\n                                            this.state = 165;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        } while (_la === 3);\n                                        this.state = 167;\n                                        this.expression();\n                                    }\n                                }\n                            }\n                            this.state = 172;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 9, this.context);\n                        }\n                        {\n                            this.state = 176;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 10, this.context);\n                            while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                if (alternative === 1) {\n                                    {\n                                        {\n                                            this.state = 173;\n                                            _la = this.tokenStream.LA(1);\n                                            if (!(_la === 3 || _la === 4)) {\n                                                this.errorHandler.recoverInline(this);\n                                            }\n                                            else {\n                                                this.errorHandler.reportMatch(this);\n                                                this.consume();\n                                            }\n                                        }\n                                    }\n                                }\n                                this.state = 178;\n                                this.errorHandler.sync(this);\n                                alternative = this.interpreter.adaptivePredict(this.tokenStream, 10, this.context);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    whileLoop() {\n        let localContext = new WhileLoopContext(this.context, this.state);\n        this.enterRule(localContext, 8, FormulaParser.RULE_whileLoop);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 181;\n                this.match(FormulaParser.WHILESTATEMENT);\n                {\n                    this.state = 185;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 182;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 187;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 188;\n                this.logicalExpression();\n                {\n                    this.state = 189;\n                    this.match(FormulaParser.R__);\n                    this.state = 190;\n                    this.innerBlock();\n                }\n                this.state = 192;\n                this.match(FormulaParser.R__);\n                this.state = 193;\n                this.match(FormulaParser.ENDPREFIX);\n                this.state = 194;\n                this.match(FormulaParser.LOOPSTATEMENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    forLoop() {\n        let localContext = new ForLoopContext(this.context, this.state);\n        this.enterRule(localContext, 10, FormulaParser.RULE_forLoop);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 196;\n                this.match(FormulaParser.FORSTATEMENT);\n                this.state = 197;\n                this.match(FormulaParser.R_);\n                this.state = 198;\n                this.match(FormulaParser.IDENT);\n                this.state = 199;\n                this.match(FormulaParser.R_);\n                this.state = 200;\n                this.match(FormulaParser.FROMSTATEMENT);\n                {\n                    this.state = 204;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 201;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 206;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 207;\n                this.logicalExpression();\n                {\n                    this.state = 211;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 208;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 213;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 214;\n                this.match(FormulaParser.TOSTATEMENT);\n                {\n                    this.state = 218;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 215;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 220;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 221;\n                this.logicalExpression();\n                this.state = 236;\n                this.errorHandler.sync(this);\n                _la = this.tokenStream.LA(1);\n                if (_la === 4 || _la === 11) {\n                    {\n                        {\n                            this.state = 225;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 222;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 227;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 228;\n                        this.match(FormulaParser.BYSTATEMENT);\n                        {\n                            this.state = 232;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 229;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 234;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 235;\n                        this.logicalExpression();\n                    }\n                }\n                this.state = 240;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 19, this.context)) {\n                    case 1:\n                        {\n                            this.state = 238;\n                            this.match(FormulaParser.R__);\n                            this.state = 239;\n                            this.innerBlock();\n                        }\n                        break;\n                }\n                this.state = 242;\n                this.match(FormulaParser.R__);\n                this.state = 243;\n                this.match(FormulaParser.ENDPREFIX);\n                this.state = 244;\n                this.match(FormulaParser.LOOPSTATEMENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    forInLoop() {\n        let localContext = new ForInLoopContext(this.context, this.state);\n        this.enterRule(localContext, 12, FormulaParser.RULE_forInLoop);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 246;\n                this.match(FormulaParser.FORSTATEMENT);\n                this.state = 247;\n                this.match(FormulaParser.R_);\n                this.state = 248;\n                this.match(FormulaParser.IDENT);\n                this.state = 249;\n                this.match(FormulaParser.R_);\n                this.state = 250;\n                this.match(FormulaParser.INSTATEMENT);\n                {\n                    this.state = 254;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 251;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 256;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 257;\n                this.logicalExpression();\n                this.state = 260;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 21, this.context)) {\n                    case 1:\n                        {\n                            this.state = 258;\n                            this.match(FormulaParser.R__);\n                            this.state = 259;\n                            this.innerBlock();\n                        }\n                        break;\n                }\n                this.state = 262;\n                this.match(FormulaParser.R__);\n                this.state = 263;\n                this.match(FormulaParser.ENDPREFIX);\n                this.state = 264;\n                this.match(FormulaParser.LOOPSTATEMENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    ifThenElse() {\n        let localContext = new IfThenElseContext(this.context, this.state);\n        this.enterRule(localContext, 14, FormulaParser.RULE_ifThenElse);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 266;\n                this.match(FormulaParser.IFSTATEMENT);\n                {\n                    this.state = 270;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 267;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 272;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 273;\n                this.logicalExpression();\n                {\n                    this.state = 277;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 23, this.context);\n                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                        if (alternative === 1) {\n                            {\n                                {\n                                    this.state = 274;\n                                    _la = this.tokenStream.LA(1);\n                                    if (!(_la === 3 || _la === 4)) {\n                                        this.errorHandler.recoverInline(this);\n                                    }\n                                    else {\n                                        this.errorHandler.reportMatch(this);\n                                        this.consume();\n                                    }\n                                }\n                            }\n                        }\n                        this.state = 279;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 23, this.context);\n                    }\n                }\n                this.state = 281;\n                this.errorHandler.sync(this);\n                _la = this.tokenStream.LA(1);\n                if (_la === 14) {\n                    {\n                        this.state = 280;\n                        this.match(FormulaParser.THENSTATEMENT);\n                    }\n                }\n                this.state = 285;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 25, this.context)) {\n                    case 1:\n                        {\n                            this.state = 283;\n                            this.match(FormulaParser.R__);\n                            this.state = 284;\n                            this.innerBlock();\n                        }\n                        break;\n                }\n                this.state = 313;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 30, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                this.state = 287;\n                                this.match(FormulaParser.R__);\n                                this.state = 288;\n                                this.match(FormulaParser.ELSESTATEMENT);\n                                this.state = 289;\n                                this.match(FormulaParser.R_);\n                                this.state = 290;\n                                this.match(FormulaParser.IFSTATEMENT);\n                                {\n                                    this.state = 294;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 291;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 296;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 297;\n                                this.logicalExpression();\n                                {\n                                    this.state = 301;\n                                    this.errorHandler.sync(this);\n                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 27, this.context);\n                                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                        if (alternative === 1) {\n                                            {\n                                                {\n                                                    this.state = 298;\n                                                    _la = this.tokenStream.LA(1);\n                                                    if (!(_la === 3 || _la === 4)) {\n                                                        this.errorHandler.recoverInline(this);\n                                                    }\n                                                    else {\n                                                        this.errorHandler.reportMatch(this);\n                                                        this.consume();\n                                                    }\n                                                }\n                                            }\n                                        }\n                                        this.state = 303;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 27, this.context);\n                                    }\n                                }\n                                this.state = 305;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                                if (_la === 14) {\n                                    {\n                                        this.state = 304;\n                                        this.match(FormulaParser.THENSTATEMENT);\n                                    }\n                                }\n                                this.state = 309;\n                                this.errorHandler.sync(this);\n                                switch (this.interpreter.adaptivePredict(this.tokenStream, 29, this.context)) {\n                                    case 1:\n                                        {\n                                            this.state = 307;\n                                            this.match(FormulaParser.R__);\n                                            this.state = 308;\n                                            this.innerBlock();\n                                        }\n                                        break;\n                                }\n                            }\n                        }\n                    }\n                    this.state = 315;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 30, this.context);\n                }\n                this.state = 322;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 32, this.context)) {\n                    case 1:\n                        {\n                            this.state = 316;\n                            this.match(FormulaParser.R__);\n                            this.state = 317;\n                            this.match(FormulaParser.ELSESTATEMENT);\n                            this.state = 320;\n                            this.errorHandler.sync(this);\n                            switch (this.interpreter.adaptivePredict(this.tokenStream, 31, this.context)) {\n                                case 1:\n                                    {\n                                        this.state = 318;\n                                        this.match(FormulaParser.R__);\n                                        this.state = 319;\n                                        this.innerBlock();\n                                    }\n                                    break;\n                            }\n                        }\n                        break;\n                }\n                this.state = 324;\n                this.match(FormulaParser.R__);\n                this.state = 325;\n                this.match(FormulaParser.ENDPREFIX);\n                this.state = 326;\n                this.match(FormulaParser.IFSTATEMENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    functionDef() {\n        let localContext = new FunctionDefContext(this.context, this.state);\n        this.enterRule(localContext, 16, FormulaParser.RULE_functionDef);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 328;\n                this.match(FormulaParser.FUNCTIONSTATEMENT);\n                this.state = 329;\n                this.match(FormulaParser.R_);\n                this.state = 330;\n                this.match(FormulaParser.IDENT);\n                {\n                    this.state = 334;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 331;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 336;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 337;\n                this.match(FormulaParser.LPAREN);\n                this.state = 413;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 46, this.context)) {\n                    case 1:\n                        {\n                            {\n                                this.state = 341;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                                while (_la === 4) {\n                                    {\n                                        {\n                                            this.state = 338;\n                                            this.match(FormulaParser.R_);\n                                        }\n                                    }\n                                    this.state = 343;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                }\n                            }\n                            this.state = 344;\n                            this.match(FormulaParser.IDENT);\n                            this.state = 378;\n                            this.errorHandler.sync(this);\n                            switch (this.interpreter.adaptivePredict(this.tokenStream, 40, this.context)) {\n                                case 1:\n                                    {\n                                        {\n                                            this.state = 348;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 345;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 350;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 351;\n                                        this.match(FormulaParser.EQUALS);\n                                        {\n                                            this.state = 355;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 352;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 357;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 358;\n                                        this.defaultValue();\n                                    }\n                                    break;\n                                case 2:\n                                    {\n                                        this.state = 375;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 39, this.context);\n                                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                            if (alternative === 1) {\n                                                {\n                                                    {\n                                                        {\n                                                            this.state = 362;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                            while (_la === 4) {\n                                                                {\n                                                                    {\n                                                                        this.state = 359;\n                                                                        this.match(FormulaParser.R_);\n                                                                    }\n                                                                }\n                                                                this.state = 364;\n                                                                this.errorHandler.sync(this);\n                                                                _la = this.tokenStream.LA(1);\n                                                            }\n                                                        }\n                                                        this.state = 365;\n                                                        this.match(FormulaParser.COMMA);\n                                                        {\n                                                            this.state = 369;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                            while (_la === 4) {\n                                                                {\n                                                                    {\n                                                                        this.state = 366;\n                                                                        this.match(FormulaParser.R_);\n                                                                    }\n                                                                }\n                                                                this.state = 371;\n                                                                this.errorHandler.sync(this);\n                                                                _la = this.tokenStream.LA(1);\n                                                            }\n                                                        }\n                                                        this.state = 372;\n                                                        this.match(FormulaParser.IDENT);\n                                                    }\n                                                }\n                                            }\n                                            this.state = 377;\n                                            this.errorHandler.sync(this);\n                                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 39, this.context);\n                                        }\n                                    }\n                                    break;\n                            }\n                            this.state = 410;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 45, this.context);\n                            while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                if (alternative === 1) {\n                                    {\n                                        {\n                                            {\n                                                this.state = 383;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 380;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 385;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 386;\n                                            this.match(FormulaParser.COMMA);\n                                            {\n                                                this.state = 390;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 387;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 392;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 393;\n                                            this.match(FormulaParser.IDENT);\n                                            {\n                                                this.state = 397;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 394;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 399;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 400;\n                                            this.match(FormulaParser.EQUALS);\n                                            {\n                                                this.state = 404;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 401;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 406;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 407;\n                                            this.defaultValue();\n                                        }\n                                    }\n                                }\n                                this.state = 412;\n                                this.errorHandler.sync(this);\n                                alternative = this.interpreter.adaptivePredict(this.tokenStream, 45, this.context);\n                            }\n                        }\n                        break;\n                }\n                {\n                    this.state = 418;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 415;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 420;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 421;\n                this.match(FormulaParser.RPAREN);\n                this.state = 424;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 48, this.context)) {\n                    case 1:\n                        {\n                            this.state = 422;\n                            this.match(FormulaParser.R__);\n                            this.state = 423;\n                            this.innerBlock();\n                        }\n                        break;\n                }\n                this.state = 426;\n                this.match(FormulaParser.R__);\n                this.state = 427;\n                this.match(FormulaParser.ENDPREFIX);\n                this.state = 428;\n                this.match(FormulaParser.FUNCTIONSTATEMENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    tryCatch() {\n        let localContext = new TryCatchContext(this.context, this.state);\n        this.enterRule(localContext, 18, FormulaParser.RULE_tryCatch);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 430;\n                this.match(FormulaParser.TRYSTATEMENT);\n                this.state = 433;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 49, this.context)) {\n                    case 1:\n                        {\n                            this.state = 431;\n                            this.match(FormulaParser.R__);\n                            this.state = 432;\n                            this.innerBlock();\n                        }\n                        break;\n                }\n                this.state = 435;\n                this.match(FormulaParser.R__);\n                this.state = 436;\n                this.match(FormulaParser.CATCHSTATEMENT);\n                this.state = 437;\n                this.match(FormulaParser.R_);\n                this.state = 438;\n                this.match(FormulaParser.IDENT);\n                this.state = 441;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 50, this.context)) {\n                    case 1:\n                        {\n                            this.state = 439;\n                            this.match(FormulaParser.R__);\n                            this.state = 440;\n                            this.innerBlock();\n                        }\n                        break;\n                }\n                this.state = 443;\n                this.match(FormulaParser.R__);\n                this.state = 444;\n                this.match(FormulaParser.ENDPREFIX);\n                this.state = 445;\n                this.match(FormulaParser.TRYSTATEMENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    throwExp() {\n        let localContext = new ThrowExpContext(this.context, this.state);\n        this.enterRule(localContext, 20, FormulaParser.RULE_throwExp);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 447;\n                this.match(FormulaParser.THROWSTATEMENT);\n                this.state = 448;\n                this.match(FormulaParser.R_);\n                this.state = 449;\n                this.primaryExpression();\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    anonFunctionDef() {\n        let localContext = new AnonFunctionDefContext(this.context, this.state);\n        this.enterRule(localContext, 22, FormulaParser.RULE_anonFunctionDef);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 451;\n                this.match(FormulaParser.FUNCTIONSTATEMENT);\n                {\n                    this.state = 455;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 452;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 457;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 458;\n                this.match(FormulaParser.LPAREN);\n                this.state = 534;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 64, this.context)) {\n                    case 1:\n                        {\n                            {\n                                this.state = 462;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                                while (_la === 4) {\n                                    {\n                                        {\n                                            this.state = 459;\n                                            this.match(FormulaParser.R_);\n                                        }\n                                    }\n                                    this.state = 464;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                }\n                            }\n                            this.state = 465;\n                            this.match(FormulaParser.IDENT);\n                            this.state = 499;\n                            this.errorHandler.sync(this);\n                            switch (this.interpreter.adaptivePredict(this.tokenStream, 58, this.context)) {\n                                case 1:\n                                    {\n                                        {\n                                            this.state = 469;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 466;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 471;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 472;\n                                        this.match(FormulaParser.EQUALS);\n                                        {\n                                            this.state = 476;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 473;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 478;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 479;\n                                        this.defaultValue();\n                                    }\n                                    break;\n                                case 2:\n                                    {\n                                        this.state = 496;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 57, this.context);\n                                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                            if (alternative === 1) {\n                                                {\n                                                    {\n                                                        {\n                                                            this.state = 483;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                            while (_la === 4) {\n                                                                {\n                                                                    {\n                                                                        this.state = 480;\n                                                                        this.match(FormulaParser.R_);\n                                                                    }\n                                                                }\n                                                                this.state = 485;\n                                                                this.errorHandler.sync(this);\n                                                                _la = this.tokenStream.LA(1);\n                                                            }\n                                                        }\n                                                        this.state = 486;\n                                                        this.match(FormulaParser.COMMA);\n                                                        {\n                                                            this.state = 490;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                            while (_la === 4) {\n                                                                {\n                                                                    {\n                                                                        this.state = 487;\n                                                                        this.match(FormulaParser.R_);\n                                                                    }\n                                                                }\n                                                                this.state = 492;\n                                                                this.errorHandler.sync(this);\n                                                                _la = this.tokenStream.LA(1);\n                                                            }\n                                                        }\n                                                        this.state = 493;\n                                                        this.match(FormulaParser.IDENT);\n                                                    }\n                                                }\n                                            }\n                                            this.state = 498;\n                                            this.errorHandler.sync(this);\n                                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 57, this.context);\n                                        }\n                                    }\n                                    break;\n                            }\n                            this.state = 531;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 63, this.context);\n                            while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                if (alternative === 1) {\n                                    {\n                                        {\n                                            {\n                                                this.state = 504;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 501;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 506;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 507;\n                                            this.match(FormulaParser.COMMA);\n                                            {\n                                                this.state = 511;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 508;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 513;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 514;\n                                            this.match(FormulaParser.IDENT);\n                                            {\n                                                this.state = 518;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 515;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 520;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 521;\n                                            this.match(FormulaParser.EQUALS);\n                                            {\n                                                this.state = 525;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 522;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 527;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 528;\n                                            this.defaultValue();\n                                        }\n                                    }\n                                }\n                                this.state = 533;\n                                this.errorHandler.sync(this);\n                                alternative = this.interpreter.adaptivePredict(this.tokenStream, 63, this.context);\n                            }\n                        }\n                        break;\n                }\n                {\n                    this.state = 539;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 536;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 541;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 542;\n                this.match(FormulaParser.RPAREN);\n                this.state = 557;\n                this.errorHandler.sync(this);\n                switch (this.tokenStream.LA(1)) {\n                    case FormulaParser.R__:\n                        {\n                            {\n                                this.state = 545;\n                                this.errorHandler.sync(this);\n                                switch (this.interpreter.adaptivePredict(this.tokenStream, 66, this.context)) {\n                                    case 1:\n                                        {\n                                            this.state = 543;\n                                            this.match(FormulaParser.R__);\n                                            this.state = 544;\n                                            this.innerBlock();\n                                        }\n                                        break;\n                                }\n                                this.state = 547;\n                                this.match(FormulaParser.R__);\n                                this.state = 548;\n                                this.match(FormulaParser.ENDPREFIX);\n                                this.state = 549;\n                                this.match(FormulaParser.FUNCTIONSTATEMENT);\n                            }\n                        }\n                        break;\n                    case FormulaParser.R_:\n                    case FormulaParser.WHILESTATEMENT:\n                    case FormulaParser.FORSTATEMENT:\n                    case FormulaParser.IFSTATEMENT:\n                    case FormulaParser.FUNCTIONSTATEMENT:\n                    case FormulaParser.RETURNSTATEMENT:\n                    case FormulaParser.NEWSTATEMENT:\n                    case FormulaParser.TRYSTATEMENT:\n                    case FormulaParser.THROWSTATEMENT:\n                    case FormulaParser.LPAREN:\n                    case FormulaParser.MINUS:\n                    case FormulaParser.NOT:\n                    case FormulaParser.LARR:\n                    case FormulaParser.LCURL:\n                    case FormulaParser.BOOL:\n                    case FormulaParser.IDENT:\n                    case FormulaParser.PRIMITIVE:\n                    case FormulaParser.INTEGER:\n                    case FormulaParser.FLOAT:\n                    case FormulaParser.STRING:\n                        {\n                            {\n                                this.state = 553;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                                while (_la === 4) {\n                                    {\n                                        {\n                                            this.state = 550;\n                                            this.match(FormulaParser.R_);\n                                        }\n                                    }\n                                    this.state = 555;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                }\n                            }\n                            this.state = 556;\n                            this.expression();\n                        }\n                        break;\n                    default:\n                        throw new antlr.NoViableAltException(this);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    assignment() {\n        let localContext = new AssignmentContext(this.context, this.state);\n        this.enterRule(localContext, 24, FormulaParser.RULE_assignment);\n        let _la;\n        try {\n            let alternative;\n            this.state = 706;\n            this.errorHandler.sync(this);\n            switch (this.interpreter.adaptivePredict(this.tokenStream, 93, this.context)) {\n                case 1:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 559;\n                        this.match(FormulaParser.IDENT);\n                        {\n                            this.state = 563;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 560;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 565;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 566;\n                        this.match(FormulaParser.LPAREN);\n                        this.state = 642;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 82, this.context)) {\n                            case 1:\n                                {\n                                    {\n                                        this.state = 570;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        while (_la === 4) {\n                                            {\n                                                {\n                                                    this.state = 567;\n                                                    this.match(FormulaParser.R_);\n                                                }\n                                            }\n                                            this.state = 572;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        }\n                                    }\n                                    this.state = 573;\n                                    this.match(FormulaParser.IDENT);\n                                    this.state = 607;\n                                    this.errorHandler.sync(this);\n                                    switch (this.interpreter.adaptivePredict(this.tokenStream, 76, this.context)) {\n                                        case 1:\n                                            {\n                                                {\n                                                    this.state = 577;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                    while (_la === 4) {\n                                                        {\n                                                            {\n                                                                this.state = 574;\n                                                                this.match(FormulaParser.R_);\n                                                            }\n                                                        }\n                                                        this.state = 579;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                    }\n                                                }\n                                                this.state = 580;\n                                                this.match(FormulaParser.EQUALS);\n                                                {\n                                                    this.state = 584;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                    while (_la === 4) {\n                                                        {\n                                                            {\n                                                                this.state = 581;\n                                                                this.match(FormulaParser.R_);\n                                                            }\n                                                        }\n                                                        this.state = 586;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                    }\n                                                }\n                                                this.state = 587;\n                                                this.defaultValue();\n                                            }\n                                            break;\n                                        case 2:\n                                            {\n                                                this.state = 604;\n                                                this.errorHandler.sync(this);\n                                                alternative = this.interpreter.adaptivePredict(this.tokenStream, 75, this.context);\n                                                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                                    if (alternative === 1) {\n                                                        {\n                                                            {\n                                                                {\n                                                                    this.state = 591;\n                                                                    this.errorHandler.sync(this);\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    while (_la === 4) {\n                                                                        {\n                                                                            {\n                                                                                this.state = 588;\n                                                                                this.match(FormulaParser.R_);\n                                                                            }\n                                                                        }\n                                                                        this.state = 593;\n                                                                        this.errorHandler.sync(this);\n                                                                        _la = this.tokenStream.LA(1);\n                                                                    }\n                                                                }\n                                                                this.state = 594;\n                                                                this.match(FormulaParser.COMMA);\n                                                                {\n                                                                    this.state = 598;\n                                                                    this.errorHandler.sync(this);\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    while (_la === 4) {\n                                                                        {\n                                                                            {\n                                                                                this.state = 595;\n                                                                                this.match(FormulaParser.R_);\n                                                                            }\n                                                                        }\n                                                                        this.state = 600;\n                                                                        this.errorHandler.sync(this);\n                                                                        _la = this.tokenStream.LA(1);\n                                                                    }\n                                                                }\n                                                                this.state = 601;\n                                                                this.match(FormulaParser.IDENT);\n                                                            }\n                                                        }\n                                                    }\n                                                    this.state = 606;\n                                                    this.errorHandler.sync(this);\n                                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 75, this.context);\n                                                }\n                                            }\n                                            break;\n                                    }\n                                    this.state = 639;\n                                    this.errorHandler.sync(this);\n                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 81, this.context);\n                                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                        if (alternative === 1) {\n                                            {\n                                                {\n                                                    {\n                                                        this.state = 612;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 609;\n                                                                    this.match(FormulaParser.R_);\n                                                                }\n                                                            }\n                                                            this.state = 614;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 615;\n                                                    this.match(FormulaParser.COMMA);\n                                                    {\n                                                        this.state = 619;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 616;\n                                                                    this.match(FormulaParser.R_);\n                                                                }\n                                                            }\n                                                            this.state = 621;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 622;\n                                                    this.match(FormulaParser.IDENT);\n                                                    {\n                                                        this.state = 626;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 623;\n                                                                    this.match(FormulaParser.R_);\n                                                                }\n                                                            }\n                                                            this.state = 628;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 629;\n                                                    this.match(FormulaParser.EQUALS);\n                                                    {\n                                                        this.state = 633;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 630;\n                                                                    this.match(FormulaParser.R_);\n                                                                }\n                                                            }\n                                                            this.state = 635;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 636;\n                                                    this.defaultValue();\n                                                }\n                                            }\n                                        }\n                                        this.state = 641;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 81, this.context);\n                                    }\n                                }\n                                break;\n                        }\n                        {\n                            this.state = 647;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 644;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 649;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 650;\n                        this.match(FormulaParser.RPAREN);\n                        {\n                            this.state = 654;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 651;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 656;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 657;\n                        this.match(FormulaParser.ASSIGN);\n                        {\n                            this.state = 661;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 658;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 663;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 664;\n                        this.logicalExpression();\n                    }\n                    break;\n                case 2:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 667;\n                        this.errorHandler.sync(this);\n                        switch (this.tokenStream.LA(1)) {\n                            case FormulaParser.PRIMITIVE:\n                                {\n                                    this.state = 665;\n                                    this.primitiveRef();\n                                }\n                                break;\n                            case FormulaParser.IDENT:\n                                {\n                                    this.state = 666;\n                                    this.assigned();\n                                }\n                                break;\n                            default:\n                                throw new antlr.NoViableAltException(this);\n                        }\n                        this.state = 688;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 90, this.context);\n                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                            if (alternative === 1) {\n                                {\n                                    {\n                                        {\n                                            this.state = 672;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 669;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 674;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 675;\n                                        this.match(FormulaParser.COMMA);\n                                        {\n                                            this.state = 679;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 676;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 681;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 684;\n                                        this.errorHandler.sync(this);\n                                        switch (this.tokenStream.LA(1)) {\n                                            case FormulaParser.PRIMITIVE:\n                                                {\n                                                    this.state = 682;\n                                                    this.primitiveRef();\n                                                }\n                                                break;\n                                            case FormulaParser.IDENT:\n                                                {\n                                                    this.state = 683;\n                                                    this.assigned();\n                                                }\n                                                break;\n                                            default:\n                                                throw new antlr.NoViableAltException(this);\n                                        }\n                                    }\n                                }\n                            }\n                            this.state = 690;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 90, this.context);\n                        }\n                        {\n                            this.state = 694;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 691;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 696;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 697;\n                        this.match(FormulaParser.ASSIGN);\n                        {\n                            this.state = 701;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 698;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 703;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 704;\n                        this.logicalExpression();\n                    }\n                    break;\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    assigned() {\n        let localContext = new AssignedContext(this.context, this.state);\n        this.enterRule(localContext, 26, FormulaParser.RULE_assigned);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 708;\n                this.match(FormulaParser.IDENT);\n                this.state = 710;\n                this.errorHandler.sync(this);\n                _la = this.tokenStream.LA(1);\n                if (((((_la - 28)) & ~0x1F) === 0 && ((1 << (_la - 28)) & 1310721) !== 0)) {\n                    {\n                        this.state = 709;\n                        this.selector();\n                    }\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    logicalExpression() {\n        let localContext = new LogicalExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 28, FormulaParser.RULE_logicalExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 712;\n                this.booleanXORExpression();\n                this.state = 729;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 97, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 716;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 713;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 718;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 719;\n                                this.match(FormulaParser.OR);\n                                {\n                                    this.state = 723;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 720;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 725;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 726;\n                                this.booleanXORExpression();\n                            }\n                        }\n                    }\n                    this.state = 731;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 97, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    booleanXORExpression() {\n        let localContext = new BooleanXORExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 30, FormulaParser.RULE_booleanXORExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 732;\n                this.booleanAndExpression();\n                this.state = 749;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 100, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 736;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 733;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 738;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 739;\n                                this.match(FormulaParser.XOR);\n                                {\n                                    this.state = 743;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 740;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 745;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 746;\n                                this.booleanAndExpression();\n                            }\n                        }\n                    }\n                    this.state = 751;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 100, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    booleanAndExpression() {\n        let localContext = new BooleanAndExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 32, FormulaParser.RULE_booleanAndExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 752;\n                this.equalityExpression();\n                this.state = 769;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 103, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 756;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 753;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 758;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 759;\n                                this.match(FormulaParser.AND);\n                                {\n                                    this.state = 763;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 760;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 765;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 766;\n                                this.equalityExpression();\n                            }\n                        }\n                    }\n                    this.state = 771;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 103, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    equalityExpression() {\n        let localContext = new EqualityExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 34, FormulaParser.RULE_equalityExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 772;\n                this.relationalExpression();\n                this.state = 789;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 106, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 776;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 773;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 778;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 779;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 33 || _la === 34)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                                {\n                                    this.state = 783;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 780;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 785;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 786;\n                                this.relationalExpression();\n                            }\n                        }\n                    }\n                    this.state = 791;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 106, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    relationalExpression() {\n        let localContext = new RelationalExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 36, FormulaParser.RULE_relationalExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 792;\n                this.additiveExpression();\n                this.state = 809;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 109, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 796;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 793;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 798;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 799;\n                                _la = this.tokenStream.LA(1);\n                                if (!(((((_la - 35)) & ~0x1F) === 0 && ((1 << (_la - 35)) & 15) !== 0))) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                                {\n                                    this.state = 803;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 800;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 805;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 806;\n                                this.additiveExpression();\n                            }\n                        }\n                    }\n                    this.state = 811;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 109, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    additiveExpression() {\n        let localContext = new AdditiveExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 38, FormulaParser.RULE_additiveExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 812;\n                this.multiplicativeExpression();\n                this.state = 829;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 112, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 816;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 813;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 818;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 819;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 39 || _la === 40)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                                {\n                                    this.state = 823;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 820;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 825;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 826;\n                                this.multiplicativeExpression();\n                            }\n                        }\n                    }\n                    this.state = 831;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 112, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    multiplicativeExpression() {\n        let localContext = new MultiplicativeExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 40, FormulaParser.RULE_multiplicativeExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 832;\n                this.arrayExpression();\n                this.state = 849;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 115, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 836;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 833;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 838;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 839;\n                                _la = this.tokenStream.LA(1);\n                                if (!(((((_la - 41)) & ~0x1F) === 0 && ((1 << (_la - 41)) & 7) !== 0))) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                                {\n                                    this.state = 843;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 840;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 845;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 846;\n                                this.arrayExpression();\n                            }\n                        }\n                    }\n                    this.state = 851;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 115, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    arrayExpression() {\n        let localContext = new ArrayExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 42, FormulaParser.RULE_arrayExpression);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 852;\n                this.negationExpression();\n                this.state = 855;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 116, this.context)) {\n                    case 1:\n                        {\n                            this.state = 853;\n                            this.match(FormulaParser.COLON);\n                            this.state = 854;\n                            this.negationExpression();\n                        }\n                        break;\n                }\n                this.state = 859;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 117, this.context)) {\n                    case 1:\n                        {\n                            this.state = 857;\n                            this.match(FormulaParser.COLON);\n                            this.state = 858;\n                            this.negationExpression();\n                        }\n                        break;\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    negationExpression() {\n        let localContext = new NegationExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 44, FormulaParser.RULE_negationExpression);\n        let _la;\n        try {\n            this.state = 870;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.MINUS:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 861;\n                        this.match(FormulaParser.MINUS);\n                        {\n                            this.state = 865;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 862;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 867;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 868;\n                        this.powerExpression();\n                    }\n                    break;\n                case FormulaParser.FUNCTIONSTATEMENT:\n                case FormulaParser.NEWSTATEMENT:\n                case FormulaParser.LPAREN:\n                case FormulaParser.NOT:\n                case FormulaParser.LARR:\n                case FormulaParser.LCURL:\n                case FormulaParser.BOOL:\n                case FormulaParser.IDENT:\n                case FormulaParser.PRIMITIVE:\n                case FormulaParser.INTEGER:\n                case FormulaParser.FLOAT:\n                case FormulaParser.STRING:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 869;\n                        this.powerExpression();\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    powerExpression() {\n        let localContext = new PowerExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 46, FormulaParser.RULE_powerExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 872;\n                this.unaryExpression();\n                this.state = 889;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 122, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 876;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 873;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 878;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 879;\n                                this.match(FormulaParser.POW);\n                                {\n                                    this.state = 883;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 880;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 885;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 886;\n                                this.unaryOrNegate();\n                            }\n                        }\n                    }\n                    this.state = 891;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 122, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unaryOrNegate() {\n        let localContext = new UnaryOrNegateContext(this.context, this.state);\n        this.enterRule(localContext, 48, FormulaParser.RULE_unaryOrNegate);\n        let _la;\n        try {\n            this.state = 901;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.MINUS:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 892;\n                        this.match(FormulaParser.MINUS);\n                        {\n                            this.state = 896;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 893;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 898;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 899;\n                        this.unaryExpression();\n                    }\n                    break;\n                case FormulaParser.FUNCTIONSTATEMENT:\n                case FormulaParser.NEWSTATEMENT:\n                case FormulaParser.LPAREN:\n                case FormulaParser.NOT:\n                case FormulaParser.LARR:\n                case FormulaParser.LCURL:\n                case FormulaParser.BOOL:\n                case FormulaParser.IDENT:\n                case FormulaParser.PRIMITIVE:\n                case FormulaParser.INTEGER:\n                case FormulaParser.FLOAT:\n                case FormulaParser.STRING:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 900;\n                        this.unaryExpression();\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unaryExpression() {\n        let localContext = new UnaryExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 50, FormulaParser.RULE_unaryExpression);\n        let _la;\n        try {\n            this.state = 912;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.NOT:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 903;\n                        this.match(FormulaParser.NOT);\n                        {\n                            this.state = 907;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 904;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 909;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 910;\n                        this.innerPrimaryExpression();\n                    }\n                    break;\n                case FormulaParser.FUNCTIONSTATEMENT:\n                case FormulaParser.NEWSTATEMENT:\n                case FormulaParser.LPAREN:\n                case FormulaParser.LARR:\n                case FormulaParser.LCURL:\n                case FormulaParser.BOOL:\n                case FormulaParser.IDENT:\n                case FormulaParser.PRIMITIVE:\n                case FormulaParser.INTEGER:\n                case FormulaParser.FLOAT:\n                case FormulaParser.STRING:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 911;\n                        this.innerPrimaryExpression();\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    innerPrimaryExpression() {\n        let localContext = new InnerPrimaryExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 52, FormulaParser.RULE_innerPrimaryExpression);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 914;\n                this.selectionExpression();\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    selectionExpression() {\n        let localContext = new SelectionExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 54, FormulaParser.RULE_selectionExpression);\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 916;\n                this.primaryExpression();\n                this.state = 921;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 128, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            this.state = 919;\n                            this.errorHandler.sync(this);\n                            switch (this.tokenStream.LA(1)) {\n                                case FormulaParser.DOT:\n                                case FormulaParser.LARR:\n                                case FormulaParser.LCURL:\n                                    {\n                                        this.state = 917;\n                                        this.selector();\n                                    }\n                                    break;\n                                case FormulaParser.LPAREN:\n                                    {\n                                        this.state = 918;\n                                        this.funCall();\n                                    }\n                                    break;\n                                default:\n                                    throw new antlr.NoViableAltException(this);\n                            }\n                        }\n                    }\n                    this.state = 923;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 128, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    funCall() {\n        let localContext = new FunCallContext(this.context, this.state);\n        this.enterRule(localContext, 56, FormulaParser.RULE_funCall);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 924;\n                this.match(FormulaParser.LPAREN);\n                this.state = 951;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 133, this.context)) {\n                    case 1:\n                        {\n                            {\n                                this.state = 928;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                                while (_la === 4) {\n                                    {\n                                        {\n                                            this.state = 925;\n                                            this.match(FormulaParser.R_);\n                                        }\n                                    }\n                                    this.state = 930;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                }\n                            }\n                            this.state = 931;\n                            this.logicalExpression();\n                            this.state = 948;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 132, this.context);\n                            while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                if (alternative === 1) {\n                                    {\n                                        {\n                                            {\n                                                this.state = 935;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 932;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 937;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 938;\n                                            this.match(FormulaParser.COMMA);\n                                            {\n                                                this.state = 942;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 939;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 944;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 945;\n                                            this.logicalExpression();\n                                        }\n                                    }\n                                }\n                                this.state = 950;\n                                this.errorHandler.sync(this);\n                                alternative = this.interpreter.adaptivePredict(this.tokenStream, 132, this.context);\n                            }\n                        }\n                        break;\n                }\n                {\n                    this.state = 956;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 953;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 958;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 959;\n                this.match(FormulaParser.RPAREN);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    primaryExpression() {\n        let localContext = new PrimaryExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 58, FormulaParser.RULE_primaryExpression);\n        let _la;\n        try {\n            this.state = 978;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.LPAREN:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 961;\n                        this.match(FormulaParser.LPAREN);\n                        {\n                            this.state = 965;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 962;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 967;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 968;\n                        this.logicalExpression();\n                        {\n                            this.state = 972;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 969;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 974;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 975;\n                        this.match(FormulaParser.RPAREN);\n                    }\n                    break;\n                case FormulaParser.FUNCTIONSTATEMENT:\n                case FormulaParser.NEWSTATEMENT:\n                case FormulaParser.LARR:\n                case FormulaParser.LCURL:\n                case FormulaParser.BOOL:\n                case FormulaParser.IDENT:\n                case FormulaParser.PRIMITIVE:\n                case FormulaParser.INTEGER:\n                case FormulaParser.FLOAT:\n                case FormulaParser.STRING:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 977;\n                        this.value();\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    value() {\n        let localContext = new ValueContext(this.context, this.state);\n        this.enterRule(localContext, 60, FormulaParser.RULE_value);\n        try {\n            this.state = 989;\n            this.errorHandler.sync(this);\n            switch (this.interpreter.adaptivePredict(this.tokenStream, 138, this.context)) {\n                case 1:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 980;\n                        this.number_();\n                    }\n                    break;\n                case 2:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 981;\n                        this.match(FormulaParser.BOOL);\n                    }\n                    break;\n                case 3:\n                    this.enterOuterAlt(localContext, 3);\n                    {\n                        this.state = 982;\n                        this.string_();\n                    }\n                    break;\n                case 4:\n                    this.enterOuterAlt(localContext, 4);\n                    {\n                        this.state = 983;\n                        this.material();\n                    }\n                    break;\n                case 5:\n                    this.enterOuterAlt(localContext, 5);\n                    {\n                        this.state = 984;\n                        this.symbolRef();\n                    }\n                    break;\n                case 6:\n                    this.enterOuterAlt(localContext, 6);\n                    {\n                        this.state = 985;\n                        this.primitiveRef();\n                    }\n                    break;\n                case 7:\n                    this.enterOuterAlt(localContext, 7);\n                    {\n                        this.state = 986;\n                        this.array();\n                    }\n                    break;\n                case 8:\n                    this.enterOuterAlt(localContext, 8);\n                    {\n                        this.state = 987;\n                        this.anonFunctionDef();\n                    }\n                    break;\n                case 9:\n                    this.enterOuterAlt(localContext, 9);\n                    {\n                        this.state = 988;\n                        this.newObject();\n                    }\n                    break;\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    symbolRef() {\n        let localContext = new SymbolRefContext(this.context, this.state);\n        this.enterRule(localContext, 62, FormulaParser.RULE_symbolRef);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 991;\n                this.match(FormulaParser.IDENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    memberSymbolRef() {\n        let localContext = new MemberSymbolRefContext(this.context, this.state);\n        this.enterRule(localContext, 64, FormulaParser.RULE_memberSymbolRef);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 993;\n                _la = this.tokenStream.LA(1);\n                if (!(((((_la - 41)) & ~0x1F) === 0 && ((1 << (_la - 41)) & 557057) !== 0))) {\n                    this.errorHandler.recoverInline(this);\n                }\n                else {\n                    this.errorHandler.reportMatch(this);\n                    this.consume();\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    primitiveRef() {\n        let localContext = new PrimitiveRefContext(this.context, this.state);\n        this.enterRule(localContext, 66, FormulaParser.RULE_primitiveRef);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 995;\n                this.match(FormulaParser.PRIMITIVE);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    typeRef() {\n        let localContext = new TypeRefContext(this.context, this.state);\n        this.enterRule(localContext, 68, FormulaParser.RULE_typeRef);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 997;\n                this.match(FormulaParser.IDENT);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    material() {\n        let localContext = new MaterialContext(this.context, this.state);\n        this.enterRule(localContext, 70, FormulaParser.RULE_material);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 999;\n                this.match(FormulaParser.LCURL);\n                {\n                    this.state = 1003;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 1000;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 1005;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 1006;\n                this.additiveExpression();\n                this.state = 1007;\n                this.match(FormulaParser.R_);\n                this.state = 1008;\n                this.unitMultiplicativeExpression();\n                {\n                    this.state = 1012;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 4) {\n                        {\n                            {\n                                this.state = 1009;\n                                this.match(FormulaParser.R_);\n                            }\n                        }\n                        this.state = 1014;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 1015;\n                this.match(FormulaParser.RCURL);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    array() {\n        let localContext = new ArrayContext(this.context, this.state);\n        this.enterRule(localContext, 72, FormulaParser.RULE_array);\n        let _la;\n        try {\n            let alternative;\n            this.state = 1161;\n            this.errorHandler.sync(this);\n            switch (this.interpreter.adaptivePredict(this.tokenStream, 165, this.context)) {\n                case 1:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 1017;\n                        this.match(FormulaParser.LARR);\n                        this.state = 1044;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 145, this.context)) {\n                            case 1:\n                                {\n                                    {\n                                        this.state = 1021;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        while (_la === 3 || _la === 4) {\n                                            {\n                                                {\n                                                    this.state = 1018;\n                                                    _la = this.tokenStream.LA(1);\n                                                    if (!(_la === 3 || _la === 4)) {\n                                                        this.errorHandler.recoverInline(this);\n                                                    }\n                                                    else {\n                                                        this.errorHandler.reportMatch(this);\n                                                        this.consume();\n                                                    }\n                                                }\n                                            }\n                                            this.state = 1023;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        }\n                                    }\n                                    this.state = 1024;\n                                    this.label();\n                                    this.state = 1041;\n                                    this.errorHandler.sync(this);\n                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 144, this.context);\n                                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                        if (alternative === 1) {\n                                            {\n                                                {\n                                                    {\n                                                        this.state = 1028;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1025;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1030;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1031;\n                                                    this.match(FormulaParser.COMMA);\n                                                    {\n                                                        this.state = 1035;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1032;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1037;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1038;\n                                                    this.label();\n                                                }\n                                            }\n                                        }\n                                        this.state = 1043;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 144, this.context);\n                                    }\n                                }\n                                break;\n                        }\n                        {\n                            this.state = 1049;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 1046;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 1051;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1052;\n                        this.match(FormulaParser.RARR);\n                    }\n                    break;\n                case 2:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 1053;\n                        this.match(FormulaParser.LCURL);\n                        this.state = 1080;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 151, this.context)) {\n                            case 1:\n                                {\n                                    {\n                                        this.state = 1057;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        while (_la === 3 || _la === 4) {\n                                            {\n                                                {\n                                                    this.state = 1054;\n                                                    _la = this.tokenStream.LA(1);\n                                                    if (!(_la === 3 || _la === 4)) {\n                                                        this.errorHandler.recoverInline(this);\n                                                    }\n                                                    else {\n                                                        this.errorHandler.reportMatch(this);\n                                                        this.consume();\n                                                    }\n                                                }\n                                            }\n                                            this.state = 1059;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        }\n                                    }\n                                    this.state = 1060;\n                                    this.label();\n                                    this.state = 1077;\n                                    this.errorHandler.sync(this);\n                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 150, this.context);\n                                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                        if (alternative === 1) {\n                                            {\n                                                {\n                                                    {\n                                                        this.state = 1064;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1061;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1066;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1067;\n                                                    this.match(FormulaParser.COMMA);\n                                                    {\n                                                        this.state = 1071;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1068;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1073;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1074;\n                                                    this.label();\n                                                }\n                                            }\n                                        }\n                                        this.state = 1079;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 150, this.context);\n                                    }\n                                }\n                                break;\n                        }\n                        {\n                            this.state = 1085;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 1082;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 1087;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1088;\n                        this.match(FormulaParser.RCURL);\n                    }\n                    break;\n                case 3:\n                    this.enterOuterAlt(localContext, 3);\n                    {\n                        this.state = 1089;\n                        this.match(FormulaParser.LARR);\n                        this.state = 1116;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 157, this.context)) {\n                            case 1:\n                                {\n                                    {\n                                        this.state = 1093;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        while (_la === 3 || _la === 4) {\n                                            {\n                                                {\n                                                    this.state = 1090;\n                                                    _la = this.tokenStream.LA(1);\n                                                    if (!(_la === 3 || _la === 4)) {\n                                                        this.errorHandler.recoverInline(this);\n                                                    }\n                                                    else {\n                                                        this.errorHandler.reportMatch(this);\n                                                        this.consume();\n                                                    }\n                                                }\n                                            }\n                                            this.state = 1095;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        }\n                                    }\n                                    this.state = 1096;\n                                    this.logicalExpression();\n                                    this.state = 1113;\n                                    this.errorHandler.sync(this);\n                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 156, this.context);\n                                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                        if (alternative === 1) {\n                                            {\n                                                {\n                                                    {\n                                                        this.state = 1100;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1097;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1102;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1103;\n                                                    this.match(FormulaParser.COMMA);\n                                                    {\n                                                        this.state = 1107;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1104;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1109;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1110;\n                                                    this.logicalExpression();\n                                                }\n                                            }\n                                        }\n                                        this.state = 1115;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 156, this.context);\n                                    }\n                                }\n                                break;\n                        }\n                        {\n                            this.state = 1121;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 1118;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 1123;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1124;\n                        this.match(FormulaParser.RARR);\n                    }\n                    break;\n                case 4:\n                    this.enterOuterAlt(localContext, 4);\n                    {\n                        this.state = 1125;\n                        this.match(FormulaParser.LCURL);\n                        this.state = 1152;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 163, this.context)) {\n                            case 1:\n                                {\n                                    {\n                                        this.state = 1129;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                        while (_la === 3 || _la === 4) {\n                                            {\n                                                {\n                                                    this.state = 1126;\n                                                    _la = this.tokenStream.LA(1);\n                                                    if (!(_la === 3 || _la === 4)) {\n                                                        this.errorHandler.recoverInline(this);\n                                                    }\n                                                    else {\n                                                        this.errorHandler.reportMatch(this);\n                                                        this.consume();\n                                                    }\n                                                }\n                                            }\n                                            this.state = 1131;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                        }\n                                    }\n                                    this.state = 1132;\n                                    this.logicalExpression();\n                                    this.state = 1149;\n                                    this.errorHandler.sync(this);\n                                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 162, this.context);\n                                    while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                                        if (alternative === 1) {\n                                            {\n                                                {\n                                                    {\n                                                        this.state = 1136;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1133;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1138;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1139;\n                                                    this.match(FormulaParser.COMMA);\n                                                    {\n                                                        this.state = 1143;\n                                                        this.errorHandler.sync(this);\n                                                        _la = this.tokenStream.LA(1);\n                                                        while (_la === 3 || _la === 4) {\n                                                            {\n                                                                {\n                                                                    this.state = 1140;\n                                                                    _la = this.tokenStream.LA(1);\n                                                                    if (!(_la === 3 || _la === 4)) {\n                                                                        this.errorHandler.recoverInline(this);\n                                                                    }\n                                                                    else {\n                                                                        this.errorHandler.reportMatch(this);\n                                                                        this.consume();\n                                                                    }\n                                                                }\n                                                            }\n                                                            this.state = 1145;\n                                                            this.errorHandler.sync(this);\n                                                            _la = this.tokenStream.LA(1);\n                                                        }\n                                                    }\n                                                    this.state = 1146;\n                                                    this.logicalExpression();\n                                                }\n                                            }\n                                        }\n                                        this.state = 1151;\n                                        this.errorHandler.sync(this);\n                                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 162, this.context);\n                                    }\n                                }\n                                break;\n                        }\n                        {\n                            this.state = 1157;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 3 || _la === 4) {\n                                {\n                                    {\n                                        this.state = 1154;\n                                        _la = this.tokenStream.LA(1);\n                                        if (!(_la === 3 || _la === 4)) {\n                                            this.errorHandler.recoverInline(this);\n                                        }\n                                        else {\n                                            this.errorHandler.reportMatch(this);\n                                            this.consume();\n                                        }\n                                    }\n                                }\n                                this.state = 1159;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1160;\n                        this.match(FormulaParser.RCURL);\n                    }\n                    break;\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    newObject() {\n        let localContext = new NewObjectContext(this.context, this.state);\n        this.enterRule(localContext, 74, FormulaParser.RULE_newObject);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1163;\n                this.match(FormulaParser.NEWSTATEMENT);\n                this.state = 1164;\n                this.match(FormulaParser.R_);\n                this.state = 1165;\n                this.typeRef();\n                this.state = 1167;\n                this.errorHandler.sync(this);\n                switch (this.interpreter.adaptivePredict(this.tokenStream, 166, this.context)) {\n                    case 1:\n                        {\n                            this.state = 1166;\n                            this.funCall();\n                        }\n                        break;\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    defaultValue() {\n        let localContext = new DefaultValueContext(this.context, this.state);\n        this.enterRule(localContext, 76, FormulaParser.RULE_defaultValue);\n        try {\n            this.state = 1174;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.MINUS:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 1169;\n                        this.negnumber();\n                    }\n                    break;\n                case FormulaParser.INTEGER:\n                case FormulaParser.FLOAT:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 1170;\n                        this.number_();\n                    }\n                    break;\n                case FormulaParser.BOOL:\n                    this.enterOuterAlt(localContext, 3);\n                    {\n                        this.state = 1171;\n                        this.match(FormulaParser.BOOL);\n                    }\n                    break;\n                case FormulaParser.STRING:\n                    this.enterOuterAlt(localContext, 4);\n                    {\n                        this.state = 1172;\n                        this.string_();\n                    }\n                    break;\n                case FormulaParser.LARR:\n                case FormulaParser.LCURL:\n                    this.enterOuterAlt(localContext, 5);\n                    {\n                        this.state = 1173;\n                        this.array();\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    selector() {\n        let localContext = new SelectorContext(this.context, this.state);\n        this.enterRule(localContext, 78, FormulaParser.RULE_selector);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1178;\n                this.errorHandler.sync(this);\n                switch (this.tokenStream.LA(1)) {\n                    case FormulaParser.LARR:\n                    case FormulaParser.LCURL:\n                        {\n                            this.state = 1176;\n                            this.minarray();\n                        }\n                        break;\n                    case FormulaParser.DOT:\n                        {\n                            this.state = 1177;\n                            this.dotselector();\n                        }\n                        break;\n                    default:\n                        throw new antlr.NoViableAltException(this);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    minarray() {\n        let localContext = new MinarrayContext(this.context, this.state);\n        this.enterRule(localContext, 80, FormulaParser.RULE_minarray);\n        let _la;\n        try {\n            let alternative;\n            this.state = 1260;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.LARR:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 1180;\n                        this.match(FormulaParser.LARR);\n                        {\n                            this.state = 1184;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1181;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1186;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1189;\n                        this.errorHandler.sync(this);\n                        switch (this.tokenStream.LA(1)) {\n                            case FormulaParser.FUNCTIONSTATEMENT:\n                            case FormulaParser.NEWSTATEMENT:\n                            case FormulaParser.LPAREN:\n                            case FormulaParser.MINUS:\n                            case FormulaParser.NOT:\n                            case FormulaParser.LARR:\n                            case FormulaParser.LCURL:\n                            case FormulaParser.BOOL:\n                            case FormulaParser.IDENT:\n                            case FormulaParser.PRIMITIVE:\n                            case FormulaParser.INTEGER:\n                            case FormulaParser.FLOAT:\n                            case FormulaParser.STRING:\n                                {\n                                    this.state = 1187;\n                                    this.logicalExpression();\n                                }\n                                break;\n                            case FormulaParser.MULT:\n                                {\n                                    this.state = 1188;\n                                    this.match(FormulaParser.MULT);\n                                }\n                                break;\n                            default:\n                                throw new antlr.NoViableAltException(this);\n                        }\n                        this.state = 1210;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 174, this.context);\n                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                            if (alternative === 1) {\n                                {\n                                    {\n                                        {\n                                            this.state = 1194;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 1191;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 1196;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 1197;\n                                        this.match(FormulaParser.COMMA);\n                                        {\n                                            this.state = 1201;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 1198;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 1203;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 1206;\n                                        this.errorHandler.sync(this);\n                                        switch (this.tokenStream.LA(1)) {\n                                            case FormulaParser.FUNCTIONSTATEMENT:\n                                            case FormulaParser.NEWSTATEMENT:\n                                            case FormulaParser.LPAREN:\n                                            case FormulaParser.MINUS:\n                                            case FormulaParser.NOT:\n                                            case FormulaParser.LARR:\n                                            case FormulaParser.LCURL:\n                                            case FormulaParser.BOOL:\n                                            case FormulaParser.IDENT:\n                                            case FormulaParser.PRIMITIVE:\n                                            case FormulaParser.INTEGER:\n                                            case FormulaParser.FLOAT:\n                                            case FormulaParser.STRING:\n                                                {\n                                                    this.state = 1204;\n                                                    this.logicalExpression();\n                                                }\n                                                break;\n                                            case FormulaParser.MULT:\n                                                {\n                                                    this.state = 1205;\n                                                    this.match(FormulaParser.MULT);\n                                                }\n                                                break;\n                                            default:\n                                                throw new antlr.NoViableAltException(this);\n                                        }\n                                    }\n                                }\n                            }\n                            this.state = 1212;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 174, this.context);\n                        }\n                        {\n                            this.state = 1216;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1213;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1218;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1219;\n                        this.match(FormulaParser.RARR);\n                    }\n                    break;\n                case FormulaParser.LCURL:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 1220;\n                        this.match(FormulaParser.LCURL);\n                        {\n                            this.state = 1224;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1221;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1226;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1229;\n                        this.errorHandler.sync(this);\n                        switch (this.tokenStream.LA(1)) {\n                            case FormulaParser.FUNCTIONSTATEMENT:\n                            case FormulaParser.NEWSTATEMENT:\n                            case FormulaParser.LPAREN:\n                            case FormulaParser.MINUS:\n                            case FormulaParser.NOT:\n                            case FormulaParser.LARR:\n                            case FormulaParser.LCURL:\n                            case FormulaParser.BOOL:\n                            case FormulaParser.IDENT:\n                            case FormulaParser.PRIMITIVE:\n                            case FormulaParser.INTEGER:\n                            case FormulaParser.FLOAT:\n                            case FormulaParser.STRING:\n                                {\n                                    this.state = 1227;\n                                    this.logicalExpression();\n                                }\n                                break;\n                            case FormulaParser.MULT:\n                                {\n                                    this.state = 1228;\n                                    this.match(FormulaParser.MULT);\n                                }\n                                break;\n                            default:\n                                throw new antlr.NoViableAltException(this);\n                        }\n                        this.state = 1250;\n                        this.errorHandler.sync(this);\n                        alternative = this.interpreter.adaptivePredict(this.tokenStream, 181, this.context);\n                        while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                            if (alternative === 1) {\n                                {\n                                    {\n                                        {\n                                            this.state = 1234;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 1231;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 1236;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 1237;\n                                        this.match(FormulaParser.COMMA);\n                                        {\n                                            this.state = 1241;\n                                            this.errorHandler.sync(this);\n                                            _la = this.tokenStream.LA(1);\n                                            while (_la === 4) {\n                                                {\n                                                    {\n                                                        this.state = 1238;\n                                                        this.match(FormulaParser.R_);\n                                                    }\n                                                }\n                                                this.state = 1243;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                            }\n                                        }\n                                        this.state = 1246;\n                                        this.errorHandler.sync(this);\n                                        switch (this.tokenStream.LA(1)) {\n                                            case FormulaParser.FUNCTIONSTATEMENT:\n                                            case FormulaParser.NEWSTATEMENT:\n                                            case FormulaParser.LPAREN:\n                                            case FormulaParser.MINUS:\n                                            case FormulaParser.NOT:\n                                            case FormulaParser.LARR:\n                                            case FormulaParser.LCURL:\n                                            case FormulaParser.BOOL:\n                                            case FormulaParser.IDENT:\n                                            case FormulaParser.PRIMITIVE:\n                                            case FormulaParser.INTEGER:\n                                            case FormulaParser.FLOAT:\n                                            case FormulaParser.STRING:\n                                                {\n                                                    this.state = 1244;\n                                                    this.logicalExpression();\n                                                }\n                                                break;\n                                            case FormulaParser.MULT:\n                                                {\n                                                    this.state = 1245;\n                                                    this.match(FormulaParser.MULT);\n                                                }\n                                                break;\n                                            default:\n                                                throw new antlr.NoViableAltException(this);\n                                        }\n                                    }\n                                }\n                            }\n                            this.state = 1252;\n                            this.errorHandler.sync(this);\n                            alternative = this.interpreter.adaptivePredict(this.tokenStream, 181, this.context);\n                        }\n                        {\n                            this.state = 1256;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1253;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1258;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1259;\n                        this.match(FormulaParser.RCURL);\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    dotselector() {\n        let localContext = new DotselectorContext(this.context, this.state);\n        this.enterRule(localContext, 82, FormulaParser.RULE_dotselector);\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1264;\n                this.errorHandler.sync(this);\n                alternative = 1;\n                do {\n                    switch (alternative) {\n                        case 1:\n                            {\n                                {\n                                    this.state = 1262;\n                                    this.match(FormulaParser.DOT);\n                                    this.state = 1263;\n                                    this.memberSymbolRef();\n                                }\n                            }\n                            break;\n                        default:\n                            throw new antlr.NoViableAltException(this);\n                    }\n                    this.state = 1266;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 184, this.context);\n                } while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    arrayName() {\n        let localContext = new ArrayNameContext(this.context, this.state);\n        this.enterRule(localContext, 84, FormulaParser.RULE_arrayName);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1268;\n                _la = this.tokenStream.LA(1);\n                if (!(((((_la - 41)) & ~0x1F) === 0 && ((1 << (_la - 41)) & 557057) !== 0))) {\n                    this.errorHandler.recoverInline(this);\n                }\n                else {\n                    this.errorHandler.reportMatch(this);\n                    this.consume();\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    label() {\n        let localContext = new LabelContext(this.context, this.state);\n        this.enterRule(localContext, 86, FormulaParser.RULE_label);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1270;\n                this.arrayName();\n                {\n                    this.state = 1274;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 3 || _la === 4) {\n                        {\n                            {\n                                this.state = 1271;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 3 || _la === 4)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                            }\n                        }\n                        this.state = 1276;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 1277;\n                this.match(FormulaParser.COLON);\n                {\n                    this.state = 1281;\n                    this.errorHandler.sync(this);\n                    _la = this.tokenStream.LA(1);\n                    while (_la === 3 || _la === 4) {\n                        {\n                            {\n                                this.state = 1278;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 3 || _la === 4)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                            }\n                        }\n                        this.state = 1283;\n                        this.errorHandler.sync(this);\n                        _la = this.tokenStream.LA(1);\n                    }\n                }\n                this.state = 1284;\n                this.logicalExpression();\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    number_() {\n        let localContext = new NumberContext(this.context, this.state);\n        this.enterRule(localContext, 88, FormulaParser.RULE_number);\n        let _la;\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1286;\n                _la = this.tokenStream.LA(1);\n                if (!(_la === 58 || _la === 59)) {\n                    this.errorHandler.recoverInline(this);\n                }\n                else {\n                    this.errorHandler.reportMatch(this);\n                    this.consume();\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    negnumber() {\n        let localContext = new NegnumberContext(this.context, this.state);\n        this.enterRule(localContext, 90, FormulaParser.RULE_negnumber);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1288;\n                this.match(FormulaParser.MINUS);\n                this.state = 1289;\n                this.number_();\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    string_() {\n        let localContext = new StringContext(this.context, this.state);\n        this.enterRule(localContext, 92, FormulaParser.RULE_string);\n        try {\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1291;\n                this.match(FormulaParser.STRING);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unitMultiplicativeExpression() {\n        let localContext = new UnitMultiplicativeExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 94, FormulaParser.RULE_unitMultiplicativeExpression);\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1293;\n                this.unitInnerMultiplicativeExpression();\n                this.state = 1300;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 187, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                this.state = 1294;\n                                this.match(FormulaParser.R_);\n                                this.state = 1295;\n                                this.match(FormulaParser.PER);\n                                this.state = 1296;\n                                this.match(FormulaParser.R_);\n                                this.state = 1297;\n                                this.unitInnerMultiplicativeExpression();\n                            }\n                        }\n                    }\n                    this.state = 1302;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 187, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unitInnerMultiplicativeExpression() {\n        let localContext = new UnitInnerMultiplicativeExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 96, FormulaParser.RULE_unitInnerMultiplicativeExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1303;\n                this.unitClump();\n                this.state = 1320;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 190, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 1307;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 1304;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 1309;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 1310;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 41 || _la === 42)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                                {\n                                    this.state = 1314;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 1311;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 1316;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 1317;\n                                this.unitClump();\n                            }\n                        }\n                    }\n                    this.state = 1322;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 190, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unitClump() {\n        let localContext = new UnitClumpContext(this.context, this.state);\n        this.enterRule(localContext, 98, FormulaParser.RULE_unitClump);\n        let _la;\n        try {\n            this.state = 1356;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.INTEGER:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        {\n                            this.state = 1323;\n                            this.match(FormulaParser.INTEGER);\n                            {\n                                this.state = 1327;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                                while (_la === 4) {\n                                    {\n                                        {\n                                            this.state = 1324;\n                                            this.match(FormulaParser.R_);\n                                        }\n                                    }\n                                    this.state = 1329;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                }\n                            }\n                            this.state = 1330;\n                            this.match(FormulaParser.DIV);\n                        }\n                        {\n                            this.state = 1335;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1332;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1337;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1338;\n                        this.unitPowerExpression();\n                        this.state = 1341;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 193, this.context)) {\n                            case 1:\n                                {\n                                    this.state = 1339;\n                                    this.match(FormulaParser.R_);\n                                    this.state = 1340;\n                                    this.match(FormulaParser.CUBED);\n                                }\n                                break;\n                        }\n                        this.state = 1345;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 194, this.context)) {\n                            case 1:\n                                {\n                                    this.state = 1343;\n                                    this.match(FormulaParser.R_);\n                                    this.state = 1344;\n                                    this.match(FormulaParser.SQUARED);\n                                }\n                                break;\n                        }\n                    }\n                    break;\n                case FormulaParser.LPAREN:\n                case FormulaParser.IDENT:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 1347;\n                        this.unitPowerExpression();\n                        this.state = 1350;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 195, this.context)) {\n                            case 1:\n                                {\n                                    this.state = 1348;\n                                    this.match(FormulaParser.R_);\n                                    this.state = 1349;\n                                    this.match(FormulaParser.CUBED);\n                                }\n                                break;\n                        }\n                        this.state = 1354;\n                        this.errorHandler.sync(this);\n                        switch (this.interpreter.adaptivePredict(this.tokenStream, 196, this.context)) {\n                            case 1:\n                                {\n                                    this.state = 1352;\n                                    this.match(FormulaParser.R_);\n                                    this.state = 1353;\n                                    this.match(FormulaParser.SQUARED);\n                                }\n                                break;\n                        }\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unitPowerExpression() {\n        let localContext = new UnitPowerExpressionContext(this.context, this.state);\n        this.enterRule(localContext, 100, FormulaParser.RULE_unitPowerExpression);\n        let _la;\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1358;\n                this.unit();\n                this.state = 1384;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 202, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                {\n                                    this.state = 1362;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 1359;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 1364;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 1365;\n                                this.match(FormulaParser.POW);\n                                this.state = 1373;\n                                this.errorHandler.sync(this);\n                                switch (this.interpreter.adaptivePredict(this.tokenStream, 200, this.context)) {\n                                    case 1:\n                                        {\n                                            {\n                                                this.state = 1369;\n                                                this.errorHandler.sync(this);\n                                                _la = this.tokenStream.LA(1);\n                                                while (_la === 4) {\n                                                    {\n                                                        {\n                                                            this.state = 1366;\n                                                            this.match(FormulaParser.R_);\n                                                        }\n                                                    }\n                                                    this.state = 1371;\n                                                    this.errorHandler.sync(this);\n                                                    _la = this.tokenStream.LA(1);\n                                                }\n                                            }\n                                            this.state = 1372;\n                                            this.match(FormulaParser.MINUS);\n                                        }\n                                        break;\n                                }\n                                {\n                                    this.state = 1378;\n                                    this.errorHandler.sync(this);\n                                    _la = this.tokenStream.LA(1);\n                                    while (_la === 4) {\n                                        {\n                                            {\n                                                this.state = 1375;\n                                                this.match(FormulaParser.R_);\n                                            }\n                                        }\n                                        this.state = 1380;\n                                        this.errorHandler.sync(this);\n                                        _la = this.tokenStream.LA(1);\n                                    }\n                                }\n                                this.state = 1381;\n                                _la = this.tokenStream.LA(1);\n                                if (!(_la === 58 || _la === 59)) {\n                                    this.errorHandler.recoverInline(this);\n                                }\n                                else {\n                                    this.errorHandler.reportMatch(this);\n                                    this.consume();\n                                }\n                            }\n                        }\n                    }\n                    this.state = 1386;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 202, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unit() {\n        let localContext = new UnitContext(this.context, this.state);\n        this.enterRule(localContext, 102, FormulaParser.RULE_unit);\n        let _la;\n        try {\n            this.state = 1404;\n            this.errorHandler.sync(this);\n            switch (this.tokenStream.LA(1)) {\n                case FormulaParser.IDENT:\n                    this.enterOuterAlt(localContext, 1);\n                    {\n                        this.state = 1387;\n                        this.unitRef();\n                    }\n                    break;\n                case FormulaParser.LPAREN:\n                    this.enterOuterAlt(localContext, 2);\n                    {\n                        this.state = 1388;\n                        this.match(FormulaParser.LPAREN);\n                        {\n                            this.state = 1392;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1389;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1394;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1395;\n                        this.unitMultiplicativeExpression();\n                        {\n                            this.state = 1399;\n                            this.errorHandler.sync(this);\n                            _la = this.tokenStream.LA(1);\n                            while (_la === 4) {\n                                {\n                                    {\n                                        this.state = 1396;\n                                        this.match(FormulaParser.R_);\n                                    }\n                                }\n                                this.state = 1401;\n                                this.errorHandler.sync(this);\n                                _la = this.tokenStream.LA(1);\n                            }\n                        }\n                        this.state = 1402;\n                        this.match(FormulaParser.RPAREN);\n                    }\n                    break;\n                default:\n                    throw new antlr.NoViableAltException(this);\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    unitRef() {\n        let localContext = new UnitRefContext(this.context, this.state);\n        this.enterRule(localContext, 104, FormulaParser.RULE_unitRef);\n        try {\n            let alternative;\n            this.enterOuterAlt(localContext, 1);\n            {\n                this.state = 1406;\n                this.match(FormulaParser.IDENT);\n                this.state = 1411;\n                this.errorHandler.sync(this);\n                alternative = this.interpreter.adaptivePredict(this.tokenStream, 206, this.context);\n                while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) {\n                    if (alternative === 1) {\n                        {\n                            {\n                                this.state = 1407;\n                                this.match(FormulaParser.R_);\n                                this.state = 1408;\n                                this.match(FormulaParser.IDENT);\n                            }\n                        }\n                    }\n                    this.state = 1413;\n                    this.errorHandler.sync(this);\n                    alternative = this.interpreter.adaptivePredict(this.tokenStream, 206, this.context);\n                }\n            }\n        }\n        catch (re) {\n            if (re instanceof antlr.RecognitionException) {\n                this.errorHandler.reportError(this, re);\n                this.errorHandler.recover(this, re);\n            }\n            else {\n                throw re;\n            }\n        }\n        finally {\n            this.exitRule();\n        }\n        return localContext;\n    }\n    static _serializedATN = [\n        4, 1, 60, 1415, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6,\n        7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7,\n        13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2,\n        20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7,\n        26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2,\n        33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7,\n        39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2,\n        46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7,\n        52, 1, 0, 5, 0, 108, 8, 0, 10, 0, 12, 0, 111, 9, 0, 1, 0, 1, 0, 4, 0, 115, 8, 0, 11, 0, 12,\n        0, 116, 1, 0, 5, 0, 120, 8, 0, 10, 0, 12, 0, 123, 9, 0, 1, 0, 5, 0, 126, 8, 0, 10, 0, 12,\n        0, 129, 9, 0, 3, 0, 131, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n        1, 1, 1, 3, 1, 145, 8, 1, 1, 2, 1, 2, 5, 2, 149, 8, 2, 10, 2, 12, 2, 152, 9, 2, 1, 2, 1, 2,\n        1, 3, 5, 3, 157, 8, 3, 10, 3, 12, 3, 160, 9, 3, 1, 3, 1, 3, 4, 3, 164, 8, 3, 11, 3, 12, 3,\n        165, 1, 3, 5, 3, 169, 8, 3, 10, 3, 12, 3, 172, 9, 3, 1, 3, 5, 3, 175, 8, 3, 10, 3, 12, 3,\n        178, 9, 3, 3, 3, 180, 8, 3, 1, 4, 1, 4, 5, 4, 184, 8, 4, 10, 4, 12, 4, 187, 9, 4, 1, 4, 1,\n        4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 203, 8, 5, 10,\n        5, 12, 5, 206, 9, 5, 1, 5, 1, 5, 5, 5, 210, 8, 5, 10, 5, 12, 5, 213, 9, 5, 1, 5, 1, 5, 5, 5,\n        217, 8, 5, 10, 5, 12, 5, 220, 9, 5, 1, 5, 1, 5, 5, 5, 224, 8, 5, 10, 5, 12, 5, 227, 9, 5,\n        1, 5, 1, 5, 5, 5, 231, 8, 5, 10, 5, 12, 5, 234, 9, 5, 1, 5, 3, 5, 237, 8, 5, 1, 5, 1, 5, 3,\n        5, 241, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 253, 8, 6, 10,\n        6, 12, 6, 256, 9, 6, 1, 6, 1, 6, 1, 6, 3, 6, 261, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 5,\n        7, 269, 8, 7, 10, 7, 12, 7, 272, 9, 7, 1, 7, 1, 7, 5, 7, 276, 8, 7, 10, 7, 12, 7, 279, 9,\n        7, 1, 7, 3, 7, 282, 8, 7, 1, 7, 1, 7, 3, 7, 286, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 5, 7, 293,\n        8, 7, 10, 7, 12, 7, 296, 9, 7, 1, 7, 1, 7, 5, 7, 300, 8, 7, 10, 7, 12, 7, 303, 9, 7, 1, 7,\n        3, 7, 306, 8, 7, 1, 7, 1, 7, 3, 7, 310, 8, 7, 5, 7, 312, 8, 7, 10, 7, 12, 7, 315, 9, 7, 1,\n        7, 1, 7, 1, 7, 1, 7, 3, 7, 321, 8, 7, 3, 7, 323, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1,\n        8, 1, 8, 5, 8, 333, 8, 8, 10, 8, 12, 8, 336, 9, 8, 1, 8, 1, 8, 5, 8, 340, 8, 8, 10, 8, 12,\n        8, 343, 9, 8, 1, 8, 1, 8, 5, 8, 347, 8, 8, 10, 8, 12, 8, 350, 9, 8, 1, 8, 1, 8, 5, 8, 354,\n        8, 8, 10, 8, 12, 8, 357, 9, 8, 1, 8, 1, 8, 5, 8, 361, 8, 8, 10, 8, 12, 8, 364, 9, 8, 1, 8,\n        1, 8, 5, 8, 368, 8, 8, 10, 8, 12, 8, 371, 9, 8, 1, 8, 5, 8, 374, 8, 8, 10, 8, 12, 8, 377,\n        9, 8, 3, 8, 379, 8, 8, 1, 8, 5, 8, 382, 8, 8, 10, 8, 12, 8, 385, 9, 8, 1, 8, 1, 8, 5, 8, 389,\n        8, 8, 10, 8, 12, 8, 392, 9, 8, 1, 8, 1, 8, 5, 8, 396, 8, 8, 10, 8, 12, 8, 399, 9, 8, 1, 8,\n        1, 8, 5, 8, 403, 8, 8, 10, 8, 12, 8, 406, 9, 8, 1, 8, 5, 8, 409, 8, 8, 10, 8, 12, 8, 412,\n        9, 8, 3, 8, 414, 8, 8, 1, 8, 5, 8, 417, 8, 8, 10, 8, 12, 8, 420, 9, 8, 1, 8, 1, 8, 1, 8, 3,\n        8, 425, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 3, 9, 434, 8, 9, 1, 9, 1, 9, 1, 9, 1,\n        9, 1, 9, 1, 9, 3, 9, 442, 8, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1,\n        11, 5, 11, 454, 8, 11, 10, 11, 12, 11, 457, 9, 11, 1, 11, 1, 11, 5, 11, 461, 8, 11, 10,\n        11, 12, 11, 464, 9, 11, 1, 11, 1, 11, 5, 11, 468, 8, 11, 10, 11, 12, 11, 471, 9, 11, 1,\n        11, 1, 11, 5, 11, 475, 8, 11, 10, 11, 12, 11, 478, 9, 11, 1, 11, 1, 11, 5, 11, 482, 8,\n        11, 10, 11, 12, 11, 485, 9, 11, 1, 11, 1, 11, 5, 11, 489, 8, 11, 10, 11, 12, 11, 492,\n        9, 11, 1, 11, 5, 11, 495, 8, 11, 10, 11, 12, 11, 498, 9, 11, 3, 11, 500, 8, 11, 1, 11,\n        5, 11, 503, 8, 11, 10, 11, 12, 11, 506, 9, 11, 1, 11, 1, 11, 5, 11, 510, 8, 11, 10, 11,\n        12, 11, 513, 9, 11, 1, 11, 1, 11, 5, 11, 517, 8, 11, 10, 11, 12, 11, 520, 9, 11, 1, 11,\n        1, 11, 5, 11, 524, 8, 11, 10, 11, 12, 11, 527, 9, 11, 1, 11, 5, 11, 530, 8, 11, 10, 11,\n        12, 11, 533, 9, 11, 3, 11, 535, 8, 11, 1, 11, 5, 11, 538, 8, 11, 10, 11, 12, 11, 541,\n        9, 11, 1, 11, 1, 11, 1, 11, 3, 11, 546, 8, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 552, 8,\n        11, 10, 11, 12, 11, 555, 9, 11, 1, 11, 3, 11, 558, 8, 11, 1, 12, 1, 12, 5, 12, 562, 8,\n        12, 10, 12, 12, 12, 565, 9, 12, 1, 12, 1, 12, 5, 12, 569, 8, 12, 10, 12, 12, 12, 572,\n        9, 12, 1, 12, 1, 12, 5, 12, 576, 8, 12, 10, 12, 12, 12, 579, 9, 12, 1, 12, 1, 12, 5, 12,\n        583, 8, 12, 10, 12, 12, 12, 586, 9, 12, 1, 12, 1, 12, 5, 12, 590, 8, 12, 10, 12, 12, 12,\n        593, 9, 12, 1, 12, 1, 12, 5, 12, 597, 8, 12, 10, 12, 12, 12, 600, 9, 12, 1, 12, 5, 12,\n        603, 8, 12, 10, 12, 12, 12, 606, 9, 12, 3, 12, 608, 8, 12, 1, 12, 5, 12, 611, 8, 12, 10,\n        12, 12, 12, 614, 9, 12, 1, 12, 1, 12, 5, 12, 618, 8, 12, 10, 12, 12, 12, 621, 9, 12, 1,\n        12, 1, 12, 5, 12, 625, 8, 12, 10, 12, 12, 12, 628, 9, 12, 1, 12, 1, 12, 5, 12, 632, 8,\n        12, 10, 12, 12, 12, 635, 9, 12, 1, 12, 5, 12, 638, 8, 12, 10, 12, 12, 12, 641, 9, 12,\n        3, 12, 643, 8, 12, 1, 12, 5, 12, 646, 8, 12, 10, 12, 12, 12, 649, 9, 12, 1, 12, 1, 12,\n        5, 12, 653, 8, 12, 10, 12, 12, 12, 656, 9, 12, 1, 12, 1, 12, 5, 12, 660, 8, 12, 10, 12,\n        12, 12, 663, 9, 12, 1, 12, 1, 12, 1, 12, 3, 12, 668, 8, 12, 1, 12, 5, 12, 671, 8, 12, 10,\n        12, 12, 12, 674, 9, 12, 1, 12, 1, 12, 5, 12, 678, 8, 12, 10, 12, 12, 12, 681, 9, 12, 1,\n        12, 1, 12, 3, 12, 685, 8, 12, 5, 12, 687, 8, 12, 10, 12, 12, 12, 690, 9, 12, 1, 12, 5,\n        12, 693, 8, 12, 10, 12, 12, 12, 696, 9, 12, 1, 12, 1, 12, 5, 12, 700, 8, 12, 10, 12, 12,\n        12, 703, 9, 12, 1, 12, 1, 12, 3, 12, 707, 8, 12, 1, 13, 1, 13, 3, 13, 711, 8, 13, 1, 14,\n        1, 14, 5, 14, 715, 8, 14, 10, 14, 12, 14, 718, 9, 14, 1, 14, 1, 14, 5, 14, 722, 8, 14,\n        10, 14, 12, 14, 725, 9, 14, 1, 14, 5, 14, 728, 8, 14, 10, 14, 12, 14, 731, 9, 14, 1, 15,\n        1, 15, 5, 15, 735, 8, 15, 10, 15, 12, 15, 738, 9, 15, 1, 15, 1, 15, 5, 15, 742, 8, 15,\n        10, 15, 12, 15, 745, 9, 15, 1, 15, 5, 15, 748, 8, 15, 10, 15, 12, 15, 751, 9, 15, 1, 16,\n        1, 16, 5, 16, 755, 8, 16, 10, 16, 12, 16, 758, 9, 16, 1, 16, 1, 16, 5, 16, 762, 8, 16,\n        10, 16, 12, 16, 765, 9, 16, 1, 16, 5, 16, 768, 8, 16, 10, 16, 12, 16, 771, 9, 16, 1, 17,\n        1, 17, 5, 17, 775, 8, 17, 10, 17, 12, 17, 778, 9, 17, 1, 17, 1, 17, 5, 17, 782, 8, 17,\n        10, 17, 12, 17, 785, 9, 17, 1, 17, 5, 17, 788, 8, 17, 10, 17, 12, 17, 791, 9, 17, 1, 18,\n        1, 18, 5, 18, 795, 8, 18, 10, 18, 12, 18, 798, 9, 18, 1, 18, 1, 18, 5, 18, 802, 8, 18,\n        10, 18, 12, 18, 805, 9, 18, 1, 18, 5, 18, 808, 8, 18, 10, 18, 12, 18, 811, 9, 18, 1, 19,\n        1, 19, 5, 19, 815, 8, 19, 10, 19, 12, 19, 818, 9, 19, 1, 19, 1, 19, 5, 19, 822, 8, 19,\n        10, 19, 12, 19, 825, 9, 19, 1, 19, 5, 19, 828, 8, 19, 10, 19, 12, 19, 831, 9, 19, 1, 20,\n        1, 20, 5, 20, 835, 8, 20, 10, 20, 12, 20, 838, 9, 20, 1, 20, 1, 20, 5, 20, 842, 8, 20,\n        10, 20, 12, 20, 845, 9, 20, 1, 20, 5, 20, 848, 8, 20, 10, 20, 12, 20, 851, 9, 20, 1, 21,\n        1, 21, 1, 21, 3, 21, 856, 8, 21, 1, 21, 1, 21, 3, 21, 860, 8, 21, 1, 22, 1, 22, 5, 22, 864,\n        8, 22, 10, 22, 12, 22, 867, 9, 22, 1, 22, 1, 22, 3, 22, 871, 8, 22, 1, 23, 1, 23, 5, 23,\n        875, 8, 23, 10, 23, 12, 23, 878, 9, 23, 1, 23, 1, 23, 5, 23, 882, 8, 23, 10, 23, 12, 23,\n        885, 9, 23, 1, 23, 5, 23, 888, 8, 23, 10, 23, 12, 23, 891, 9, 23, 1, 24, 1, 24, 5, 24,\n        895, 8, 24, 10, 24, 12, 24, 898, 9, 24, 1, 24, 1, 24, 3, 24, 902, 8, 24, 1, 25, 1, 25,\n        5, 25, 906, 8, 25, 10, 25, 12, 25, 909, 9, 25, 1, 25, 1, 25, 3, 25, 913, 8, 25, 1, 26,\n        1, 26, 1, 27, 1, 27, 1, 27, 5, 27, 920, 8, 27, 10, 27, 12, 27, 923, 9, 27, 1, 28, 1, 28,\n        5, 28, 927, 8, 28, 10, 28, 12, 28, 930, 9, 28, 1, 28, 1, 28, 5, 28, 934, 8, 28, 10, 28,\n        12, 28, 937, 9, 28, 1, 28, 1, 28, 5, 28, 941, 8, 28, 10, 28, 12, 28, 944, 9, 28, 1, 28,\n        5, 28, 947, 8, 28, 10, 28, 12, 28, 950, 9, 28, 3, 28, 952, 8, 28, 1, 28, 5, 28, 955, 8,\n        28, 10, 28, 12, 28, 958, 9, 28, 1, 28, 1, 28, 1, 29, 1, 29, 5, 29, 964, 8, 29, 10, 29,\n        12, 29, 967, 9, 29, 1, 29, 1, 29, 5, 29, 971, 8, 29, 10, 29, 12, 29, 974, 9, 29, 1, 29,\n        1, 29, 1, 29, 3, 29, 979, 8, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30,\n        1, 30, 3, 30, 990, 8, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35,\n        1, 35, 5, 35, 1002, 8, 35, 10, 35, 12, 35, 1005, 9, 35, 1, 35, 1, 35, 1, 35, 1, 35, 5,\n        35, 1011, 8, 35, 10, 35, 12, 35, 1014, 9, 35, 1, 35, 1, 35, 1, 36, 1, 36, 5, 36, 1020,\n        8, 36, 10, 36, 12, 36, 1023, 9, 36, 1, 36, 1, 36, 5, 36, 1027, 8, 36, 10, 36, 12, 36,\n        1030, 9, 36, 1, 36, 1, 36, 5, 36, 1034, 8, 36, 10, 36, 12, 36, 1037, 9, 36, 1, 36, 5,\n        36, 1040, 8, 36, 10, 36, 12, 36, 1043, 9, 36, 3, 36, 1045, 8, 36, 1, 36, 5, 36, 1048,\n        8, 36, 10, 36, 12, 36, 1051, 9, 36, 1, 36, 1, 36, 1, 36, 5, 36, 1056, 8, 36, 10, 36, 12,\n        36, 1059, 9, 36, 1, 36, 1, 36, 5, 36, 1063, 8, 36, 10, 36, 12, 36, 1066, 9, 36, 1, 36,\n        1, 36, 5, 36, 1070, 8, 36, 10, 36, 12, 36, 1073, 9, 36, 1, 36, 5, 36, 1076, 8, 36, 10,\n        36, 12, 36, 1079, 9, 36, 3, 36, 1081, 8, 36, 1, 36, 5, 36, 1084, 8, 36, 10, 36, 12, 36,\n        1087, 9, 36, 1, 36, 1, 36, 1, 36, 5, 36, 1092, 8, 36, 10, 36, 12, 36, 1095, 9, 36, 1,\n        36, 1, 36, 5, 36, 1099, 8, 36, 10, 36, 12, 36, 1102, 9, 36, 1, 36, 1, 36, 5, 36, 1106,\n        8, 36, 10, 36, 12, 36, 1109, 9, 36, 1, 36, 5, 36, 1112, 8, 36, 10, 36, 12, 36, 1115,\n        9, 36, 3, 36, 1117, 8, 36, 1, 36, 5, 36, 1120, 8, 36, 10, 36, 12, 36, 1123, 9, 36, 1,\n        36, 1, 36, 1, 36, 5, 36, 1128, 8, 36, 10, 36, 12, 36, 1131, 9, 36, 1, 36, 1, 36, 5, 36,\n        1135, 8, 36, 10, 36, 12, 36, 1138, 9, 36, 1, 36, 1, 36, 5, 36, 1142, 8, 36, 10, 36, 12,\n        36, 1145, 9, 36, 1, 36, 5, 36, 1148, 8, 36, 10, 36, 12, 36, 1151, 9, 36, 3, 36, 1153,\n        8, 36, 1, 36, 5, 36, 1156, 8, 36, 10, 36, 12, 36, 1159, 9, 36, 1, 36, 3, 36, 1162, 8,\n        36, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 1168, 8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3,\n        38, 1175, 8, 38, 1, 39, 1, 39, 3, 39, 1179, 8, 39, 1, 40, 1, 40, 5, 40, 1183, 8, 40, 10,\n        40, 12, 40, 1186, 9, 40, 1, 40, 1, 40, 3, 40, 1190, 8, 40, 1, 40, 5, 40, 1193, 8, 40,\n        10, 40, 12, 40, 1196, 9, 40, 1, 40, 1, 40, 5, 40, 1200, 8, 40, 10, 40, 12, 40, 1203,\n        9, 40, 1, 40, 1, 40, 3, 40, 1207, 8, 40, 5, 40, 1209, 8, 40, 10, 40, 12, 40, 1212, 9,\n        40, 1, 40, 5, 40, 1215, 8, 40, 10, 40, 12, 40, 1218, 9, 40, 1, 40, 1, 40, 1, 40, 5, 40,\n        1223, 8, 40, 10, 40, 12, 40, 1226, 9, 40, 1, 40, 1, 40, 3, 40, 1230, 8, 40, 1, 40, 5,\n        40, 1233, 8, 40, 10, 40, 12, 40, 1236, 9, 40, 1, 40, 1, 40, 5, 40, 1240, 8, 40, 10, 40,\n        12, 40, 1243, 9, 40, 1, 40, 1, 40, 3, 40, 1247, 8, 40, 5, 40, 1249, 8, 40, 10, 40, 12,\n        40, 1252, 9, 40, 1, 40, 5, 40, 1255, 8, 40, 10, 40, 12, 40, 1258, 9, 40, 1, 40, 3, 40,\n        1261, 8, 40, 1, 41, 1, 41, 4, 41, 1265, 8, 41, 11, 41, 12, 41, 1266, 1, 42, 1, 42, 1,\n        43, 1, 43, 5, 43, 1273, 8, 43, 10, 43, 12, 43, 1276, 9, 43, 1, 43, 1, 43, 5, 43, 1280,\n        8, 43, 10, 43, 12, 43, 1283, 9, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1,\n        46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 5, 47, 1299, 8, 47, 10, 47, 12, 47, 1302,\n        9, 47, 1, 48, 1, 48, 5, 48, 1306, 8, 48, 10, 48, 12, 48, 1309, 9, 48, 1, 48, 1, 48, 5,\n        48, 1313, 8, 48, 10, 48, 12, 48, 1316, 9, 48, 1, 48, 5, 48, 1319, 8, 48, 10, 48, 12,\n        48, 1322, 9, 48, 1, 49, 1, 49, 5, 49, 1326, 8, 49, 10, 49, 12, 49, 1329, 9, 49, 1, 49,\n        1, 49, 1, 49, 5, 49, 1334, 8, 49, 10, 49, 12, 49, 1337, 9, 49, 1, 49, 1, 49, 1, 49, 3,\n        49, 1342, 8, 49, 1, 49, 1, 49, 3, 49, 1346, 8, 49, 1, 49, 1, 49, 1, 49, 3, 49, 1351, 8,\n        49, 1, 49, 1, 49, 3, 49, 1355, 8, 49, 3, 49, 1357, 8, 49, 1, 50, 1, 50, 5, 50, 1361, 8,\n        50, 10, 50, 12, 50, 1364, 9, 50, 1, 50, 1, 50, 5, 50, 1368, 8, 50, 10, 50, 12, 50, 1371,\n        9, 50, 1, 50, 3, 50, 1374, 8, 50, 1, 50, 5, 50, 1377, 8, 50, 10, 50, 12, 50, 1380, 9,\n        50, 1, 50, 5, 50, 1383, 8, 50, 10, 50, 12, 50, 1386, 9, 50, 1, 51, 1, 51, 1, 51, 5, 51,\n        1391, 8, 51, 10, 51, 12, 51, 1394, 9, 51, 1, 51, 1, 51, 5, 51, 1398, 8, 51, 10, 51, 12,\n        51, 1401, 9, 51, 1, 51, 1, 51, 3, 51, 1405, 8, 51, 1, 52, 1, 52, 1, 52, 5, 52, 1410, 8,\n        52, 10, 52, 12, 52, 1413, 9, 52, 1, 52, 0, 0, 53, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,\n        22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,\n        66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 0,\n        8, 1, 0, 3, 4, 1, 0, 33, 34, 1, 0, 35, 38, 1, 0, 39, 40, 1, 0, 41, 43, 3, 0, 41, 41, 56, 56,\n        60, 60, 1, 0, 58, 59, 1, 0, 41, 42, 1588, 0, 109, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 4, 146,\n        1, 0, 0, 0, 6, 158, 1, 0, 0, 0, 8, 181, 1, 0, 0, 0, 10, 196, 1, 0, 0, 0, 12, 246, 1, 0, 0,\n        0, 14, 266, 1, 0, 0, 0, 16, 328, 1, 0, 0, 0, 18, 430, 1, 0, 0, 0, 20, 447, 1, 0, 0, 0, 22,\n        451, 1, 0, 0, 0, 24, 706, 1, 0, 0, 0, 26, 708, 1, 0, 0, 0, 28, 712, 1, 0, 0, 0, 30, 732,\n        1, 0, 0, 0, 32, 752, 1, 0, 0, 0, 34, 772, 1, 0, 0, 0, 36, 792, 1, 0, 0, 0, 38, 812, 1, 0,\n        0, 0, 40, 832, 1, 0, 0, 0, 42, 852, 1, 0, 0, 0, 44, 870, 1, 0, 0, 0, 46, 872, 1, 0, 0, 0,\n        48, 901, 1, 0, 0, 0, 50, 912, 1, 0, 0, 0, 52, 914, 1, 0, 0, 0, 54, 916, 1, 0, 0, 0, 56, 924,\n        1, 0, 0, 0, 58, 978, 1, 0, 0, 0, 60, 989, 1, 0, 0, 0, 62, 991, 1, 0, 0, 0, 64, 993, 1, 0,\n        0, 0, 66, 995, 1, 0, 0, 0, 68, 997, 1, 0, 0, 0, 70, 999, 1, 0, 0, 0, 72, 1161, 1, 0, 0, 0,\n        74, 1163, 1, 0, 0, 0, 76, 1174, 1, 0, 0, 0, 78, 1178, 1, 0, 0, 0, 80, 1260, 1, 0, 0, 0,\n        82, 1264, 1, 0, 0, 0, 84, 1268, 1, 0, 0, 0, 86, 1270, 1, 0, 0, 0, 88, 1286, 1, 0, 0, 0,\n        90, 1288, 1, 0, 0, 0, 92, 1291, 1, 0, 0, 0, 94, 1293, 1, 0, 0, 0, 96, 1303, 1, 0, 0, 0,\n        98, 1356, 1, 0, 0, 0, 100, 1358, 1, 0, 0, 0, 102, 1404, 1, 0, 0, 0, 104, 1406, 1, 0, 0,\n        0, 106, 108, 7, 0, 0, 0, 107, 106, 1, 0, 0, 0, 108, 111, 1, 0, 0, 0, 109, 107, 1, 0, 0,\n        0, 109, 110, 1, 0, 0, 0, 110, 130, 1, 0, 0, 0, 111, 109, 1, 0, 0, 0, 112, 121, 3, 2, 1,\n        0, 113, 115, 5, 3, 0, 0, 114, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 114, 1, 0, 0,\n        0, 116, 117, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 120, 3, 2, 1, 0, 119, 114, 1, 0, 0,\n        0, 120, 123, 1, 0, 0, 0, 121, 119, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 127, 1, 0, 0,\n        0, 123, 121, 1, 0, 0, 0, 124, 126, 7, 0, 0, 0, 125, 124, 1, 0, 0, 0, 126, 129, 1, 0, 0,\n        0, 127, 125, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128, 131, 1, 0, 0, 0, 129, 127, 1, 0, 0,\n        0, 130, 112, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 133, 5, 0, 0,\n        1, 133, 1, 1, 0, 0, 0, 134, 145, 3, 24, 12, 0, 135, 145, 3, 28, 14, 0, 136, 145, 3, 8,\n        4, 0, 137, 145, 3, 10, 5, 0, 138, 145, 3, 12, 6, 0, 139, 145, 3, 14, 7, 0, 140, 145, 3,\n        16, 8, 0, 141, 145, 3, 4, 2, 0, 142, 145, 3, 18, 9, 0, 143, 145, 3, 20, 10, 0, 144, 134,\n        1, 0, 0, 0, 144, 135, 1, 0, 0, 0, 144, 136, 1, 0, 0, 0, 144, 137, 1, 0, 0, 0, 144, 138,\n        1, 0, 0, 0, 144, 139, 1, 0, 0, 0, 144, 140, 1, 0, 0, 0, 144, 141, 1, 0, 0, 0, 144, 142,\n        1, 0, 0, 0, 144, 143, 1, 0, 0, 0, 145, 3, 1, 0, 0, 0, 146, 150, 5, 19, 0, 0, 147, 149, 5,\n        4, 0, 0, 148, 147, 1, 0, 0, 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 150, 151, 1,\n        0, 0, 0, 151, 153, 1, 0, 0, 0, 152, 150, 1, 0, 0, 0, 153, 154, 3, 28, 14, 0, 154, 5, 1,\n        0, 0, 0, 155, 157, 7, 0, 0, 0, 156, 155, 1, 0, 0, 0, 157, 160, 1, 0, 0, 0, 158, 156, 1,\n        0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 179, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 161, 170, 3,\n        2, 1, 0, 162, 164, 5, 3, 0, 0, 163, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 163, 1,\n        0, 0, 0, 165, 166, 1, 0, 0, 0, 166, 167, 1, 0, 0, 0, 167, 169, 3, 2, 1, 0, 168, 163, 1,\n        0, 0, 0, 169, 172, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 170, 171, 1, 0, 0, 0, 171, 176, 1,\n        0, 0, 0, 172, 170, 1, 0, 0, 0, 173, 175, 7, 0, 0, 0, 174, 173, 1, 0, 0, 0, 175, 178, 1,\n        0, 0, 0, 176, 174, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 180, 1, 0, 0, 0, 178, 176, 1,\n        0, 0, 0, 179, 161, 1, 0, 0, 0, 179, 180, 1, 0, 0, 0, 180, 7, 1, 0, 0, 0, 181, 185, 5, 6,\n        0, 0, 182, 184, 5, 4, 0, 0, 183, 182, 1, 0, 0, 0, 184, 187, 1, 0, 0, 0, 185, 183, 1, 0,\n        0, 0, 185, 186, 1, 0, 0, 0, 186, 188, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 188, 189, 3, 28,\n        14, 0, 189, 190, 5, 3, 0, 0, 190, 191, 3, 6, 3, 0, 191, 192, 1, 0, 0, 0, 192, 193, 5, 3,\n        0, 0, 193, 194, 5, 17, 0, 0, 194, 195, 5, 12, 0, 0, 195, 9, 1, 0, 0, 0, 196, 197, 5, 7,\n        0, 0, 197, 198, 5, 4, 0, 0, 198, 199, 5, 56, 0, 0, 199, 200, 5, 4, 0, 0, 200, 204, 5, 8,\n        0, 0, 201, 203, 5, 4, 0, 0, 202, 201, 1, 0, 0, 0, 203, 206, 1, 0, 0, 0, 204, 202, 1, 0,\n        0, 0, 204, 205, 1, 0, 0, 0, 205, 207, 1, 0, 0, 0, 206, 204, 1, 0, 0, 0, 207, 211, 3, 28,\n        14, 0, 208, 210, 5, 4, 0, 0, 209, 208, 1, 0, 0, 0, 210, 213, 1, 0, 0, 0, 211, 209, 1, 0,\n        0, 0, 211, 212, 1, 0, 0, 0, 212, 214, 1, 0, 0, 0, 213, 211, 1, 0, 0, 0, 214, 218, 5, 10,\n        0, 0, 215, 217, 5, 4, 0, 0, 216, 215, 1, 0, 0, 0, 217, 220, 1, 0, 0, 0, 218, 216, 1, 0,\n        0, 0, 218, 219, 1, 0, 0, 0, 219, 221, 1, 0, 0, 0, 220, 218, 1, 0, 0, 0, 221, 236, 3, 28,\n        14, 0, 222, 224, 5, 4, 0, 0, 223, 222, 1, 0, 0, 0, 224, 227, 1, 0, 0, 0, 225, 223, 1, 0,\n        0, 0, 225, 226, 1, 0, 0, 0, 226, 228, 1, 0, 0, 0, 227, 225, 1, 0, 0, 0, 228, 232, 5, 11,\n        0, 0, 229, 231, 5, 4, 0, 0, 230, 229, 1, 0, 0, 0, 231, 234, 1, 0, 0, 0, 232, 230, 1, 0,\n        0, 0, 232, 233, 1, 0, 0, 0, 233, 235, 1, 0, 0, 0, 234, 232, 1, 0, 0, 0, 235, 237, 3, 28,\n        14, 0, 236, 225, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 240, 1, 0, 0, 0, 238, 239, 5, 3,\n        0, 0, 239, 241, 3, 6, 3, 0, 240, 238, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 1, 0,\n        0, 0, 242, 243, 5, 3, 0, 0, 243, 244, 5, 17, 0, 0, 244, 245, 5, 12, 0, 0, 245, 11, 1, 0,\n        0, 0, 246, 247, 5, 7, 0, 0, 247, 248, 5, 4, 0, 0, 248, 249, 5, 56, 0, 0, 249, 250, 5, 4,\n        0, 0, 250, 254, 5, 9, 0, 0, 251, 253, 5, 4, 0, 0, 252, 251, 1, 0, 0, 0, 253, 256, 1, 0,\n        0, 0, 254, 252, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 257, 1, 0, 0, 0, 256, 254, 1, 0,\n        0, 0, 257, 260, 3, 28, 14, 0, 258, 259, 5, 3, 0, 0, 259, 261, 3, 6, 3, 0, 260, 258, 1,\n        0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263, 5, 3, 0, 0, 263, 264, 5,\n        17, 0, 0, 264, 265, 5, 12, 0, 0, 265, 13, 1, 0, 0, 0, 266, 270, 5, 13, 0, 0, 267, 269,\n        5, 4, 0, 0, 268, 267, 1, 0, 0, 0, 269, 272, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 270, 271,\n        1, 0, 0, 0, 271, 273, 1, 0, 0, 0, 272, 270, 1, 0, 0, 0, 273, 277, 3, 28, 14, 0, 274, 276,\n        7, 0, 0, 0, 275, 274, 1, 0, 0, 0, 276, 279, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 277, 278,\n        1, 0, 0, 0, 278, 281, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 280, 282, 5, 14, 0, 0, 281, 280,\n        1, 0, 0, 0, 281, 282, 1, 0, 0, 0, 282, 285, 1, 0, 0, 0, 283, 284, 5, 3, 0, 0, 284, 286,\n        3, 6, 3, 0, 285, 283, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, 313, 1, 0, 0, 0, 287, 288,\n        5, 3, 0, 0, 288, 289, 5, 15, 0, 0, 289, 290, 5, 4, 0, 0, 290, 294, 5, 13, 0, 0, 291, 293,\n        5, 4, 0, 0, 292, 291, 1, 0, 0, 0, 293, 296, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 295,\n        1, 0, 0, 0, 295, 297, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 297, 301, 3, 28, 14, 0, 298, 300,\n        7, 0, 0, 0, 299, 298, 1, 0, 0, 0, 300, 303, 1, 0, 0, 0, 301, 299, 1, 0, 0, 0, 301, 302,\n        1, 0, 0, 0, 302, 305, 1, 0, 0, 0, 303, 301, 1, 0, 0, 0, 304, 306, 5, 14, 0, 0, 305, 304,\n        1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 309, 1, 0, 0, 0, 307, 308, 5, 3, 0, 0, 308, 310,\n        3, 6, 3, 0, 309, 307, 1, 0, 0, 0, 309, 310, 1, 0, 0, 0, 310, 312, 1, 0, 0, 0, 311, 287,\n        1, 0, 0, 0, 312, 315, 1, 0, 0, 0, 313, 311, 1, 0, 0, 0, 313, 314, 1, 0, 0, 0, 314, 322,\n        1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 316, 317, 5, 3, 0, 0, 317, 320, 5, 15, 0, 0, 318, 319,\n        5, 3, 0, 0, 319, 321, 3, 6, 3, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 323,\n        1, 0, 0, 0, 322, 316, 1, 0, 0, 0, 322, 323, 1, 0, 0, 0, 323, 324, 1, 0, 0, 0, 324, 325,\n        5, 3, 0, 0, 325, 326, 5, 17, 0, 0, 326, 327, 5, 13, 0, 0, 327, 15, 1, 0, 0, 0, 328, 329,\n        5, 16, 0, 0, 329, 330, 5, 4, 0, 0, 330, 334, 5, 56, 0, 0, 331, 333, 5, 4, 0, 0, 332, 331,\n        1, 0, 0, 0, 333, 336, 1, 0, 0, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 337,\n        1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 413, 5, 24, 0, 0, 338, 340, 5, 4, 0, 0, 339, 338,\n        1, 0, 0, 0, 340, 343, 1, 0, 0, 0, 341, 339, 1, 0, 0, 0, 341, 342, 1, 0, 0, 0, 342, 344,\n        1, 0, 0, 0, 343, 341, 1, 0, 0, 0, 344, 378, 5, 56, 0, 0, 345, 347, 5, 4, 0, 0, 346, 345,\n        1, 0, 0, 0, 347, 350, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 348, 349, 1, 0, 0, 0, 349, 351,\n        1, 0, 0, 0, 350, 348, 1, 0, 0, 0, 351, 355, 5, 33, 0, 0, 352, 354, 5, 4, 0, 0, 353, 352,\n        1, 0, 0, 0, 354, 357, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 355, 356, 1, 0, 0, 0, 356, 358,\n        1, 0, 0, 0, 357, 355, 1, 0, 0, 0, 358, 379, 3, 76, 38, 0, 359, 361, 5, 4, 0, 0, 360, 359,\n        1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 365,\n        1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 369, 5, 25, 0, 0, 366, 368, 5, 4, 0, 0, 367, 366,\n        1, 0, 0, 0, 368, 371, 1, 0, 0, 0, 369, 367, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 372,\n        1, 0, 0, 0, 371, 369, 1, 0, 0, 0, 372, 374, 5, 56, 0, 0, 373, 362, 1, 0, 0, 0, 374, 377,\n        1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 379, 1, 0, 0, 0, 377, 375,\n        1, 0, 0, 0, 378, 348, 1, 0, 0, 0, 378, 375, 1, 0, 0, 0, 379, 410, 1, 0, 0, 0, 380, 382,\n        5, 4, 0, 0, 381, 380, 1, 0, 0, 0, 382, 385, 1, 0, 0, 0, 383, 381, 1, 0, 0, 0, 383, 384,\n        1, 0, 0, 0, 384, 386, 1, 0, 0, 0, 385, 383, 1, 0, 0, 0, 386, 390, 5, 25, 0, 0, 387, 389,\n        5, 4, 0, 0, 388, 387, 1, 0, 0, 0, 389, 392, 1, 0, 0, 0, 390, 388, 1, 0, 0, 0, 390, 391,\n        1, 0, 0, 0, 391, 393, 1, 0, 0, 0, 392, 390, 1, 0, 0, 0, 393, 397, 5, 56, 0, 0, 394, 396,\n        5, 4, 0, 0, 395, 394, 1, 0, 0, 0, 396, 399, 1, 0, 0, 0, 397, 395, 1, 0, 0, 0, 397, 398,\n        1, 0, 0, 0, 398, 400, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 400, 404, 5, 33, 0, 0, 401, 403,\n        5, 4, 0, 0, 402, 401, 1, 0, 0, 0, 403, 406, 1, 0, 0, 0, 404, 402, 1, 0, 0, 0, 404, 405,\n        1, 0, 0, 0, 405, 407, 1, 0, 0, 0, 406, 404, 1, 0, 0, 0, 407, 409, 3, 76, 38, 0, 408, 383,\n        1, 0, 0, 0, 409, 412, 1, 0, 0, 0, 410, 408, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 411, 414,\n        1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 413, 341, 1, 0, 0, 0, 413, 414, 1, 0, 0, 0, 414, 418,\n        1, 0, 0, 0, 415, 417, 5, 4, 0, 0, 416, 415, 1, 0, 0, 0, 417, 420, 1, 0, 0, 0, 418, 416,\n        1, 0, 0, 0, 418, 419, 1, 0, 0, 0, 419, 421, 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 421, 424,\n        5, 26, 0, 0, 422, 423, 5, 3, 0, 0, 423, 425, 3, 6, 3, 0, 424, 422, 1, 0, 0, 0, 424, 425,\n        1, 0, 0, 0, 425, 426, 1, 0, 0, 0, 426, 427, 5, 3, 0, 0, 427, 428, 5, 17, 0, 0, 428, 429,\n        5, 16, 0, 0, 429, 17, 1, 0, 0, 0, 430, 433, 5, 21, 0, 0, 431, 432, 5, 3, 0, 0, 432, 434,\n        3, 6, 3, 0, 433, 431, 1, 0, 0, 0, 433, 434, 1, 0, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436,\n        5, 3, 0, 0, 436, 437, 5, 22, 0, 0, 437, 438, 5, 4, 0, 0, 438, 441, 5, 56, 0, 0, 439, 440,\n        5, 3, 0, 0, 440, 442, 3, 6, 3, 0, 441, 439, 1, 0, 0, 0, 441, 442, 1, 0, 0, 0, 442, 443,\n        1, 0, 0, 0, 443, 444, 5, 3, 0, 0, 444, 445, 5, 17, 0, 0, 445, 446, 5, 21, 0, 0, 446, 19,\n        1, 0, 0, 0, 447, 448, 5, 23, 0, 0, 448, 449, 5, 4, 0, 0, 449, 450, 3, 58, 29, 0, 450, 21,\n        1, 0, 0, 0, 451, 455, 5, 16, 0, 0, 452, 454, 5, 4, 0, 0, 453, 452, 1, 0, 0, 0, 454, 457,\n        1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 458, 1, 0, 0, 0, 457, 455,\n        1, 0, 0, 0, 458, 534, 5, 24, 0, 0, 459, 461, 5, 4, 0, 0, 460, 459, 1, 0, 0, 0, 461, 464,\n        1, 0, 0, 0, 462, 460, 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 465, 1, 0, 0, 0, 464, 462,\n        1, 0, 0, 0, 465, 499, 5, 56, 0, 0, 466, 468, 5, 4, 0, 0, 467, 466, 1, 0, 0, 0, 468, 471,\n        1, 0, 0, 0, 469, 467, 1, 0, 0, 0, 469, 470, 1, 0, 0, 0, 470, 472, 1, 0, 0, 0, 471, 469,\n        1, 0, 0, 0, 472, 476, 5, 33, 0, 0, 473, 475, 5, 4, 0, 0, 474, 473, 1, 0, 0, 0, 475, 478,\n        1, 0, 0, 0, 476, 474, 1, 0, 0, 0, 476, 477, 1, 0, 0, 0, 477, 479, 1, 0, 0, 0, 478, 476,\n        1, 0, 0, 0, 479, 500, 3, 76, 38, 0, 480, 482, 5, 4, 0, 0, 481, 480, 1, 0, 0, 0, 482, 485,\n        1, 0, 0, 0, 483, 481, 1, 0, 0, 0, 483, 484, 1, 0, 0, 0, 484, 486, 1, 0, 0, 0, 485, 483,\n        1, 0, 0, 0, 486, 490, 5, 25, 0, 0, 487, 489, 5, 4, 0, 0, 488, 487, 1, 0, 0, 0, 489, 492,\n        1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 490, 491, 1, 0, 0, 0, 491, 493, 1, 0, 0, 0, 492, 490,\n        1, 0, 0, 0, 493, 495, 5, 56, 0, 0, 494, 483, 1, 0, 0, 0, 495, 498, 1, 0, 0, 0, 496, 494,\n        1, 0, 0, 0, 496, 497, 1, 0, 0, 0, 497, 500, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 499, 469,\n        1, 0, 0, 0, 499, 496, 1, 0, 0, 0, 500, 531, 1, 0, 0, 0, 501, 503, 5, 4, 0, 0, 502, 501,\n        1, 0, 0, 0, 503, 506, 1, 0, 0, 0, 504, 502, 1, 0, 0, 0, 504, 505, 1, 0, 0, 0, 505, 507,\n        1, 0, 0, 0, 506, 504, 1, 0, 0, 0, 507, 511, 5, 25, 0, 0, 508, 510, 5, 4, 0, 0, 509, 508,\n        1, 0, 0, 0, 510, 513, 1, 0, 0, 0, 511, 509, 1, 0, 0, 0, 511, 512, 1, 0, 0, 0, 512, 514,\n        1, 0, 0, 0, 513, 511, 1, 0, 0, 0, 514, 518, 5, 56, 0, 0, 515, 517, 5, 4, 0, 0, 516, 515,\n        1, 0, 0, 0, 517, 520, 1, 0, 0, 0, 518, 516, 1, 0, 0, 0, 518, 519, 1, 0, 0, 0, 519, 521,\n        1, 0, 0, 0, 520, 518, 1, 0, 0, 0, 521, 525, 5, 33, 0, 0, 522, 524, 5, 4, 0, 0, 523, 522,\n        1, 0, 0, 0, 524, 527, 1, 0, 0, 0, 525, 523, 1, 0, 0, 0, 525, 526, 1, 0, 0, 0, 526, 528,\n        1, 0, 0, 0, 527, 525, 1, 0, 0, 0, 528, 530, 3, 76, 38, 0, 529, 504, 1, 0, 0, 0, 530, 533,\n        1, 0, 0, 0, 531, 529, 1, 0, 0, 0, 531, 532, 1, 0, 0, 0, 532, 535, 1, 0, 0, 0, 533, 531,\n        1, 0, 0, 0, 534, 462, 1, 0, 0, 0, 534, 535, 1, 0, 0, 0, 535, 539, 1, 0, 0, 0, 536, 538,\n        5, 4, 0, 0, 537, 536, 1, 0, 0, 0, 538, 541, 1, 0, 0, 0, 539, 537, 1, 0, 0, 0, 539, 540,\n        1, 0, 0, 0, 540, 542, 1, 0, 0, 0, 541, 539, 1, 0, 0, 0, 542, 557, 5, 26, 0, 0, 543, 544,\n        5, 3, 0, 0, 544, 546, 3, 6, 3, 0, 545, 543, 1, 0, 0, 0, 545, 546, 1, 0, 0, 0, 546, 547,\n        1, 0, 0, 0, 547, 548, 5, 3, 0, 0, 548, 549, 5, 17, 0, 0, 549, 558, 5, 16, 0, 0, 550, 552,\n        5, 4, 0, 0, 551, 550, 1, 0, 0, 0, 552, 555, 1, 0, 0, 0, 553, 551, 1, 0, 0, 0, 553, 554,\n        1, 0, 0, 0, 554, 556, 1, 0, 0, 0, 555, 553, 1, 0, 0, 0, 556, 558, 3, 2, 1, 0, 557, 545,\n        1, 0, 0, 0, 557, 553, 1, 0, 0, 0, 558, 23, 1, 0, 0, 0, 559, 563, 5, 56, 0, 0, 560, 562,\n        5, 4, 0, 0, 561, 560, 1, 0, 0, 0, 562, 565, 1, 0, 0, 0, 563, 561, 1, 0, 0, 0, 563, 564,\n        1, 0, 0, 0, 564, 566, 1, 0, 0, 0, 565, 563, 1, 0, 0, 0, 566, 642, 5, 24, 0, 0, 567, 569,\n        5, 4, 0, 0, 568, 567, 1, 0, 0, 0, 569, 572, 1, 0, 0, 0, 570, 568, 1, 0, 0, 0, 570, 571,\n        1, 0, 0, 0, 571, 573, 1, 0, 0, 0, 572, 570, 1, 0, 0, 0, 573, 607, 5, 56, 0, 0, 574, 576,\n        5, 4, 0, 0, 575, 574, 1, 0, 0, 0, 576, 579, 1, 0, 0, 0, 577, 575, 1, 0, 0, 0, 577, 578,\n        1, 0, 0, 0, 578, 580, 1, 0, 0, 0, 579, 577, 1, 0, 0, 0, 580, 584, 5, 33, 0, 0, 581, 583,\n        5, 4, 0, 0, 582, 581, 1, 0, 0, 0, 583, 586, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 584, 585,\n        1, 0, 0, 0, 585, 587, 1, 0, 0, 0, 586, 584, 1, 0, 0, 0, 587, 608, 3, 76, 38, 0, 588, 590,\n        5, 4, 0, 0, 589, 588, 1, 0, 0, 0, 590, 593, 1, 0, 0, 0, 591, 589, 1, 0, 0, 0, 591, 592,\n        1, 0, 0, 0, 592, 594, 1, 0, 0, 0, 593, 591, 1, 0, 0, 0, 594, 598, 5, 25, 0, 0, 595, 597,\n        5, 4, 0, 0, 596, 595, 1, 0, 0, 0, 597, 600, 1, 0, 0, 0, 598, 596, 1, 0, 0, 0, 598, 599,\n        1, 0, 0, 0, 599, 601, 1, 0, 0, 0, 600, 598, 1, 0, 0, 0, 601, 603, 5, 56, 0, 0, 602, 591,\n        1, 0, 0, 0, 603, 606, 1, 0, 0, 0, 604, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 608,\n        1, 0, 0, 0, 606, 604, 1, 0, 0, 0, 607, 577, 1, 0, 0, 0, 607, 604, 1, 0, 0, 0, 608, 639,\n        1, 0, 0, 0, 609, 611, 5, 4, 0, 0, 610, 609, 1, 0, 0, 0, 611, 614, 1, 0, 0, 0, 612, 610,\n        1, 0, 0, 0, 612, 613, 1, 0, 0, 0, 613, 615, 1, 0, 0, 0, 614, 612, 1, 0, 0, 0, 615, 619,\n        5, 25, 0, 0, 616, 618, 5, 4, 0, 0, 617, 616, 1, 0, 0, 0, 618, 621, 1, 0, 0, 0, 619, 617,\n        1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 622, 1, 0, 0, 0, 621, 619, 1, 0, 0, 0, 622, 626,\n        5, 56, 0, 0, 623, 625, 5, 4, 0, 0, 624, 623, 1, 0, 0, 0, 625, 628, 1, 0, 0, 0, 626, 624,\n        1, 0, 0, 0, 626, 627, 1, 0, 0, 0, 627, 629, 1, 0, 0, 0, 628, 626, 1, 0, 0, 0, 629, 633,\n        5, 33, 0, 0, 630, 632, 5, 4, 0, 0, 631, 630, 1, 0, 0, 0, 632, 635, 1, 0, 0, 0, 633, 631,\n        1, 0, 0, 0, 633, 634, 1, 0, 0, 0, 634, 636, 1, 0, 0, 0, 635, 633, 1, 0, 0, 0, 636, 638,\n        3, 76, 38, 0, 637, 612, 1, 0, 0, 0, 638, 641, 1, 0, 0, 0, 639, 637, 1, 0, 0, 0, 639, 640,\n        1, 0, 0, 0, 640, 643, 1, 0, 0, 0, 641, 639, 1, 0, 0, 0, 642, 570, 1, 0, 0, 0, 642, 643,\n        1, 0, 0, 0, 643, 647, 1, 0, 0, 0, 644, 646, 5, 4, 0, 0, 645, 644, 1, 0, 0, 0, 646, 649,\n        1, 0, 0, 0, 647, 645, 1, 0, 0, 0, 647, 648, 1, 0, 0, 0, 648, 650, 1, 0, 0, 0, 649, 647,\n        1, 0, 0, 0, 650, 654, 5, 26, 0, 0, 651, 653, 5, 4, 0, 0, 652, 651, 1, 0, 0, 0, 653, 656,\n        1, 0, 0, 0, 654, 652, 1, 0, 0, 0, 654, 655, 1, 0, 0, 0, 655, 657, 1, 0, 0, 0, 656, 654,\n        1, 0, 0, 0, 657, 661, 5, 27, 0, 0, 658, 660, 5, 4, 0, 0, 659, 658, 1, 0, 0, 0, 660, 663,\n        1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 664, 1, 0, 0, 0, 663, 661,\n        1, 0, 0, 0, 664, 707, 3, 28, 14, 0, 665, 668, 3, 66, 33, 0, 666, 668, 3, 26, 13, 0, 667,\n        665, 1, 0, 0, 0, 667, 666, 1, 0, 0, 0, 668, 688, 1, 0, 0, 0, 669, 671, 5, 4, 0, 0, 670,\n        669, 1, 0, 0, 0, 671, 674, 1, 0, 0, 0, 672, 670, 1, 0, 0, 0, 672, 673, 1, 0, 0, 0, 673,\n        675, 1, 0, 0, 0, 674, 672, 1, 0, 0, 0, 675, 679, 5, 25, 0, 0, 676, 678, 5, 4, 0, 0, 677,\n        676, 1, 0, 0, 0, 678, 681, 1, 0, 0, 0, 679, 677, 1, 0, 0, 0, 679, 680, 1, 0, 0, 0, 680,\n        684, 1, 0, 0, 0, 681, 679, 1, 0, 0, 0, 682, 685, 3, 66, 33, 0, 683, 685, 3, 26, 13, 0,\n        684, 682, 1, 0, 0, 0, 684, 683, 1, 0, 0, 0, 685, 687, 1, 0, 0, 0, 686, 672, 1, 0, 0, 0,\n        687, 690, 1, 0, 0, 0, 688, 686, 1, 0, 0, 0, 688, 689, 1, 0, 0, 0, 689, 694, 1, 0, 0, 0,\n        690, 688, 1, 0, 0, 0, 691, 693, 5, 4, 0, 0, 692, 691, 1, 0, 0, 0, 693, 696, 1, 0, 0, 0,\n        694, 692, 1, 0, 0, 0, 694, 695, 1, 0, 0, 0, 695, 697, 1, 0, 0, 0, 696, 694, 1, 0, 0, 0,\n        697, 701, 5, 27, 0, 0, 698, 700, 5, 4, 0, 0, 699, 698, 1, 0, 0, 0, 700, 703, 1, 0, 0, 0,\n        701, 699, 1, 0, 0, 0, 701, 702, 1, 0, 0, 0, 702, 704, 1, 0, 0, 0, 703, 701, 1, 0, 0, 0,\n        704, 705, 3, 28, 14, 0, 705, 707, 1, 0, 0, 0, 706, 559, 1, 0, 0, 0, 706, 667, 1, 0, 0,\n        0, 707, 25, 1, 0, 0, 0, 708, 710, 5, 56, 0, 0, 709, 711, 3, 78, 39, 0, 710, 709, 1, 0,\n        0, 0, 710, 711, 1, 0, 0, 0, 711, 27, 1, 0, 0, 0, 712, 729, 3, 30, 15, 0, 713, 715, 5, 4,\n        0, 0, 714, 713, 1, 0, 0, 0, 715, 718, 1, 0, 0, 0, 716, 714, 1, 0, 0, 0, 716, 717, 1, 0,\n        0, 0, 717, 719, 1, 0, 0, 0, 718, 716, 1, 0, 0, 0, 719, 723, 5, 30, 0, 0, 720, 722, 5, 4,\n        0, 0, 721, 720, 1, 0, 0, 0, 722, 725, 1, 0, 0, 0, 723, 721, 1, 0, 0, 0, 723, 724, 1, 0,\n        0, 0, 724, 726, 1, 0, 0, 0, 725, 723, 1, 0, 0, 0, 726, 728, 3, 30, 15, 0, 727, 716, 1,\n        0, 0, 0, 728, 731, 1, 0, 0, 0, 729, 727, 1, 0, 0, 0, 729, 730, 1, 0, 0, 0, 730, 29, 1, 0,\n        0, 0, 731, 729, 1, 0, 0, 0, 732, 749, 3, 32, 16, 0, 733, 735, 5, 4, 0, 0, 734, 733, 1,\n        0, 0, 0, 735, 738, 1, 0, 0, 0, 736, 734, 1, 0, 0, 0, 736, 737, 1, 0, 0, 0, 737, 739, 1,\n        0, 0, 0, 738, 736, 1, 0, 0, 0, 739, 743, 5, 31, 0, 0, 740, 742, 5, 4, 0, 0, 741, 740, 1,\n        0, 0, 0, 742, 745, 1, 0, 0, 0, 743, 741, 1, 0, 0, 0, 743, 744, 1, 0, 0, 0, 744, 746, 1,\n        0, 0, 0, 745, 743, 1, 0, 0, 0, 746, 748, 3, 32, 16, 0, 747, 736, 1, 0, 0, 0, 748, 751,\n        1, 0, 0, 0, 749, 747, 1, 0, 0, 0, 749, 750, 1, 0, 0, 0, 750, 31, 1, 0, 0, 0, 751, 749, 1,\n        0, 0, 0, 752, 769, 3, 34, 17, 0, 753, 755, 5, 4, 0, 0, 754, 753, 1, 0, 0, 0, 755, 758,\n        1, 0, 0, 0, 756, 754, 1, 0, 0, 0, 756, 757, 1, 0, 0, 0, 757, 759, 1, 0, 0, 0, 758, 756,\n        1, 0, 0, 0, 759, 763, 5, 32, 0, 0, 760, 762, 5, 4, 0, 0, 761, 760, 1, 0, 0, 0, 762, 765,\n        1, 0, 0, 0, 763, 761, 1, 0, 0, 0, 763, 764, 1, 0, 0, 0, 764, 766, 1, 0, 0, 0, 765, 763,\n        1, 0, 0, 0, 766, 768, 3, 34, 17, 0, 767, 756, 1, 0, 0, 0, 768, 771, 1, 0, 0, 0, 769, 767,\n        1, 0, 0, 0, 769, 770, 1, 0, 0, 0, 770, 33, 1, 0, 0, 0, 771, 769, 1, 0, 0, 0, 772, 789, 3,\n        36, 18, 0, 773, 775, 5, 4, 0, 0, 774, 773, 1, 0, 0, 0, 775, 778, 1, 0, 0, 0, 776, 774,\n        1, 0, 0, 0, 776, 777, 1, 0, 0, 0, 777, 779, 1, 0, 0, 0, 778, 776, 1, 0, 0, 0, 779, 783,\n        7, 1, 0, 0, 780, 782, 5, 4, 0, 0, 781, 780, 1, 0, 0, 0, 782, 785, 1, 0, 0, 0, 783, 781,\n        1, 0, 0, 0, 783, 784, 1, 0, 0, 0, 784, 786, 1, 0, 0, 0, 785, 783, 1, 0, 0, 0, 786, 788,\n        3, 36, 18, 0, 787, 776, 1, 0, 0, 0, 788, 791, 1, 0, 0, 0, 789, 787, 1, 0, 0, 0, 789, 790,\n        1, 0, 0, 0, 790, 35, 1, 0, 0, 0, 791, 789, 1, 0, 0, 0, 792, 809, 3, 38, 19, 0, 793, 795,\n        5, 4, 0, 0, 794, 793, 1, 0, 0, 0, 795, 798, 1, 0, 0, 0, 796, 794, 1, 0, 0, 0, 796, 797,\n        1, 0, 0, 0, 797, 799, 1, 0, 0, 0, 798, 796, 1, 0, 0, 0, 799, 803, 7, 2, 0, 0, 800, 802,\n        5, 4, 0, 0, 801, 800, 1, 0, 0, 0, 802, 805, 1, 0, 0, 0, 803, 801, 1, 0, 0, 0, 803, 804,\n        1, 0, 0, 0, 804, 806, 1, 0, 0, 0, 805, 803, 1, 0, 0, 0, 806, 808, 3, 38, 19, 0, 807, 796,\n        1, 0, 0, 0, 808, 811, 1, 0, 0, 0, 809, 807, 1, 0, 0, 0, 809, 810, 1, 0, 0, 0, 810, 37, 1,\n        0, 0, 0, 811, 809, 1, 0, 0, 0, 812, 829, 3, 40, 20, 0, 813, 815, 5, 4, 0, 0, 814, 813,\n        1, 0, 0, 0, 815, 818, 1, 0, 0, 0, 816, 814, 1, 0, 0, 0, 816, 817, 1, 0, 0, 0, 817, 819,\n        1, 0, 0, 0, 818, 816, 1, 0, 0, 0, 819, 823, 7, 3, 0, 0, 820, 822, 5, 4, 0, 0, 821, 820,\n        1, 0, 0, 0, 822, 825, 1, 0, 0, 0, 823, 821, 1, 0, 0, 0, 823, 824, 1, 0, 0, 0, 824, 826,\n        1, 0, 0, 0, 825, 823, 1, 0, 0, 0, 826, 828, 3, 40, 20, 0, 827, 816, 1, 0, 0, 0, 828, 831,\n        1, 0, 0, 0, 829, 827, 1, 0, 0, 0, 829, 830, 1, 0, 0, 0, 830, 39, 1, 0, 0, 0, 831, 829, 1,\n        0, 0, 0, 832, 849, 3, 42, 21, 0, 833, 835, 5, 4, 0, 0, 834, 833, 1, 0, 0, 0, 835, 838,\n        1, 0, 0, 0, 836, 834, 1, 0, 0, 0, 836, 837, 1, 0, 0, 0, 837, 839, 1, 0, 0, 0, 838, 836,\n        1, 0, 0, 0, 839, 843, 7, 4, 0, 0, 840, 842, 5, 4, 0, 0, 841, 840, 1, 0, 0, 0, 842, 845,\n        1, 0, 0, 0, 843, 841, 1, 0, 0, 0, 843, 844, 1, 0, 0, 0, 844, 846, 1, 0, 0, 0, 845, 843,\n        1, 0, 0, 0, 846, 848, 3, 42, 21, 0, 847, 836, 1, 0, 0, 0, 848, 851, 1, 0, 0, 0, 849, 847,\n        1, 0, 0, 0, 849, 850, 1, 0, 0, 0, 850, 41, 1, 0, 0, 0, 851, 849, 1, 0, 0, 0, 852, 855, 3,\n        44, 22, 0, 853, 854, 5, 29, 0, 0, 854, 856, 3, 44, 22, 0, 855, 853, 1, 0, 0, 0, 855, 856,\n        1, 0, 0, 0, 856, 859, 1, 0, 0, 0, 857, 858, 5, 29, 0, 0, 858, 860, 3, 44, 22, 0, 859, 857,\n        1, 0, 0, 0, 859, 860, 1, 0, 0, 0, 860, 43, 1, 0, 0, 0, 861, 865, 5, 40, 0, 0, 862, 864,\n        5, 4, 0, 0, 863, 862, 1, 0, 0, 0, 864, 867, 1, 0, 0, 0, 865, 863, 1, 0, 0, 0, 865, 866,\n        1, 0, 0, 0, 866, 868, 1, 0, 0, 0, 867, 865, 1, 0, 0, 0, 868, 871, 3, 46, 23, 0, 869, 871,\n        3, 46, 23, 0, 870, 861, 1, 0, 0, 0, 870, 869, 1, 0, 0, 0, 871, 45, 1, 0, 0, 0, 872, 889,\n        3, 50, 25, 0, 873, 875, 5, 4, 0, 0, 874, 873, 1, 0, 0, 0, 875, 878, 1, 0, 0, 0, 876, 874,\n        1, 0, 0, 0, 876, 877, 1, 0, 0, 0, 877, 879, 1, 0, 0, 0, 878, 876, 1, 0, 0, 0, 879, 883,\n        5, 44, 0, 0, 880, 882, 5, 4, 0, 0, 881, 880, 1, 0, 0, 0, 882, 885, 1, 0, 0, 0, 883, 881,\n        1, 0, 0, 0, 883, 884, 1, 0, 0, 0, 884, 886, 1, 0, 0, 0, 885, 883, 1, 0, 0, 0, 886, 888,\n        3, 48, 24, 0, 887, 876, 1, 0, 0, 0, 888, 891, 1, 0, 0, 0, 889, 887, 1, 0, 0, 0, 889, 890,\n        1, 0, 0, 0, 890, 47, 1, 0, 0, 0, 891, 889, 1, 0, 0, 0, 892, 896, 5, 40, 0, 0, 893, 895,\n        5, 4, 0, 0, 894, 893, 1, 0, 0, 0, 895, 898, 1, 0, 0, 0, 896, 894, 1, 0, 0, 0, 896, 897,\n        1, 0, 0, 0, 897, 899, 1, 0, 0, 0, 898, 896, 1, 0, 0, 0, 899, 902, 3, 50, 25, 0, 900, 902,\n        3, 50, 25, 0, 901, 892, 1, 0, 0, 0, 901, 900, 1, 0, 0, 0, 902, 49, 1, 0, 0, 0, 903, 907,\n        5, 45, 0, 0, 904, 906, 5, 4, 0, 0, 905, 904, 1, 0, 0, 0, 906, 909, 1, 0, 0, 0, 907, 905,\n        1, 0, 0, 0, 907, 908, 1, 0, 0, 0, 908, 910, 1, 0, 0, 0, 909, 907, 1, 0, 0, 0, 910, 913,\n        3, 52, 26, 0, 911, 913, 3, 52, 26, 0, 912, 903, 1, 0, 0, 0, 912, 911, 1, 0, 0, 0, 913,\n        51, 1, 0, 0, 0, 914, 915, 3, 54, 27, 0, 915, 53, 1, 0, 0, 0, 916, 921, 3, 58, 29, 0, 917,\n        920, 3, 78, 39, 0, 918, 920, 3, 56, 28, 0, 919, 917, 1, 0, 0, 0, 919, 918, 1, 0, 0, 0,\n        920, 923, 1, 0, 0, 0, 921, 919, 1, 0, 0, 0, 921, 922, 1, 0, 0, 0, 922, 55, 1, 0, 0, 0, 923,\n        921, 1, 0, 0, 0, 924, 951, 5, 24, 0, 0, 925, 927, 5, 4, 0, 0, 926, 925, 1, 0, 0, 0, 927,\n        930, 1, 0, 0, 0, 928, 926, 1, 0, 0, 0, 928, 929, 1, 0, 0, 0, 929, 931, 1, 0, 0, 0, 930,\n        928, 1, 0, 0, 0, 931, 948, 3, 28, 14, 0, 932, 934, 5, 4, 0, 0, 933, 932, 1, 0, 0, 0, 934,\n        937, 1, 0, 0, 0, 935, 933, 1, 0, 0, 0, 935, 936, 1, 0, 0, 0, 936, 938, 1, 0, 0, 0, 937,\n        935, 1, 0, 0, 0, 938, 942, 5, 25, 0, 0, 939, 941, 5, 4, 0, 0, 940, 939, 1, 0, 0, 0, 941,\n        944, 1, 0, 0, 0, 942, 940, 1, 0, 0, 0, 942, 943, 1, 0, 0, 0, 943, 945, 1, 0, 0, 0, 944,\n        942, 1, 0, 0, 0, 945, 947, 3, 28, 14, 0, 946, 935, 1, 0, 0, 0, 947, 950, 1, 0, 0, 0, 948,\n        946, 1, 0, 0, 0, 948, 949, 1, 0, 0, 0, 949, 952, 1, 0, 0, 0, 950, 948, 1, 0, 0, 0, 951,\n        928, 1, 0, 0, 0, 951, 952, 1, 0, 0, 0, 952, 956, 1, 0, 0, 0, 953, 955, 5, 4, 0, 0, 954,\n        953, 1, 0, 0, 0, 955, 958, 1, 0, 0, 0, 956, 954, 1, 0, 0, 0, 956, 957, 1, 0, 0, 0, 957,\n        959, 1, 0, 0, 0, 958, 956, 1, 0, 0, 0, 959, 960, 5, 26, 0, 0, 960, 57, 1, 0, 0, 0, 961,\n        965, 5, 24, 0, 0, 962, 964, 7, 0, 0, 0, 963, 962, 1, 0, 0, 0, 964, 967, 1, 0, 0, 0, 965,\n        963, 1, 0, 0, 0, 965, 966, 1, 0, 0, 0, 966, 968, 1, 0, 0, 0, 967, 965, 1, 0, 0, 0, 968,\n        972, 3, 28, 14, 0, 969, 971, 7, 0, 0, 0, 970, 969, 1, 0, 0, 0, 971, 974, 1, 0, 0, 0, 972,\n        970, 1, 0, 0, 0, 972, 973, 1, 0, 0, 0, 973, 975, 1, 0, 0, 0, 974, 972, 1, 0, 0, 0, 975,\n        976, 5, 26, 0, 0, 976, 979, 1, 0, 0, 0, 977, 979, 3, 60, 30, 0, 978, 961, 1, 0, 0, 0, 978,\n        977, 1, 0, 0, 0, 979, 59, 1, 0, 0, 0, 980, 990, 3, 88, 44, 0, 981, 990, 5, 50, 0, 0, 982,\n        990, 3, 92, 46, 0, 983, 990, 3, 70, 35, 0, 984, 990, 3, 62, 31, 0, 985, 990, 3, 66, 33,\n        0, 986, 990, 3, 72, 36, 0, 987, 990, 3, 22, 11, 0, 988, 990, 3, 74, 37, 0, 989, 980,\n        1, 0, 0, 0, 989, 981, 1, 0, 0, 0, 989, 982, 1, 0, 0, 0, 989, 983, 1, 0, 0, 0, 989, 984,\n        1, 0, 0, 0, 989, 985, 1, 0, 0, 0, 989, 986, 1, 0, 0, 0, 989, 987, 1, 0, 0, 0, 989, 988,\n        1, 0, 0, 0, 990, 61, 1, 0, 0, 0, 991, 992, 5, 56, 0, 0, 992, 63, 1, 0, 0, 0, 993, 994, 7,\n        5, 0, 0, 994, 65, 1, 0, 0, 0, 995, 996, 5, 57, 0, 0, 996, 67, 1, 0, 0, 0, 997, 998, 5, 56,\n        0, 0, 998, 69, 1, 0, 0, 0, 999, 1003, 5, 48, 0, 0, 1000, 1002, 5, 4, 0, 0, 1001, 1000,\n        1, 0, 0, 0, 1002, 1005, 1, 0, 0, 0, 1003, 1001, 1, 0, 0, 0, 1003, 1004, 1, 0, 0, 0, 1004,\n        1006, 1, 0, 0, 0, 1005, 1003, 1, 0, 0, 0, 1006, 1007, 3, 38, 19, 0, 1007, 1008, 5, 4,\n        0, 0, 1008, 1012, 3, 94, 47, 0, 1009, 1011, 5, 4, 0, 0, 1010, 1009, 1, 0, 0, 0, 1011,\n        1014, 1, 0, 0, 0, 1012, 1010, 1, 0, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1015, 1, 0, 0,\n        0, 1014, 1012, 1, 0, 0, 0, 1015, 1016, 5, 49, 0, 0, 1016, 71, 1, 0, 0, 0, 1017, 1044,\n        5, 46, 0, 0, 1018, 1020, 7, 0, 0, 0, 1019, 1018, 1, 0, 0, 0, 1020, 1023, 1, 0, 0, 0, 1021,\n        1019, 1, 0, 0, 0, 1021, 1022, 1, 0, 0, 0, 1022, 1024, 1, 0, 0, 0, 1023, 1021, 1, 0, 0,\n        0, 1024, 1041, 3, 86, 43, 0, 1025, 1027, 7, 0, 0, 0, 1026, 1025, 1, 0, 0, 0, 1027, 1030,\n        1, 0, 0, 0, 1028, 1026, 1, 0, 0, 0, 1028, 1029, 1, 0, 0, 0, 1029, 1031, 1, 0, 0, 0, 1030,\n        1028, 1, 0, 0, 0, 1031, 1035, 5, 25, 0, 0, 1032, 1034, 7, 0, 0, 0, 1033, 1032, 1, 0,\n        0, 0, 1034, 1037, 1, 0, 0, 0, 1035, 1033, 1, 0, 0, 0, 1035, 1036, 1, 0, 0, 0, 1036, 1038,\n        1, 0, 0, 0, 1037, 1035, 1, 0, 0, 0, 1038, 1040, 3, 86, 43, 0, 1039, 1028, 1, 0, 0, 0,\n        1040, 1043, 1, 0, 0, 0, 1041, 1039, 1, 0, 0, 0, 1041, 1042, 1, 0, 0, 0, 1042, 1045,\n        1, 0, 0, 0, 1043, 1041, 1, 0, 0, 0, 1044, 1021, 1, 0, 0, 0, 1044, 1045, 1, 0, 0, 0, 1045,\n        1049, 1, 0, 0, 0, 1046, 1048, 7, 0, 0, 0, 1047, 1046, 1, 0, 0, 0, 1048, 1051, 1, 0, 0,\n        0, 1049, 1047, 1, 0, 0, 0, 1049, 1050, 1, 0, 0, 0, 1050, 1052, 1, 0, 0, 0, 1051, 1049,\n        1, 0, 0, 0, 1052, 1162, 5, 47, 0, 0, 1053, 1080, 5, 48, 0, 0, 1054, 1056, 7, 0, 0, 0,\n        1055, 1054, 1, 0, 0, 0, 1056, 1059, 1, 0, 0, 0, 1057, 1055, 1, 0, 0, 0, 1057, 1058,\n        1, 0, 0, 0, 1058, 1060, 1, 0, 0, 0, 1059, 1057, 1, 0, 0, 0, 1060, 1077, 3, 86, 43, 0,\n        1061, 1063, 7, 0, 0, 0, 1062, 1061, 1, 0, 0, 0, 1063, 1066, 1, 0, 0, 0, 1064, 1062,\n        1, 0, 0, 0, 1064, 1065, 1, 0, 0, 0, 1065, 1067, 1, 0, 0, 0, 1066, 1064, 1, 0, 0, 0, 1067,\n        1071, 5, 25, 0, 0, 1068, 1070, 7, 0, 0, 0, 1069, 1068, 1, 0, 0, 0, 1070, 1073, 1, 0,\n        0, 0, 1071, 1069, 1, 0, 0, 0, 1071, 1072, 1, 0, 0, 0, 1072, 1074, 1, 0, 0, 0, 1073, 1071,\n        1, 0, 0, 0, 1074, 1076, 3, 86, 43, 0, 1075, 1064, 1, 0, 0, 0, 1076, 1079, 1, 0, 0, 0,\n        1077, 1075, 1, 0, 0, 0, 1077, 1078, 1, 0, 0, 0, 1078, 1081, 1, 0, 0, 0, 1079, 1077,\n        1, 0, 0, 0, 1080, 1057, 1, 0, 0, 0, 1080, 1081, 1, 0, 0, 0, 1081, 1085, 1, 0, 0, 0, 1082,\n        1084, 7, 0, 0, 0, 1083, 1082, 1, 0, 0, 0, 1084, 1087, 1, 0, 0, 0, 1085, 1083, 1, 0, 0,\n        0, 1085, 1086, 1, 0, 0, 0, 1086, 1088, 1, 0, 0, 0, 1087, 1085, 1, 0, 0, 0, 1088, 1162,\n        5, 49, 0, 0, 1089, 1116, 5, 46, 0, 0, 1090, 1092, 7, 0, 0, 0, 1091, 1090, 1, 0, 0, 0,\n        1092, 1095, 1, 0, 0, 0, 1093, 1091, 1, 0, 0, 0, 1093, 1094, 1, 0, 0, 0, 1094, 1096,\n        1, 0, 0, 0, 1095, 1093, 1, 0, 0, 0, 1096, 1113, 3, 28, 14, 0, 1097, 1099, 7, 0, 0, 0,\n        1098, 1097, 1, 0, 0, 0, 1099, 1102, 1, 0, 0, 0, 1100, 1098, 1, 0, 0, 0, 1100, 1101,\n        1, 0, 0, 0, 1101, 1103, 1, 0, 0, 0, 1102, 1100, 1, 0, 0, 0, 1103, 1107, 5, 25, 0, 0, 1104,\n        1106, 7, 0, 0, 0, 1105, 1104, 1, 0, 0, 0, 1106, 1109, 1, 0, 0, 0, 1107, 1105, 1, 0, 0,\n        0, 1107, 1108, 1, 0, 0, 0, 1108, 1110, 1, 0, 0, 0, 1109, 1107, 1, 0, 0, 0, 1110, 1112,\n        3, 28, 14, 0, 1111, 1100, 1, 0, 0, 0, 1112, 1115, 1, 0, 0, 0, 1113, 1111, 1, 0, 0, 0,\n        1113, 1114, 1, 0, 0, 0, 1114, 1117, 1, 0, 0, 0, 1115, 1113, 1, 0, 0, 0, 1116, 1093,\n        1, 0, 0, 0, 1116, 1117, 1, 0, 0, 0, 1117, 1121, 1, 0, 0, 0, 1118, 1120, 7, 0, 0, 0, 1119,\n        1118, 1, 0, 0, 0, 1120, 1123, 1, 0, 0, 0, 1121, 1119, 1, 0, 0, 0, 1121, 1122, 1, 0, 0,\n        0, 1122, 1124, 1, 0, 0, 0, 1123, 1121, 1, 0, 0, 0, 1124, 1162, 5, 47, 0, 0, 1125, 1152,\n        5, 48, 0, 0, 1126, 1128, 7, 0, 0, 0, 1127, 1126, 1, 0, 0, 0, 1128, 1131, 1, 0, 0, 0, 1129,\n        1127, 1, 0, 0, 0, 1129, 1130, 1, 0, 0, 0, 1130, 1132, 1, 0, 0, 0, 1131, 1129, 1, 0, 0,\n        0, 1132, 1149, 3, 28, 14, 0, 1133, 1135, 7, 0, 0, 0, 1134, 1133, 1, 0, 0, 0, 1135, 1138,\n        1, 0, 0, 0, 1136, 1134, 1, 0, 0, 0, 1136, 1137, 1, 0, 0, 0, 1137, 1139, 1, 0, 0, 0, 1138,\n        1136, 1, 0, 0, 0, 1139, 1143, 5, 25, 0, 0, 1140, 1142, 7, 0, 0, 0, 1141, 1140, 1, 0,\n        0, 0, 1142, 1145, 1, 0, 0, 0, 1143, 1141, 1, 0, 0, 0, 1143, 1144, 1, 0, 0, 0, 1144, 1146,\n        1, 0, 0, 0, 1145, 1143, 1, 0, 0, 0, 1146, 1148, 3, 28, 14, 0, 1147, 1136, 1, 0, 0, 0,\n        1148, 1151, 1, 0, 0, 0, 1149, 1147, 1, 0, 0, 0, 1149, 1150, 1, 0, 0, 0, 1150, 1153,\n        1, 0, 0, 0, 1151, 1149, 1, 0, 0, 0, 1152, 1129, 1, 0, 0, 0, 1152, 1153, 1, 0, 0, 0, 1153,\n        1157, 1, 0, 0, 0, 1154, 1156, 7, 0, 0, 0, 1155, 1154, 1, 0, 0, 0, 1156, 1159, 1, 0, 0,\n        0, 1157, 1155, 1, 0, 0, 0, 1157, 1158, 1, 0, 0, 0, 1158, 1160, 1, 0, 0, 0, 1159, 1157,\n        1, 0, 0, 0, 1160, 1162, 5, 49, 0, 0, 1161, 1017, 1, 0, 0, 0, 1161, 1053, 1, 0, 0, 0, 1161,\n        1089, 1, 0, 0, 0, 1161, 1125, 1, 0, 0, 0, 1162, 73, 1, 0, 0, 0, 1163, 1164, 5, 20, 0,\n        0, 1164, 1165, 5, 4, 0, 0, 1165, 1167, 3, 68, 34, 0, 1166, 1168, 3, 56, 28, 0, 1167,\n        1166, 1, 0, 0, 0, 1167, 1168, 1, 0, 0, 0, 1168, 75, 1, 0, 0, 0, 1169, 1175, 3, 90, 45,\n        0, 1170, 1175, 3, 88, 44, 0, 1171, 1175, 5, 50, 0, 0, 1172, 1175, 3, 92, 46, 0, 1173,\n        1175, 3, 72, 36, 0, 1174, 1169, 1, 0, 0, 0, 1174, 1170, 1, 0, 0, 0, 1174, 1171, 1, 0,\n        0, 0, 1174, 1172, 1, 0, 0, 0, 1174, 1173, 1, 0, 0, 0, 1175, 77, 1, 0, 0, 0, 1176, 1179,\n        3, 80, 40, 0, 1177, 1179, 3, 82, 41, 0, 1178, 1176, 1, 0, 0, 0, 1178, 1177, 1, 0, 0,\n        0, 1179, 79, 1, 0, 0, 0, 1180, 1184, 5, 46, 0, 0, 1181, 1183, 5, 4, 0, 0, 1182, 1181,\n        1, 0, 0, 0, 1183, 1186, 1, 0, 0, 0, 1184, 1182, 1, 0, 0, 0, 1184, 1185, 1, 0, 0, 0, 1185,\n        1189, 1, 0, 0, 0, 1186, 1184, 1, 0, 0, 0, 1187, 1190, 3, 28, 14, 0, 1188, 1190, 5, 41,\n        0, 0, 1189, 1187, 1, 0, 0, 0, 1189, 1188, 1, 0, 0, 0, 1190, 1210, 1, 0, 0, 0, 1191, 1193,\n        5, 4, 0, 0, 1192, 1191, 1, 0, 0, 0, 1193, 1196, 1, 0, 0, 0, 1194, 1192, 1, 0, 0, 0, 1194,\n        1195, 1, 0, 0, 0, 1195, 1197, 1, 0, 0, 0, 1196, 1194, 1, 0, 0, 0, 1197, 1201, 5, 25,\n        0, 0, 1198, 1200, 5, 4, 0, 0, 1199, 1198, 1, 0, 0, 0, 1200, 1203, 1, 0, 0, 0, 1201, 1199,\n        1, 0, 0, 0, 1201, 1202, 1, 0, 0, 0, 1202, 1206, 1, 0, 0, 0, 1203, 1201, 1, 0, 0, 0, 1204,\n        1207, 3, 28, 14, 0, 1205, 1207, 5, 41, 0, 0, 1206, 1204, 1, 0, 0, 0, 1206, 1205, 1,\n        0, 0, 0, 1207, 1209, 1, 0, 0, 0, 1208, 1194, 1, 0, 0, 0, 1209, 1212, 1, 0, 0, 0, 1210,\n        1208, 1, 0, 0, 0, 1210, 1211, 1, 0, 0, 0, 1211, 1216, 1, 0, 0, 0, 1212, 1210, 1, 0, 0,\n        0, 1213, 1215, 5, 4, 0, 0, 1214, 1213, 1, 0, 0, 0, 1215, 1218, 1, 0, 0, 0, 1216, 1214,\n        1, 0, 0, 0, 1216, 1217, 1, 0, 0, 0, 1217, 1219, 1, 0, 0, 0, 1218, 1216, 1, 0, 0, 0, 1219,\n        1261, 5, 47, 0, 0, 1220, 1224, 5, 48, 0, 0, 1221, 1223, 5, 4, 0, 0, 1222, 1221, 1, 0,\n        0, 0, 1223, 1226, 1, 0, 0, 0, 1224, 1222, 1, 0, 0, 0, 1224, 1225, 1, 0, 0, 0, 1225, 1229,\n        1, 0, 0, 0, 1226, 1224, 1, 0, 0, 0, 1227, 1230, 3, 28, 14, 0, 1228, 1230, 5, 41, 0, 0,\n        1229, 1227, 1, 0, 0, 0, 1229, 1228, 1, 0, 0, 0, 1230, 1250, 1, 0, 0, 0, 1231, 1233,\n        5, 4, 0, 0, 1232, 1231, 1, 0, 0, 0, 1233, 1236, 1, 0, 0, 0, 1234, 1232, 1, 0, 0, 0, 1234,\n        1235, 1, 0, 0, 0, 1235, 1237, 1, 0, 0, 0, 1236, 1234, 1, 0, 0, 0, 1237, 1241, 5, 25,\n        0, 0, 1238, 1240, 5, 4, 0, 0, 1239, 1238, 1, 0, 0, 0, 1240, 1243, 1, 0, 0, 0, 1241, 1239,\n        1, 0, 0, 0, 1241, 1242, 1, 0, 0, 0, 1242, 1246, 1, 0, 0, 0, 1243, 1241, 1, 0, 0, 0, 1244,\n        1247, 3, 28, 14, 0, 1245, 1247, 5, 41, 0, 0, 1246, 1244, 1, 0, 0, 0, 1246, 1245, 1,\n        0, 0, 0, 1247, 1249, 1, 0, 0, 0, 1248, 1234, 1, 0, 0, 0, 1249, 1252, 1, 0, 0, 0, 1250,\n        1248, 1, 0, 0, 0, 1250, 1251, 1, 0, 0, 0, 1251, 1256, 1, 0, 0, 0, 1252, 1250, 1, 0, 0,\n        0, 1253, 1255, 5, 4, 0, 0, 1254, 1253, 1, 0, 0, 0, 1255, 1258, 1, 0, 0, 0, 1256, 1254,\n        1, 0, 0, 0, 1256, 1257, 1, 0, 0, 0, 1257, 1259, 1, 0, 0, 0, 1258, 1256, 1, 0, 0, 0, 1259,\n        1261, 5, 49, 0, 0, 1260, 1180, 1, 0, 0, 0, 1260, 1220, 1, 0, 0, 0, 1261, 81, 1, 0, 0,\n        0, 1262, 1263, 5, 28, 0, 0, 1263, 1265, 3, 64, 32, 0, 1264, 1262, 1, 0, 0, 0, 1265,\n        1266, 1, 0, 0, 0, 1266, 1264, 1, 0, 0, 0, 1266, 1267, 1, 0, 0, 0, 1267, 83, 1, 0, 0, 0,\n        1268, 1269, 7, 5, 0, 0, 1269, 85, 1, 0, 0, 0, 1270, 1274, 3, 84, 42, 0, 1271, 1273,\n        7, 0, 0, 0, 1272, 1271, 1, 0, 0, 0, 1273, 1276, 1, 0, 0, 0, 1274, 1272, 1, 0, 0, 0, 1274,\n        1275, 1, 0, 0, 0, 1275, 1277, 1, 0, 0, 0, 1276, 1274, 1, 0, 0, 0, 1277, 1281, 5, 29,\n        0, 0, 1278, 1280, 7, 0, 0, 0, 1279, 1278, 1, 0, 0, 0, 1280, 1283, 1, 0, 0, 0, 1281, 1279,\n        1, 0, 0, 0, 1281, 1282, 1, 0, 0, 0, 1282, 1284, 1, 0, 0, 0, 1283, 1281, 1, 0, 0, 0, 1284,\n        1285, 3, 28, 14, 0, 1285, 87, 1, 0, 0, 0, 1286, 1287, 7, 6, 0, 0, 1287, 89, 1, 0, 0, 0,\n        1288, 1289, 5, 40, 0, 0, 1289, 1290, 3, 88, 44, 0, 1290, 91, 1, 0, 0, 0, 1291, 1292,\n        5, 60, 0, 0, 1292, 93, 1, 0, 0, 0, 1293, 1300, 3, 96, 48, 0, 1294, 1295, 5, 4, 0, 0, 1295,\n        1296, 5, 51, 0, 0, 1296, 1297, 5, 4, 0, 0, 1297, 1299, 3, 96, 48, 0, 1298, 1294, 1,\n        0, 0, 0, 1299, 1302, 1, 0, 0, 0, 1300, 1298, 1, 0, 0, 0, 1300, 1301, 1, 0, 0, 0, 1301,\n        95, 1, 0, 0, 0, 1302, 1300, 1, 0, 0, 0, 1303, 1320, 3, 98, 49, 0, 1304, 1306, 5, 4, 0,\n        0, 1305, 1304, 1, 0, 0, 0, 1306, 1309, 1, 0, 0, 0, 1307, 1305, 1, 0, 0, 0, 1307, 1308,\n        1, 0, 0, 0, 1308, 1310, 1, 0, 0, 0, 1309, 1307, 1, 0, 0, 0, 1310, 1314, 7, 7, 0, 0, 1311,\n        1313, 5, 4, 0, 0, 1312, 1311, 1, 0, 0, 0, 1313, 1316, 1, 0, 0, 0, 1314, 1312, 1, 0, 0,\n        0, 1314, 1315, 1, 0, 0, 0, 1315, 1317, 1, 0, 0, 0, 1316, 1314, 1, 0, 0, 0, 1317, 1319,\n        3, 98, 49, 0, 1318, 1307, 1, 0, 0, 0, 1319, 1322, 1, 0, 0, 0, 1320, 1318, 1, 0, 0, 0,\n        1320, 1321, 1, 0, 0, 0, 1321, 97, 1, 0, 0, 0, 1322, 1320, 1, 0, 0, 0, 1323, 1327, 5,\n        58, 0, 0, 1324, 1326, 5, 4, 0, 0, 1325, 1324, 1, 0, 0, 0, 1326, 1329, 1, 0, 0, 0, 1327,\n        1325, 1, 0, 0, 0, 1327, 1328, 1, 0, 0, 0, 1328, 1330, 1, 0, 0, 0, 1329, 1327, 1, 0, 0,\n        0, 1330, 1331, 5, 42, 0, 0, 1331, 1335, 1, 0, 0, 0, 1332, 1334, 5, 4, 0, 0, 1333, 1332,\n        1, 0, 0, 0, 1334, 1337, 1, 0, 0, 0, 1335, 1333, 1, 0, 0, 0, 1335, 1336, 1, 0, 0, 0, 1336,\n        1338, 1, 0, 0, 0, 1337, 1335, 1, 0, 0, 0, 1338, 1341, 3, 100, 50, 0, 1339, 1340, 5,\n        4, 0, 0, 1340, 1342, 5, 53, 0, 0, 1341, 1339, 1, 0, 0, 0, 1341, 1342, 1, 0, 0, 0, 1342,\n        1345, 1, 0, 0, 0, 1343, 1344, 5, 4, 0, 0, 1344, 1346, 5, 52, 0, 0, 1345, 1343, 1, 0,\n        0, 0, 1345, 1346, 1, 0, 0, 0, 1346, 1357, 1, 0, 0, 0, 1347, 1350, 3, 100, 50, 0, 1348,\n        1349, 5, 4, 0, 0, 1349, 1351, 5, 53, 0, 0, 1350, 1348, 1, 0, 0, 0, 1350, 1351, 1, 0,\n        0, 0, 1351, 1354, 1, 0, 0, 0, 1352, 1353, 5, 4, 0, 0, 1353, 1355, 5, 52, 0, 0, 1354,\n        1352, 1, 0, 0, 0, 1354, 1355, 1, 0, 0, 0, 1355, 1357, 1, 0, 0, 0, 1356, 1323, 1, 0, 0,\n        0, 1356, 1347, 1, 0, 0, 0, 1357, 99, 1, 0, 0, 0, 1358, 1384, 3, 102, 51, 0, 1359, 1361,\n        5, 4, 0, 0, 1360, 1359, 1, 0, 0, 0, 1361, 1364, 1, 0, 0, 0, 1362, 1360, 1, 0, 0, 0, 1362,\n        1363, 1, 0, 0, 0, 1363, 1365, 1, 0, 0, 0, 1364, 1362, 1, 0, 0, 0, 1365, 1373, 5, 44,\n        0, 0, 1366, 1368, 5, 4, 0, 0, 1367, 1366, 1, 0, 0, 0, 1368, 1371, 1, 0, 0, 0, 1369, 1367,\n        1, 0, 0, 0, 1369, 1370, 1, 0, 0, 0, 1370, 1372, 1, 0, 0, 0, 1371, 1369, 1, 0, 0, 0, 1372,\n        1374, 5, 40, 0, 0, 1373, 1369, 1, 0, 0, 0, 1373, 1374, 1, 0, 0, 0, 1374, 1378, 1, 0,\n        0, 0, 1375, 1377, 5, 4, 0, 0, 1376, 1375, 1, 0, 0, 0, 1377, 1380, 1, 0, 0, 0, 1378, 1376,\n        1, 0, 0, 0, 1378, 1379, 1, 0, 0, 0, 1379, 1381, 1, 0, 0, 0, 1380, 1378, 1, 0, 0, 0, 1381,\n        1383, 7, 6, 0, 0, 1382, 1362, 1, 0, 0, 0, 1383, 1386, 1, 0, 0, 0, 1384, 1382, 1, 0, 0,\n        0, 1384, 1385, 1, 0, 0, 0, 1385, 101, 1, 0, 0, 0, 1386, 1384, 1, 0, 0, 0, 1387, 1405,\n        3, 104, 52, 0, 1388, 1392, 5, 24, 0, 0, 1389, 1391, 5, 4, 0, 0, 1390, 1389, 1, 0, 0,\n        0, 1391, 1394, 1, 0, 0, 0, 1392, 1390, 1, 0, 0, 0, 1392, 1393, 1, 0, 0, 0, 1393, 1395,\n        1, 0, 0, 0, 1394, 1392, 1, 0, 0, 0, 1395, 1399, 3, 94, 47, 0, 1396, 1398, 5, 4, 0, 0,\n        1397, 1396, 1, 0, 0, 0, 1398, 1401, 1, 0, 0, 0, 1399, 1397, 1, 0, 0, 0, 1399, 1400,\n        1, 0, 0, 0, 1400, 1402, 1, 0, 0, 0, 1401, 1399, 1, 0, 0, 0, 1402, 1403, 5, 26, 0, 0, 1403,\n        1405, 1, 0, 0, 0, 1404, 1387, 1, 0, 0, 0, 1404, 1388, 1, 0, 0, 0, 1405, 103, 1, 0, 0,\n        0, 1406, 1411, 5, 56, 0, 0, 1407, 1408, 5, 4, 0, 0, 1408, 1410, 5, 56, 0, 0, 1409, 1407,\n        1, 0, 0, 0, 1410, 1413, 1, 0, 0, 0, 1411, 1409, 1, 0, 0, 0, 1411, 1412, 1, 0, 0, 0, 1412,\n        105, 1, 0, 0, 0, 1413, 1411, 1, 0, 0, 0, 207, 109, 116, 121, 127, 130, 144, 150, 158,\n        165, 170, 176, 179, 185, 204, 211, 218, 225, 232, 236, 240, 254, 260, 270, 277,\n        281, 285, 294, 301, 305, 309, 313, 320, 322, 334, 341, 348, 355, 362, 369, 375,\n        378, 383, 390, 397, 404, 410, 413, 418, 424, 433, 441, 455, 462, 469, 476, 483,\n        490, 496, 499, 504, 511, 518, 525, 531, 534, 539, 545, 553, 557, 563, 570, 577,\n        584, 591, 598, 604, 607, 612, 619, 626, 633, 639, 642, 647, 654, 661, 667, 672,\n        679, 684, 688, 694, 701, 706, 710, 716, 723, 729, 736, 743, 749, 756, 763, 769,\n        776, 783, 789, 796, 803, 809, 816, 823, 829, 836, 843, 849, 855, 859, 865, 870,\n        876, 883, 889, 896, 901, 907, 912, 919, 921, 928, 935, 942, 948, 951, 956, 965,\n        972, 978, 989, 1003, 1012, 1021, 1028, 1035, 1041, 1044, 1049, 1057, 1064, 1071,\n        1077, 1080, 1085, 1093, 1100, 1107, 1113, 1116, 1121, 1129, 1136, 1143, 1149,\n        1152, 1157, 1161, 1167, 1174, 1178, 1184, 1189, 1194, 1201, 1206, 1210, 1216,\n        1224, 1229, 1234, 1241, 1246, 1250, 1256, 1260, 1266, 1274, 1281, 1300, 1307,\n        1314, 1320, 1327, 1335, 1341, 1345, 1350, 1354, 1356, 1362, 1369, 1373, 1378,\n        1384, 1392, 1399, 1404, 1411\n    ];\n    static __ATN;\n    static get _ATN() {\n        if (!FormulaParser.__ATN) {\n            FormulaParser.__ATN = new antlr.ATNDeserializer().deserialize(FormulaParser._serializedATN);\n        }\n        return FormulaParser.__ATN;\n    }\n    static vocabulary = new antlr.Vocabulary(FormulaParser.literalNames, FormulaParser.symbolicNames, []);\n    get vocabulary() {\n        return FormulaParser.vocabulary;\n    }\n    static decisionsToDFA = FormulaParser._ATN.decisionToState.map((ds, index) => new antlr.DFA(ds, index));\n}\nexport class LinesContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    EOF() {\n        return this.getToken(FormulaParser.EOF, 0);\n    }\n    expression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(ExpressionContext);\n        }\n        return this.getRuleContext(i, ExpressionContext);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_lines;\n    }\n}\nexport class ExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    assignment() {\n        return this.getRuleContext(0, AssignmentContext);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    whileLoop() {\n        return this.getRuleContext(0, WhileLoopContext);\n    }\n    forLoop() {\n        return this.getRuleContext(0, ForLoopContext);\n    }\n    forInLoop() {\n        return this.getRuleContext(0, ForInLoopContext);\n    }\n    ifThenElse() {\n        return this.getRuleContext(0, IfThenElseContext);\n    }\n    functionDef() {\n        return this.getRuleContext(0, FunctionDefContext);\n    }\n    returnExp() {\n        return this.getRuleContext(0, ReturnExpContext);\n    }\n    tryCatch() {\n        return this.getRuleContext(0, TryCatchContext);\n    }\n    throwExp() {\n        return this.getRuleContext(0, ThrowExpContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_expression;\n    }\n}\nexport class ReturnExpContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    RETURNSTATEMENT() {\n        return this.getToken(FormulaParser.RETURNSTATEMENT, 0);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_returnExp;\n    }\n}\nexport class InnerBlockContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    expression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(ExpressionContext);\n        }\n        return this.getRuleContext(i, ExpressionContext);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_innerBlock;\n    }\n}\nexport class WhileLoopContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    WHILESTATEMENT() {\n        return this.getToken(FormulaParser.WHILESTATEMENT, 0);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    LOOPSTATEMENT() {\n        return this.getToken(FormulaParser.LOOPSTATEMENT, 0);\n    }\n    innerBlock() {\n        return this.getRuleContext(0, InnerBlockContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_whileLoop;\n    }\n}\nexport class ForLoopContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    FORSTATEMENT() {\n        return this.getToken(FormulaParser.FORSTATEMENT, 0);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    FROMSTATEMENT() {\n        return this.getToken(FormulaParser.FROMSTATEMENT, 0);\n    }\n    logicalExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(LogicalExpressionContext);\n        }\n        return this.getRuleContext(i, LogicalExpressionContext);\n    }\n    TOSTATEMENT() {\n        return this.getToken(FormulaParser.TOSTATEMENT, 0);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    LOOPSTATEMENT() {\n        return this.getToken(FormulaParser.LOOPSTATEMENT, 0);\n    }\n    BYSTATEMENT() {\n        return this.getToken(FormulaParser.BYSTATEMENT, 0);\n    }\n    innerBlock() {\n        return this.getRuleContext(0, InnerBlockContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_forLoop;\n    }\n}\nexport class ForInLoopContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    FORSTATEMENT() {\n        return this.getToken(FormulaParser.FORSTATEMENT, 0);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    INSTATEMENT() {\n        return this.getToken(FormulaParser.INSTATEMENT, 0);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    LOOPSTATEMENT() {\n        return this.getToken(FormulaParser.LOOPSTATEMENT, 0);\n    }\n    innerBlock() {\n        return this.getRuleContext(0, InnerBlockContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_forInLoop;\n    }\n}\nexport class IfThenElseContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IFSTATEMENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.IFSTATEMENT);\n        }\n        else {\n            return this.getToken(FormulaParser.IFSTATEMENT, i);\n        }\n    }\n    logicalExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(LogicalExpressionContext);\n        }\n        return this.getRuleContext(i, LogicalExpressionContext);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    THENSTATEMENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.THENSTATEMENT);\n        }\n        else {\n            return this.getToken(FormulaParser.THENSTATEMENT, i);\n        }\n    }\n    innerBlock(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(InnerBlockContext);\n        }\n        return this.getRuleContext(i, InnerBlockContext);\n    }\n    ELSESTATEMENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.ELSESTATEMENT);\n        }\n        else {\n            return this.getToken(FormulaParser.ELSESTATEMENT, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_ifThenElse;\n    }\n}\nexport class FunctionDefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    FUNCTIONSTATEMENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.FUNCTIONSTATEMENT);\n        }\n        else {\n            return this.getToken(FormulaParser.FUNCTIONSTATEMENT, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    IDENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.IDENT);\n        }\n        else {\n            return this.getToken(FormulaParser.IDENT, i);\n        }\n    }\n    LPAREN() {\n        return this.getToken(FormulaParser.LPAREN, 0);\n    }\n    RPAREN() {\n        return this.getToken(FormulaParser.RPAREN, 0);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    innerBlock() {\n        return this.getRuleContext(0, InnerBlockContext);\n    }\n    EQUALS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.EQUALS);\n        }\n        else {\n            return this.getToken(FormulaParser.EQUALS, i);\n        }\n    }\n    defaultValue(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(DefaultValueContext);\n        }\n        return this.getRuleContext(i, DefaultValueContext);\n    }\n    COMMA(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COMMA);\n        }\n        else {\n            return this.getToken(FormulaParser.COMMA, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_functionDef;\n    }\n}\nexport class TryCatchContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    TRYSTATEMENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.TRYSTATEMENT);\n        }\n        else {\n            return this.getToken(FormulaParser.TRYSTATEMENT, i);\n        }\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    CATCHSTATEMENT() {\n        return this.getToken(FormulaParser.CATCHSTATEMENT, 0);\n    }\n    R_() {\n        return this.getToken(FormulaParser.R_, 0);\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    innerBlock(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(InnerBlockContext);\n        }\n        return this.getRuleContext(i, InnerBlockContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_tryCatch;\n    }\n}\nexport class ThrowExpContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    THROWSTATEMENT() {\n        return this.getToken(FormulaParser.THROWSTATEMENT, 0);\n    }\n    R_() {\n        return this.getToken(FormulaParser.R_, 0);\n    }\n    primaryExpression() {\n        return this.getRuleContext(0, PrimaryExpressionContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_throwExp;\n    }\n}\nexport class AnonFunctionDefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    FUNCTIONSTATEMENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.FUNCTIONSTATEMENT);\n        }\n        else {\n            return this.getToken(FormulaParser.FUNCTIONSTATEMENT, i);\n        }\n    }\n    LPAREN() {\n        return this.getToken(FormulaParser.LPAREN, 0);\n    }\n    RPAREN() {\n        return this.getToken(FormulaParser.RPAREN, 0);\n    }\n    expression() {\n        return this.getRuleContext(0, ExpressionContext);\n    }\n    IDENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.IDENT);\n        }\n        else {\n            return this.getToken(FormulaParser.IDENT, i);\n        }\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    ENDPREFIX() {\n        return this.getToken(FormulaParser.ENDPREFIX, 0);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    EQUALS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.EQUALS);\n        }\n        else {\n            return this.getToken(FormulaParser.EQUALS, i);\n        }\n    }\n    defaultValue(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(DefaultValueContext);\n        }\n        return this.getRuleContext(i, DefaultValueContext);\n    }\n    COMMA(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COMMA);\n        }\n        else {\n            return this.getToken(FormulaParser.COMMA, i);\n        }\n    }\n    innerBlock() {\n        return this.getRuleContext(0, InnerBlockContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_anonFunctionDef;\n    }\n}\nexport class AssignmentContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.IDENT);\n        }\n        else {\n            return this.getToken(FormulaParser.IDENT, i);\n        }\n    }\n    LPAREN() {\n        return this.getToken(FormulaParser.LPAREN, 0);\n    }\n    RPAREN() {\n        return this.getToken(FormulaParser.RPAREN, 0);\n    }\n    ASSIGN() {\n        return this.getToken(FormulaParser.ASSIGN, 0);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    EQUALS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.EQUALS);\n        }\n        else {\n            return this.getToken(FormulaParser.EQUALS, i);\n        }\n    }\n    defaultValue(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(DefaultValueContext);\n        }\n        return this.getRuleContext(i, DefaultValueContext);\n    }\n    COMMA(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COMMA);\n        }\n        else {\n            return this.getToken(FormulaParser.COMMA, i);\n        }\n    }\n    primitiveRef(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(PrimitiveRefContext);\n        }\n        return this.getRuleContext(i, PrimitiveRefContext);\n    }\n    assigned(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(AssignedContext);\n        }\n        return this.getRuleContext(i, AssignedContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_assignment;\n    }\n}\nexport class AssignedContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    selector() {\n        return this.getRuleContext(0, SelectorContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_assigned;\n    }\n}\nexport class LogicalExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    booleanXORExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(BooleanXORExpressionContext);\n        }\n        return this.getRuleContext(i, BooleanXORExpressionContext);\n    }\n    OR(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.OR);\n        }\n        else {\n            return this.getToken(FormulaParser.OR, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_logicalExpression;\n    }\n}\nexport class BooleanXORExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    booleanAndExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(BooleanAndExpressionContext);\n        }\n        return this.getRuleContext(i, BooleanAndExpressionContext);\n    }\n    XOR(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.XOR);\n        }\n        else {\n            return this.getToken(FormulaParser.XOR, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_booleanXORExpression;\n    }\n}\nexport class BooleanAndExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    equalityExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(EqualityExpressionContext);\n        }\n        return this.getRuleContext(i, EqualityExpressionContext);\n    }\n    AND(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.AND);\n        }\n        else {\n            return this.getToken(FormulaParser.AND, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_booleanAndExpression;\n    }\n}\nexport class EqualityExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    relationalExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(RelationalExpressionContext);\n        }\n        return this.getRuleContext(i, RelationalExpressionContext);\n    }\n    EQUALS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.EQUALS);\n        }\n        else {\n            return this.getToken(FormulaParser.EQUALS, i);\n        }\n    }\n    NOTEQUALS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.NOTEQUALS);\n        }\n        else {\n            return this.getToken(FormulaParser.NOTEQUALS, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_equalityExpression;\n    }\n}\nexport class RelationalExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    additiveExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(AdditiveExpressionContext);\n        }\n        return this.getRuleContext(i, AdditiveExpressionContext);\n    }\n    LT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.LT);\n        }\n        else {\n            return this.getToken(FormulaParser.LT, i);\n        }\n    }\n    LTEQ(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.LTEQ);\n        }\n        else {\n            return this.getToken(FormulaParser.LTEQ, i);\n        }\n    }\n    GT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.GT);\n        }\n        else {\n            return this.getToken(FormulaParser.GT, i);\n        }\n    }\n    GTEQ(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.GTEQ);\n        }\n        else {\n            return this.getToken(FormulaParser.GTEQ, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_relationalExpression;\n    }\n}\nexport class AdditiveExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    multiplicativeExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(MultiplicativeExpressionContext);\n        }\n        return this.getRuleContext(i, MultiplicativeExpressionContext);\n    }\n    PLUS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.PLUS);\n        }\n        else {\n            return this.getToken(FormulaParser.PLUS, i);\n        }\n    }\n    MINUS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.MINUS);\n        }\n        else {\n            return this.getToken(FormulaParser.MINUS, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_additiveExpression;\n    }\n}\nexport class MultiplicativeExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    arrayExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(ArrayExpressionContext);\n        }\n        return this.getRuleContext(i, ArrayExpressionContext);\n    }\n    MULT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.MULT);\n        }\n        else {\n            return this.getToken(FormulaParser.MULT, i);\n        }\n    }\n    DIV(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.DIV);\n        }\n        else {\n            return this.getToken(FormulaParser.DIV, i);\n        }\n    }\n    MOD(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.MOD);\n        }\n        else {\n            return this.getToken(FormulaParser.MOD, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_multiplicativeExpression;\n    }\n}\nexport class ArrayExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    negationExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(NegationExpressionContext);\n        }\n        return this.getRuleContext(i, NegationExpressionContext);\n    }\n    COLON(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COLON);\n        }\n        else {\n            return this.getToken(FormulaParser.COLON, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_arrayExpression;\n    }\n}\nexport class NegationExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    MINUS() {\n        return this.getToken(FormulaParser.MINUS, 0);\n    }\n    powerExpression() {\n        return this.getRuleContext(0, PowerExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_negationExpression;\n    }\n}\nexport class PowerExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    unaryExpression() {\n        return this.getRuleContext(0, UnaryExpressionContext);\n    }\n    POW(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.POW);\n        }\n        else {\n            return this.getToken(FormulaParser.POW, i);\n        }\n    }\n    unaryOrNegate(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(UnaryOrNegateContext);\n        }\n        return this.getRuleContext(i, UnaryOrNegateContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_powerExpression;\n    }\n}\nexport class UnaryOrNegateContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    MINUS() {\n        return this.getToken(FormulaParser.MINUS, 0);\n    }\n    unaryExpression() {\n        return this.getRuleContext(0, UnaryExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unaryOrNegate;\n    }\n}\nexport class UnaryExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    NOT() {\n        return this.getToken(FormulaParser.NOT, 0);\n    }\n    innerPrimaryExpression() {\n        return this.getRuleContext(0, InnerPrimaryExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unaryExpression;\n    }\n}\nexport class InnerPrimaryExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    selectionExpression() {\n        return this.getRuleContext(0, SelectionExpressionContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_innerPrimaryExpression;\n    }\n}\nexport class SelectionExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    primaryExpression() {\n        return this.getRuleContext(0, PrimaryExpressionContext);\n    }\n    selector(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(SelectorContext);\n        }\n        return this.getRuleContext(i, SelectorContext);\n    }\n    funCall(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(FunCallContext);\n        }\n        return this.getRuleContext(i, FunCallContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_selectionExpression;\n    }\n}\nexport class FunCallContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    LPAREN() {\n        return this.getToken(FormulaParser.LPAREN, 0);\n    }\n    RPAREN() {\n        return this.getToken(FormulaParser.RPAREN, 0);\n    }\n    logicalExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(LogicalExpressionContext);\n        }\n        return this.getRuleContext(i, LogicalExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    COMMA(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COMMA);\n        }\n        else {\n            return this.getToken(FormulaParser.COMMA, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_funCall;\n    }\n}\nexport class PrimaryExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    LPAREN() {\n        return this.getToken(FormulaParser.LPAREN, 0);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    RPAREN() {\n        return this.getToken(FormulaParser.RPAREN, 0);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    value() {\n        return this.getRuleContext(0, ValueContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_primaryExpression;\n    }\n}\nexport class ValueContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    number() {\n        return this.getRuleContext(0, NumberContext);\n    }\n    BOOL() {\n        return this.getToken(FormulaParser.BOOL, 0);\n    }\n    string() {\n        return this.getRuleContext(0, StringContext);\n    }\n    material() {\n        return this.getRuleContext(0, MaterialContext);\n    }\n    symbolRef() {\n        return this.getRuleContext(0, SymbolRefContext);\n    }\n    primitiveRef() {\n        return this.getRuleContext(0, PrimitiveRefContext);\n    }\n    array() {\n        return this.getRuleContext(0, ArrayContext);\n    }\n    anonFunctionDef() {\n        return this.getRuleContext(0, AnonFunctionDefContext);\n    }\n    newObject() {\n        return this.getRuleContext(0, NewObjectContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_value;\n    }\n}\nexport class SymbolRefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_symbolRef;\n    }\n}\nexport class MemberSymbolRefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    STRING() {\n        return this.getToken(FormulaParser.STRING, 0);\n    }\n    MULT() {\n        return this.getToken(FormulaParser.MULT, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_memberSymbolRef;\n    }\n}\nexport class PrimitiveRefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    PRIMITIVE() {\n        return this.getToken(FormulaParser.PRIMITIVE, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_primitiveRef;\n    }\n}\nexport class TypeRefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_typeRef;\n    }\n}\nexport class MaterialContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    LCURL() {\n        return this.getToken(FormulaParser.LCURL, 0);\n    }\n    additiveExpression() {\n        return this.getRuleContext(0, AdditiveExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    unitMultiplicativeExpression() {\n        return this.getRuleContext(0, UnitMultiplicativeExpressionContext);\n    }\n    RCURL() {\n        return this.getToken(FormulaParser.RCURL, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_material;\n    }\n}\nexport class ArrayContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    LARR() {\n        return this.getToken(FormulaParser.LARR, 0);\n    }\n    RARR() {\n        return this.getToken(FormulaParser.RARR, 0);\n    }\n    label(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(LabelContext);\n        }\n        return this.getRuleContext(i, LabelContext);\n    }\n    COMMA(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COMMA);\n        }\n        else {\n            return this.getToken(FormulaParser.COMMA, i);\n        }\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    LCURL() {\n        return this.getToken(FormulaParser.LCURL, 0);\n    }\n    RCURL() {\n        return this.getToken(FormulaParser.RCURL, 0);\n    }\n    logicalExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(LogicalExpressionContext);\n        }\n        return this.getRuleContext(i, LogicalExpressionContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_array;\n    }\n}\nexport class NewObjectContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    NEWSTATEMENT() {\n        return this.getToken(FormulaParser.NEWSTATEMENT, 0);\n    }\n    R_() {\n        return this.getToken(FormulaParser.R_, 0);\n    }\n    typeRef() {\n        return this.getRuleContext(0, TypeRefContext);\n    }\n    funCall() {\n        return this.getRuleContext(0, FunCallContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_newObject;\n    }\n}\nexport class DefaultValueContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    negnumber() {\n        return this.getRuleContext(0, NegnumberContext);\n    }\n    number() {\n        return this.getRuleContext(0, NumberContext);\n    }\n    BOOL() {\n        return this.getToken(FormulaParser.BOOL, 0);\n    }\n    string() {\n        return this.getRuleContext(0, StringContext);\n    }\n    array() {\n        return this.getRuleContext(0, ArrayContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_defaultValue;\n    }\n}\nexport class SelectorContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    minarray() {\n        return this.getRuleContext(0, MinarrayContext);\n    }\n    dotselector() {\n        return this.getRuleContext(0, DotselectorContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_selector;\n    }\n}\nexport class MinarrayContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    LARR() {\n        return this.getToken(FormulaParser.LARR, 0);\n    }\n    RARR() {\n        return this.getToken(FormulaParser.RARR, 0);\n    }\n    logicalExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(LogicalExpressionContext);\n        }\n        return this.getRuleContext(i, LogicalExpressionContext);\n    }\n    MULT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.MULT);\n        }\n        else {\n            return this.getToken(FormulaParser.MULT, i);\n        }\n    }\n    COMMA(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.COMMA);\n        }\n        else {\n            return this.getToken(FormulaParser.COMMA, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    LCURL() {\n        return this.getToken(FormulaParser.LCURL, 0);\n    }\n    RCURL() {\n        return this.getToken(FormulaParser.RCURL, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_minarray;\n    }\n}\nexport class DotselectorContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    DOT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.DOT);\n        }\n        else {\n            return this.getToken(FormulaParser.DOT, i);\n        }\n    }\n    memberSymbolRef(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(MemberSymbolRefContext);\n        }\n        return this.getRuleContext(i, MemberSymbolRefContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_dotselector;\n    }\n}\nexport class ArrayNameContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT() {\n        return this.getToken(FormulaParser.IDENT, 0);\n    }\n    STRING() {\n        return this.getToken(FormulaParser.STRING, 0);\n    }\n    MULT() {\n        return this.getToken(FormulaParser.MULT, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_arrayName;\n    }\n}\nexport class LabelContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    arrayName() {\n        return this.getRuleContext(0, ArrayNameContext);\n    }\n    COLON() {\n        return this.getToken(FormulaParser.COLON, 0);\n    }\n    logicalExpression() {\n        return this.getRuleContext(0, LogicalExpressionContext);\n    }\n    R__(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R__);\n        }\n        else {\n            return this.getToken(FormulaParser.R__, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_label;\n    }\n}\nexport class NumberContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    INTEGER() {\n        return this.getToken(FormulaParser.INTEGER, 0);\n    }\n    FLOAT() {\n        return this.getToken(FormulaParser.FLOAT, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_number;\n    }\n}\nexport class NegnumberContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    MINUS() {\n        return this.getToken(FormulaParser.MINUS, 0);\n    }\n    number() {\n        return this.getRuleContext(0, NumberContext);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_negnumber;\n    }\n}\nexport class StringContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    STRING() {\n        return this.getToken(FormulaParser.STRING, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_string;\n    }\n}\nexport class UnitMultiplicativeExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    unitInnerMultiplicativeExpression(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(UnitInnerMultiplicativeExpressionContext);\n        }\n        return this.getRuleContext(i, UnitInnerMultiplicativeExpressionContext);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    PER(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.PER);\n        }\n        else {\n            return this.getToken(FormulaParser.PER, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unitMultiplicativeExpression;\n    }\n}\nexport class UnitInnerMultiplicativeExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    unitClump(i) {\n        if (i === undefined) {\n            return this.getRuleContexts(UnitClumpContext);\n        }\n        return this.getRuleContext(i, UnitClumpContext);\n    }\n    MULT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.MULT);\n        }\n        else {\n            return this.getToken(FormulaParser.MULT, i);\n        }\n    }\n    DIV(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.DIV);\n        }\n        else {\n            return this.getToken(FormulaParser.DIV, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unitInnerMultiplicativeExpression;\n    }\n}\nexport class UnitClumpContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    unitPowerExpression() {\n        return this.getRuleContext(0, UnitPowerExpressionContext);\n    }\n    INTEGER() {\n        return this.getToken(FormulaParser.INTEGER, 0);\n    }\n    DIV() {\n        return this.getToken(FormulaParser.DIV, 0);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    CUBED() {\n        return this.getToken(FormulaParser.CUBED, 0);\n    }\n    SQUARED() {\n        return this.getToken(FormulaParser.SQUARED, 0);\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unitClump;\n    }\n}\nexport class UnitPowerExpressionContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    unit() {\n        return this.getRuleContext(0, UnitContext);\n    }\n    POW(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.POW);\n        }\n        else {\n            return this.getToken(FormulaParser.POW, i);\n        }\n    }\n    INTEGER(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.INTEGER);\n        }\n        else {\n            return this.getToken(FormulaParser.INTEGER, i);\n        }\n    }\n    FLOAT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.FLOAT);\n        }\n        else {\n            return this.getToken(FormulaParser.FLOAT, i);\n        }\n    }\n    MINUS(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.MINUS);\n        }\n        else {\n            return this.getToken(FormulaParser.MINUS, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unitPowerExpression;\n    }\n}\nexport class UnitContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    unitRef() {\n        return this.getRuleContext(0, UnitRefContext);\n    }\n    LPAREN() {\n        return this.getToken(FormulaParser.LPAREN, 0);\n    }\n    unitMultiplicativeExpression() {\n        return this.getRuleContext(0, UnitMultiplicativeExpressionContext);\n    }\n    RPAREN() {\n        return this.getToken(FormulaParser.RPAREN, 0);\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unit;\n    }\n}\nexport class UnitRefContext extends antlr.ParserRuleContext {\n    constructor(parent, invokingState) {\n        super(parent, invokingState);\n    }\n    IDENT(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.IDENT);\n        }\n        else {\n            return this.getToken(FormulaParser.IDENT, i);\n        }\n    }\n    R_(i) {\n        if (i === undefined) {\n            return this.getTokens(FormulaParser.R_);\n        }\n        else {\n            return this.getToken(FormulaParser.R_, i);\n        }\n    }\n    get ruleIndex() {\n        return FormulaParser.RULE_unitRef;\n    }\n}\n", "src/formula/grammar/FormulaLexer.js": "// eslint-disable\n// @ts-nocheck\n\nimport * as antlr from \"../../../vendor/antlr4ng-all.js\";\nexport class FormulaLexer extends antlr.Lexer {\n    static COMMENT = 1;\n    static LINE_COMMENT = 2;\n    static R__ = 3;\n    static R_ = 4;\n    static NEWLINES = 5;\n    static WHILESTATEMENT = 6;\n    static FORSTATEMENT = 7;\n    static FROMSTATEMENT = 8;\n    static INSTATEMENT = 9;\n    static TOSTATEMENT = 10;\n    static BYSTATEMENT = 11;\n    static LOOPSTATEMENT = 12;\n    static IFSTATEMENT = 13;\n    static THENSTATEMENT = 14;\n    static ELSESTATEMENT = 15;\n    static FUNCTIONSTATEMENT = 16;\n    static ENDPREFIX = 17;\n    static ENDBLOCK = 18;\n    static RETURNSTATEMENT = 19;\n    static NEWSTATEMENT = 20;\n    static TRYSTATEMENT = 21;\n    static CATCHSTATEMENT = 22;\n    static THROWSTATEMENT = 23;\n    static LPAREN = 24;\n    static COMMA = 25;\n    static RPAREN = 26;\n    static ASSIGN = 27;\n    static DOT = 28;\n    static COLON = 29;\n    static OR = 30;\n    static XOR = 31;\n    static AND = 32;\n    static EQUALS = 33;\n    static NOTEQUALS = 34;\n    static LT = 35;\n    static LTEQ = 36;\n    static GT = 37;\n    static GTEQ = 38;\n    static PLUS = 39;\n    static MINUS = 40;\n    static MULT = 41;\n    static DIV = 42;\n    static MOD = 43;\n    static POW = 44;\n    static NOT = 45;\n    static LARR = 46;\n    static RARR = 47;\n    static LCURL = 48;\n    static RCURL = 49;\n    static BOOL = 50;\n    static PER = 51;\n    static SQUARED = 52;\n    static CUBED = 53;\n    static LBRACKET = 54;\n    static RBRACKET = 55;\n    static IDENT = 56;\n    static PRIMITIVE = 57;\n    static INTEGER = 58;\n    static FLOAT = 59;\n    static STRING = 60;\n    static channelNames = [\n        \"DEFAULT_TOKEN_CHANNEL\", \"HIDDEN\"\n    ];\n    static literalNames = [\n        null, null, null, null, null, null, \"'while'\", \"'for'\", \"'from'\",\n        \"'in'\", \"'to'\", \"'by'\", \"'loop'\", \"'if'\", \"'then'\", \"'else'\", \"'function'\",\n        null, \"'end'\", \"'return'\", \"'new'\", \"'try'\", \"'catch'\", \"'throw'\",\n        \"'('\", \"','\", \"')'\", \"'<-'\", \"'.'\", \"':'\", null, \"'xor'\", null,\n        null, null, \"'<'\", \"'<='\", \"'>'\", \"'>='\", \"'+'\", \"'-'\", \"'*'\", \"'/'\",\n        null, \"'^'\", null, null, null, \"'{'\", \"'}'\", null, \"'per'\", \"'squared'\",\n        \"'cubed'\", \"'['\", \"']'\"\n    ];\n    static symbolicNames = [\n        null, \"COMMENT\", \"LINE_COMMENT\", \"R__\", \"R_\", \"NEWLINES\", \"WHILESTATEMENT\",\n        \"FORSTATEMENT\", \"FROMSTATEMENT\", \"INSTATEMENT\", \"TOSTATEMENT\", \"BYSTATEMENT\",\n        \"LOOPSTATEMENT\", \"IFSTATEMENT\", \"THENSTATEMENT\", \"ELSESTATEMENT\",\n        \"FUNCTIONSTATEMENT\", \"ENDPREFIX\", \"ENDBLOCK\", \"RETURNSTATEMENT\",\n        \"NEWSTATEMENT\", \"TRYSTATEMENT\", \"CATCHSTATEMENT\", \"THROWSTATEMENT\",\n        \"LPAREN\", \"COMMA\", \"RPAREN\", \"ASSIGN\", \"DOT\", \"COLON\", \"OR\", \"XOR\",\n        \"AND\", \"EQUALS\", \"NOTEQUALS\", \"LT\", \"LTEQ\", \"GT\", \"GTEQ\", \"PLUS\",\n        \"MINUS\", \"MULT\", \"DIV\", \"MOD\", \"POW\", \"NOT\", \"LARR\", \"RARR\", \"LCURL\",\n        \"RCURL\", \"BOOL\", \"PER\", \"SQUARED\", \"CUBED\", \"LBRACKET\", \"RBRACKET\",\n        \"IDENT\", \"PRIMITIVE\", \"INTEGER\", \"FLOAT\", \"STRING\"\n    ];\n    static modeNames = [\n        \"DEFAULT_MODE\",\n    ];\n    static ruleNames = [\n        \"COMMENT\", \"LINE_COMMENT\", \"SPACE\", \"R__\", \"R_\", \"NEWLINES\", \"WHILESTATEMENT\",\n        \"FORSTATEMENT\", \"FROMSTATEMENT\", \"INSTATEMENT\", \"TOSTATEMENT\", \"BYSTATEMENT\",\n        \"LOOPSTATEMENT\", \"IFSTATEMENT\", \"THENSTATEMENT\", \"ELSESTATEMENT\",\n        \"FUNCTIONSTATEMENT\", \"ENDPREFIX\", \"ENDBLOCK\", \"RETURNSTATEMENT\",\n        \"NEWSTATEMENT\", \"TRYSTATEMENT\", \"CATCHSTATEMENT\", \"THROWSTATEMENT\",\n        \"LPAREN\", \"COMMA\", \"RPAREN\", \"ASSIGN\", \"DOT\", \"COLON\", \"OR\", \"XOR\",\n        \"AND\", \"EQUALS\", \"NOTEQUALS\", \"LT\", \"LTEQ\", \"GT\", \"GTEQ\", \"PLUS\",\n        \"MINUS\", \"MULT\", \"DIV\", \"MOD\", \"POW\", \"NOT\", \"LARR\", \"RARR\", \"LCURL\",\n        \"RCURL\", \"BOOL\", \"PER\", \"SQUARED\", \"CUBED\", \"LBRACKET\", \"RBRACKET\",\n        \"IDENT\", \"PRIMITIVE\", \"INTEGER\", \"FLOAT\", \"STRING\",\n    ];\n    constructor(input) {\n        super(input);\n        this.interpreter = new antlr.LexerATNSimulator(this, FormulaLexer._ATN, FormulaLexer.decisionsToDFA, new antlr.PredictionContextCache());\n    }\n    get grammarFileName() { return \"Formula.g\"; }\n    get literalNames() { return FormulaLexer.literalNames; }\n    get symbolicNames() { return FormulaLexer.symbolicNames; }\n    get ruleNames() { return FormulaLexer.ruleNames; }\n    get serializedATN() { return FormulaLexer._serializedATN; }\n    get channelNames() { return FormulaLexer.channelNames; }\n    get modeNames() { return FormulaLexer.modeNames; }\n    static _serializedATN = [\n        4, 0, 60, 495, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5,\n        2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2,\n        13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7,\n        19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2,\n        26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7,\n        32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2,\n        39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7,\n        45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2,\n        52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7,\n        58, 2, 59, 7, 59, 2, 60, 7, 60, 1, 0, 3, 0, 125, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 131, 8,\n        0, 10, 0, 12, 0, 134, 9, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 140, 8, 0, 1, 0, 1, 0, 1, 1, 3, 1,\n        145, 8, 1, 1, 1, 1, 1, 1, 1, 3, 1, 150, 8, 1, 1, 1, 5, 1, 153, 8, 1, 10, 1, 12, 1, 156, 9,\n        1, 1, 1, 3, 1, 159, 8, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 5, 3, 166, 8, 3, 10, 3, 12, 3, 169,\n        9, 3, 1, 3, 1, 3, 5, 3, 173, 8, 3, 10, 3, 12, 3, 176, 9, 3, 4, 3, 178, 8, 3, 11, 3, 12, 3,\n        179, 1, 4, 4, 4, 183, 8, 4, 11, 4, 12, 4, 184, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1,\n        6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10,\n        1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14,\n        1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16,\n        1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 4, 17, 245, 8, 17, 11, 17,\n        12, 17, 246, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19,\n        1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22,\n        1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26,\n        1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 297,\n        8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 308, 8, 32,\n        1, 33, 1, 33, 1, 33, 3, 33, 313, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 319, 8, 34, 1,\n        35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 40, 1,\n        40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 343, 8, 43, 1, 44, 1,\n        44, 1, 45, 1, 45, 1, 45, 1, 45, 3, 45, 351, 8, 45, 1, 46, 1, 46, 1, 46, 3, 46, 356, 8, 46,\n        1, 47, 1, 47, 1, 47, 3, 47, 361, 8, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50,\n        1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 376, 8, 50, 1, 51, 1, 51, 1, 51, 1, 51,\n        1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53,\n        1, 53, 1, 54, 1, 54, 1, 55, 1, 55, 1, 56, 1, 56, 5, 56, 402, 8, 56, 10, 56, 12, 56, 405,\n        9, 56, 1, 57, 1, 57, 4, 57, 409, 8, 57, 11, 57, 12, 57, 410, 1, 57, 1, 57, 1, 57, 1, 57,\n        1, 57, 4, 57, 418, 8, 57, 11, 57, 12, 57, 419, 1, 57, 1, 57, 1, 57, 3, 57, 425, 8, 57,\n        1, 58, 4, 58, 428, 8, 58, 11, 58, 12, 58, 429, 1, 58, 1, 58, 3, 58, 434, 8, 58, 1, 58,\n        5, 58, 437, 8, 58, 10, 58, 12, 58, 440, 9, 58, 3, 58, 442, 8, 58, 1, 59, 5, 59, 445, 8,\n        59, 10, 59, 12, 59, 448, 9, 59, 1, 59, 1, 59, 4, 59, 452, 8, 59, 11, 59, 12, 59, 453,\n        1, 59, 4, 59, 457, 8, 59, 11, 59, 12, 59, 458, 1, 59, 3, 59, 462, 8, 59, 1, 59, 1, 59,\n        3, 59, 466, 8, 59, 1, 59, 5, 59, 469, 8, 59, 10, 59, 12, 59, 472, 9, 59, 3, 59, 474, 8,\n        59, 1, 60, 1, 60, 5, 60, 478, 8, 60, 10, 60, 12, 60, 481, 9, 60, 1, 60, 1, 60, 1, 60, 1,\n        60, 1, 60, 5, 60, 488, 8, 60, 10, 60, 12, 60, 491, 9, 60, 1, 60, 3, 60, 494, 8, 60, 4,\n        132, 410, 419, 479, 0, 61, 1, 1, 3, 2, 5, 0, 7, 3, 9, 4, 11, 5, 13, 6, 15, 7, 17, 8, 19,\n        9, 21, 10, 23, 11, 25, 12, 27, 13, 29, 14, 31, 15, 33, 16, 35, 17, 37, 18, 39, 19, 41,\n        20, 43, 21, 45, 22, 47, 23, 49, 24, 51, 25, 53, 26, 55, 27, 57, 28, 59, 29, 61, 30, 63,\n        31, 65, 32, 67, 33, 69, 34, 71, 35, 73, 36, 75, 37, 77, 38, 79, 39, 81, 40, 83, 41, 85,\n        42, 87, 43, 89, 44, 91, 45, 93, 46, 95, 47, 97, 48, 99, 49, 101, 50, 103, 51, 105, 52,\n        107, 53, 109, 54, 111, 55, 113, 56, 115, 57, 117, 58, 119, 59, 121, 60, 1, 0, 28, 2,\n        0, 10, 10, 13, 13, 3, 0, 9, 9, 12, 12, 32, 32, 2, 0, 87, 87, 119, 119, 2, 0, 72, 72, 104,\n        104, 2, 0, 73, 73, 105, 105, 2, 0, 76, 76, 108, 108, 2, 0, 69, 69, 101, 101, 2, 0, 70,\n        70, 102, 102, 2, 0, 79, 79, 111, 111, 2, 0, 82, 82, 114, 114, 2, 0, 77, 77, 109, 109,\n        2, 0, 78, 78, 110, 110, 2, 0, 84, 84, 116, 116, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121,\n        121, 2, 0, 80, 80, 112, 112, 2, 0, 83, 83, 115, 115, 2, 0, 85, 85, 117, 117, 2, 0, 67,\n        67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 65, 65, 97, 97, 2, 0, 88, 88, 120, 120, 2, 0,\n        81, 81, 113, 113, 677, 0, 65, 90, 97, 122, 170, 170, 181, 181, 186, 186, 192, 214,\n        216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887,\n        890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153,\n        1162, 1327, 1329, 1366, 1369, 1369, 1376, 1416, 1488, 1514, 1519, 1522, 1568,\n        1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788,\n        1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036,\n        2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136,\n        2144, 2154, 2160, 2183, 2185, 2190, 2208, 2249, 2308, 2361, 2365, 2365, 2384,\n        2384, 2392, 2401, 2417, 2432, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480,\n        2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544,\n        2545, 2556, 2556, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611,\n        2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703,\n        2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768,\n        2784, 2785, 2809, 2809, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866,\n        2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947,\n        2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979,\n        2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112,\n        3114, 3129, 3133, 3133, 3160, 3162, 3165, 3165, 3168, 3169, 3200, 3200, 3205,\n        3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3293, 3294,\n        3296, 3297, 3313, 3314, 3332, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406,\n        3406, 3412, 3414, 3423, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515,\n        3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716,\n        3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3760, 3762, 3763, 3773, 3773,\n        3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976,\n        3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,\n        4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304,\n        4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744,\n        4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808,\n        4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5109, 5112, 5117,\n        5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5873, 5880, 5888, 5905, 5919,\n        5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108,\n        6176, 6264, 6272, 6276, 6279, 6312, 6314, 6314, 6320, 6389, 6400, 6430, 6480,\n        6509, 6512, 6516, 6528, 6571, 6576, 6601, 6656, 6678, 6688, 6740, 6823, 6823,\n        6917, 6963, 6981, 6988, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245,\n        7247, 7258, 7293, 7296, 7306, 7312, 7354, 7357, 7359, 7401, 7404, 7406, 7411,\n        7413, 7414, 7418, 7418, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008,\n        8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116,\n        8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160,\n        8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450,\n        8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488,\n        8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8579, 8580,\n        11264, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565,\n        11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,\n        11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736,\n        11742, 11823, 11823, 12293, 12294, 12337, 12341, 12347, 12348, 12353, 12438,\n        12445, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704,\n        12735, 12784, 12799, 13312, 19903, 19968, 42124, 42192, 42237, 42240, 42508,\n        42512, 42527, 42538, 42539, 42560, 42606, 42623, 42653, 42656, 42725, 42775,\n        42783, 42786, 42888, 42891, 42957, 42960, 42961, 42963, 42963, 42965, 42972,\n        42994, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138,\n        43187, 43250, 43255, 43259, 43259, 43261, 43262, 43274, 43301, 43312, 43334,\n        43360, 43388, 43396, 43442, 43471, 43471, 43488, 43492, 43494, 43503, 43514,\n        43518, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642,\n        43646, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714,\n        43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790,\n        43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, 43868, 43881, 43888,\n        44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217,\n        64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312,\n        64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829,\n        64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313,\n        65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,\n        65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599,\n        65613, 65616, 65629, 65664, 65786, 66176, 66204, 66208, 66256, 66304, 66335,\n        66349, 66368, 66370, 66377, 66384, 66421, 66432, 66461, 66464, 66499, 66504,\n        66511, 66560, 66717, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915,\n        66928, 66938, 66940, 66954, 66956, 66962, 66964, 66965, 66967, 66977, 66979,\n        66993, 66995, 67001, 67003, 67004, 67008, 67059, 67072, 67382, 67392, 67413,\n        67424, 67431, 67456, 67461, 67463, 67504, 67506, 67514, 67584, 67589, 67592,\n        67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702,\n        67712, 67742, 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968,\n        68023, 68030, 68031, 68096, 68096, 68112, 68115, 68117, 68119, 68121, 68149,\n        68192, 68220, 68224, 68252, 68288, 68295, 68297, 68324, 68352, 68405, 68416,\n        68437, 68448, 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850,\n        68864, 68899, 68938, 68965, 68975, 68997, 69248, 69289, 69296, 69297, 69314,\n        69316, 69376, 69404, 69415, 69415, 69424, 69445, 69488, 69505, 69552, 69572,\n        69600, 69622, 69635, 69687, 69745, 69746, 69749, 69749, 69763, 69807, 69840,\n        69864, 69891, 69926, 69956, 69956, 69959, 69959, 69968, 70002, 70006, 70006,\n        70019, 70066, 70081, 70084, 70106, 70106, 70108, 70108, 70144, 70161, 70163,\n        70187, 70207, 70208, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301,\n        70303, 70312, 70320, 70366, 70405, 70412, 70415, 70416, 70419, 70440, 70442,\n        70448, 70450, 70451, 70453, 70457, 70461, 70461, 70480, 70480, 70493, 70497,\n        70528, 70537, 70539, 70539, 70542, 70542, 70544, 70581, 70583, 70583, 70609,\n        70609, 70611, 70611, 70656, 70708, 70727, 70730, 70751, 70753, 70784, 70831,\n        70852, 70853, 70855, 70855, 71040, 71086, 71128, 71131, 71168, 71215, 71236,\n        71236, 71296, 71338, 71352, 71352, 71424, 71450, 71488, 71494, 71680, 71723,\n        71840, 71903, 71935, 71942, 71945, 71945, 71948, 71955, 71957, 71958, 71960,\n        71983, 71999, 71999, 72001, 72001, 72096, 72103, 72106, 72144, 72161, 72161,\n        72163, 72163, 72192, 72192, 72203, 72242, 72250, 72250, 72272, 72272, 72284,\n        72329, 72349, 72349, 72368, 72440, 72640, 72672, 72704, 72712, 72714, 72750,\n        72768, 72768, 72818, 72847, 72960, 72966, 72968, 72969, 72971, 73008, 73030,\n        73030, 73056, 73061, 73063, 73064, 73066, 73097, 73112, 73112, 73440, 73458,\n        73474, 73474, 73476, 73488, 73490, 73523, 73648, 73648, 73728, 74649, 74880,\n        75075, 77712, 77808, 77824, 78895, 78913, 78918, 78944, 82938, 82944, 83526,\n        90368, 90397, 92160, 92728, 92736, 92766, 92784, 92862, 92880, 92909, 92928,\n        92975, 92992, 92995, 93027, 93047, 93053, 93071, 93504, 93548, 93760, 93823,\n        93952, 94026, 94032, 94032, 94099, 94111, 94176, 94177, 94179, 94179, 94208,\n        100343, 100352, 101589, 101631, 101640, 110576, 110579, 110581, 110587, 110589,\n        110590, 110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948,\n        110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808,\n        113817, 119808, 119892, 119894, 119964, 119966, 119967, 119970, 119970, 119973,\n        119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005,\n        120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123,\n        120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, 120485, 120488,\n        120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630,\n        120654, 120656, 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772,\n        120779, 122624, 122654, 122661, 122666, 122928, 122989, 123136, 123180, 123191,\n        123197, 123214, 123214, 123536, 123565, 123584, 123627, 124112, 124139, 124368,\n        124397, 124400, 124400, 124896, 124902, 124904, 124907, 124909, 124910, 124912,\n        124926, 124928, 125124, 125184, 125251, 125259, 125259, 126464, 126467, 126469,\n        126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516,\n        126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537,\n        126537, 126539, 126539, 126541, 126543, 126545, 126546, 126548, 126548, 126551,\n        126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561,\n        126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585,\n        126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, 126627, 126629,\n        126633, 126635, 126651, 131072, 173791, 173824, 177977, 177984, 178205, 178208,\n        183969, 183984, 191456, 191472, 192093, 194560, 195101, 196608, 201546, 201552,\n        205743, 771, 0, 48, 57, 65, 90, 95, 95, 97, 122, 170, 170, 178, 179, 181, 181, 185,\n        186, 188, 190, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750,\n        750, 880, 884, 886, 887, 890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910,\n        929, 931, 1013, 1015, 1153, 1162, 1327, 1329, 1366, 1369, 1369, 1376, 1416, 1488,\n        1514, 1519, 1522, 1568, 1610, 1632, 1641, 1646, 1647, 1649, 1747, 1749, 1749,\n        1765, 1766, 1774, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969,\n        1969, 1984, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084,\n        2088, 2088, 2112, 2136, 2144, 2154, 2160, 2183, 2185, 2190, 2208, 2249, 2308,\n        2361, 2365, 2365, 2384, 2384, 2392, 2401, 2406, 2415, 2417, 2432, 2437, 2444,\n        2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510,\n        2510, 2524, 2525, 2527, 2529, 2534, 2545, 2548, 2553, 2556, 2556, 2565, 2570,\n        2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649,\n        2652, 2654, 2654, 2662, 2671, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728,\n        2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2790,\n        2799, 2809, 2809, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,\n        2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2918, 2927, 2929, 2935, 2947,\n        2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975,\n        2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3046, 3058, 3077, 3084, 3086,\n        3088, 3090, 3112, 3114, 3129, 3133, 3133, 3160, 3162, 3165, 3165, 3168, 3169,\n        3174, 3183, 3192, 3198, 3200, 3200, 3205, 3212, 3214, 3216, 3218, 3240, 3242,\n        3251, 3253, 3257, 3261, 3261, 3293, 3294, 3296, 3297, 3302, 3311, 3313, 3314,\n        3332, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3412, 3414, 3416,\n        3425, 3430, 3448, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517,\n        3520, 3526, 3558, 3567, 3585, 3632, 3634, 3635, 3648, 3654, 3664, 3673, 3713,\n        3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3760, 3762, 3763,\n        3773, 3773, 3776, 3780, 3782, 3782, 3792, 3801, 3804, 3807, 3840, 3840, 3872,\n        3891, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4169, 4176, 4181,\n        4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4240,\n        4249, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685,\n        4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786,\n        4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885,\n        4888, 4954, 4969, 4988, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743,\n        5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5905, 5919, 5937, 5952, 5969,\n        5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6112, 6121, 6128,\n        6137, 6160, 6169, 6176, 6264, 6272, 6276, 6279, 6312, 6314, 6314, 6320, 6389,\n        6400, 6430, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6618, 6656,\n        6678, 6688, 6740, 6784, 6793, 6800, 6809, 6823, 6823, 6917, 6963, 6981, 6988,\n        6992, 7001, 7043, 7072, 7086, 7141, 7168, 7203, 7232, 7241, 7245, 7293, 7296,\n        7306, 7312, 7354, 7357, 7359, 7401, 7404, 7406, 7411, 7413, 7414, 7418, 7418,\n        7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025,\n        8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126,\n        8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182,\n        8188, 8304, 8305, 8308, 8313, 8319, 8329, 8336, 8348, 8450, 8450, 8455, 8455,\n        8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490,\n        8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8528, 8585, 9312, 9371,\n        9450, 9471, 10102, 10131, 11264, 11492, 11499, 11502, 11506, 11507, 11517,\n        11517, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631,\n        11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712,\n        11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,\n        12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449,\n        12538, 12540, 12543, 12549, 12591, 12593, 12686, 12690, 12693, 12704, 12735,\n        12784, 12799, 12832, 12841, 12872, 12879, 12881, 12895, 12928, 12937, 12977,\n        12991, 13312, 19903, 19968, 42124, 42192, 42237, 42240, 42508, 42512, 42539,\n        42560, 42606, 42623, 42653, 42656, 42735, 42775, 42783, 42786, 42888, 42891,\n        42957, 42960, 42961, 42963, 42963, 42965, 42972, 42994, 43009, 43011, 43013,\n        43015, 43018, 43020, 43042, 43056, 43061, 43072, 43123, 43138, 43187, 43216,\n        43225, 43250, 43255, 43259, 43259, 43261, 43262, 43264, 43301, 43312, 43334,\n        43360, 43388, 43396, 43442, 43471, 43481, 43488, 43492, 43494, 43518, 43520,\n        43560, 43584, 43586, 43588, 43595, 43600, 43609, 43616, 43638, 43642, 43642,\n        43646, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714,\n        43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790,\n        43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, 43868, 43881, 43888,\n        44002, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109,\n        64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298,\n        64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,\n        64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142,\n        65276, 65296, 65305, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479,\n        65482, 65487, 65490, 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576,\n        65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65799, 65843,\n        65856, 65912, 65930, 65931, 66176, 66204, 66208, 66256, 66273, 66299, 66304,\n        66339, 66349, 66378, 66384, 66421, 66432, 66461, 66464, 66499, 66504, 66511,\n        66513, 66517, 66560, 66717, 66720, 66729, 66736, 66771, 66776, 66811, 66816,\n        66855, 66864, 66915, 66928, 66938, 66940, 66954, 66956, 66962, 66964, 66965,\n        66967, 66977, 66979, 66993, 66995, 67001, 67003, 67004, 67008, 67059, 67072,\n        67382, 67392, 67413, 67424, 67431, 67456, 67461, 67463, 67504, 67506, 67514,\n        67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647,\n        67669, 67672, 67702, 67705, 67742, 67751, 67759, 67808, 67826, 67828, 67829,\n        67835, 67867, 67872, 67897, 67968, 68023, 68028, 68047, 68050, 68096, 68112,\n        68115, 68117, 68119, 68121, 68149, 68160, 68168, 68192, 68222, 68224, 68255,\n        68288, 68295, 68297, 68324, 68331, 68335, 68352, 68405, 68416, 68437, 68440,\n        68466, 68472, 68497, 68521, 68527, 68608, 68680, 68736, 68786, 68800, 68850,\n        68858, 68899, 68912, 68921, 68928, 68965, 68975, 68997, 69216, 69246, 69248,\n        69289, 69296, 69297, 69314, 69316, 69376, 69415, 69424, 69445, 69457, 69460,\n        69488, 69505, 69552, 69579, 69600, 69622, 69635, 69687, 69714, 69743, 69745,\n        69746, 69749, 69749, 69763, 69807, 69840, 69864, 69872, 69881, 69891, 69926,\n        69942, 69951, 69956, 69956, 69959, 69959, 69968, 70002, 70006, 70006, 70019,\n        70066, 70081, 70084, 70096, 70106, 70108, 70108, 70113, 70132, 70144, 70161,\n        70163, 70187, 70207, 70208, 70272, 70278, 70280, 70280, 70282, 70285, 70287,\n        70301, 70303, 70312, 70320, 70366, 70384, 70393, 70405, 70412, 70415, 70416,\n        70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70461, 70461, 70480,\n        70480, 70493, 70497, 70528, 70537, 70539, 70539, 70542, 70542, 70544, 70581,\n        70583, 70583, 70609, 70609, 70611, 70611, 70656, 70708, 70727, 70730, 70736,\n        70745, 70751, 70753, 70784, 70831, 70852, 70853, 70855, 70855, 70864, 70873,\n        71040, 71086, 71128, 71131, 71168, 71215, 71236, 71236, 71248, 71257, 71296,\n        71338, 71352, 71352, 71360, 71369, 71376, 71395, 71424, 71450, 71472, 71483,\n        71488, 71494, 71680, 71723, 71840, 71922, 71935, 71942, 71945, 71945, 71948,\n        71955, 71957, 71958, 71960, 71983, 71999, 71999, 72001, 72001, 72016, 72025,\n        72096, 72103, 72106, 72144, 72161, 72161, 72163, 72163, 72192, 72192, 72203,\n        72242, 72250, 72250, 72272, 72272, 72284, 72329, 72349, 72349, 72368, 72440,\n        72640, 72672, 72688, 72697, 72704, 72712, 72714, 72750, 72768, 72768, 72784,\n        72812, 72818, 72847, 72960, 72966, 72968, 72969, 72971, 73008, 73030, 73030,\n        73040, 73049, 73056, 73061, 73063, 73064, 73066, 73097, 73112, 73112, 73120,\n        73129, 73440, 73458, 73474, 73474, 73476, 73488, 73490, 73523, 73552, 73561,\n        73648, 73648, 73664, 73684, 73728, 74649, 74752, 74862, 74880, 75075, 77712,\n        77808, 77824, 78895, 78913, 78918, 78944, 82938, 82944, 83526, 90368, 90397,\n        90416, 90425, 92160, 92728, 92736, 92766, 92768, 92777, 92784, 92862, 92864,\n        92873, 92880, 92909, 92928, 92975, 92992, 92995, 93008, 93017, 93019, 93025,\n        93027, 93047, 93053, 93071, 93504, 93548, 93552, 93561, 93760, 93846, 93952,\n        94026, 94032, 94032, 94099, 94111, 94176, 94177, 94179, 94179, 94208, 100343,\n        100352, 101589, 101631, 101640, 110576, 110579, 110581, 110587, 110589, 110590,\n        110592, 110882, 110898, 110898, 110928, 110930, 110933, 110933, 110948, 110951,\n        110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817,\n        118000, 118009, 119488, 119507, 119520, 119539, 119648, 119672, 119808, 119892,\n        119894, 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,\n        119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, 120074,\n        120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132,\n        120134, 120134, 120138, 120144, 120146, 120485, 120488, 120512, 120514, 120538,\n        120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,\n        120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 120782, 120831,\n        122624, 122654, 122661, 122666, 122928, 122989, 123136, 123180, 123191, 123197,\n        123200, 123209, 123214, 123214, 123536, 123565, 123584, 123627, 123632, 123641,\n        124112, 124139, 124144, 124153, 124368, 124397, 124400, 124410, 124896, 124902,\n        124904, 124907, 124909, 124910, 124912, 124926, 124928, 125124, 125127, 125135,\n        125184, 125251, 125259, 125259, 125264, 125273, 126065, 126123, 126125, 126127,\n        126129, 126132, 126209, 126253, 126255, 126269, 126464, 126467, 126469, 126495,\n        126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, 126519,\n        126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537,\n        126539, 126539, 126541, 126543, 126545, 126546, 126548, 126548, 126551, 126551,\n        126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562,\n        126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588,\n        126590, 126590, 126592, 126601, 126603, 126619, 126625, 126627, 126629, 126633,\n        126635, 126651, 127232, 127244, 130032, 130041, 131072, 173791, 173824, 177977,\n        177984, 178205, 178208, 183969, 183984, 191456, 191472, 192093, 194560, 195101,\n        196608, 201546, 201552, 205743, 2, 0, 91, 91, 93, 93, 2, 0, 43, 43, 45, 45, 1, 0,\n        34, 34, 533, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1,\n        0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1,\n        0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1,\n        0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1,\n        0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1,\n        0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1,\n        0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1,\n        0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1,\n        0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1,\n        0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101,\n        1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0,\n        0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1,\n        0, 0, 0, 0, 121, 1, 0, 0, 0, 1, 124, 1, 0, 0, 0, 3, 144, 1, 0, 0, 0, 5, 162, 1, 0, 0, 0, 7,\n        167, 1, 0, 0, 0, 9, 182, 1, 0, 0, 0, 11, 186, 1, 0, 0, 0, 13, 188, 1, 0, 0, 0, 15, 194, 1,\n        0, 0, 0, 17, 198, 1, 0, 0, 0, 19, 203, 1, 0, 0, 0, 21, 206, 1, 0, 0, 0, 23, 209, 1, 0, 0,\n        0, 25, 212, 1, 0, 0, 0, 27, 217, 1, 0, 0, 0, 29, 220, 1, 0, 0, 0, 31, 225, 1, 0, 0, 0, 33,\n        230, 1, 0, 0, 0, 35, 239, 1, 0, 0, 0, 37, 248, 1, 0, 0, 0, 39, 252, 1, 0, 0, 0, 41, 259,\n        1, 0, 0, 0, 43, 263, 1, 0, 0, 0, 45, 267, 1, 0, 0, 0, 47, 273, 1, 0, 0, 0, 49, 279, 1, 0,\n        0, 0, 51, 281, 1, 0, 0, 0, 53, 283, 1, 0, 0, 0, 55, 285, 1, 0, 0, 0, 57, 288, 1, 0, 0, 0,\n        59, 290, 1, 0, 0, 0, 61, 296, 1, 0, 0, 0, 63, 298, 1, 0, 0, 0, 65, 307, 1, 0, 0, 0, 67, 312,\n        1, 0, 0, 0, 69, 318, 1, 0, 0, 0, 71, 320, 1, 0, 0, 0, 73, 322, 1, 0, 0, 0, 75, 325, 1, 0,\n        0, 0, 77, 327, 1, 0, 0, 0, 79, 330, 1, 0, 0, 0, 81, 332, 1, 0, 0, 0, 83, 334, 1, 0, 0, 0,\n        85, 336, 1, 0, 0, 0, 87, 342, 1, 0, 0, 0, 89, 344, 1, 0, 0, 0, 91, 350, 1, 0, 0, 0, 93, 355,\n        1, 0, 0, 0, 95, 360, 1, 0, 0, 0, 97, 362, 1, 0, 0, 0, 99, 364, 1, 0, 0, 0, 101, 375, 1, 0,\n        0, 0, 103, 377, 1, 0, 0, 0, 105, 381, 1, 0, 0, 0, 107, 389, 1, 0, 0, 0, 109, 395, 1, 0,\n        0, 0, 111, 397, 1, 0, 0, 0, 113, 399, 1, 0, 0, 0, 115, 424, 1, 0, 0, 0, 117, 427, 1, 0,\n        0, 0, 119, 461, 1, 0, 0, 0, 121, 493, 1, 0, 0, 0, 123, 125, 3, 9, 4, 0, 124, 123, 1, 0,\n        0, 0, 124, 125, 1, 0, 0, 0, 125, 126, 1, 0, 0, 0, 126, 127, 5, 47, 0, 0, 127, 128, 5, 42,\n        0, 0, 128, 132, 1, 0, 0, 0, 129, 131, 9, 0, 0, 0, 130, 129, 1, 0, 0, 0, 131, 134, 1, 0,\n        0, 0, 132, 133, 1, 0, 0, 0, 132, 130, 1, 0, 0, 0, 133, 135, 1, 0, 0, 0, 134, 132, 1, 0,\n        0, 0, 135, 136, 5, 42, 0, 0, 136, 137, 5, 47, 0, 0, 137, 139, 1, 0, 0, 0, 138, 140, 3,\n        9, 4, 0, 139, 138, 1, 0, 0, 0, 139, 140, 1, 0, 0, 0, 140, 141, 1, 0, 0, 0, 141, 142, 6,\n        0, 0, 0, 142, 2, 1, 0, 0, 0, 143, 145, 3, 9, 4, 0, 144, 143, 1, 0, 0, 0, 144, 145, 1, 0,\n        0, 0, 145, 149, 1, 0, 0, 0, 146, 147, 5, 47, 0, 0, 147, 150, 5, 47, 0, 0, 148, 150, 5,\n        35, 0, 0, 149, 146, 1, 0, 0, 0, 149, 148, 1, 0, 0, 0, 150, 154, 1, 0, 0, 0, 151, 153, 8,\n        0, 0, 0, 152, 151, 1, 0, 0, 0, 153, 156, 1, 0, 0, 0, 154, 152, 1, 0, 0, 0, 154, 155, 1,\n        0, 0, 0, 155, 158, 1, 0, 0, 0, 156, 154, 1, 0, 0, 0, 157, 159, 3, 9, 4, 0, 158, 157, 1,\n        0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 161, 6, 1, 0, 0, 161, 4, 1, 0,\n        0, 0, 162, 163, 7, 1, 0, 0, 163, 6, 1, 0, 0, 0, 164, 166, 3, 5, 2, 0, 165, 164, 1, 0, 0,\n        0, 166, 169, 1, 0, 0, 0, 167, 165, 1, 0, 0, 0, 167, 168, 1, 0, 0, 0, 168, 177, 1, 0, 0,\n        0, 169, 167, 1, 0, 0, 0, 170, 174, 3, 11, 5, 0, 171, 173, 3, 5, 2, 0, 172, 171, 1, 0, 0,\n        0, 173, 176, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 178, 1, 0, 0,\n        0, 176, 174, 1, 0, 0, 0, 177, 170, 1, 0, 0, 0, 178, 179, 1, 0, 0, 0, 179, 177, 1, 0, 0,\n        0, 179, 180, 1, 0, 0, 0, 180, 8, 1, 0, 0, 0, 181, 183, 3, 5, 2, 0, 182, 181, 1, 0, 0, 0,\n        183, 184, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 184, 185, 1, 0, 0, 0, 185, 10, 1, 0, 0, 0, 186,\n        187, 7, 0, 0, 0, 187, 12, 1, 0, 0, 0, 188, 189, 7, 2, 0, 0, 189, 190, 7, 3, 0, 0, 190, 191,\n        7, 4, 0, 0, 191, 192, 7, 5, 0, 0, 192, 193, 7, 6, 0, 0, 193, 14, 1, 0, 0, 0, 194, 195, 7,\n        7, 0, 0, 195, 196, 7, 8, 0, 0, 196, 197, 7, 9, 0, 0, 197, 16, 1, 0, 0, 0, 198, 199, 7, 7,\n        0, 0, 199, 200, 7, 9, 0, 0, 200, 201, 7, 8, 0, 0, 201, 202, 7, 10, 0, 0, 202, 18, 1, 0,\n        0, 0, 203, 204, 7, 4, 0, 0, 204, 205, 7, 11, 0, 0, 205, 20, 1, 0, 0, 0, 206, 207, 7, 12,\n        0, 0, 207, 208, 7, 8, 0, 0, 208, 22, 1, 0, 0, 0, 209, 210, 7, 13, 0, 0, 210, 211, 7, 14,\n        0, 0, 211, 24, 1, 0, 0, 0, 212, 213, 7, 5, 0, 0, 213, 214, 7, 8, 0, 0, 214, 215, 7, 8, 0,\n        0, 215, 216, 7, 15, 0, 0, 216, 26, 1, 0, 0, 0, 217, 218, 7, 4, 0, 0, 218, 219, 7, 7, 0,\n        0, 219, 28, 1, 0, 0, 0, 220, 221, 7, 12, 0, 0, 221, 222, 7, 3, 0, 0, 222, 223, 7, 6, 0,\n        0, 223, 224, 7, 11, 0, 0, 224, 30, 1, 0, 0, 0, 225, 226, 7, 6, 0, 0, 226, 227, 7, 5, 0,\n        0, 227, 228, 7, 16, 0, 0, 228, 229, 7, 6, 0, 0, 229, 32, 1, 0, 0, 0, 230, 231, 7, 7, 0,\n        0, 231, 232, 7, 17, 0, 0, 232, 233, 7, 11, 0, 0, 233, 234, 7, 18, 0, 0, 234, 235, 7, 12,\n        0, 0, 235, 236, 7, 4, 0, 0, 236, 237, 7, 8, 0, 0, 237, 238, 7, 11, 0, 0, 238, 34, 1, 0,\n        0, 0, 239, 240, 7, 6, 0, 0, 240, 241, 7, 11, 0, 0, 241, 242, 7, 19, 0, 0, 242, 244, 1,\n        0, 0, 0, 243, 245, 3, 5, 2, 0, 244, 243, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 244, 1,\n        0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 36, 1, 0, 0, 0, 248, 249, 7, 6, 0, 0, 249, 250, 7, 11,\n        0, 0, 250, 251, 7, 19, 0, 0, 251, 38, 1, 0, 0, 0, 252, 253, 7, 9, 0, 0, 253, 254, 7, 6,\n        0, 0, 254, 255, 7, 12, 0, 0, 255, 256, 7, 17, 0, 0, 256, 257, 7, 9, 0, 0, 257, 258, 7,\n        11, 0, 0, 258, 40, 1, 0, 0, 0, 259, 260, 7, 11, 0, 0, 260, 261, 7, 6, 0, 0, 261, 262, 7,\n        2, 0, 0, 262, 42, 1, 0, 0, 0, 263, 264, 7, 12, 0, 0, 264, 265, 7, 9, 0, 0, 265, 266, 7,\n        14, 0, 0, 266, 44, 1, 0, 0, 0, 267, 268, 7, 18, 0, 0, 268, 269, 7, 20, 0, 0, 269, 270,\n        7, 12, 0, 0, 270, 271, 7, 18, 0, 0, 271, 272, 7, 3, 0, 0, 272, 46, 1, 0, 0, 0, 273, 274,\n        7, 12, 0, 0, 274, 275, 7, 3, 0, 0, 275, 276, 7, 9, 0, 0, 276, 277, 7, 8, 0, 0, 277, 278,\n        7, 2, 0, 0, 278, 48, 1, 0, 0, 0, 279, 280, 5, 40, 0, 0, 280, 50, 1, 0, 0, 0, 281, 282, 5,\n        44, 0, 0, 282, 52, 1, 0, 0, 0, 283, 284, 5, 41, 0, 0, 284, 54, 1, 0, 0, 0, 285, 286, 5,\n        60, 0, 0, 286, 287, 5, 45, 0, 0, 287, 56, 1, 0, 0, 0, 288, 289, 5, 46, 0, 0, 289, 58, 1,\n        0, 0, 0, 290, 291, 5, 58, 0, 0, 291, 60, 1, 0, 0, 0, 292, 293, 5, 124, 0, 0, 293, 297,\n        5, 124, 0, 0, 294, 295, 7, 8, 0, 0, 295, 297, 7, 9, 0, 0, 296, 292, 1, 0, 0, 0, 296, 294,\n        1, 0, 0, 0, 297, 62, 1, 0, 0, 0, 298, 299, 7, 21, 0, 0, 299, 300, 7, 8, 0, 0, 300, 301,\n        7, 9, 0, 0, 301, 64, 1, 0, 0, 0, 302, 303, 5, 38, 0, 0, 303, 308, 5, 38, 0, 0, 304, 305,\n        7, 20, 0, 0, 305, 306, 7, 11, 0, 0, 306, 308, 7, 19, 0, 0, 307, 302, 1, 0, 0, 0, 307, 304,\n        1, 0, 0, 0, 308, 66, 1, 0, 0, 0, 309, 313, 5, 61, 0, 0, 310, 311, 5, 61, 0, 0, 311, 313,\n        5, 61, 0, 0, 312, 309, 1, 0, 0, 0, 312, 310, 1, 0, 0, 0, 313, 68, 1, 0, 0, 0, 314, 315,\n        5, 33, 0, 0, 315, 319, 5, 61, 0, 0, 316, 317, 5, 60, 0, 0, 317, 319, 5, 62, 0, 0, 318,\n        314, 1, 0, 0, 0, 318, 316, 1, 0, 0, 0, 319, 70, 1, 0, 0, 0, 320, 321, 5, 60, 0, 0, 321,\n        72, 1, 0, 0, 0, 322, 323, 5, 60, 0, 0, 323, 324, 5, 61, 0, 0, 324, 74, 1, 0, 0, 0, 325,\n        326, 5, 62, 0, 0, 326, 76, 1, 0, 0, 0, 327, 328, 5, 62, 0, 0, 328, 329, 5, 61, 0, 0, 329,\n        78, 1, 0, 0, 0, 330, 331, 5, 43, 0, 0, 331, 80, 1, 0, 0, 0, 332, 333, 5, 45, 0, 0, 333,\n        82, 1, 0, 0, 0, 334, 335, 5, 42, 0, 0, 335, 84, 1, 0, 0, 0, 336, 337, 5, 47, 0, 0, 337,\n        86, 1, 0, 0, 0, 338, 343, 5, 37, 0, 0, 339, 340, 7, 10, 0, 0, 340, 341, 7, 8, 0, 0, 341,\n        343, 7, 19, 0, 0, 342, 338, 1, 0, 0, 0, 342, 339, 1, 0, 0, 0, 343, 88, 1, 0, 0, 0, 344,\n        345, 5, 94, 0, 0, 345, 90, 1, 0, 0, 0, 346, 351, 5, 33, 0, 0, 347, 348, 7, 11, 0, 0, 348,\n        349, 7, 8, 0, 0, 349, 351, 7, 12, 0, 0, 350, 346, 1, 0, 0, 0, 350, 347, 1, 0, 0, 0, 351,\n        92, 1, 0, 0, 0, 352, 356, 5, 171, 0, 0, 353, 354, 5, 60, 0, 0, 354, 356, 5, 60, 0, 0, 355,\n        352, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 356, 94, 1, 0, 0, 0, 357, 361, 5, 187, 0, 0, 358,\n        359, 5, 62, 0, 0, 359, 361, 5, 62, 0, 0, 360, 357, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0, 361,\n        96, 1, 0, 0, 0, 362, 363, 5, 123, 0, 0, 363, 98, 1, 0, 0, 0, 364, 365, 5, 125, 0, 0, 365,\n        100, 1, 0, 0, 0, 366, 367, 7, 12, 0, 0, 367, 368, 7, 9, 0, 0, 368, 369, 7, 17, 0, 0, 369,\n        376, 7, 6, 0, 0, 370, 371, 7, 7, 0, 0, 371, 372, 7, 20, 0, 0, 372, 373, 7, 5, 0, 0, 373,\n        374, 7, 16, 0, 0, 374, 376, 7, 6, 0, 0, 375, 366, 1, 0, 0, 0, 375, 370, 1, 0, 0, 0, 376,\n        102, 1, 0, 0, 0, 377, 378, 7, 15, 0, 0, 378, 379, 7, 6, 0, 0, 379, 380, 7, 9, 0, 0, 380,\n        104, 1, 0, 0, 0, 381, 382, 7, 16, 0, 0, 382, 383, 7, 22, 0, 0, 383, 384, 7, 17, 0, 0, 384,\n        385, 7, 20, 0, 0, 385, 386, 7, 9, 0, 0, 386, 387, 7, 6, 0, 0, 387, 388, 7, 19, 0, 0, 388,\n        106, 1, 0, 0, 0, 389, 390, 7, 18, 0, 0, 390, 391, 7, 17, 0, 0, 391, 392, 7, 13, 0, 0, 392,\n        393, 7, 6, 0, 0, 393, 394, 7, 19, 0, 0, 394, 108, 1, 0, 0, 0, 395, 396, 5, 91, 0, 0, 396,\n        110, 1, 0, 0, 0, 397, 398, 5, 93, 0, 0, 398, 112, 1, 0, 0, 0, 399, 403, 7, 23, 0, 0, 400,\n        402, 7, 24, 0, 0, 401, 400, 1, 0, 0, 0, 402, 405, 1, 0, 0, 0, 403, 401, 1, 0, 0, 0, 403,\n        404, 1, 0, 0, 0, 404, 114, 1, 0, 0, 0, 405, 403, 1, 0, 0, 0, 406, 408, 3, 109, 54, 0, 407,\n        409, 8, 25, 0, 0, 408, 407, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 410,\n        408, 1, 0, 0, 0, 411, 412, 1, 0, 0, 0, 412, 413, 3, 111, 55, 0, 413, 425, 1, 0, 0, 0, 414,\n        415, 3, 109, 54, 0, 415, 417, 3, 109, 54, 0, 416, 418, 8, 25, 0, 0, 417, 416, 1, 0, 0,\n        0, 418, 419, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 419, 417, 1, 0, 0, 0, 420, 421, 1, 0, 0,\n        0, 421, 422, 3, 111, 55, 0, 422, 423, 3, 111, 55, 0, 423, 425, 1, 0, 0, 0, 424, 406,\n        1, 0, 0, 0, 424, 414, 1, 0, 0, 0, 425, 116, 1, 0, 0, 0, 426, 428, 2, 48, 57, 0, 427, 426,\n        1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 427, 1, 0, 0, 0, 429, 430, 1, 0, 0, 0, 430, 441,\n        1, 0, 0, 0, 431, 433, 7, 6, 0, 0, 432, 434, 7, 26, 0, 0, 433, 432, 1, 0, 0, 0, 433, 434,\n        1, 0, 0, 0, 434, 438, 1, 0, 0, 0, 435, 437, 2, 48, 57, 0, 436, 435, 1, 0, 0, 0, 437, 440,\n        1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 438, 439, 1, 0, 0, 0, 439, 442, 1, 0, 0, 0, 440, 438,\n        1, 0, 0, 0, 441, 431, 1, 0, 0, 0, 441, 442, 1, 0, 0, 0, 442, 118, 1, 0, 0, 0, 443, 445,\n        2, 48, 57, 0, 444, 443, 1, 0, 0, 0, 445, 448, 1, 0, 0, 0, 446, 444, 1, 0, 0, 0, 446, 447,\n        1, 0, 0, 0, 447, 449, 1, 0, 0, 0, 448, 446, 1, 0, 0, 0, 449, 451, 5, 46, 0, 0, 450, 452,\n        2, 48, 57, 0, 451, 450, 1, 0, 0, 0, 452, 453, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454,\n        1, 0, 0, 0, 454, 462, 1, 0, 0, 0, 455, 457, 2, 48, 57, 0, 456, 455, 1, 0, 0, 0, 457, 458,\n        1, 0, 0, 0, 458, 456, 1, 0, 0, 0, 458, 459, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 462,\n        5, 46, 0, 0, 461, 446, 1, 0, 0, 0, 461, 456, 1, 0, 0, 0, 462, 473, 1, 0, 0, 0, 463, 465,\n        7, 6, 0, 0, 464, 466, 7, 26, 0, 0, 465, 464, 1, 0, 0, 0, 465, 466, 1, 0, 0, 0, 466, 470,\n        1, 0, 0, 0, 467, 469, 2, 48, 57, 0, 468, 467, 1, 0, 0, 0, 469, 472, 1, 0, 0, 0, 470, 468,\n        1, 0, 0, 0, 470, 471, 1, 0, 0, 0, 471, 474, 1, 0, 0, 0, 472, 470, 1, 0, 0, 0, 473, 463,\n        1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 120, 1, 0, 0, 0, 475, 479, 5, 39, 0, 0, 476, 478,\n        9, 0, 0, 0, 477, 476, 1, 0, 0, 0, 478, 481, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 479, 477,\n        1, 0, 0, 0, 480, 482, 1, 0, 0, 0, 481, 479, 1, 0, 0, 0, 482, 494, 5, 39, 0, 0, 483, 489,\n        5, 34, 0, 0, 484, 485, 5, 92, 0, 0, 485, 488, 5, 34, 0, 0, 486, 488, 8, 27, 0, 0, 487,\n        484, 1, 0, 0, 0, 487, 486, 1, 0, 0, 0, 488, 491, 1, 0, 0, 0, 489, 487, 1, 0, 0, 0, 489,\n        490, 1, 0, 0, 0, 490, 492, 1, 0, 0, 0, 491, 489, 1, 0, 0, 0, 492, 494, 5, 34, 0, 0, 493,\n        475, 1, 0, 0, 0, 493, 483, 1, 0, 0, 0, 494, 122, 1, 0, 0, 0, 41, 0, 124, 132, 139, 144,\n        149, 154, 158, 167, 174, 179, 184, 246, 296, 307, 312, 318, 342, 350, 355, 360,\n        375, 403, 410, 419, 424, 429, 433, 438, 441, 446, 453, 458, 461, 465, 470, 473,\n        479, 487, 489, 493, 1, 0, 1, 0\n    ];\n    static __ATN;\n    static get _ATN() {\n        if (!FormulaLexer.__ATN) {\n            FormulaLexer.__ATN = new antlr.ATNDeserializer().deserialize(FormulaLexer._serializedATN);\n        }\n        return FormulaLexer.__ATN;\n    }\n    static vocabulary = new antlr.Vocabulary(FormulaLexer.literalNames, FormulaLexer.symbolicNames, []);\n    get vocabulary() {\n        return FormulaLexer.vocabulary;\n    }\n    static decisionsToDFA = FormulaLexer._ATN.decisionToState.map((ds, index) => new antlr.DFA(ds, index));\n}\n", "vendor/avl/LICENSE": "The MIT License (MIT)\n\nCopyright (c) 2017 Alexander Milevski <info@w8r.name>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "vendor/avl/utils.js": "// @ts-nocheck\n\n/**\n * Prints tree horizontally\n * @param  {Node}                       root\n * @param  {function(node:Node):String} [printNode]\n * @return {String}\n */\nexport function print (root, printNode = (n) => n.key) {\n  let out = [];\n  row(root, \"\", true, (v) => out.push(v), printNode);\n  return out.join(\"\");\n}\n\n/**\n * Prints level of the tree\n * @param  {Node}                        root\n * @param  {String}                      prefix\n * @param  {Boolean}                     isTail\n * @param  {Function(in:string):void}    out\n * @param  {Function(node:Node):String}  printNode\n */\nfunction row (root, prefix, isTail, out, printNode) {\n  if (root) {\n    out(`${ prefix }${ isTail ? \"\u2514\u2500\u2500 \" : \"\u251c\u2500\u2500 \" }${ printNode(root) }\\n`);\n    const indent = prefix + (isTail ? \"    \" : \"\u2502   \");\n    if (root.left)  row(root.left,  indent, false, out, printNode);\n    if (root.right) row(root.right, indent, true,  out, printNode);\n  }\n}\n\n/**\n * Is the tree balanced (none of the subtrees differ in height by more than 1)\n * @param  {Node}    root\n * @return {Boolean}\n */\nexport function isBalanced(root) {\n  if (root === null) return true; // If node is empty then return true\n\n  // Get the height of left and right sub trees\n  let lh = height(root.left);\n  let rh = height(root.right);\n\n  if (Math.abs(lh - rh) <= 1 &&\n      isBalanced(root.left)  &&\n      isBalanced(root.right)) return true;\n\n  // If we reach here then tree is not height-balanced\n  return false;\n}\n\n/**\n * The function Compute the 'height' of a tree.\n * Height is the number of nodes along the longest path\n * from the root node down to the farthest leaf node.\n *\n * @param  {Node} node\n * @return {Number}\n */\nfunction height(node) {\n  return node ? (1 + Math.max(height(node.left), height(node.right))) : 0;\n}\n\nexport function loadRecursive (parent, keys, values, start, end) {\n  const size = end - start;\n  if (size > 0) {\n    const middle = start + Math.floor(size / 2);\n    const key    = keys[middle];\n    const data   = values[middle];\n    const node   = { key, data, parent };\n    node.left    = loadRecursive(node, keys, values, start, middle);\n    node.right   = loadRecursive(node, keys, values, middle + 1, end);\n    return node;\n  }\n  return null;\n}\n\nexport function markBalance(node) {\n  if (node === null) return 0;\n  const lh = markBalance(node.left);\n  const rh = markBalance(node.right);\n\n  node.balanceFactor = lh - rh;\n  return Math.max(lh, rh) + 1;\n}\n\nexport function sort(keys, values, left, right, compare) {\n  if (left >= right) return;\n\n  // eslint-disable-next-line no-bitwise\n  const pivot = keys[(left + right) >> 1];\n  let i = left - 1;\n  let j = right + 1;\n\n  // eslint-disable-next-line no-constant-condition\n  while (true) {\n    do i++; while (compare(keys[i], pivot) < 0);\n    do j--; while (compare(keys[j], pivot) > 0);\n    if (i >= j) break;\n\n    let tmp = keys[i];\n    keys[i] = keys[j];\n    keys[j] = tmp;\n\n    tmp = values[i];\n    values[i] = values[j];\n    values[j] = tmp;\n  }\n\n  sort(keys, values,  left,     j, compare);\n  sort(keys, values, j + 1, right, compare);\n}", "vendor/avl/avl.js": "// @ts-nocheck\n\nimport { print, isBalanced, loadRecursive, markBalance, sort } from \"./utils.js\";\n\n// function createNode (parent, left, right, height, key, data) {\n//   return { parent, left, right, balanceFactor: height, key, data };\n// }\n\n/**\n * @typedef {{\n *   parent:        ?Node,\n *   left:          ?Node,\n *   right:         ?Node,\n *   balanceFactor: number,\n *   key:           Key,\n *   data:          Value\n * }} Node\n */\n\n/**\n * @typedef {import(\"../../src/TaskScheduler\").Task} Key\n */\n\n/**\n * @typedef {*} Value\n */\n\n/**\n * Default comparison function\n * @param {Key} a\n * @param {Key} b\n * @returns {number}\n */\nfunction DEFAULT_COMPARE (a, b) {\n  return a > b ? 1 : a < b ? -1 : 0;\n}\n\n/**\n * Single left rotation\n * @param  {Node} node\n * @return {Node}\n */\nfunction rotateLeft (node) {\n  let rightNode = node.right;\n  node.right    = rightNode.left;\n\n  if (rightNode.left) rightNode.left.parent = node;\n\n  rightNode.parent = node.parent;\n  if (rightNode.parent) {\n    if (rightNode.parent.left === node) {\n      rightNode.parent.left = rightNode;\n    } else {\n      rightNode.parent.right = rightNode;\n    }\n  }\n\n  node.parent    = rightNode;\n  rightNode.left = node;\n\n  node.balanceFactor += 1;\n  if (rightNode.balanceFactor < 0) {\n    node.balanceFactor -= rightNode.balanceFactor;\n  }\n\n  rightNode.balanceFactor += 1;\n  if (node.balanceFactor > 0) {\n    rightNode.balanceFactor += node.balanceFactor;\n  }\n  return rightNode;\n}\n\nfunction rotateRight (node) {\n  let leftNode = node.left;\n  node.left = leftNode.right;\n  if (node.left) node.left.parent = node;\n\n  leftNode.parent = node.parent;\n  if (leftNode.parent) {\n    if (leftNode.parent.left === node) {\n      leftNode.parent.left = leftNode;\n    } else {\n      leftNode.parent.right = leftNode;\n    }\n  }\n\n  node.parent    = leftNode;\n  leftNode.right = node;\n\n  node.balanceFactor -= 1;\n  if (leftNode.balanceFactor > 0) {\n    node.balanceFactor -= leftNode.balanceFactor;\n  }\n\n  leftNode.balanceFactor -= 1;\n  if (node.balanceFactor < 0) {\n    leftNode.balanceFactor += node.balanceFactor;\n  }\n\n  return leftNode;\n}\n\n// function leftBalance (node) {\n//   if (node.left.balanceFactor === -1) rotateLeft(node.left);\n//   return rotateRight(node);\n// }\n\n// function rightBalance (node) {\n//   if (node.right.balanceFactor === 1) rotateRight(node.right);\n//   return rotateLeft(node);\n// }\n\nexport default class AVLTree {\n  /**\n   * Callback for comparator\n   * @callback comparatorCallback\n   * @param {Key} a\n   * @param {Key} b\n   * @returns {number}\n   */\n\n  /**\n   * @class AVLTree\n   * @constructor\n   * @param  {comparatorCallback} [comparator]\n   * @param  {boolean}            [noDuplicates=false] Disallow duplicates\n   */\n  constructor (comparator, noDuplicates = false) {\n    this._comparator = comparator || DEFAULT_COMPARE;\n    this._root = null;\n    this._size = 0;\n    this._noDuplicates = !!noDuplicates;\n  }\n\n  /**\n   * Clear the tree\n   * @return {AVLTree}\n   */\n  destroy() {\n    return this.clear();\n  }\n\n  /**\n   * Clear the tree\n   * @return {AVLTree}\n   */\n  clear() {\n    this._root = null;\n    this._size = 0;\n    return this;\n  }\n\n  /**\n   * Number of nodes\n   * @return {number}\n   */\n  get size () {\n    return this._size;\n  }\n\n  /**\n   * Whether the tree contains a node with the given key\n   * @param  {Key} key\n   * @return {boolean} true/false\n   */\n  contains (key) {\n    if (this._root)  {\n      let node       = this._root;\n      let comparator = this._comparator;\n      while (node)  {\n        let cmp = comparator(key, node.key);\n        if      (cmp === 0) return true;\n        else if (cmp < 0)   node = node.left;\n        else                node = node.right;\n      }\n    }\n    return false;\n  }\n\n  /* eslint-disable class-methods-use-this */\n\n  /**\n   * Successor node\n   * @param  {Node} node\n   * @return {?Node}\n   */\n  next (node) {\n    let successor = node;\n    if (successor) {\n      if (successor.right) {\n        successor = successor.right;\n        while (successor.left) successor = successor.left;\n      } else {\n        successor = node.parent;\n        while (successor && successor.right === node) {\n          node = successor; successor = successor.parent;\n        }\n      }\n    }\n    return successor;\n  }\n\n  /**\n   * Predecessor node\n   * @param  {Node} node\n   * @return {?Node}\n   */\n  prev (node) {\n    let predecessor = node;\n    if (predecessor) {\n      if (predecessor.left) {\n        predecessor = predecessor.left;\n        while (predecessor.right) predecessor = predecessor.right;\n      } else {\n        predecessor = node.parent;\n        while (predecessor && predecessor.left === node) {\n          node = predecessor;\n          predecessor = predecessor.parent;\n        }\n      }\n    }\n    return predecessor;\n  }\n  /* eslint-enable class-methods-use-this */\n\n  /**\n   * Callback for forEach\n   * @callback forEachCallback\n   * @param {Node} node\n   * @param {number} index\n   */\n\n  /**\n   * @param  {forEachCallback} callback\n   * @return {AVLTree}\n   */\n  forEach(callback) {\n    let current = this._root;\n    let s = [], done = false, i = 0;\n\n    while (!done) {\n      // Reach the left most Node of the current Node\n      if (current) {\n        // Place pointer to a tree node on the stack\n        // before traversing the node's left subtree\n        s.push(current);\n        current = current.left;\n      } else {\n        // BackTrack from the empty subtree and visit the Node\n        // at the top of the stack; however, if the stack is\n        // empty you are done\n        if (s.length > 0) {\n          current = s.pop();\n          callback(current, i++);\n\n          // We have visited the node and its left\n          // subtree. Now, it's right subtree's turn\n          current = current.right;\n        } else done = true;\n      }\n    }\n    return this;\n  }\n\n  /**\n   * Walk key range from `low` to `high`. Stops if `fn` returns a value.\n   * @param  {Key}      low\n   * @param  {Key}      high\n   * @param  {Function} fn\n   * @param  {*?}       ctx\n   * @return {SplayTree}\n   */\n  range(low, high, fn, ctx) {\n    const Q = [];\n    const compare = this._comparator;\n    let node = this._root, cmp;\n\n    while (Q.length !== 0 || node) {\n      if (node) {\n        Q.push(node);\n        node = node.left;\n      } else {\n        node = Q.pop();\n        cmp = compare(node.key, high);\n        if (cmp > 0) {\n          break;\n        } else if (compare(node.key, low) >= 0) {\n          if (fn.call(ctx, node)) return this; // stop if smth is returned\n        }\n        node = node.right;\n      }\n    }\n    return this;\n  }\n\n  /**\n   * Returns all keys in order\n   * @return {Array<Key>}\n   */\n  keys () {\n    let current = this._root;\n    let s = [], r = [], done = false;\n\n    while (!done) {\n      if (current) {\n        s.push(current);\n        current = current.left;\n      } else {\n        if (s.length > 0) {\n          current = s.pop();\n          r.push(current.key);\n          current = current.right;\n        } else done = true;\n      }\n    }\n    return r;\n  }\n\n  /**\n   * Returns `data` fields of all nodes in order.\n   * @return {Array<Value>}\n   */\n  values () {\n    let current = this._root;\n    let s = [], r = [], done = false;\n\n    while (!done) {\n      if (current) {\n        s.push(current);\n        current = current.left;\n      } else {\n        if (s.length > 0) {\n          current = s.pop();\n          r.push(current.data);\n          current = current.right;\n        } else done = true;\n      }\n    }\n    return r;\n  }\n\n  /**\n   * Returns node at given index\n   * @param  {number} index\n   * @return {?Node}\n   */\n  at (index) {\n    // removed after a consideration, more misleading than useful\n    // index = index % this.size;\n    // if (index < 0) index = this.size - index;\n\n    let current = this._root;\n    let s = [], done = false, i = 0;\n\n    while (!done) {\n      if (current) {\n        s.push(current);\n        current = current.left;\n      } else {\n        if (s.length > 0) {\n          current = s.pop();\n          if (i === index) return current;\n          i++;\n          current = current.right;\n        } else done = true;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Returns node with the minimum key\n   * @return {?Node}\n   */\n  minNode () {\n    let node = this._root;\n    if (!node) return null;\n    while (node.left) node = node.left;\n    return node;\n  }\n\n  /**\n   * Returns node with the max key\n   * @return {?Node}\n   */\n  maxNode () {\n    let node = this._root;\n    if (!node) return null;\n    while (node.right) node = node.right;\n    return node;\n  }\n\n  /**\n   * Min key\n   * @return {?Key}\n   */\n  min () {\n    let node = this._root;\n    if (!node) return null;\n    while (node.left) node = node.left;\n    return node.key;\n  }\n\n  /**\n   * Max key\n   * @return {?Key}\n   */\n  max () {\n    let node = this._root;\n    if (!node) return null;\n    while (node.right) node = node.right;\n    return node.key;\n  }\n\n  /**\n   * @return {boolean} true/false\n   */\n  isEmpty() {\n    return !this._root;\n  }\n\n  /**\n   * Removes and returns the node with smallest key\n   * @return {?Node}\n   */\n  pop () {\n    let node = this._root, returnValue = null;\n    if (node) {\n      while (node.left) node = node.left;\n      returnValue = { key: node.key, data: node.data };\n      this.remove(node.key);\n    }\n    return returnValue;\n  }\n\n  /**\n   * Removes and returns the node with highest key\n   * @return {?Node}\n   */\n  popMax () {\n    let node = this._root, returnValue = null;\n    if (node) {\n      while (node.right) node = node.right;\n      returnValue = { key: node.key, data: node.data };\n      this.remove(node.key);\n    }\n    return returnValue;\n  }\n\n  /**\n   * Find node by key\n   * @param  {Key} key\n   * @return {?Node}\n   */\n  find (key) {\n    let root = this._root;\n    // if (root === null)    return null;\n    // if (key === root.key) return root;\n\n    let subtree = root, cmp;\n    let compare = this._comparator;\n    while (subtree) {\n      cmp = compare(key, subtree.key);\n      if      (cmp === 0) return subtree;\n      else if (cmp < 0)   subtree = subtree.left;\n      else                subtree = subtree.right;\n    }\n\n    return null;\n  }\n\n  /**\n   * Insert a node into the tree\n   * @param  {Key} key\n   * @param  {Value} [data]\n   * @return {?Node}\n   */\n  insert (key, data) {\n    if (!this._root) {\n      this._root = {\n        parent: null, left: null, right: null, balanceFactor: 0,\n        key, data\n      };\n      this._size++;\n      return this._root;\n    }\n\n    let compare = this._comparator;\n    let node    = this._root;\n    let parent  = null;\n    let cmp     = 0;\n\n    if (this._noDuplicates) {\n      while (node) {\n        cmp = compare(key, node.key);\n        parent = node;\n        if      (cmp === 0) return null;\n        else if (cmp < 0)   node = node.left;\n        else                node = node.right;\n      }\n    } else {\n      while (node) {\n        cmp = compare(key, node.key);\n        parent = node;\n        if      (cmp <= 0)  node = node.left; // return null;\n        else                node = node.right;\n      }\n    }\n\n    let newNode = {\n      left: null,\n      right: null,\n      balanceFactor: 0,\n      parent, key, data\n    };\n    let newRoot;\n    if (cmp <= 0) parent.left  = newNode;\n    else         parent.right = newNode;\n\n    while (parent) {\n      cmp = compare(parent.key, key);\n      if (cmp < 0) parent.balanceFactor -= 1;\n      else         parent.balanceFactor += 1;\n\n      if        (parent.balanceFactor === 0) break;\n      else if   (parent.balanceFactor < -1) {\n        // inlined\n        // var newRoot = rightBalance(parent);\n        if (parent.right.balanceFactor === 1) rotateRight(parent.right);\n        newRoot = rotateLeft(parent);\n\n        if (parent === this._root) this._root = newRoot;\n        break;\n      } else if (parent.balanceFactor > 1) {\n        // inlined\n        // var newRoot = leftBalance(parent);\n        if (parent.left.balanceFactor === -1) rotateLeft(parent.left);\n        newRoot = rotateRight(parent);\n\n        if (parent === this._root) this._root = newRoot;\n        break;\n      }\n      parent = parent.parent;\n    }\n\n    this._size++;\n    return newNode;\n  }\n\n  /**\n   * Removes the node from the tree. If not found, returns null.\n   * @param  {Key} key\n   * @return {?Node}\n   */\n  remove (key) {\n    if (!this._root) return null;\n\n    let node = this._root;\n    let compare = this._comparator;\n    let cmp = 0;\n\n    while (node) {\n      cmp = compare(key, node.key);\n      if      (cmp === 0) break;\n      else if (cmp < 0)   node = node.left;\n      else                node = node.right;\n    }\n    if (!node) return null;\n\n    let returnValue = node.key;\n    let max, min;\n\n    if (node.left) {\n      max = node.left;\n\n      while (max.left || max.right) {\n        while (max.right) max = max.right;\n\n        node.key = max.key;\n        node.data = max.data;\n        if (max.left) {\n          node = max;\n          max = max.left;\n        }\n      }\n\n      node.key  = max.key;\n      node.data = max.data;\n      node = max;\n    }\n\n    if (node.right) {\n      min = node.right;\n\n      while (min.left || min.right) {\n        while (min.left) min = min.left;\n\n        node.key  = min.key;\n        node.data = min.data;\n        if (min.right) {\n          node = min;\n          min = min.right;\n        }\n      }\n\n      node.key  = min.key;\n      node.data = min.data;\n      node = min;\n    }\n\n    let parent = node.parent;\n    let pp     = node;\n    let newRoot;\n\n    while (parent) {\n      if (parent.left === pp) parent.balanceFactor -= 1;\n      else                    parent.balanceFactor += 1;\n\n      if        (parent.balanceFactor < -1) {\n        // inlined\n        // var newRoot = rightBalance(parent);\n        if (parent.right.balanceFactor === 1) rotateRight(parent.right);\n        newRoot = rotateLeft(parent);\n\n        if (parent === this._root) this._root = newRoot;\n        parent = newRoot;\n      } else if (parent.balanceFactor > 1) {\n        // inlined\n        // var newRoot = leftBalance(parent);\n        if (parent.left.balanceFactor === -1) rotateLeft(parent.left);\n        newRoot = rotateRight(parent);\n\n        if (parent === this._root) this._root = newRoot;\n        parent = newRoot;\n      }\n\n      if (parent.balanceFactor === -1 || parent.balanceFactor === 1) break;\n\n      pp     = parent;\n      parent = parent.parent;\n    }\n\n    if (node.parent) {\n      if (node.parent.left === node) node.parent.left  = null;\n      else                           node.parent.right = null;\n    }\n\n    if (node === this._root) this._root = null;\n\n    this._size--;\n    return returnValue;\n  }\n\n  /**\n   * Bulk-load items\n   * @param  {Array<Key>}  keys\n   * @param  {Array<Value>}  [values]\n   * @param {boolean=} presort\n   * @return {AVLTree}\n   */\n  load(keys = [], values = [], presort = false) {\n    if (this._size !== 0) throw new Error(\"bulk-load: tree is not empty\");\n    const size = keys.length;\n    if (presort) sort(keys, values, 0, size - 1, this._comparator);\n    this._root = loadRecursive(null, keys, values, 0, size);\n    markBalance(this._root);\n    this._size = size;\n    return this;\n  }\n\n  /**\n   * Returns true if the tree is balanced\n   * @return {boolean}\n   */\n  isBalanced() {\n    return isBalanced(this._root);\n  }\n\n  /**\n   * String representation of the tree - primitive horizontal print-out\n   * @param  {function(Node):string} [printNode]\n   * @return {string}\n   */\n  toString (printNode) {\n    return print(this._root, printNode);\n  }\n}\n\nAVLTree.default = AVLTree;", "vendor/xmldom/LICENSE": "Copyright 2019 - present Christopher J. Brody and other contributors, as listed in: https://github.com/xmldom/xmldom/graphs/contributors\nCopyright 2012 - 2017 @jindw <jindw@xidea.org> and other contributors, as listed in: https://github.com/jindw/xmldom/graphs/contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "vendor/xmldom/sax.js": "// @ts-nocheck\n/* eslint-disable */\n\nimport { NAMESPACE } from './conventions.js';\n\n//[4]   \tNameStartChar\t   ::=   \t\":\" | [A-Z] | \"_\" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]\n//[4a]   \tNameChar\t   ::=   \tNameStartChar | \"-\" | \".\" | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]\n//[5]   \tName\t   ::=   \tNameStartChar (NameChar)*\nvar nameStartChar = /[A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]///\\u10000-\\uEFFFF\nvar nameChar = new RegExp(\"[\\\\-\\\\.0-9\"+nameStartChar.source.slice(1,-1)+\"\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040]\");\nvar tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\\:'+nameStartChar.source+nameChar.source+'*)?$');\n//var tagNamePattern = /^[a-zA-Z_][\\w\\-\\.]*(?:\\:[a-zA-Z_][\\w\\-\\.]*)?$/\n//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')\n\n//S_TAG,\tS_ATTR,\tS_EQ,\tS_ATTR_NOQUOT_VALUE\n//S_ATTR_SPACE,\tS_ATTR_END,\tS_TAG_SPACE, S_TAG_CLOSE\nvar S_TAG = 0;//tag name offerring\nvar S_ATTR = 1;//attr name offerring \nvar S_ATTR_SPACE=2;//attr name end and space offer\nvar S_EQ = 3;//=space?\nvar S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)\nvar S_ATTR_END = 5;//attr value end and no space(quot end)\nvar S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)\nvar S_TAG_CLOSE = 7;//closed el<el />\n\n/**\n * Creates an error that will not be caught by XMLReader aka the SAX parser.\n *\n * @param {string} message\n * @param {any?} locator Optional, can provide details about the location in the source\n * @constructor\n */\nexport function ParseError(message, locator) {\n\tthis.message = message\n\tthis.locator = locator\n\tif(Error.captureStackTrace) Error.captureStackTrace(this, ParseError);\n}\nParseError.prototype = new Error();\nParseError.prototype.name = ParseError.name\n\nexport function XMLReader(){\n\t\n}\n\nXMLReader.prototype = {\n\tparse:function(source,defaultNSMap,entityMap){\n\t\tvar domBuilder = this.domBuilder;\n\t\tdomBuilder.startDocument();\n\t\t_copy(defaultNSMap ,defaultNSMap = {})\n\t\tparse(source,defaultNSMap,entityMap,\n\t\t\t\tdomBuilder,this.errorHandler);\n\t\tdomBuilder.endDocument();\n\t}\n}\nfunction parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){\n\tfunction fixedFromCharCode(code) {\n\t\t// String.prototype.fromCharCode does not supports\n\t\t// > 2 bytes unicode chars directly\n\t\tif (code > 0xffff) {\n\t\t\tcode -= 0x10000;\n\t\t\tvar surrogate1 = 0xd800 + (code >> 10)\n\t\t\t\t, surrogate2 = 0xdc00 + (code & 0x3ff);\n\n\t\t\treturn String.fromCharCode(surrogate1, surrogate2);\n\t\t} else {\n\t\t\treturn String.fromCharCode(code);\n\t\t}\n\t}\n\tfunction entityReplacer(a){\n\t\tvar k = a.slice(1,-1);\n\t\tif(k in entityMap){\n\t\t\treturn entityMap[k]; \n\t\t}else if(k.charAt(0) === '#'){\n\t\t\treturn fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))\n\t\t}else{\n\t\t\terrorHandler.error('entity not found:'+a);\n\t\t\treturn a;\n\t\t}\n\t}\n\tfunction appendText(end){//has some bugs\n\t\tif(end>start){\n\t\t\tvar xt = source.substring(start,end).replace(/&#?\\w+;/g,entityReplacer);\n\t\t\tlocator&&position(start);\n\t\t\tdomBuilder.characters(xt,0,end-start);\n\t\t\tstart = end\n\t\t}\n\t}\n\tfunction position(p,m){\n\t\twhile(p>=lineEnd && (m = linePattern.exec(source))){\n\t\t\tlineStart = m.index;\n\t\t\tlineEnd = lineStart + m[0].length;\n\t\t\tlocator.lineNumber++;\n\t\t\t//console.log('line++:',locator,startPos,endPos)\n\t\t}\n\t\tlocator.columnNumber = p-lineStart+1;\n\t}\n\tvar lineStart = 0;\n\tvar lineEnd = 0;\n\tvar linePattern = /.*(?:\\r\\n?|\\n)|.*$/g\n\tvar locator = domBuilder.locator;\n\t\n\tvar parseStack = [{currentNSMap:defaultNSMapCopy}]\n\tvar closeMap = {};\n\tvar start = 0;\n\twhile(true){\n\t\ttry{\n\t\t\tvar tagStart = source.indexOf('<',start);\n\t\t\tif(tagStart<0){\n\t\t\t\tif(!source.substr(start).match(/^\\s*$/)){\n\t\t\t\t\tvar doc = domBuilder.doc;\n\t    \t\t\tvar text = doc.createTextNode(source.substr(start));\n\t    \t\t\tdoc.appendChild(text);\n\t    \t\t\tdomBuilder.currentElement = text;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(tagStart>start){\n\t\t\t\tappendText(tagStart);\n\t\t\t}\n\t\t\tswitch(source.charAt(tagStart+1)){\n\t\t\tcase '/':\n\t\t\t\tvar end = source.indexOf('>',tagStart+3);\n\t\t\t\tvar tagName = source.substring(tagStart+2,end);\n\t\t\t\tvar config = parseStack.pop();\n\t\t\t\tif(end<0){\n\t\t\t\t\t\n\t        \t\ttagName = source.substring(tagStart+2).replace(/[\\s<].*/,'');\n\t        \t\terrorHandler.error(\"end tag name: \"+tagName+' is not complete:'+config.tagName);\n\t        \t\tend = tagStart+1+tagName.length;\n\t        \t}else if(tagName.match(/\\s</)){\n\t        \t\ttagName = tagName.replace(/[\\s<].*/,'');\n\t        \t\terrorHandler.error(\"end tag name: \"+tagName+' maybe not complete');\n\t        \t\tend = tagStart+1+tagName.length;\n\t\t\t\t}\n\t\t\t\tvar localNSMap = config.localNSMap;\n\t\t\t\tvar endMatch = config.tagName == tagName;\n\t\t\t\tvar endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()\n\t\t        if(endIgnoreCaseMach){\n\t\t        \tdomBuilder.endElement(config.uri,config.localName,tagName);\n\t\t\t\t\tif(localNSMap){\n\t\t\t\t\t\tfor(var prefix in localNSMap){\n\t\t\t\t\t\t\tdomBuilder.endPrefixMapping(prefix) ;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(!endMatch){\n\t\t            \terrorHandler.fatalError(\"end tag name: \"+tagName+' is not match the current start tagName:'+config.tagName ); // No known test case\n\t\t\t\t\t}\n\t\t        }else{\n\t\t        \tparseStack.push(config)\n\t\t        }\n\t\t\t\t\n\t\t\t\tend++;\n\t\t\t\tbreak;\n\t\t\t\t// end elment\n\t\t\tcase '?':// <?...?>\n\t\t\t\tlocator&&position(tagStart);\n\t\t\t\tend = parseInstruction(source,tagStart,domBuilder);\n\t\t\t\tbreak;\n\t\t\tcase '!':// <!doctype,<![CDATA,<!--\n\t\t\t\tlocator&&position(tagStart);\n\t\t\t\tend = parseDCC(source,tagStart,domBuilder,errorHandler);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tlocator&&position(tagStart);\n\t\t\t\tvar el = new ElementAttributes();\n\t\t\t\tvar currentNSMap = parseStack[parseStack.length-1].currentNSMap;\n\t\t\t\t//elStartEnd\n\t\t\t\tvar end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);\n\t\t\t\tvar len = el.length;\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){\n\t\t\t\t\tel.closed = true;\n\t\t\t\t\tif(!entityMap.nbsp){\n\t\t\t\t\t\terrorHandler.warning('unclosed xml attribute');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(locator && len){\n\t\t\t\t\tvar locator2 = copyLocator(locator,{});\n\t\t\t\t\t//try{//attribute position fixed\n\t\t\t\t\tfor(var i = 0;i<len;i++){\n\t\t\t\t\t\tvar a = el[i];\n\t\t\t\t\t\tposition(a.offset);\n\t\t\t\t\t\ta.locator = copyLocator(locator,{});\n\t\t\t\t\t}\n\t\t\t\t\tdomBuilder.locator = locator2\n\t\t\t\t\tif(appendElement(el,domBuilder,currentNSMap)){\n\t\t\t\t\t\tparseStack.push(el)\n\t\t\t\t\t}\n\t\t\t\t\tdomBuilder.locator = locator;\n\t\t\t\t}else{\n\t\t\t\t\tif(appendElement(el,domBuilder,currentNSMap)){\n\t\t\t\t\t\tparseStack.push(el)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (NAMESPACE.isHTML(el.uri) && !el.closed) {\n\t\t\t\t\tend = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)\n\t\t\t\t} else {\n\t\t\t\t\tend++;\n\t\t\t\t}\n\t\t\t}\n\t\t}catch(e){\n\t\t\tif (e instanceof ParseError) {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\terrorHandler.error('element parse error: '+e)\n\t\t\tend = -1;\n\t\t}\n\t\tif(end>start){\n\t\t\tstart = end;\n\t\t}else{\n\t\t\t//TODO: \u8fd9\u91cc\u6709\u53ef\u80fdsax\u56de\u9000\uff0c\u6709\u4f4d\u7f6e\u9519\u8bef\u98ce\u9669\n\t\t\tappendText(Math.max(tagStart,start)+1);\n\t\t}\n\t}\n}\nfunction copyLocator(f,t){\n\tt.lineNumber = f.lineNumber;\n\tt.columnNumber = f.columnNumber;\n\treturn t;\n}\n\n/**\n * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);\n * @return end of the elementStartPart(end of elementEndPart for selfClosed el)\n */\nfunction parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){\n\n\t/**\n\t * @param {string} qname\n\t * @param {string} value\n\t * @param {number} startIndex\n\t */\n\tfunction addAttribute(qname, value, startIndex) {\n\t\tif (qname in el.attributeNames) errorHandler.fatalError('Attribute ' + qname + ' redefined')\n\t\tel.addValue(qname, value, startIndex)\n\t}\n\tvar attrName;\n\tvar value;\n\tvar p = ++start;\n\tvar s = S_TAG;//status\n\twhile(true){\n\t\tvar c = source.charAt(p);\n\t\tswitch(c){\n\t\tcase '=':\n\t\t\tif(s === S_ATTR){//attrName\n\t\t\t\tattrName = source.slice(start,p);\n\t\t\t\ts = S_EQ;\n\t\t\t}else if(s === S_ATTR_SPACE){\n\t\t\t\ts = S_EQ;\n\t\t\t}else{\n\t\t\t\t//fatalError: equal must after attrName or space after attrName\n\t\t\t\tthrow new Error('attribute equal must after attrName'); // No known test case\n\t\t\t}\n\t\t\tbreak;\n\t\tcase '\\'':\n\t\tcase '\"':\n\t\t\tif(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE\n\t\t\t\t){//equal\n\t\t\t\tif(s === S_ATTR){\n\t\t\t\t\terrorHandler.warning('attribute value must after \"=\"')\n\t\t\t\t\tattrName = source.slice(start,p)\n\t\t\t\t}\n\t\t\t\tstart = p+1;\n\t\t\t\tp = source.indexOf(c,start)\n\t\t\t\tif(p>0){\n\t\t\t\t\tvalue = source.slice(start,p).replace(/&#?\\w+;/g,entityReplacer);\n\t\t\t\t\taddAttribute(attrName, value, start-1);\n\t\t\t\t\ts = S_ATTR_END;\n\t\t\t\t}else{\n\t\t\t\t\t//fatalError: no end quot match\n\t\t\t\t\tthrow new Error('attribute value no end \\''+c+'\\' match');\n\t\t\t\t}\n\t\t\t}else if(s == S_ATTR_NOQUOT_VALUE){\n\t\t\t\tvalue = source.slice(start,p).replace(/&#?\\w+;/g,entityReplacer);\n\t\t\t\t//console.log(attrName,value,start,p)\n\t\t\t\taddAttribute(attrName, value, start);\n\t\t\t\t//console.dir(el)\n\t\t\t\terrorHandler.warning('attribute \"'+attrName+'\" missed start quot('+c+')!!');\n\t\t\t\tstart = p+1;\n\t\t\t\ts = S_ATTR_END\n\t\t\t}else{\n\t\t\t\t//fatalError: no equal before\n\t\t\t\tthrow new Error('attribute value must after \"=\"'); // No known test case\n\t\t\t}\n\t\t\tbreak;\n\t\tcase '/':\n\t\t\tswitch(s){\n\t\t\tcase S_TAG:\n\t\t\t\tel.setTagName(source.slice(start,p));\n\t\t\tcase S_ATTR_END:\n\t\t\tcase S_TAG_SPACE:\n\t\t\tcase S_TAG_CLOSE:\n\t\t\t\ts =S_TAG_CLOSE;\n\t\t\t\tel.closed = true;\n\t\t\tcase S_ATTR_NOQUOT_VALUE:\n\t\t\tcase S_ATTR:\n\t\t\tcase S_ATTR_SPACE:\n\t\t\t\tbreak;\n\t\t\t//case S_EQ:\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"attribute invalid close char('/')\") // No known test case\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ''://end document\n\t\t\terrorHandler.error('unexpected end of input');\n\t\t\tif(s == S_TAG){\n\t\t\t\tel.setTagName(source.slice(start,p));\n\t\t\t}\n\t\t\treturn p;\n\t\tcase '>':\n\t\t\tswitch(s){\n\t\t\tcase S_TAG:\n\t\t\t\tel.setTagName(source.slice(start,p));\n\t\t\tcase S_ATTR_END:\n\t\t\tcase S_TAG_SPACE:\n\t\t\tcase S_TAG_CLOSE:\n\t\t\t\tbreak;//normal\n\t\t\tcase S_ATTR_NOQUOT_VALUE://Compatible state\n\t\t\tcase S_ATTR:\n\t\t\t\tvalue = source.slice(start,p);\n\t\t\t\tif(value.slice(-1) === '/'){\n\t\t\t\t\tel.closed  = true;\n\t\t\t\t\tvalue = value.slice(0,-1)\n\t\t\t\t}\n\t\t\tcase S_ATTR_SPACE:\n\t\t\t\tif(s === S_ATTR_SPACE){\n\t\t\t\t\tvalue = attrName;\n\t\t\t\t}\n\t\t\t\tif(s == S_ATTR_NOQUOT_VALUE){\n\t\t\t\t\terrorHandler.warning('attribute \"'+value+'\" missed quot(\")!');\n\t\t\t\t\taddAttribute(attrName, value.replace(/&#?\\w+;/g,entityReplacer), start)\n\t\t\t\t}else{\n\t\t\t\t\tif(!NAMESPACE.isHTML(currentNSMap['']) || !value.match(/^(?:disabled|checked|selected)$/i)){\n\t\t\t\t\t\terrorHandler.warning('attribute \"'+value+'\" missed value!! \"'+value+'\" instead!!')\n\t\t\t\t\t}\n\t\t\t\t\taddAttribute(value, value, start)\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase S_EQ:\n\t\t\t\tthrow new Error('attribute value missed!!');\n\t\t\t}\n//\t\t\tconsole.log(tagName,tagNamePattern,tagNamePattern.test(tagName))\n\t\t\treturn p;\n\t\t/*xml space '\\x20' | #x9 | #xD | #xA; */\n\t\tcase '\\u0080':\n\t\t\tc = ' ';\n\t\tdefault:\n\t\t\tif(c<= ' '){//space\n\t\t\t\tswitch(s){\n\t\t\t\tcase S_TAG:\n\t\t\t\t\tel.setTagName(source.slice(start,p));//tagName\n\t\t\t\t\ts = S_TAG_SPACE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_ATTR:\n\t\t\t\t\tattrName = source.slice(start,p)\n\t\t\t\t\ts = S_ATTR_SPACE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_ATTR_NOQUOT_VALUE:\n\t\t\t\t\tvar value = source.slice(start,p).replace(/&#?\\w+;/g,entityReplacer);\n\t\t\t\t\terrorHandler.warning('attribute \"'+value+'\" missed quot(\")!!');\n\t\t\t\t\taddAttribute(attrName, value, start)\n\t\t\t\tcase S_ATTR_END:\n\t\t\t\t\ts = S_TAG_SPACE;\n\t\t\t\t\tbreak;\n\t\t\t\t//case S_TAG_SPACE:\n\t\t\t\t//case S_EQ:\n\t\t\t\t//case S_ATTR_SPACE:\n\t\t\t\t//\tvoid();break;\n\t\t\t\t//case S_TAG_CLOSE:\n\t\t\t\t\t//ignore warning\n\t\t\t\t}\n\t\t\t}else{//not space\n//S_TAG,\tS_ATTR,\tS_EQ,\tS_ATTR_NOQUOT_VALUE\n//S_ATTR_SPACE,\tS_ATTR_END,\tS_TAG_SPACE, S_TAG_CLOSE\n\t\t\t\tswitch(s){\n\t\t\t\t//case S_TAG:void();break;\n\t\t\t\t//case S_ATTR:void();break;\n\t\t\t\t//case S_ATTR_NOQUOT_VALUE:void();break;\n\t\t\t\tcase S_ATTR_SPACE:\n\t\t\t\t\tvar tagName =  el.tagName;\n\t\t\t\t\tif (!NAMESPACE.isHTML(currentNSMap['']) || !attrName.match(/^(?:disabled|checked|selected)$/i)) {\n\t\t\t\t\t\terrorHandler.warning('attribute \"'+attrName+'\" missed value!! \"'+attrName+'\" instead2!!')\n\t\t\t\t\t}\n\t\t\t\t\taddAttribute(attrName, attrName, start);\n\t\t\t\t\tstart = p;\n\t\t\t\t\ts = S_ATTR;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_ATTR_END:\n\t\t\t\t\terrorHandler.warning('attribute space is required\"'+attrName+'\"!!')\n\t\t\t\tcase S_TAG_SPACE:\n\t\t\t\t\ts = S_ATTR;\n\t\t\t\t\tstart = p;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_EQ:\n\t\t\t\t\ts = S_ATTR_NOQUOT_VALUE;\n\t\t\t\t\tstart = p;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_TAG_CLOSE:\n\t\t\t\t\tthrow new Error(\"elements closed character '/' and '>' must be connected to\");\n\t\t\t\t}\n\t\t\t}\n\t\t}//end outer switch\n\t\t//console.log('p++',p)\n\t\tp++;\n\t}\n}\n/**\n * @return true if has new namespace define\n */\nfunction appendElement(el,domBuilder,currentNSMap){\n\tvar tagName = el.tagName;\n\tvar localNSMap = null;\n\t//var currentNSMap = parseStack[parseStack.length-1].currentNSMap;\n\tvar i = el.length;\n\twhile(i--){\n\t\tvar a = el[i];\n\t\tvar qName = a.qName;\n\t\tvar value = a.value;\n\t\tvar nsp = qName.indexOf(':');\n\t\tif(nsp>0){\n\t\t\tvar prefix = a.prefix = qName.slice(0,nsp);\n\t\t\tvar localName = qName.slice(nsp+1);\n\t\t\tvar nsPrefix = prefix === 'xmlns' && localName\n\t\t}else{\n\t\t\tlocalName = qName;\n\t\t\tprefix = null\n\t\t\tnsPrefix = qName === 'xmlns' && ''\n\t\t}\n\t\t//can not set prefix,because prefix !== ''\n\t\ta.localName = localName ;\n\t\t//prefix == null for no ns prefix attribute \n\t\tif(nsPrefix !== false){//hack!!\n\t\t\tif(localNSMap == null){\n\t\t\t\tlocalNSMap = {}\n\t\t\t\t//console.log(currentNSMap,0)\n\t\t\t\t_copy(currentNSMap,currentNSMap={})\n\t\t\t\t//console.log(currentNSMap,1)\n\t\t\t}\n\t\t\tcurrentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;\n\t\t\ta.uri = NAMESPACE.XMLNS\n\t\t\tdomBuilder.startPrefixMapping(nsPrefix, value) \n\t\t}\n\t}\n\tvar i = el.length;\n\twhile(i--){\n\t\ta = el[i];\n\t\tvar prefix = a.prefix;\n\t\tif(prefix){//no prefix attribute has no namespace\n\t\t\tif(prefix === 'xml'){\n\t\t\t\ta.uri = NAMESPACE.XML;\n\t\t\t}if(prefix !== 'xmlns'){\n\t\t\t\ta.uri = currentNSMap[prefix || '']\n\t\t\t\t\n\t\t\t\t//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}\n\t\t\t}\n\t\t}\n\t}\n\tvar nsp = tagName.indexOf(':');\n\tif(nsp>0){\n\t\tprefix = el.prefix = tagName.slice(0,nsp);\n\t\tlocalName = el.localName = tagName.slice(nsp+1);\n\t}else{\n\t\tprefix = null;//important!!\n\t\tlocalName = el.localName = tagName;\n\t}\n\t//no prefix element has default namespace\n\tvar ns = el.uri = currentNSMap[prefix || ''];\n\tdomBuilder.startElement(ns,localName,tagName,el);\n\t//endPrefixMapping and startPrefixMapping have not any help for dom builder\n\t//localNSMap = null\n\tif(el.closed){\n\t\tdomBuilder.endElement(ns,localName,tagName);\n\t\tif(localNSMap){\n\t\t\tfor(prefix in localNSMap){\n\t\t\t\tdomBuilder.endPrefixMapping(prefix) \n\t\t\t}\n\t\t}\n\t}else{\n\t\tel.currentNSMap = currentNSMap;\n\t\tel.localNSMap = localNSMap;\n\t\t//parseStack.push(el);\n\t\treturn true;\n\t}\n}\nfunction parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){\n\tif(/^(?:script|textarea)$/i.test(tagName)){\n\t\tvar elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);\n\t\tvar text = source.substring(elStartEnd+1,elEndStart);\n\t\tif(/[&<]/.test(text)){\n\t\t\tif(/^script$/i.test(tagName)){\n\t\t\t\t//if(!/\\]\\]>/.test(text)){\n\t\t\t\t\t//lexHandler.startCDATA();\n\t\t\t\t\tdomBuilder.characters(text,0,text.length);\n\t\t\t\t\t//lexHandler.endCDATA();\n\t\t\t\t\treturn elEndStart;\n\t\t\t\t//}\n\t\t\t}//}else{//text area\n\t\t\t\ttext = text.replace(/&#?\\w+;/g,entityReplacer);\n\t\t\t\tdomBuilder.characters(text,0,text.length);\n\t\t\t\treturn elEndStart;\n\t\t\t//}\n\t\t\t\n\t\t}\n\t}\n\treturn elStartEnd+1;\n}\nfunction fixSelfClosed(source,elStartEnd,tagName,closeMap){\n\t//if(tagName in closeMap){\n\tvar pos = closeMap[tagName];\n\tif(pos == null){\n\t\t//console.log(tagName)\n\t\tpos =  source.lastIndexOf('</'+tagName+'>')\n\t\tif(pos<elStartEnd){//\u5fd8\u8bb0\u95ed\u5408\n\t\t\tpos = source.lastIndexOf('</'+tagName)\n\t\t}\n\t\tcloseMap[tagName] =pos\n\t}\n\treturn pos<elStartEnd;\n\t//} \n}\nfunction _copy(source,target){\n\tfor(var n in source){target[n] = source[n]}\n}\nfunction parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'\n\tvar next= source.charAt(start+2)\n\tswitch(next){\n\tcase '-':\n\t\tif(source.charAt(start + 3) === '-'){\n\t\t\tvar end = source.indexOf('-->',start+4);\n\t\t\t//append comment source.substring(4,end)//<!--\n\t\t\tif(end>start){\n\t\t\t\tdomBuilder.comment(source,start+4,end-start-4);\n\t\t\t\treturn end+3;\n\t\t\t}else{\n\t\t\t\terrorHandler.error(\"Unclosed comment\");\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}else{\n\t\t\t//error\n\t\t\treturn -1;\n\t\t}\n\tdefault:\n\t\tif(source.substr(start+3,6) == 'CDATA['){\n\t\t\tvar end = source.indexOf(']]>',start+9);\n\t\t\tdomBuilder.startCDATA();\n\t\t\tdomBuilder.characters(source,start+9,end-start-9);\n\t\t\tdomBuilder.endCDATA() \n\t\t\treturn end+3;\n\t\t}\n\t\t//<!DOCTYPE\n\t\t//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) \n\t\tvar matchs = split(source,start);\n\t\tvar len = matchs.length;\n\t\tif(len>1 && /!doctype/i.test(matchs[0][0])){\n\t\t\tvar name = matchs[1][0];\n\t\t\tvar pubid = false;\n\t\t\tvar sysid = false;\n\t\t\tif(len>3){\n\t\t\t\tif(/^public$/i.test(matchs[2][0])){\n\t\t\t\t\tpubid = matchs[3][0];\n\t\t\t\t\tsysid = len>4 && matchs[4][0];\n\t\t\t\t}else if(/^system$/i.test(matchs[2][0])){\n\t\t\t\t\tsysid = matchs[3][0];\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar lastMatch = matchs[len-1]\n\t\t\tdomBuilder.startDTD(name, pubid, sysid);\n\t\t\tdomBuilder.endDTD();\n\t\t\t\n\t\t\treturn lastMatch.index+lastMatch[0].length\n\t\t}\n\t}\n\treturn -1;\n}\n\n\n\nfunction parseInstruction(source,start,domBuilder){\n\tvar end = source.indexOf('?>',start);\n\tif(end){\n\t\tvar match = source.substring(start,end).match(/^<\\?(\\S*)\\s*([\\s\\S]*?)\\s*$/);\n\t\tif(match){\n\t\t\tvar len = match[0].length;\n\t\t\tdomBuilder.processingInstruction(match[1], match[2]) ;\n\t\t\treturn end+2;\n\t\t}else{//error\n\t\t\treturn -1;\n\t\t}\n\t}\n\treturn -1;\n}\n\nfunction ElementAttributes(){\n\tthis.attributeNames = {}\n}\nElementAttributes.prototype = {\n\tsetTagName:function(tagName){\n\t\tif(!tagNamePattern.test(tagName)){\n\t\t\tthrow new Error('invalid tagName:'+tagName)\n\t\t}\n\t\tthis.tagName = tagName\n\t},\n\taddValue:function(qName, value, offset) {\n\t\tif(!tagNamePattern.test(qName)){\n\t\t\tthrow new Error('invalid attribute:'+qName)\n\t\t}\n\t\tthis.attributeNames[qName] = this.length;\n\t\tthis[this.length++] = {qName:qName,value:value,offset:offset}\n\t},\n\tlength:0,\n\tgetLocalName:function(i){return this[i].localName},\n\tgetLocator:function(i){return this[i].locator},\n\tgetQName:function(i){return this[i].qName},\n\tgetURI:function(i){return this[i].uri},\n\tgetValue:function(i){return this[i].value}\n//\t,getIndex:function(uri, localName)){\n//\t\tif(localName){\n//\t\t\t\n//\t\t}else{\n//\t\t\tvar qName = uri\n//\t\t}\n//\t},\n//\tgetValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},\n//\tgetType:function(uri,localName){}\n//\tgetType:function(i){},\n}\n\n\n\nfunction split(source,start){\n\tvar match;\n\tvar buf = [];\n\tvar reg = /'[^']+'|\"[^\"]+\"|[^\\s<>\\/=]+=?|(\\/?\\s*>|<)/g;\n\treg.lastIndex = start;\n\treg.exec(source);//skip <\n\twhile(match = reg.exec(source)){\n\t\tbuf.push(match);\n\t\tif(match[1])return buf;\n\t}\n}\n\n", "vendor/xmldom/dom-parser.js": "// @ts-nocheck\n/* eslint-disable */\n\nimport * as conventions from './conventions.js';\nimport * as entities from './entities.js';\nimport { DOMImplementation as DI, XMLSerializer as XS } from './dom.js';\nimport * as sax from './sax.js';\n\nexport let DOMImplementation = DI;\nexport let XMLSerializer = XS;\n\nvar NAMESPACE = conventions.NAMESPACE;\n\nexport function DOMParser(options){\n\tthis.options = options ||{locator:{}};\n}\n\nDOMParser.prototype.parseFromString = function(source,mimeType){\n\tvar options = this.options;\n\tvar sax =  new XMLReader();\n\tvar domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler\n\tvar errorHandler = options.errorHandler;\n\tvar locator = options.locator;\n\tvar defaultNSMap = options.xmlns||{};\n\tvar isHTML = /\\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1;\n  \tvar entityMap = isHTML ? entities.HTML_ENTITIES : entities.XML_ENTITIES;\n\tif(locator){\n\t\tdomBuilder.setDocumentLocator(locator)\n\t}\n\n\tsax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);\n\tsax.domBuilder = options.domBuilder || domBuilder;\n\tif(isHTML){\n\t\tdefaultNSMap[''] = NAMESPACE.HTML;\n\t}\n\tdefaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML;\n\tif(source && typeof source === 'string'){\n\t\tsax.parse(source,defaultNSMap,entityMap);\n\t}else{\n\t\tsax.errorHandler.error(\"invalid doc source\");\n\t}\n\treturn domBuilder.doc;\n}\nfunction buildErrorHandler(errorImpl,domBuilder,locator){\n\tif(!errorImpl){\n\t\tif(domBuilder instanceof DOMHandler){\n\t\t\treturn domBuilder;\n\t\t}\n\t\terrorImpl = domBuilder ;\n\t}\n\tvar errorHandler = {}\n\tvar isCallback = errorImpl instanceof Function;\n\tlocator = locator||{}\n\tfunction build(key){\n\t\tvar fn = errorImpl[key];\n\t\tif(!fn && isCallback){\n\t\t\tfn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;\n\t\t}\n\t\terrorHandler[key] = fn && function(msg){\n\t\t\tfn('[xmldom '+key+']\\t'+msg+_locator(locator));\n\t\t}||function(){};\n\t}\n\tbuild('warning');\n\tbuild('error');\n\tbuild('fatalError');\n\treturn errorHandler;\n}\n\n//console.log('#\\n\\n\\n\\n\\n\\n\\n####')\n/**\n * +ContentHandler+ErrorHandler\n * +LexicalHandler+EntityResolver2\n * -DeclHandler-DTDHandler\n *\n * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler\n * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2\n * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html\n */\nfunction DOMHandler() {\n    this.cdata = false;\n}\nfunction position(locator,node){\n\tnode.lineNumber = locator.lineNumber;\n\tnode.columnNumber = locator.columnNumber;\n}\n/**\n * @see org.xml.sax.ContentHandler#startDocument\n * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html\n */\nDOMHandler.prototype = {\n\tstartDocument : function() {\n    \tthis.doc = new DOMImplementation().createDocument(null, null, null);\n    \tif (this.locator) {\n        \tthis.doc.documentURI = this.locator.systemId;\n    \t}\n\t},\n\tstartElement:function(namespaceURI, localName, qName, attrs) {\n\t\tvar doc = this.doc;\n\t    var el = doc.createElementNS(namespaceURI, qName||localName);\n\t    var len = attrs.length;\n\t    appendElement(this, el);\n\t    this.currentElement = el;\n\n\t\tthis.locator && position(this.locator,el)\n\t    for (var i = 0 ; i < len; i++) {\n\t        var namespaceURI = attrs.getURI(i);\n\t        var value = attrs.getValue(i);\n\t        var qName = attrs.getQName(i);\n\t\t\tvar attr = doc.createAttributeNS(namespaceURI, qName);\n\t\t\tthis.locator &&position(attrs.getLocator(i),attr);\n\t\t\tattr.value = attr.nodeValue = value;\n\t\t\tel.setAttributeNode(attr)\n\t    }\n\t},\n\tendElement:function(namespaceURI, localName, qName) {\n\t\tvar current = this.currentElement\n\t\tvar tagName = current.tagName;\n\t\tthis.currentElement = current.parentNode;\n\t},\n\tstartPrefixMapping:function(prefix, uri) {\n\t},\n\tendPrefixMapping:function(prefix) {\n\t},\n\tprocessingInstruction:function(target, data) {\n\t    var ins = this.doc.createProcessingInstruction(target, data);\n\t    this.locator && position(this.locator,ins)\n\t    appendElement(this, ins);\n\t},\n\tignorableWhitespace:function(ch, start, length) {\n\t},\n\tcharacters:function(chars, start, length) {\n\t\tchars = _toString.apply(this,arguments)\n\t\t//console.log(chars)\n\t\tif(chars){\n\t\t\tif (this.cdata) {\n\t\t\t\tvar charNode = this.doc.createCDATASection(chars);\n\t\t\t} else {\n\t\t\t\tvar charNode = this.doc.createTextNode(chars);\n\t\t\t}\n\t\t\tif(this.currentElement){\n\t\t\t\tthis.currentElement.appendChild(charNode);\n\t\t\t}else if(/^\\s*$/.test(chars)){\n\t\t\t\tthis.doc.appendChild(charNode);\n\t\t\t\t//process xml\n\t\t\t}\n\t\t\tthis.locator && position(this.locator,charNode)\n\t\t}\n\t},\n\tskippedEntity:function(name) {\n\t},\n\tendDocument:function() {\n\t\tthis.doc.normalize();\n\t},\n\tsetDocumentLocator:function (locator) {\n\t    if(this.locator = locator){// && !('lineNumber' in locator)){\n\t    \tlocator.lineNumber = 0;\n\t    }\n\t},\n\t//LexicalHandler\n\tcomment:function(chars, start, length) {\n\t\tchars = _toString.apply(this,arguments)\n\t    var comm = this.doc.createComment(chars);\n\t    this.locator && position(this.locator,comm)\n\t    appendElement(this, comm);\n\t},\n\n\tstartCDATA:function() {\n\t    //used in characters() methods\n\t    this.cdata = true;\n\t},\n\tendCDATA:function() {\n\t    this.cdata = false;\n\t},\n\n\tstartDTD:function(name, publicId, systemId) {\n\t\tvar impl = this.doc.implementation;\n\t    if (impl && impl.createDocumentType) {\n\t        var dt = impl.createDocumentType(name, publicId, systemId);\n\t        this.locator && position(this.locator,dt)\n\t        appendElement(this, dt);\n\t    }\n\t},\n\t/**\n\t * @see org.xml.sax.ErrorHandler\n\t * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html\n\t */\n\twarning:function(error) {\n\t\tconsole.warn('[xmldom warning]\\t'+error,_locator(this.locator));\n\t},\n\terror:function(error) {\n\t\tconsole.error('[xmldom error]\\t'+error,_locator(this.locator));\n\t},\n\tfatalError:function(error) {\n\t\tthrow new ParseError(error, this.locator);\n\t}\n}\nfunction _locator(l){\n\tif(l){\n\t\treturn '\\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'\n\t}\n}\nfunction _toString(chars,start,length){\n\tif(typeof chars == 'string'){\n\t\treturn chars.substr(start,length)\n\t}else{//java sax connect width xmldom on rhino(what about: \"? && !(chars instanceof String)\")\n\t\tif(chars.length >= start+length || start){\n\t\t\treturn new java.lang.String(chars,start,length)+'';\n\t\t}\n\t\treturn chars;\n\t}\n}\n\n/*\n * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html\n * used method of org.xml.sax.ext.LexicalHandler:\n *  #comment(chars, start, length)\n *  #startCDATA()\n *  #endCDATA()\n *  #startDTD(name, publicId, systemId)\n *\n *\n * IGNORED method of org.xml.sax.ext.LexicalHandler:\n *  #endDTD()\n *  #startEntity(name)\n *  #endEntity(name)\n *\n *\n * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html\n * IGNORED method of org.xml.sax.ext.DeclHandler\n * \t#attributeDecl(eName, aName, type, mode, value)\n *  #elementDecl(name, model)\n *  #externalEntityDecl(name, publicId, systemId)\n *  #internalEntityDecl(name, value)\n * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html\n * IGNORED method of org.xml.sax.EntityResolver2\n *  #resolveEntity(String name,String publicId,String baseURI,String systemId)\n *  #resolveEntity(publicId, systemId)\n *  #getExternalSubset(name, baseURI)\n * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html\n * IGNORED method of org.xml.sax.DTDHandler\n *  #notationDecl(name, publicId, systemId) {};\n *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};\n */\n\"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl\".replace(/\\w+/g,function(key){\n\tDOMHandler.prototype[key] = function(){return null}\n})\n\n/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */\nfunction appendElement (hander,node) {\n    if (!hander.currentElement) {\n        hander.doc.appendChild(node);\n    } else {\n        hander.currentElement.appendChild(node);\n    }\n}//appendChild and setAttributeNS are preformance key\n\n//if(typeof require == 'function'){;\nvar XMLReader = sax.XMLReader;\nvar ParseError = sax.ParseError;\n\nexport let __DOMHandler = DOMHandler;\n//}\n", "vendor/xmldom/entities.js": "// @ts-nocheck\n/* eslint-disable */\n\nimport { freeze } from './conventions.js';\n\n/**\n * The entities that are predefined in every XML document.\n *\n * @see https://www.w3.org/TR/2006/REC-xml11-20060816/#sec-predefined-ent W3C XML 1.1\n * @see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent W3C XML 1.0\n * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML Wikipedia\n */\nexport let XML_ENTITIES = freeze({amp:'&', apos:\"'\", gt:'>', lt:'<', quot:'\"'})\n\n/**\n * A map of currently 241 entities that are detected in an HTML document.\n * They contain all entries from `XML_ENTITIES`.\n *\n * @see XML_ENTITIES\n * @see DOMParser.parseFromString\n * @see DOMImplementation.prototype.createHTMLDocument\n * @see https://html.spec.whatwg.org/#named-character-references WHATWG HTML(5) Spec\n * @see https://www.w3.org/TR/xml-entity-names/ W3C XML Entity Names\n * @see https://www.w3.org/TR/html4/sgml/entities.html W3C HTML4/SGML\n * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Character_entity_references_in_HTML Wikipedia (HTML)\n * @see https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Entities_representing_special_characters_in_XHTML Wikpedia (XHTML)\n */\nexport let HTML_ENTITIES = freeze({\n       lt: '<',\n       gt: '>',\n       amp: '&',\n       quot: '\"',\n       apos: \"'\",\n       Agrave: \"\u00c0\",\n       Aacute: \"\u00c1\",\n       Acirc: \"\u00c2\",\n       Atilde: \"\u00c3\",\n       Auml: \"\u00c4\",\n       Aring: \"\u00c5\",\n       AElig: \"\u00c6\",\n       Ccedil: \"\u00c7\",\n       Egrave: \"\u00c8\",\n       Eacute: \"\u00c9\",\n       Ecirc: \"\u00ca\",\n       Euml: \"\u00cb\",\n       Igrave: \"\u00cc\",\n       Iacute: \"\u00cd\",\n       Icirc: \"\u00ce\",\n       Iuml: \"\u00cf\",\n       ETH: \"\u00d0\",\n       Ntilde: \"\u00d1\",\n       Ograve: \"\u00d2\",\n       Oacute: \"\u00d3\",\n       Ocirc: \"\u00d4\",\n       Otilde: \"\u00d5\",\n       Ouml: \"\u00d6\",\n       Oslash: \"\u00d8\",\n       Ugrave: \"\u00d9\",\n       Uacute: \"\u00da\",\n       Ucirc: \"\u00db\",\n       Uuml: \"\u00dc\",\n       Yacute: \"\u00dd\",\n       THORN: \"\u00de\",\n       szlig: \"\u00df\",\n       agrave: \"\u00e0\",\n       aacute: \"\u00e1\",\n       acirc: \"\u00e2\",\n       atilde: \"\u00e3\",\n       auml: \"\u00e4\",\n       aring: \"\u00e5\",\n       aelig: \"\u00e6\",\n       ccedil: \"\u00e7\",\n       egrave: \"\u00e8\",\n       eacute: \"\u00e9\",\n       ecirc: \"\u00ea\",\n       euml: \"\u00eb\",\n       igrave: \"\u00ec\",\n       iacute: \"\u00ed\",\n       icirc: \"\u00ee\",\n       iuml: \"\u00ef\",\n       eth: \"\u00f0\",\n       ntilde: \"\u00f1\",\n       ograve: \"\u00f2\",\n       oacute: \"\u00f3\",\n       ocirc: \"\u00f4\",\n       otilde: \"\u00f5\",\n       ouml: \"\u00f6\",\n       oslash: \"\u00f8\",\n       ugrave: \"\u00f9\",\n       uacute: \"\u00fa\",\n       ucirc: \"\u00fb\",\n       uuml: \"\u00fc\",\n       yacute: \"\u00fd\",\n       thorn: \"\u00fe\",\n       yuml: \"\u00ff\",\n       nbsp: \"\\u00a0\",\n       iexcl: \"\u00a1\",\n       cent: \"\u00a2\",\n       pound: \"\u00a3\",\n       curren: \"\u00a4\",\n       yen: \"\u00a5\",\n       brvbar: \"\u00a6\",\n       sect: \"\u00a7\",\n       uml: \"\u00a8\",\n       copy: \"\u00a9\",\n       ordf: \"\u00aa\",\n       laquo: \"\u00ab\",\n       not: \"\u00ac\",\n       shy: \"\u00ad\u00ad\",\n       reg: \"\u00ae\",\n       macr: \"\u00af\",\n       deg: \"\u00b0\",\n       plusmn: \"\u00b1\",\n       sup2: \"\u00b2\",\n       sup3: \"\u00b3\",\n       acute: \"\u00b4\",\n       micro: \"\u00b5\",\n       para: \"\u00b6\",\n       middot: \"\u00b7\",\n       cedil: \"\u00b8\",\n       sup1: \"\u00b9\",\n       ordm: \"\u00ba\",\n       raquo: \"\u00bb\",\n       frac14: \"\u00bc\",\n       frac12: \"\u00bd\",\n       frac34: \"\u00be\",\n       iquest: \"\u00bf\",\n       times: \"\u00d7\",\n       divide: \"\u00f7\",\n       forall: \"\u2200\",\n       part: \"\u2202\",\n       exist: \"\u2203\",\n       empty: \"\u2205\",\n       nabla: \"\u2207\",\n       isin: \"\u2208\",\n       notin: \"\u2209\",\n       ni: \"\u220b\",\n       prod: \"\u220f\",\n       sum: \"\u2211\",\n       minus: \"\u2212\",\n       lowast: \"\u2217\",\n       radic: \"\u221a\",\n       prop: \"\u221d\",\n       infin: \"\u221e\",\n       ang: \"\u2220\",\n       and: \"\u2227\",\n       or: \"\u2228\",\n       cap: \"\u2229\",\n       cup: \"\u222a\",\n       'int': \"\u222b\",\n       there4: \"\u2234\",\n       sim: \"\u223c\",\n       cong: \"\u2245\",\n       asymp: \"\u2248\",\n       ne: \"\u2260\",\n       equiv: \"\u2261\",\n       le: \"\u2264\",\n       ge: \"\u2265\",\n       sub: \"\u2282\",\n       sup: \"\u2283\",\n       nsub: \"\u2284\",\n       sube: \"\u2286\",\n       supe: \"\u2287\",\n       oplus: \"\u2295\",\n       otimes: \"\u2297\",\n       perp: \"\u22a5\",\n       sdot: \"\u22c5\",\n       Alpha: \"\u0391\",\n       Beta: \"\u0392\",\n       Gamma: \"\u0393\",\n       Delta: \"\u0394\",\n       Epsilon: \"\u0395\",\n       Zeta: \"\u0396\",\n       Eta: \"\u0397\",\n       Theta: \"\u0398\",\n       Iota: \"\u0399\",\n       Kappa: \"\u039a\",\n       Lambda: \"\u039b\",\n       Mu: \"\u039c\",\n       Nu: \"\u039d\",\n       Xi: \"\u039e\",\n       Omicron: \"\u039f\",\n       Pi: \"\u03a0\",\n       Rho: \"\u03a1\",\n       Sigma: \"\u03a3\",\n       Tau: \"\u03a4\",\n       Upsilon: \"\u03a5\",\n       Phi: \"\u03a6\",\n       Chi: \"\u03a7\",\n       Psi: \"\u03a8\",\n       Omega: \"\u03a9\",\n       alpha: \"\u03b1\",\n       beta: \"\u03b2\",\n       gamma: \"\u03b3\",\n       delta: \"\u03b4\",\n       epsilon: \"\u03b5\",\n       zeta: \"\u03b6\",\n       eta: \"\u03b7\",\n       theta: \"\u03b8\",\n       iota: \"\u03b9\",\n       kappa: \"\u03ba\",\n       lambda: \"\u03bb\",\n       mu: \"\u03bc\",\n       nu: \"\u03bd\",\n       xi: \"\u03be\",\n       omicron: \"\u03bf\",\n       pi: \"\u03c0\",\n       rho: \"\u03c1\",\n       sigmaf: \"\u03c2\",\n       sigma: \"\u03c3\",\n       tau: \"\u03c4\",\n       upsilon: \"\u03c5\",\n       phi: \"\u03c6\",\n       chi: \"\u03c7\",\n       psi: \"\u03c8\",\n       omega: \"\u03c9\",\n       thetasym: \"\u03d1\",\n       upsih: \"\u03d2\",\n       piv: \"\u03d6\",\n       OElig: \"\u0152\",\n       oelig: \"\u0153\",\n       Scaron: \"\u0160\",\n       scaron: \"\u0161\",\n       Yuml: \"\u0178\",\n       fnof: \"\u0192\",\n       circ: \"\u02c6\",\n       tilde: \"\u02dc\",\n       ensp: \"\u2002\",\n       emsp: \"\u2003\",\n       thinsp: \"\u2009\",\n       zwnj: \"\u200c\",\n       zwj: \"\u200d\",\n       lrm: \"\u200e\",\n       rlm: \"\u200f\",\n       ndash: \"\u2013\",\n       mdash: \"\u2014\",\n       lsquo: \"\u2018\",\n       rsquo: \"\u2019\",\n       sbquo: \"\u201a\",\n       ldquo: \"\u201c\",\n       rdquo: \"\u201d\",\n       bdquo: \"\u201e\",\n       dagger: \"\u2020\",\n       Dagger: \"\u2021\",\n       bull: \"\u2022\",\n       hellip: \"\u2026\",\n       permil: \"\u2030\",\n       prime: \"\u2032\",\n       Prime: \"\u2033\",\n       lsaquo: \"\u2039\",\n       rsaquo: \"\u203a\",\n       oline: \"\u203e\",\n       euro: \"\u20ac\",\n       trade: \"\u2122\",\n       larr: \"\u2190\",\n       uarr: \"\u2191\",\n       rarr: \"\u2192\",\n       darr: \"\u2193\",\n       harr: \"\u2194\",\n       crarr: \"\u21b5\",\n       lceil: \"\u2308\",\n       rceil: \"\u2309\",\n       lfloor: \"\u230a\",\n       rfloor: \"\u230b\",\n       loz: \"\u25ca\",\n       spades: \"\u2660\",\n       clubs: \"\u2663\",\n       hearts: \"\u2665\",\n       diams: \"\u2666\"\n});\n", "vendor/xmldom/dom.js": "// @ts-nocheck\n/* eslint-disable */\n\nimport * as conventions from './conventions.js';\n\nvar NAMESPACE = conventions.NAMESPACE;\n\nfunction copy(src,dest){\n\tfor(var p in src){\n\t\tdest[p] = src[p];\n\t}\n}\n\n/**\n^\\w+\\.prototype\\.([_\\w]+)\\s*=\\s*((?:.*\\{\\s*?[\\r\\n][\\s\\S]*?^})|\\S.*?(?=[;\\r\\n]));?\n^\\w+\\.prototype\\.([_\\w]+)\\s*=\\s*(\\S.*?(?=[;\\r\\n]));?\n */\nfunction _extends(Class,Super){\n\tvar pt = Class.prototype;\n\tif(!(pt instanceof Super)){\n\t\tfunction t(){};\n\t\tt.prototype = Super.prototype;\n\t\tt = new t();\n\t\tcopy(pt,t);\n\t\tClass.prototype = pt = t;\n\t}\n\tif(pt.constructor != Class){\n\t\tif(typeof Class != 'function'){\n\t\t\tconsole.error(\"unknow Class:\"+Class)\n\t\t}\n\t\tpt.constructor = Class\n\t}\n}\n\n// Node Types\nvar NodeType = {}\nvar ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;\nvar ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;\nvar TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;\nvar CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;\nvar ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;\nvar ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;\nvar PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;\nvar COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;\nvar DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;\nvar DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;\nvar DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;\nvar NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;\n\n// ExceptionCode\nvar ExceptionCode = {}\nvar ExceptionMessage = {};\nvar INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]=\"Index size error\"),1);\nvar DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]=\"DOMString size error\"),2);\nvar HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]=\"Hierarchy request error\"),3);\nvar WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]=\"Wrong document\"),4);\nvar INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]=\"Invalid character\"),5);\nvar NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]=\"No data allowed\"),6);\nvar NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]=\"No modification allowed\"),7);\nvar NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]=\"Not found\"),8);\nvar NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]=\"Not supported\"),9);\nvar INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]=\"Attribute in use\"),10);\n//level2\nvar INVALID_STATE_ERR        \t= ExceptionCode.INVALID_STATE_ERR        \t= ((ExceptionMessage[11]=\"Invalid state\"),11);\nvar SYNTAX_ERR               \t= ExceptionCode.SYNTAX_ERR               \t= ((ExceptionMessage[12]=\"Syntax error\"),12);\nvar INVALID_MODIFICATION_ERR \t= ExceptionCode.INVALID_MODIFICATION_ERR \t= ((ExceptionMessage[13]=\"Invalid modification\"),13);\nvar NAMESPACE_ERR            \t= ExceptionCode.NAMESPACE_ERR           \t= ((ExceptionMessage[14]=\"Invalid namespace\"),14);\nvar INVALID_ACCESS_ERR       \t= ExceptionCode.INVALID_ACCESS_ERR      \t= ((ExceptionMessage[15]=\"Invalid access\"),15);\n\n/**\n * DOM Level 2\n * Object DOMException\n * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html\n * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html\n */\nexport function DOMException(code, message) {\n\tif(message instanceof Error){\n\t\tvar error = message;\n\t}else{\n\t\terror = this;\n\t\tError.call(this, ExceptionMessage[code]);\n\t\tthis.message = ExceptionMessage[code];\n\t\tif(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);\n\t}\n\terror.code = code;\n\tif(message) this.message = this.message + \": \" + message;\n\treturn error;\n};\nDOMException.prototype = Error.prototype;\ncopy(ExceptionCode,DOMException)\n\n/**\n * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177\n * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.\n * The items in the NodeList are accessible via an integral index, starting from 0.\n */\nexport function NodeList() {\n};\nNodeList.prototype = {\n\t/**\n\t * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.\n\t * @standard level1\n\t */\n\tlength:0, \n\t/**\n\t * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.\n\t * @standard level1\n\t * @param index  unsigned long \n\t *   Index into the collection.\n\t * @return Node\n\t * \tThe node at the indexth position in the NodeList, or null if that is not a valid index. \n\t */\n\titem: function(index) {\n\t\treturn this[index] || null;\n\t},\n\ttoString:function(isHTML,nodeFilter){\n\t\tfor(var buf = [], i = 0;i<this.length;i++){\n\t\t\tserializeToString(this[i],buf,isHTML,nodeFilter);\n\t\t}\n\t\treturn buf.join('');\n\t}\n};\n\nfunction LiveNodeList(node,refresh){\n\tthis._node = node;\n\tthis._refresh = refresh\n\t_updateLiveList(this);\n}\nfunction _updateLiveList(list){\n\tvar inc = list._node._inc || list._node.ownerDocument._inc;\n\tif(list._inc != inc){\n\t\tvar ls = list._refresh(list._node);\n\t\t//console.log(ls.length)\n\t\t__set__(list,'length',ls.length);\n\t\tcopy(ls,list);\n\t\tlist._inc = inc;\n\t}\n}\nLiveNodeList.prototype.item = function(i){\n\t_updateLiveList(this);\n\treturn this[i];\n}\n\n_extends(LiveNodeList,NodeList);\n\n/**\n * Objects implementing the NamedNodeMap interface are used\n * to represent collections of nodes that can be accessed by name.\n * Note that NamedNodeMap does not inherit from NodeList;\n * NamedNodeMaps are not maintained in any particular order.\n * Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index,\n * but this is simply to allow convenient enumeration of the contents of a NamedNodeMap,\n * and does not imply that the DOM specifies an order to these Nodes.\n * NamedNodeMap objects in the DOM are live.\n * used for attributes or DocumentType entities \n */\nfunction NamedNodeMap() {\n};\n\nfunction _findNodeIndex(list,node){\n\tvar i = list.length;\n\twhile(i--){\n\t\tif(list[i] === node){return i}\n\t}\n}\n\nfunction _addNamedNode(el,list,newAttr,oldAttr){\n\tif(oldAttr){\n\t\tlist[_findNodeIndex(list,oldAttr)] = newAttr;\n\t}else{\n\t\tlist[list.length++] = newAttr;\n\t}\n\tif(el){\n\t\tnewAttr.ownerElement = el;\n\t\tvar doc = el.ownerDocument;\n\t\tif(doc){\n\t\t\toldAttr && _onRemoveAttribute(doc,el,oldAttr);\n\t\t\t_onAddAttribute(doc,el,newAttr);\n\t\t}\n\t}\n}\nfunction _removeNamedNode(el,list,attr){\n\t//console.log('remove attr:'+attr)\n\tvar i = _findNodeIndex(list,attr);\n\tif(i>=0){\n\t\tvar lastIndex = list.length-1\n\t\twhile(i<lastIndex){\n\t\t\tlist[i] = list[++i]\n\t\t}\n\t\tlist.length = lastIndex;\n\t\tif(el){\n\t\t\tvar doc = el.ownerDocument;\n\t\t\tif(doc){\n\t\t\t\t_onRemoveAttribute(doc,el,attr);\n\t\t\t\tattr.ownerElement = null;\n\t\t\t}\n\t\t}\n\t}else{\n\t\tthrow DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))\n\t}\n}\nNamedNodeMap.prototype = {\n\tlength:0,\n\titem:NodeList.prototype.item,\n\tgetNamedItem: function(key) {\n//\t\tif(key.indexOf(':')>0 || key == 'xmlns'){\n//\t\t\treturn null;\n//\t\t}\n\t\t//console.log()\n\t\tvar i = this.length;\n\t\twhile(i--){\n\t\t\tvar attr = this[i];\n\t\t\t//console.log(attr.nodeName,key)\n\t\t\tif(attr.nodeName == key){\n\t\t\t\treturn attr;\n\t\t\t}\n\t\t}\n\t},\n\tsetNamedItem: function(attr) {\n\t\tvar el = attr.ownerElement;\n\t\tif(el && el!=this._ownerElement){\n\t\t\tthrow new DOMException(INUSE_ATTRIBUTE_ERR);\n\t\t}\n\t\tvar oldAttr = this.getNamedItem(attr.nodeName);\n\t\t_addNamedNode(this._ownerElement,this,attr,oldAttr);\n\t\treturn oldAttr;\n\t},\n\t/* returns Node */\n\tsetNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR\n\t\tvar el = attr.ownerElement, oldAttr;\n\t\tif(el && el!=this._ownerElement){\n\t\t\tthrow new DOMException(INUSE_ATTRIBUTE_ERR);\n\t\t}\n\t\toldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);\n\t\t_addNamedNode(this._ownerElement,this,attr,oldAttr);\n\t\treturn oldAttr;\n\t},\n\n\t/* returns Node */\n\tremoveNamedItem: function(key) {\n\t\tvar attr = this.getNamedItem(key);\n\t\t_removeNamedNode(this._ownerElement,this,attr);\n\t\treturn attr;\n\t\t\n\t\t\n\t},// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR\n\t\n\t//for level2\n\tremoveNamedItemNS:function(namespaceURI,localName){\n\t\tvar attr = this.getNamedItemNS(namespaceURI,localName);\n\t\t_removeNamedNode(this._ownerElement,this,attr);\n\t\treturn attr;\n\t},\n\tgetNamedItemNS: function(namespaceURI, localName) {\n\t\tvar i = this.length;\n\t\twhile(i--){\n\t\t\tvar node = this[i];\n\t\t\tif(node.localName == localName && node.namespaceURI == namespaceURI){\n\t\t\t\treturn node;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n};\n\n/**\n * The DOMImplementation interface represents an object providing methods\n * which are not dependent on any particular document.\n * Such an object is returned by the `Document.implementation` property.\n *\n * __The individual methods describe the differences compared to the specs.__\n *\n * @constructor\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation MDN\n * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 DOM Level 1 Core (Initial)\n * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-102161490 DOM Level 2 Core\n * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-102161490 DOM Level 3 Core\n * @see https://dom.spec.whatwg.org/#domimplementation DOM Living Standard\n */\nexport function DOMImplementation() {\n}\n\nDOMImplementation.prototype = {\n\t/**\n\t * The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given feature is supported.\n\t * The different implementations fairly diverged in what kind of features were reported.\n\t * The latest version of the spec settled to force this method to always return true, where the functionality was accurate and in use.\n\t *\n\t * @deprecated It is deprecated and modern browsers return true in all cases.\n\t *\n\t * @param {string} feature\n\t * @param {string} [version]\n\t * @returns {boolean} always true\n\t *\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/hasFeature MDN\n\t * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-5CED94D7 DOM Level 1 Core\n\t * @see https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature DOM Living Standard\n\t */\n\thasFeature: function(feature, version) {\n\t\t\treturn true;\n\t},\n\t/**\n\t * Creates an XML Document object of the specified type with its document element.\n\t *\n\t * __It behaves slightly different from the description in the living standard__:\n\t * - There is no interface/class `XMLDocument`, it returns a `Document` instance.\n\t * - `contentType`, `encoding`, `mode`, `origin`, `url` fields are currently not declared.\n\t * - this implementation is not validating names or qualified names\n\t *   (when parsing XML strings, the SAX parser takes care of that)\n\t *\n\t * @param {string|null} namespaceURI\n\t * @param {string} qualifiedName\n\t * @param {DocumentType=null} doctype\n\t * @returns {Document}\n\t *\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN\n\t * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial)\n\t * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument  DOM Level 2 Core\n\t *\n\t * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract\n\t * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names\n\t * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names\n\t */\n\tcreateDocument: function(namespaceURI,  qualifiedName, doctype){\n\t\tvar doc = new Document();\n\t\tdoc.implementation = this;\n\t\tdoc.childNodes = new NodeList();\n\t\tdoc.doctype = doctype || null;\n\t\tif (doctype){\n\t\t\tdoc.appendChild(doctype);\n\t\t}\n\t\tif (qualifiedName){\n\t\t\tvar root = doc.createElementNS(namespaceURI, qualifiedName);\n\t\t\tdoc.appendChild(root);\n\t\t}\n\t\treturn doc;\n\t},\n\t/**\n\t * Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`.\n\t *\n\t * __This behavior is slightly different from the in the specs__:\n\t * - this implementation is not validating names or qualified names\n\t *   (when parsing XML strings, the SAX parser takes care of that)\n\t *\n\t * @param {string} qualifiedName\n\t * @param {string} [publicId]\n\t * @param {string} [systemId]\n\t * @returns {DocumentType} which can either be used with `DOMImplementation.createDocument` upon document creation\n\t * \t\t\t\t  or can be put into the document via methods like `Node.insertBefore()` or `Node.replaceChild()`\n\t *\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN\n\t * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core\n\t * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard\n\t *\n\t * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract\n\t * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names\n\t * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names\n\t */\n\tcreateDocumentType: function(qualifiedName, publicId, systemId){\n\t\tvar node = new DocumentType();\n\t\tnode.name = qualifiedName;\n\t\tnode.nodeName = qualifiedName;\n\t\tnode.publicId = publicId || '';\n\t\tnode.systemId = systemId || '';\n\n\t\treturn node;\n\t}\n};\n\n\n/**\n * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247\n */\n\nexport function Node() {\n};\n\nNode.prototype = {\n\tfirstChild : null,\n\tlastChild : null,\n\tpreviousSibling : null,\n\tnextSibling : null,\n\tattributes : null,\n\tparentNode : null,\n\tchildNodes : null,\n\townerDocument : null,\n\tnodeValue : null,\n\tnamespaceURI : null,\n\tprefix : null,\n\tlocalName : null,\n\t// Modified in DOM Level 2:\n\tinsertBefore:function(newChild, refChild){//raises \n\t\treturn _insertBefore(this,newChild,refChild);\n\t},\n\treplaceChild:function(newChild, oldChild){//raises \n\t\tthis.insertBefore(newChild,oldChild);\n\t\tif(oldChild){\n\t\t\tthis.removeChild(oldChild);\n\t\t}\n\t},\n\tremoveChild:function(oldChild){\n\t\treturn _removeChild(this,oldChild);\n\t},\n\tappendChild:function(newChild){\n\t\treturn this.insertBefore(newChild,null);\n\t},\n\thasChildNodes:function(){\n\t\treturn this.firstChild != null;\n\t},\n\tcloneNode:function(deep){\n\t\treturn cloneNode(this.ownerDocument||this,this,deep);\n\t},\n\t// Modified in DOM Level 2:\n\tnormalize:function(){\n\t\tvar child = this.firstChild;\n\t\twhile(child){\n\t\t\tvar next = child.nextSibling;\n\t\t\tif(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){\n\t\t\t\tthis.removeChild(next);\n\t\t\t\tchild.appendData(next.data);\n\t\t\t}else{\n\t\t\t\tchild.normalize();\n\t\t\t\tchild = next;\n\t\t\t}\n\t\t}\n\t},\n  \t// Introduced in DOM Level 2:\n\tisSupported:function(feature, version){\n\t\treturn this.ownerDocument.implementation.hasFeature(feature,version);\n\t},\n    // Introduced in DOM Level 2:\n    hasAttributes:function(){\n    \treturn this.attributes.length>0;\n    },\n    lookupPrefix:function(namespaceURI){\n    \tvar el = this;\n    \twhile(el){\n    \t\tvar map = el._nsMap;\n    \t\t//console.dir(map)\n    \t\tif(map){\n    \t\t\tfor(var n in map){\n    \t\t\t\tif(map[n] == namespaceURI){\n    \t\t\t\t\treturn n;\n    \t\t\t\t}\n    \t\t\t}\n    \t\t}\n    \t\tel = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;\n    \t}\n    \treturn null;\n    },\n    // Introduced in DOM Level 3:\n    lookupNamespaceURI:function(prefix){\n    \tvar el = this;\n    \twhile(el){\n    \t\tvar map = el._nsMap;\n    \t\t//console.dir(map)\n    \t\tif(map){\n    \t\t\tif(prefix in map){\n    \t\t\t\treturn map[prefix] ;\n    \t\t\t}\n    \t\t}\n    \t\tel = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;\n    \t}\n    \treturn null;\n    },\n    // Introduced in DOM Level 3:\n    isDefaultNamespace:function(namespaceURI){\n    \tvar prefix = this.lookupPrefix(namespaceURI);\n    \treturn prefix == null;\n    }\n};\n\n\nfunction _xmlEncoder(c){\n\treturn c == '<' && '&lt;' ||\n         c == '>' && '&gt;' ||\n         c == '&' && '&amp;' ||\n         c == '\"' && '&quot;' ||\n         '&#'+c.charCodeAt()+';'\n}\n\n\ncopy(NodeType,Node);\ncopy(NodeType,Node.prototype);\n\n/**\n * @param callback return true for continue,false for break\n * @return boolean true: break visit;\n */\nfunction _visitNode(node,callback){\n\tif(callback(node)){\n\t\treturn true;\n\t}\n\tif(node = node.firstChild){\n\t\tdo{\n\t\t\tif(_visitNode(node,callback)){return true}\n        }while(node=node.nextSibling)\n    }\n}\n\n\n\nfunction Document(){\n}\n\nfunction _onAddAttribute(doc,el,newAttr){\n\tdoc && doc._inc++;\n\tvar ns = newAttr.namespaceURI ;\n\tif(ns === NAMESPACE.XMLNS){\n\t\t//update namespace\n\t\tel._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value\n\t}\n}\n\nfunction _onRemoveAttribute(doc,el,newAttr,remove){\n\tdoc && doc._inc++;\n\tvar ns = newAttr.namespaceURI ;\n\tif(ns === NAMESPACE.XMLNS){\n\t\t//update namespace\n\t\tdelete el._nsMap[newAttr.prefix?newAttr.localName:'']\n\t}\n}\n\nfunction _onUpdateChild(doc,el,newChild){\n\tif(doc && doc._inc){\n\t\tdoc._inc++;\n\t\t//update childNodes\n\t\tvar cs = el.childNodes;\n\t\tif(newChild){\n\t\t\tcs[cs.length++] = newChild;\n\t\t}else{\n\t\t\t//console.log(1)\n\t\t\tvar child = el.firstChild;\n\t\t\tvar i = 0;\n\t\t\twhile(child){\n\t\t\t\tcs[i++] = child;\n\t\t\t\tchild =child.nextSibling;\n\t\t\t}\n\t\t\tcs.length = i;\n\t\t}\n\t}\n}\n\n/**\n * attributes;\n * children;\n * \n * writeable properties:\n * nodeValue,Attr:value,CharacterData:data\n * prefix\n */\nfunction _removeChild(parentNode,child){\n\tvar previous = child.previousSibling;\n\tvar next = child.nextSibling;\n\tif(previous){\n\t\tprevious.nextSibling = next;\n\t}else{\n\t\tparentNode.firstChild = next\n\t}\n\tif(next){\n\t\tnext.previousSibling = previous;\n\t}else{\n\t\tparentNode.lastChild = previous;\n\t}\n\t_onUpdateChild(parentNode.ownerDocument,parentNode);\n\treturn child;\n}\n/**\n * preformance key(refChild == null)\n */\nfunction _insertBefore(parentNode,newChild,nextChild){\n\tvar cp = newChild.parentNode;\n\tif(cp){\n\t\tcp.removeChild(newChild);//remove and update\n\t}\n\tif(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){\n\t\tvar newFirst = newChild.firstChild;\n\t\tif (newFirst == null) {\n\t\t\treturn newChild;\n\t\t}\n\t\tvar newLast = newChild.lastChild;\n\t}else{\n\t\tnewFirst = newLast = newChild;\n\t}\n\tvar pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;\n\n\tnewFirst.previousSibling = pre;\n\tnewLast.nextSibling = nextChild;\n\t\n\t\n\tif(pre){\n\t\tpre.nextSibling = newFirst;\n\t}else{\n\t\tparentNode.firstChild = newFirst;\n\t}\n\tif(nextChild == null){\n\t\tparentNode.lastChild = newLast;\n\t}else{\n\t\tnextChild.previousSibling = newLast;\n\t}\n\tdo{\n\t\tnewFirst.parentNode = parentNode;\n\t}while(newFirst !== newLast && (newFirst= newFirst.nextSibling))\n\t_onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);\n\t//console.log(parentNode.lastChild.nextSibling == null)\n\tif (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {\n\t\tnewChild.firstChild = newChild.lastChild = null;\n\t}\n\treturn newChild;\n}\nfunction _appendSingleChild(parentNode,newChild){\n\tvar cp = newChild.parentNode;\n\tif(cp){\n\t\tvar pre = parentNode.lastChild;\n\t\tcp.removeChild(newChild);//remove and update\n\t\tvar pre = parentNode.lastChild;\n\t}\n\tvar pre = parentNode.lastChild;\n\tnewChild.parentNode = parentNode;\n\tnewChild.previousSibling = pre;\n\tnewChild.nextSibling = null;\n\tif(pre){\n\t\tpre.nextSibling = newChild;\n\t}else{\n\t\tparentNode.firstChild = newChild;\n\t}\n\tparentNode.lastChild = newChild;\n\t_onUpdateChild(parentNode.ownerDocument,parentNode,newChild);\n\treturn newChild;\n\t//console.log(\"__aa\",parentNode.lastChild.nextSibling == null)\n}\nDocument.prototype = {\n\t//implementation : null,\n\tnodeName :  '#document',\n\tnodeType :  DOCUMENT_NODE,\n\tdoctype :  null,\n\tdocumentElement :  null,\n\t_inc : 1,\n\t\n\tinsertBefore :  function(newChild, refChild){//raises \n\t\tif(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){\n\t\t\tvar child = newChild.firstChild;\n\t\t\twhile(child){\n\t\t\t\tvar next = child.nextSibling;\n\t\t\t\tthis.insertBefore(child,refChild);\n\t\t\t\tchild = next;\n\t\t\t}\n\t\t\treturn newChild;\n\t\t}\n\t\tif(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){\n\t\t\tthis.documentElement = newChild;\n\t\t}\n\t\t\n\t\treturn _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;\n\t},\n\tremoveChild :  function(oldChild){\n\t\tif(this.documentElement == oldChild){\n\t\t\tthis.documentElement = null;\n\t\t}\n\t\treturn _removeChild(this,oldChild);\n\t},\n\t// Introduced in DOM Level 2:\n\timportNode : function(importedNode,deep){\n\t\treturn importNode(this,importedNode,deep);\n\t},\n\t// Introduced in DOM Level 2:\n\tgetElementById :\tfunction(id){\n\t\tvar rtv = null;\n\t\t_visitNode(this.documentElement,function(node){\n\t\t\tif(node.nodeType == ELEMENT_NODE){\n\t\t\t\tif(node.getAttribute('id') == id){\n\t\t\t\t\trtv = node;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\treturn rtv;\n\t},\n\t\n\tgetElementsByClassName: function(className) {\n\t\tvar pattern = new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\");\n\t\treturn new LiveNodeList(this, function(base) {\n\t\t\tvar ls = [];\n\t\t\t_visitNode(base.documentElement, function(node) {\n\t\t\t\tif(node !== base && node.nodeType == ELEMENT_NODE) {\n\t\t\t\t\tif(pattern.test(node.getAttribute('class'))) {\n\t\t\t\t\t\tls.push(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn ls;\n\t\t});\n\t},\n\t\n\t//document factory method:\n\tcreateElement :\tfunction(tagName){\n\t\tvar node = new Element();\n\t\tnode.ownerDocument = this;\n\t\tnode.nodeName = tagName;\n\t\tnode.tagName = tagName;\n\t\tnode.localName = tagName;\n\t\tnode.childNodes = new NodeList();\n\t\tvar attrs\t= node.attributes = new NamedNodeMap();\n\t\tattrs._ownerElement = node;\n\t\treturn node;\n\t},\n\tcreateDocumentFragment :\tfunction(){\n\t\tvar node = new DocumentFragment();\n\t\tnode.ownerDocument = this;\n\t\tnode.childNodes = new NodeList();\n\t\treturn node;\n\t},\n\tcreateTextNode :\tfunction(data){\n\t\tvar node = new Text();\n\t\tnode.ownerDocument = this;\n\t\tnode.appendData(data)\n\t\treturn node;\n\t},\n\tcreateComment :\tfunction(data){\n\t\tvar node = new Comment();\n\t\tnode.ownerDocument = this;\n\t\tnode.appendData(data)\n\t\treturn node;\n\t},\n\tcreateCDATASection :\tfunction(data){\n\t\tvar node = new CDATASection();\n\t\tnode.ownerDocument = this;\n\t\tnode.appendData(data)\n\t\treturn node;\n\t},\n\tcreateProcessingInstruction :\tfunction(target,data){\n\t\tvar node = new ProcessingInstruction();\n\t\tnode.ownerDocument = this;\n\t\tnode.tagName = node.target = target;\n\t\tnode.nodeValue= node.data = data;\n\t\treturn node;\n\t},\n\tcreateAttribute :\tfunction(name){\n\t\tvar node = new Attr();\n\t\tnode.ownerDocument\t= this;\n\t\tnode.name = name;\n\t\tnode.nodeName\t= name;\n\t\tnode.localName = name;\n\t\tnode.specified = true;\n\t\treturn node;\n\t},\n\tcreateEntityReference :\tfunction(name){\n\t\tvar node = new EntityReference();\n\t\tnode.ownerDocument\t= this;\n\t\tnode.nodeName\t= name;\n\t\treturn node;\n\t},\n\t// Introduced in DOM Level 2:\n\tcreateElementNS :\tfunction(namespaceURI,qualifiedName){\n\t\tvar node = new Element();\n\t\tvar pl = qualifiedName.split(':');\n\t\tvar attrs\t= node.attributes = new NamedNodeMap();\n\t\tnode.childNodes = new NodeList();\n\t\tnode.ownerDocument = this;\n\t\tnode.nodeName = qualifiedName;\n\t\tnode.tagName = qualifiedName;\n\t\tnode.namespaceURI = namespaceURI;\n\t\tif(pl.length == 2){\n\t\t\tnode.prefix = pl[0];\n\t\t\tnode.localName = pl[1];\n\t\t}else{\n\t\t\t//el.prefix = null;\n\t\t\tnode.localName = qualifiedName;\n\t\t}\n\t\tattrs._ownerElement = node;\n\t\treturn node;\n\t},\n\t// Introduced in DOM Level 2:\n\tcreateAttributeNS :\tfunction(namespaceURI,qualifiedName){\n\t\tvar node = new Attr();\n\t\tvar pl = qualifiedName.split(':');\n\t\tnode.ownerDocument = this;\n\t\tnode.nodeName = qualifiedName;\n\t\tnode.name = qualifiedName;\n\t\tnode.namespaceURI = namespaceURI;\n\t\tnode.specified = true;\n\t\tif(pl.length == 2){\n\t\t\tnode.prefix = pl[0];\n\t\t\tnode.localName = pl[1];\n\t\t}else{\n\t\t\t//el.prefix = null;\n\t\t\tnode.localName = qualifiedName;\n\t\t}\n\t\treturn node;\n\t}\n};\n_extends(Document,Node);\n\n\nexport function Element() {\n\tthis._nsMap = {};\n};\nElement.prototype = {\n\tnodeType : ELEMENT_NODE,\n\thasAttribute : function(name){\n\t\treturn this.getAttributeNode(name)!=null;\n\t},\n\tgetAttribute : function(name){\n\t\tvar attr = this.getAttributeNode(name);\n\t\treturn attr && attr.value || '';\n\t},\n\tgetAttributeNode : function(name){\n\t\treturn this.attributes.getNamedItem(name);\n\t},\n\tsetAttribute : function(name, value){\n\t\tvar attr = this.ownerDocument.createAttribute(name);\n\t\tattr.value = attr.nodeValue = \"\" + value;\n\t\tthis.setAttributeNode(attr)\n\t},\n\tremoveAttribute : function(name){\n\t\tvar attr = this.getAttributeNode(name)\n\t\tattr && this.removeAttributeNode(attr);\n\t},\n\t\n\t//four real opeartion method\n\tappendChild:function(newChild){\n\t\tif(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){\n\t\t\treturn this.insertBefore(newChild,null);\n\t\t}else{\n\t\t\treturn _appendSingleChild(this,newChild);\n\t\t}\n\t},\n\tsetAttributeNode : function(newAttr){\n\t\treturn this.attributes.setNamedItem(newAttr);\n\t},\n\tsetAttributeNodeNS : function(newAttr){\n\t\treturn this.attributes.setNamedItemNS(newAttr);\n\t},\n\tremoveAttributeNode : function(oldAttr){\n\t\t//console.log(this == oldAttr.ownerElement)\n\t\treturn this.attributes.removeNamedItem(oldAttr.nodeName);\n\t},\n\t//get real attribute name,and remove it by removeAttributeNode\n\tremoveAttributeNS : function(namespaceURI, localName){\n\t\tvar old = this.getAttributeNodeNS(namespaceURI, localName);\n\t\told && this.removeAttributeNode(old);\n\t},\n\t\n\thasAttributeNS : function(namespaceURI, localName){\n\t\treturn this.getAttributeNodeNS(namespaceURI, localName)!=null;\n\t},\n\tgetAttributeNS : function(namespaceURI, localName){\n\t\tvar attr = this.getAttributeNodeNS(namespaceURI, localName);\n\t\treturn attr && attr.value || '';\n\t},\n\tsetAttributeNS : function(namespaceURI, qualifiedName, value){\n\t\tvar attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);\n\t\tattr.value = attr.nodeValue = \"\" + value;\n\t\tthis.setAttributeNode(attr)\n\t},\n\tgetAttributeNodeNS : function(namespaceURI, localName){\n\t\treturn this.attributes.getNamedItemNS(namespaceURI, localName);\n\t},\n\t\n\tgetElementsByTagName : function(tagName){\n\t\treturn new LiveNodeList(this,function(base){\n\t\t\tvar ls = [];\n\t\t\t_visitNode(base,function(node){\n\t\t\t\tif(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){\n\t\t\t\t\tls.push(node);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn ls;\n\t\t});\n\t},\n\tgetElementsByTagNameNS : function(namespaceURI, localName){\n\t\treturn new LiveNodeList(this,function(base){\n\t\t\tvar ls = [];\n\t\t\t_visitNode(base,function(node){\n\t\t\t\tif(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){\n\t\t\t\t\tls.push(node);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn ls;\n\t\t\t\n\t\t});\n\t}\n};\nDocument.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;\nDocument.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;\n\n\n_extends(Element,Node);\nfunction Attr() {\n};\nAttr.prototype.nodeType = ATTRIBUTE_NODE;\n_extends(Attr,Node);\n\n\nfunction CharacterData() {\n};\nCharacterData.prototype = {\n\tdata : '',\n\tsubstringData : function(offset, count) {\n\t\treturn this.data.substring(offset, offset+count);\n\t},\n\tappendData: function(text) {\n\t\ttext = this.data+text;\n\t\tthis.nodeValue = this.data = text;\n\t\tthis.length = text.length;\n\t},\n\tinsertData: function(offset,text) {\n\t\tthis.replaceData(offset,0,text);\n\t\n\t},\n\tappendChild:function(newChild){\n\t\tthrow new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])\n\t},\n\tdeleteData: function(offset, count) {\n\t\tthis.replaceData(offset,count,\"\");\n\t},\n\treplaceData: function(offset, count, text) {\n\t\tvar start = this.data.substring(0,offset);\n\t\tvar end = this.data.substring(offset+count);\n\t\ttext = start + text + end;\n\t\tthis.nodeValue = this.data = text;\n\t\tthis.length = text.length;\n\t}\n}\n_extends(CharacterData,Node);\nfunction Text() {\n};\nText.prototype = {\n\tnodeName : \"#text\",\n\tnodeType : TEXT_NODE,\n\tsplitText : function(offset) {\n\t\tvar text = this.data;\n\t\tvar newText = text.substring(offset);\n\t\ttext = text.substring(0, offset);\n\t\tthis.data = this.nodeValue = text;\n\t\tthis.length = text.length;\n\t\tvar newNode = this.ownerDocument.createTextNode(newText);\n\t\tif(this.parentNode){\n\t\t\tthis.parentNode.insertBefore(newNode, this.nextSibling);\n\t\t}\n\t\treturn newNode;\n\t}\n}\n_extends(Text,CharacterData);\nfunction Comment() {\n};\nComment.prototype = {\n\tnodeName : \"#comment\",\n\tnodeType : COMMENT_NODE\n}\n_extends(Comment,CharacterData);\n\nfunction CDATASection() {\n};\nCDATASection.prototype = {\n\tnodeName : \"#cdata-section\",\n\tnodeType : CDATA_SECTION_NODE\n}\n_extends(CDATASection,CharacterData);\n\n\nexport function DocumentType() {\n};\nDocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;\n_extends(DocumentType,Node);\n\nfunction Notation() {\n};\nNotation.prototype.nodeType = NOTATION_NODE;\n_extends(Notation,Node);\n\nfunction Entity() {\n};\nEntity.prototype.nodeType = ENTITY_NODE;\n_extends(Entity,Node);\n\nfunction EntityReference() {\n};\nEntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;\n_extends(EntityReference,Node);\n\nfunction DocumentFragment() {\n};\nDocumentFragment.prototype.nodeName =\t\"#document-fragment\";\nDocumentFragment.prototype.nodeType =\tDOCUMENT_FRAGMENT_NODE;\n_extends(DocumentFragment,Node);\n\n\nfunction ProcessingInstruction() {\n}\nProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;\n_extends(ProcessingInstruction,Node);\nexport function XMLSerializer(){}\nXMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){\n\treturn nodeSerializeToString.call(node,isHtml,nodeFilter);\n}\nNode.prototype.toString = nodeSerializeToString;\nfunction nodeSerializeToString(isHtml,nodeFilter){\n\tvar buf = [];\n\tvar refNode = this.nodeType == 9 && this.documentElement || this;\n\tvar prefix = refNode.prefix;\n\tvar uri = refNode.namespaceURI;\n\t\n\tif(uri && prefix == null){\n\t\t//console.log(prefix)\n\t\tvar prefix = refNode.lookupPrefix(uri);\n\t\tif(prefix == null){\n\t\t\t//isHTML = true;\n\t\t\tvar visibleNamespaces=[\n\t\t\t{namespace:uri,prefix:null}\n\t\t\t//{namespace:uri,prefix:''}\n\t\t\t]\n\t\t}\n\t}\n\tserializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);\n\t//console.log('###',this.nodeType,uri,prefix,buf.join(''))\n\treturn buf.join('');\n}\n\nfunction needNamespaceDefine(node, isHTML, visibleNamespaces) {\n\tvar prefix = node.prefix || '';\n\tvar uri = node.namespaceURI;\n\t// According to [Namespaces in XML 1.0](https://www.w3.org/TR/REC-xml-names/#ns-using) ,\n\t// and more specifically https://www.w3.org/TR/REC-xml-names/#nsc-NoPrefixUndecl :\n\t// > In a namespace declaration for a prefix [...], the attribute value MUST NOT be empty.\n\t// in a similar manner [Namespaces in XML 1.1](https://www.w3.org/TR/xml-names11/#ns-using)\n\t// and more specifically https://www.w3.org/TR/xml-names11/#nsc-NSDeclared :\n\t// > [...] Furthermore, the attribute value [...] must not be an empty string.\n\t// so serializing empty namespace value like xmlns:ds=\"\" would produce an invalid XML document.\n\tif (!uri) {\n\t\treturn false;\n\t}\n\tif (prefix === \"xml\" && uri === NAMESPACE.XML || uri === NAMESPACE.XMLNS) {\n\t\treturn false;\n\t}\n\t\n\tvar i = visibleNamespaces.length \n\twhile (i--) {\n\t\tvar ns = visibleNamespaces[i];\n\t\t// get namespace prefix\n\t\tif (ns.prefix === prefix) {\n\t\t\treturn ns.namespace !== uri;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){\n\tif(nodeFilter){\n\t\tnode = nodeFilter(node);\n\t\tif(node){\n\t\t\tif(typeof node == 'string'){\n\t\t\t\tbuf.push(node);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}else{\n\t\t\treturn;\n\t\t}\n\t\t//buf.sort.apply(attrs, attributeSorter);\n\t}\n\n\tswitch(node.nodeType){\n\tcase ELEMENT_NODE:\n\t\tif (!visibleNamespaces) visibleNamespaces = [];\n\t\tvar startVisibleNamespaces = visibleNamespaces.length;\n\t\tvar attrs = node.attributes;\n\t\tvar len = attrs.length;\n\t\tvar child = node.firstChild;\n\t\tvar nodeName = node.tagName;\n\t\t\n\t\tisHTML = NAMESPACE.isHTML(node.namespaceURI) || isHTML\n\t\tbuf.push('<',nodeName);\n\n\t\tfor(var i=0;i<len;i++){\n\t\t\t// add namespaces for attributes\n\t\t\tvar attr = attrs.item(i);\n\t\t\tif (attr.prefix == 'xmlns') {\n\t\t\t\tvisibleNamespaces.push({ prefix: attr.localName, namespace: attr.value });\n\t\t\t}else if(attr.nodeName == 'xmlns'){\n\t\t\t\tvisibleNamespaces.push({ prefix: '', namespace: attr.value });\n\t\t\t}\n\t\t}\n\n\t\tfor(var i=0;i<len;i++){\n\t\t\tvar attr = attrs.item(i);\n\t\t\tif (needNamespaceDefine(attr,isHTML, visibleNamespaces)) {\n\t\t\t\tvar prefix = attr.prefix||'';\n\t\t\t\tvar uri = attr.namespaceURI;\n\t\t\t\tvar ns = prefix ? ' xmlns:' + prefix : \" xmlns\";\n\t\t\t\tbuf.push(ns, '=\"' , uri , '\"');\n\t\t\t\tvisibleNamespaces.push({ prefix: prefix, namespace:uri });\n\t\t\t}\n\t\t\tserializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);\n\t\t}\n\n\t\t// add namespace for current node\t\t\n\t\tif (needNamespaceDefine(node,isHTML, visibleNamespaces)) {\n\t\t\tvar prefix = node.prefix||'';\n\t\t\tvar uri = node.namespaceURI;\n\t\t\tvar ns = prefix ? ' xmlns:' + prefix : \" xmlns\";\n\t\t\tbuf.push(ns, '=\"' , uri , '\"');\n\t\t\tvisibleNamespaces.push({ prefix: prefix, namespace:uri });\n\t\t}\n\t\t\n\t\tif(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){\n\t\t\tbuf.push('>');\n\t\t\t//if is cdata child node\n\t\t\tif(isHTML && /^script$/i.test(nodeName)){\n\t\t\t\twhile(child){\n\t\t\t\t\tif(child.data){\n\t\t\t\t\t\tbuf.push(child.data);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tserializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);\n\t\t\t\t\t}\n\t\t\t\t\tchild = child.nextSibling;\n\t\t\t\t}\n\t\t\t}else\n\t\t\t{\n\t\t\t\twhile(child){\n\t\t\t\t\tserializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);\n\t\t\t\t\tchild = child.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuf.push('</',nodeName,'>');\n\t\t}else{\n\t\t\tbuf.push('/>');\n\t\t}\n\t\t// remove added visible namespaces\n\t\t//visibleNamespaces.length = startVisibleNamespaces;\n\t\treturn;\n\tcase DOCUMENT_NODE:\n\tcase DOCUMENT_FRAGMENT_NODE:\n\t\tvar child = node.firstChild;\n\t\twhile(child){\n\t\t\tserializeToString(child,buf,isHTML,nodeFilter,visibleNamespaces);\n\t\t\tchild = child.nextSibling;\n\t\t}\n\t\treturn;\n\tcase ATTRIBUTE_NODE:\n\t\t/**\n\t\t * Well-formedness constraint: No < in Attribute Values\n\t\t * The replacement text of any entity referred to directly or indirectly in an attribute value must not contain a <.\n\t\t * @see https://www.w3.org/TR/xml/#CleanAttrVals\n\t\t * @see https://www.w3.org/TR/xml/#NT-AttValue\n\t\t */\n\t\treturn buf.push(' ', node.name, '=\"', node.value.replace(/[<&\"]/g,_xmlEncoder), '\"');\n\tcase TEXT_NODE:\n\t\t/**\n\t\t * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,\n\t\t * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section.\n\t\t * If they are needed elsewhere, they must be escaped using either numeric character references or the strings\n\t\t * `&amp;` and `&lt;` respectively.\n\t\t * The right angle bracket (>) may be represented using the string \" &gt; \", and must, for compatibility,\n\t\t * be escaped using either `&gt;` or a character reference when it appears in the string `]]>` in content,\n\t\t * when that string is not marking the end of a CDATA section.\n\t\t *\n\t\t * In the content of elements, character data is any string of characters\n\t\t * which does not contain the start-delimiter of any markup\n\t\t * and does not include the CDATA-section-close delimiter, `]]>`.\n\t\t *\n\t\t * @see https://www.w3.org/TR/xml/#NT-CharData\n\t\t */\n\t\treturn buf.push(node.data\n\t\t\t.replace(/[<&]/g,_xmlEncoder)\n\t\t\t.replace(/]]>/g, ']]&gt;')\n\t\t);\n\tcase CDATA_SECTION_NODE:\n\t\treturn buf.push( '<![CDATA[',node.data,']]>');\n\tcase COMMENT_NODE:\n\t\treturn buf.push( \"<!--\",node.data,\"-->\");\n\tcase DOCUMENT_TYPE_NODE:\n\t\tvar pubid = node.publicId;\n\t\tvar sysid = node.systemId;\n\t\tbuf.push('<!DOCTYPE ',node.name);\n\t\tif(pubid){\n\t\t\tbuf.push(' PUBLIC ', pubid);\n\t\t\tif (sysid && sysid!='.') {\n\t\t\t\tbuf.push(' ', sysid);\n\t\t\t}\n\t\t\tbuf.push('>');\n\t\t}else if(sysid && sysid!='.'){\n\t\t\tbuf.push(' SYSTEM ', sysid, '>');\n\t\t}else{\n\t\t\tvar sub = node.internalSubset;\n\t\t\tif(sub){\n\t\t\t\tbuf.push(\" [\",sub,\"]\");\n\t\t\t}\n\t\t\tbuf.push(\">\");\n\t\t}\n\t\treturn;\n\tcase PROCESSING_INSTRUCTION_NODE:\n\t\treturn buf.push( \"<?\",node.target,\" \",node.data,\"?>\");\n\tcase ENTITY_REFERENCE_NODE:\n\t\treturn buf.push( '&',node.nodeName,';');\n\t//case ENTITY_NODE:\n\t//case NOTATION_NODE:\n\tdefault:\n\t\tbuf.push('??',node.nodeName);\n\t}\n}\nfunction importNode(doc,node,deep){\n\tvar node2;\n\tswitch (node.nodeType) {\n\tcase ELEMENT_NODE:\n\t\tnode2 = node.cloneNode(false);\n\t\tnode2.ownerDocument = doc;\n\t\t//var attrs = node2.attributes;\n\t\t//var len = attrs.length;\n\t\t//for(var i=0;i<len;i++){\n\t\t\t//node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));\n\t\t//}\n\tcase DOCUMENT_FRAGMENT_NODE:\n\t\tbreak;\n\tcase ATTRIBUTE_NODE:\n\t\tdeep = true;\n\t\tbreak;\n\t//case ENTITY_REFERENCE_NODE:\n\t//case PROCESSING_INSTRUCTION_NODE:\n\t////case TEXT_NODE:\n\t//case CDATA_SECTION_NODE:\n\t//case COMMENT_NODE:\n\t//\tdeep = false;\n\t//\tbreak;\n\t//case DOCUMENT_NODE:\n\t//case DOCUMENT_TYPE_NODE:\n\t//cannot be imported.\n\t//case ENTITY_NODE:\n\t//case NOTATION_NODE\uff1a\n\t//can not hit in level3\n\t//default:throw e;\n\t}\n\tif(!node2){\n\t\tnode2 = node.cloneNode(false);//false\n\t}\n\tnode2.ownerDocument = doc;\n\tnode2.parentNode = null;\n\tif(deep){\n\t\tvar child = node.firstChild;\n\t\twhile(child){\n\t\t\tnode2.appendChild(importNode(doc,child,deep));\n\t\t\tchild = child.nextSibling;\n\t\t}\n\t}\n\treturn node2;\n}\n//\n//var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,\n//\t\t\t\t\tattributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};\nfunction cloneNode(doc,node,deep){\n\tvar node2 = new node.constructor();\n\tfor(var n in node){\n\t\tvar v = node[n];\n\t\tif(typeof v != 'object' ){\n\t\t\tif(v != node2[n]){\n\t\t\t\tnode2[n] = v;\n\t\t\t}\n\t\t}\n\t}\n\tif(node.childNodes){\n\t\tnode2.childNodes = new NodeList();\n\t}\n\tnode2.ownerDocument = doc;\n\tswitch (node2.nodeType) {\n\tcase ELEMENT_NODE:\n\t\tvar attrs\t= node.attributes;\n\t\tvar attrs2\t= node2.attributes = new NamedNodeMap();\n\t\tvar len = attrs.length\n\t\tattrs2._ownerElement = node2;\n\t\tfor(var i=0;i<len;i++){\n\t\t\tnode2.setAttributeNode(cloneNode(doc,attrs.item(i),true));\n\t\t}\n\t\tbreak;;\n\tcase ATTRIBUTE_NODE:\n\t\tdeep = true;\n\t}\n\tif(deep){\n\t\tvar child = node.firstChild;\n\t\twhile(child){\n\t\t\tnode2.appendChild(cloneNode(doc,child,deep));\n\t\t\tchild = child.nextSibling;\n\t\t}\n\t}\n\treturn node2;\n}\n\nfunction __set__(object,key,value){\n\tobject[key] = value\n}\n//do dynamic\ntry{\n\tif(Object.defineProperty){\n\t\tObject.defineProperty(LiveNodeList.prototype,'length',{\n\t\t\tget:function(){\n\t\t\t\t_updateLiveList(this);\n\t\t\t\treturn this.$$length;\n\t\t\t}\n\t\t});\n\n\t\tObject.defineProperty(Node.prototype,'textContent',{\n\t\t\tget:function(){\n\t\t\t\treturn getTextContent(this);\n\t\t\t},\n\n\t\t\tset:function(data){\n\t\t\t\tswitch(this.nodeType){\n\t\t\t\tcase ELEMENT_NODE:\n\t\t\t\tcase DOCUMENT_FRAGMENT_NODE:\n\t\t\t\t\twhile(this.firstChild){\n\t\t\t\t\t\tthis.removeChild(this.firstChild);\n\t\t\t\t\t}\n\t\t\t\t\tif(data || String(data)){\n\t\t\t\t\t\tthis.appendChild(this.ownerDocument.createTextNode(data));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tthis.data = data;\n\t\t\t\t\tthis.value = data;\n\t\t\t\t\tthis.nodeValue = data;\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\t\n\t\tfunction getTextContent(node){\n\t\t\tswitch(node.nodeType){\n\t\t\tcase ELEMENT_NODE:\n\t\t\tcase DOCUMENT_FRAGMENT_NODE:\n\t\t\t\tvar buf = [];\n\t\t\t\tnode = node.firstChild;\n\t\t\t\twhile(node){\n\t\t\t\t\tif(node.nodeType!==7 && node.nodeType !==8){\n\t\t\t\t\t\tbuf.push(getTextContent(node));\n\t\t\t\t\t}\n\t\t\t\t\tnode = node.nextSibling;\n\t\t\t\t}\n\t\t\t\treturn buf.join('');\n\t\t\tdefault:\n\t\t\t\treturn node.nodeValue;\n\t\t\t}\n\t\t}\n\n\t\t__set__ = function(object,key,value){\n\t\t\t//console.log(value)\n\t\t\tobject['$$'+key] = value\n\t\t}\n\t}\n}catch(e){//ie8\n}\n\n", "vendor/xmldom/conventions.js": "// @ts-nocheck\n/* eslint-disable */\n\n/**\n * \"Shallow freezes\" an object to render it immutable.\n * Uses `Object.freeze` if available,\n * otherwise the immutability is only in the type.\n *\n * Is used to create \"enum like\" objects.\n *\n * @template T\n * @param {T} object the object to freeze\n * @param {Pick<ObjectConstructor, 'freeze'> = Object} oc `Object` by default,\n * \t\t\t\tallows to inject custom object constructor for tests\n * @returns {Readonly<T>}\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze\n */\nexport function freeze(object, oc) {\n\tif (oc === undefined) {\n\t\toc = Object\n\t}\n\treturn oc && typeof oc.freeze === 'function' ? oc.freeze(object) : object\n}\n\n/**\n * All mime types that are allowed as input to `DOMParser.parseFromString`\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#Argument02 MDN\n * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#domparsersupportedtype WHATWG HTML Spec\n * @see DOMParser.prototype.parseFromString\n */\nexport let MIME_TYPE = freeze({\n\t/**\n\t * `text/html`, the only mime type that triggers treating an XML document as HTML.\n\t *\n\t * @see DOMParser.SupportedType.isHTML\n\t * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration\n\t * @see https://en.wikipedia.org/wiki/HTML Wikipedia\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN\n\t * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring WHATWG HTML Spec\n\t */\n\tHTML: 'text/html',\n\n\t/**\n\t * Helper method to check a mime type if it indicates an HTML document\n\t *\n\t * @param {string} [value]\n\t * @returns {boolean}\n\t *\n\t * @see https://www.iana.org/assignments/media-types/text/html IANA MimeType registration\n\t * @see https://en.wikipedia.org/wiki/HTML Wikipedia\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString MDN\n\t * @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-domparser-parsefromstring \t */\n\tisHTML: function (value) {\n\t\treturn value === MIME_TYPE.HTML\n\t},\n\n\t/**\n\t * `application/xml`, the standard mime type for XML documents.\n\t *\n\t * @see https://www.iana.org/assignments/media-types/application/xml IANA MimeType registration\n\t * @see https://tools.ietf.org/html/rfc7303#section-9.1 RFC 7303\n\t * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia\n\t */\n\tXML_APPLICATION: 'application/xml',\n\n\t/**\n\t * `text/html`, an alias for `application/xml`.\n\t *\n\t * @see https://tools.ietf.org/html/rfc7303#section-9.2 RFC 7303\n\t * @see https://www.iana.org/assignments/media-types/text/xml IANA MimeType registration\n\t * @see https://en.wikipedia.org/wiki/XML_and_MIME Wikipedia\n\t */\n\tXML_TEXT: 'text/xml',\n\n\t/**\n\t * `application/xhtml+xml`, indicates an XML document that has the default HTML namespace,\n\t * but is parsed as an XML document.\n\t *\n\t * @see https://www.iana.org/assignments/media-types/application/xhtml+xml IANA MimeType registration\n\t * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument WHATWG DOM Spec\n\t * @see https://en.wikipedia.org/wiki/XHTML Wikipedia\n\t */\n\tXML_XHTML_APPLICATION: 'application/xhtml+xml',\n\n\t/**\n\t * `image/svg+xml`,\n\t *\n\t * @see https://www.iana.org/assignments/media-types/image/svg+xml IANA MimeType registration\n\t * @see https://www.w3.org/TR/SVG11/ W3C SVG 1.1\n\t * @see https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Wikipedia\n\t */\n\tXML_SVG_IMAGE: 'image/svg+xml',\n})\n\n/**\n * Namespaces that are used in this code base.\n *\n * @see http://www.w3.org/TR/REC-xml-names\n */\nexport let NAMESPACE = freeze({\n\t/**\n\t * The XHTML namespace.\n\t *\n\t * @see http://www.w3.org/1999/xhtml\n\t */\n\tHTML: 'http://www.w3.org/1999/xhtml',\n\n\t/**\n\t * Checks if `uri` equals `NAMESPACE.HTML`.\n\t *\n\t * @param {string} [uri]\n\t *\n\t * @see NAMESPACE.HTML\n\t */\n\tisHTML: function (uri) {\n\t\treturn uri === NAMESPACE.HTML\n\t},\n\n\t/**\n\t * The SVG namespace.\n\t *\n\t * @see http://www.w3.org/2000/svg\n\t */\n\tSVG: 'http://www.w3.org/2000/svg',\n\n\t/**\n\t * The `xml:` namespace.\n\t *\n\t * @see http://www.w3.org/XML/1998/namespace\n\t */\n\tXML: 'http://www.w3.org/XML/1998/namespace',\n\n\t/**\n\t * The `xmlns:` namespace\n\t *\n\t * @see https://www.w3.org/2000/xmlns/\n\t */\n\tXMLNS: 'http://www.w3.org/2000/xmlns/',\n})", "vendor/jstat/LICENSE": "Copyright (c) 2013 jStat\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.", "vendor/jstat/jstat.js": "// @ts-nocheck\n/* eslint-disable */\n\nexport let jStat = {};\n\n(function (_window, factory) {\n    Object.assign(jStat, factory());\n})(this, function () {\nvar jStat = (function(Math, undefined) {\n\n// For quick reference.\nvar concat = Array.prototype.concat;\nvar slice = Array.prototype.slice;\nvar toString = Object.prototype.toString;\n\n// Calculate correction for IEEE error\n// TODO: This calculation can be improved.\nfunction calcRdx(n, m) {\n  var val = n > m ? n : m;\n  return Math.pow(10,\n                  17 - ~~(Math.log(((val > 0) ? val : -val)) * Math.LOG10E));\n}\n\n\nvar isArray = Array.isArray || function isArray(arg) {\n  return toString.call(arg) === '[object Array]';\n};\n\n\nfunction isFunction(arg) {\n  return toString.call(arg) === '[object Function]';\n}\n\n\nfunction isNumber(num) {\n  return (typeof num === 'number') ? num - num === 0 : false;\n}\n\n\n// Converts the jStat matrix to vector.\nfunction toVector(arr) {\n  return concat.apply([], arr);\n}\n\n\n// The one and only jStat constructor.\nfunction jStat() {\n  return new jStat._init(arguments);\n}\n\n\n// TODO: Remove after all references in src files have been removed.\njStat.fn = jStat.prototype;\n\n\n// By separating the initializer from the constructor it's easier to handle\n// always returning a new instance whether \"new\" was used or not.\njStat._init = function _init(args) {\n  // If first argument is an array, must be vector or matrix.\n  if (isArray(args[0])) {\n    // Check if matrix.\n    if (isArray(args[0][0])) {\n      // See if a mapping function was also passed.\n      if (isFunction(args[1]))\n        args[0] = jStat.map(args[0], args[1]);\n      // Iterate over each is faster than this.push.apply(this, args[0].\n      for (var i = 0; i < args[0].length; i++)\n        this[i] = args[0][i];\n      this.length = args[0].length;\n\n    // Otherwise must be a vector.\n    } else {\n      this[0] = isFunction(args[1]) ? jStat.map(args[0], args[1]) : args[0];\n      this.length = 1;\n    }\n\n  // If first argument is number, assume creation of sequence.\n  } else if (isNumber(args[0])) {\n    this[0] = jStat.seq.apply(null, args);\n    this.length = 1;\n\n  // Handle case when jStat object is passed to jStat.\n  } else if (args[0] instanceof jStat) {\n    // Duplicate the object and pass it back.\n    return jStat(args[0].toArray());\n\n  // Unexpected argument value, return empty jStat object.\n  // TODO: This is strange behavior. Shouldn't this throw or some such to let\n  // the user know they had bad arguments?\n  } else {\n    this[0] = [];\n    this.length = 1;\n  }\n\n  return this;\n};\njStat._init.prototype = jStat.prototype;\njStat._init.constructor = jStat;\n\n\n// Utility functions.\n// TODO: for internal use only?\njStat.utils = {\n  calcRdx: calcRdx,\n  isArray: isArray,\n  isFunction: isFunction,\n  isNumber: isNumber,\n  toVector: toVector\n};\n\n\njStat._random_fn = Math.random;\njStat.setRandom = function setRandom(fn) {\n  if (typeof fn !== 'function')\n    throw new TypeError('fn is not a function');\n  jStat._random_fn = fn;\n};\n\n\n// Easily extend the jStat object.\n// TODO: is this seriously necessary?\njStat.extend = function extend(obj) {\n  var i, j;\n\n  if (arguments.length === 1) {\n    for (j in obj)\n      jStat[j] = obj[j];\n    return this;\n  }\n\n  for (i = 1; i < arguments.length; i++) {\n    for (j in arguments[i])\n      obj[j] = arguments[i][j];\n  }\n\n  return obj;\n};\n\n\n// Returns the number of rows in the matrix.\njStat.rows = function rows(arr) {\n  return arr.length || 1;\n};\n\n\n// Returns the number of columns in the matrix.\njStat.cols = function cols(arr) {\n  return arr[0].length || 1;\n};\n\n\n// Returns the dimensions of the object { rows: i, cols: j }\njStat.dimensions = function dimensions(arr) {\n  return {\n    rows: jStat.rows(arr),\n    cols: jStat.cols(arr)\n  };\n};\n\n\n// Returns a specified row as a vector or return a sub matrix by pick some rows\njStat.row = function row(arr, index) {\n  if (isArray(index)) {\n    return index.map(function(i) {\n      return jStat.row(arr, i);\n    })\n  }\n  return arr[index];\n};\n\n\n// return row as array\n// rowa([[1,2],[3,4]],0) -> [1,2]\njStat.rowa = function rowa(arr, i) {\n  return jStat.row(arr, i);\n};\n\n\n// Returns the specified column as a vector or return a sub matrix by pick some\n// columns\njStat.col = function col(arr, index) {\n  if (isArray(index)) {\n    var submat = jStat.arange(arr.length).map(function() {\n      return new Array(index.length);\n    });\n    index.forEach(function(ind, i){\n      jStat.arange(arr.length).forEach(function(j) {\n        submat[j][i] = arr[j][ind];\n      });\n    });\n    return submat;\n  }\n  var column = new Array(arr.length);\n  for (var i = 0; i < arr.length; i++)\n    column[i] = [arr[i][index]];\n  return column;\n};\n\n\n// return column as array\n// cola([[1,2],[3,4]],0) -> [1,3]\njStat.cola = function cola(arr, i) {\n  return jStat.col(arr, i).map(function(a){ return a[0] });\n};\n\n\n// Returns the diagonal of the matrix\njStat.diag = function diag(arr) {\n  var nrow = jStat.rows(arr);\n  var res = new Array(nrow);\n  for (var row = 0; row < nrow; row++)\n    res[row] = [arr[row][row]];\n  return res;\n};\n\n\n// Returns the anti-diagonal of the matrix\njStat.antidiag = function antidiag(arr) {\n  var nrow = jStat.rows(arr) - 1;\n  var res = new Array(nrow);\n  for (var i = 0; nrow >= 0; nrow--, i++)\n    res[i] = [arr[i][nrow]];\n  return res;\n};\n\n// Transpose a matrix or array.\njStat.transpose = function transpose(arr) {\n  var obj = [];\n  var objArr, rows, cols, j, i;\n\n  // Make sure arr is in matrix format.\n  if (!isArray(arr[0]))\n    arr = [arr];\n\n  rows = arr.length;\n  cols = arr[0].length;\n\n  for (i = 0; i < cols; i++) {\n    objArr = new Array(rows);\n    for (j = 0; j < rows; j++)\n      objArr[j] = arr[j][i];\n    obj.push(objArr);\n  }\n\n  // If obj is vector, return only single array.\n  return obj.length === 1 ? obj[0] : obj;\n};\n\n\n// Map a function to an array or array of arrays.\n// \"toAlter\" is an internal variable.\njStat.map = function map(arr, func, toAlter) {\n  var row, nrow, ncol, res, col;\n\n  if (!isArray(arr[0]))\n    arr = [arr];\n\n  nrow = arr.length;\n  ncol = arr[0].length;\n  res = toAlter ? arr : new Array(nrow);\n\n  for (row = 0; row < nrow; row++) {\n    // if the row doesn't exist, create it\n    if (!res[row])\n      res[row] = new Array(ncol);\n    for (col = 0; col < ncol; col++)\n      res[row][col] = func(arr[row][col], row, col);\n  }\n\n  return res.length === 1 ? res[0] : res;\n};\n\n\n// Cumulatively combine the elements of an array or array of arrays using a function.\njStat.cumreduce = function cumreduce(arr, func, toAlter) {\n  var row, nrow, ncol, res, col;\n\n  if (!isArray(arr[0]))\n    arr = [arr];\n\n  nrow = arr.length;\n  ncol = arr[0].length;\n  res = toAlter ? arr : new Array(nrow);\n\n  for (row = 0; row < nrow; row++) {\n    // if the row doesn't exist, create it\n    if (!res[row])\n      res[row] = new Array(ncol);\n    if (ncol > 0)\n      res[row][0] = arr[row][0];\n    for (col = 1; col < ncol; col++)\n      res[row][col] = func(res[row][col-1], arr[row][col]);\n  }\n  return res.length === 1 ? res[0] : res;\n};\n\n\n// Destructively alter an array.\njStat.alter = function alter(arr, func) {\n  return jStat.map(arr, func, true);\n};\n\n\n// Generate a rows x cols matrix according to the supplied function.\njStat.create = function  create(rows, cols, func) {\n  var res = new Array(rows);\n  var i, j;\n\n  if (isFunction(cols)) {\n    func = cols;\n    cols = rows;\n  }\n\n  for (i = 0; i < rows; i++) {\n    res[i] = new Array(cols);\n    for (j = 0; j < cols; j++)\n      res[i][j] = func(i, j);\n  }\n\n  return res;\n};\n\n\nfunction retZero() { return 0; }\n\n\n// Generate a rows x cols matrix of zeros.\njStat.zeros = function zeros(rows, cols) {\n  if (!isNumber(cols))\n    cols = rows;\n  return jStat.create(rows, cols, retZero);\n};\n\n\nfunction retOne() { return 1; }\n\n\n// Generate a rows x cols matrix of ones.\njStat.ones = function ones(rows, cols) {\n  if (!isNumber(cols))\n    cols = rows;\n  return jStat.create(rows, cols, retOne);\n};\n\n\n// Generate a rows x cols matrix of uniformly random numbers.\njStat.rand = function rand(rows, cols) {\n  if (!isNumber(cols))\n    cols = rows;\n  return jStat.create(rows, cols, jStat._random_fn);\n};\n\n\nfunction retIdent(i, j) { return i === j ? 1 : 0; }\n\n\n// Generate an identity matrix of size row x cols.\njStat.identity = function identity(rows, cols) {\n  if (!isNumber(cols))\n    cols = rows;\n  return jStat.create(rows, cols, retIdent);\n};\n\n\n// Tests whether a matrix is symmetric\njStat.symmetric = function symmetric(arr) {\n  var size = arr.length;\n  var row, col;\n\n  if (arr.length !== arr[0].length)\n    return false;\n\n  for (row = 0; row < size; row++) {\n    for (col = 0; col < size; col++)\n      if (arr[col][row] !== arr[row][col])\n        return false;\n  }\n\n  return true;\n};\n\n\n// Set all values to zero.\njStat.clear = function clear(arr) {\n  return jStat.alter(arr, retZero);\n};\n\n\n// Generate sequence.\njStat.seq = function seq(min, max, length, func) {\n  if (!isFunction(func))\n    func = false;\n\n  var arr = [];\n  var hival = calcRdx(min, max);\n  var step = (max * hival - min * hival) / ((length - 1) * hival);\n  var current = min;\n  var cnt;\n\n  // Current is assigned using a technique to compensate for IEEE error.\n  // TODO: Needs better implementation.\n  for (cnt = 0;\n       current <= max && cnt < length;\n       cnt++, current = (min * hival + step * hival * cnt) / hival) {\n    arr.push((func ? func(current, cnt) : current));\n  }\n\n  return arr;\n};\n\n\n// arange(5) -> [0,1,2,3,4]\n// arange(1,5) -> [1,2,3,4]\n// arange(5,1,-1) -> [5,4,3,2]\njStat.arange = function arange(start, end, step) {\n  var rl = [];\n  var i;\n  step = step || 1;\n  if (end === undefined) {\n    end = start;\n    start = 0;\n  }\n  if (start === end || step === 0) {\n    return [];\n  }\n  if (start < end && step < 0) {\n    return [];\n  }\n  if (start > end && step > 0) {\n    return [];\n  }\n  if (step > 0) {\n    for (i = start; i < end; i += step) {\n      rl.push(i);\n    }\n  } else {\n    for (i = start; i > end; i += step) {\n      rl.push(i);\n    }\n  }\n  return rl;\n};\n\n\n// A=[[1,2,3],[4,5,6],[7,8,9]]\n// slice(A,{row:{end:2},col:{start:1}}) -> [[2,3],[5,6]]\n// slice(A,1,{start:1}) -> [5,6]\n// as numpy code A[:2,1:]\njStat.slice = (function(){\n  function _slice(list, start, end, step) {\n    // note it's not equal to range.map mode it's a bug\n    var i;\n    var rl = [];\n    var length = list.length;\n    if (start === undefined && end === undefined && step === undefined) {\n      return jStat.copy(list);\n    }\n\n    start = start || 0;\n    end = end || list.length;\n    start = start >= 0 ? start : length + start;\n    end = end >= 0 ? end : length + end;\n    step = step || 1;\n    if (start === end || step === 0) {\n      return [];\n    }\n    if (start < end && step < 0) {\n      return [];\n    }\n    if (start > end && step > 0) {\n      return [];\n    }\n    if (step > 0) {\n      for (i = start; i < end; i += step) {\n        rl.push(list[i]);\n      }\n    } else {\n      for (i = start; i > end;i += step) {\n        rl.push(list[i]);\n      }\n    }\n    return rl;\n  }\n\n  function slice(list, rcSlice) {\n    var colSlice, rowSlice;\n    rcSlice = rcSlice || {};\n    if (isNumber(rcSlice.row)) {\n      if (isNumber(rcSlice.col))\n        return list[rcSlice.row][rcSlice.col];\n      var row = jStat.rowa(list, rcSlice.row);\n      colSlice = rcSlice.col || {};\n      return _slice(row, colSlice.start, colSlice.end, colSlice.step);\n    }\n\n    if (isNumber(rcSlice.col)) {\n      var col = jStat.cola(list, rcSlice.col);\n      rowSlice = rcSlice.row || {};\n      return _slice(col, rowSlice.start, rowSlice.end, rowSlice.step);\n    }\n\n    rowSlice = rcSlice.row || {};\n    colSlice = rcSlice.col || {};\n    var rows = _slice(list, rowSlice.start, rowSlice.end, rowSlice.step);\n    return rows.map(function(row) {\n      return _slice(row, colSlice.start, colSlice.end, colSlice.step);\n    });\n  }\n\n  return slice;\n}());\n\n\n// A=[[1,2,3],[4,5,6],[7,8,9]]\n// sliceAssign(A,{row:{start:1},col:{start:1}},[[0,0],[0,0]])\n// A=[[1,2,3],[4,0,0],[7,0,0]]\njStat.sliceAssign = function sliceAssign(A, rcSlice, B) {\n  var nl, ml;\n  if (isNumber(rcSlice.row)) {\n    if (isNumber(rcSlice.col))\n      return A[rcSlice.row][rcSlice.col] = B;\n    rcSlice.col = rcSlice.col || {};\n    rcSlice.col.start = rcSlice.col.start || 0;\n    rcSlice.col.end = rcSlice.col.end || A[0].length;\n    rcSlice.col.step = rcSlice.col.step || 1;\n    nl = jStat.arange(rcSlice.col.start,\n                          Math.min(A.length, rcSlice.col.end),\n                          rcSlice.col.step);\n    var m = rcSlice.row;\n    nl.forEach(function(n, i) {\n      A[m][n] = B[i];\n    });\n    return A;\n  }\n\n  if (isNumber(rcSlice.col)) {\n    rcSlice.row = rcSlice.row || {};\n    rcSlice.row.start = rcSlice.row.start || 0;\n    rcSlice.row.end = rcSlice.row.end || A.length;\n    rcSlice.row.step = rcSlice.row.step || 1;\n    ml = jStat.arange(rcSlice.row.start,\n                          Math.min(A[0].length, rcSlice.row.end),\n                          rcSlice.row.step);\n    var n = rcSlice.col;\n    ml.forEach(function(m, j) {\n      A[m][n] = B[j];\n    });\n    return A;\n  }\n\n  if (B[0].length === undefined) {\n    B = [B];\n  }\n  rcSlice.row.start = rcSlice.row.start || 0;\n  rcSlice.row.end = rcSlice.row.end || A.length;\n  rcSlice.row.step = rcSlice.row.step || 1;\n  rcSlice.col.start = rcSlice.col.start || 0;\n  rcSlice.col.end = rcSlice.col.end || A[0].length;\n  rcSlice.col.step = rcSlice.col.step || 1;\n  ml = jStat.arange(rcSlice.row.start,\n                        Math.min(A.length, rcSlice.row.end),\n                        rcSlice.row.step);\n  nl = jStat.arange(rcSlice.col.start,\n                        Math.min(A[0].length, rcSlice.col.end),\n                        rcSlice.col.step);\n  ml.forEach(function(m, i) {\n    nl.forEach(function(n, j) {\n      A[m][n] = B[i][j];\n    });\n  });\n  return A;\n};\n\n\n// [1,2,3] ->\n// [[1,0,0],[0,2,0],[0,0,3]]\njStat.diagonal = function diagonal(diagArray) {\n  var mat = jStat.zeros(diagArray.length, diagArray.length);\n  diagArray.forEach(function(t, i) {\n    mat[i][i] = t;\n  });\n  return mat;\n};\n\n\n// return copy of A\njStat.copy = function copy(A) {\n  return A.map(function(row) {\n    if (isNumber(row))\n      return row;\n    return row.map(function(t) {\n      return t;\n    });\n  });\n};\n\n\n// TODO: Go over this entire implementation. Seems a tragic waste of resources\n// doing all this work. Instead, and while ugly, use new Function() to generate\n// a custom function for each static method.\n\n// Quick reference.\nvar jProto = jStat.prototype;\n\n// Default length.\njProto.length = 0;\n\n// For internal use only.\n// TODO: Check if they're actually used, and if they are then rename them\n// to _*\njProto.push = Array.prototype.push;\njProto.sort = Array.prototype.sort;\njProto.splice = Array.prototype.splice;\njProto.slice = Array.prototype.slice;\n\n\n// Return a clean array.\njProto.toArray = function toArray() {\n  return this.length > 1 ? slice.call(this) : slice.call(this)[0];\n};\n\n\n// Map a function to a matrix or vector.\njProto.map = function map(func, toAlter) {\n  return jStat(jStat.map(this, func, toAlter));\n};\n\n\n// Cumulatively combine the elements of a matrix or vector using a function.\njProto.cumreduce = function cumreduce(func, toAlter) {\n  return jStat(jStat.cumreduce(this, func, toAlter));\n};\n\n\n// Destructively alter an array.\njProto.alter = function alter(func) {\n  jStat.alter(this, func);\n  return this;\n};\n\n\n// Extend prototype with methods that have no argument.\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jProto[passfunc] = function(func) {\n      var self = this,\n      results;\n      // Check for callback.\n      if (func) {\n        setTimeout(function() {\n          func.call(self, jProto[passfunc].call(self));\n        });\n        return this;\n      }\n      results = jStat[passfunc](this);\n      return isArray(results) ? jStat(results) : results;\n    };\n  })(funcs[i]);\n})('transpose clear symmetric rows cols dimensions diag antidiag'.split(' '));\n\n\n// Extend prototype with methods that have one argument.\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jProto[passfunc] = function(index, func) {\n      var self = this;\n      // check for callback\n      if (func) {\n        setTimeout(function() {\n          func.call(self, jProto[passfunc].call(self, index));\n        });\n        return this;\n      }\n      return jStat(jStat[passfunc](this, index));\n    };\n  })(funcs[i]);\n})('row col'.split(' '));\n\n\n// Extend prototype with simple shortcut methods.\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jProto[passfunc] = function() {\n      return jStat(jStat[passfunc].apply(null, arguments));\n    };\n  })(funcs[i]);\n})('create zeros ones rand identity'.split(' '));\n\n\n// Exposing jStat.\nreturn jStat;\n\n}(Math));\n(function(jStat, Math) {\n\nvar isFunction = jStat.utils.isFunction;\n\n// Ascending functions for sort\nfunction ascNum(a, b) { return a - b; }\n\nfunction clip(arg, min, max) {\n  return Math.max(min, Math.min(arg, max));\n}\n\n\n// sum of an array\njStat.sum = function sum(arr) {\n  var sum = 0;\n  var i = arr.length;\n  while (--i >= 0)\n    sum += arr[i];\n  return sum;\n};\n\n\n// sum squared\njStat.sumsqrd = function sumsqrd(arr) {\n  var sum = 0;\n  var i = arr.length;\n  while (--i >= 0)\n    sum += arr[i] * arr[i];\n  return sum;\n};\n\n\n// sum of squared errors of prediction (SSE)\njStat.sumsqerr = function sumsqerr(arr) {\n  var mean = jStat.mean(arr);\n  var sum = 0;\n  var i = arr.length;\n  var tmp;\n  while (--i >= 0) {\n    tmp = arr[i] - mean;\n    sum += tmp * tmp;\n  }\n  return sum;\n};\n\n// sum of an array in each row\njStat.sumrow = function sumrow(arr) {\n  var sum = 0;\n  var i = arr.length;\n  while (--i >= 0)\n    sum += arr[i];\n  return sum;\n};\n\n// product of an array\njStat.product = function product(arr) {\n  var prod = 1;\n  var i = arr.length;\n  while (--i >= 0)\n    prod *= arr[i];\n  return prod;\n};\n\n\n// minimum value of an array\njStat.min = function min(arr) {\n  var low = arr[0];\n  var i = 0;\n  while (++i < arr.length)\n    if (arr[i] < low)\n      low = arr[i];\n  return low;\n};\n\n\n// maximum value of an array\njStat.max = function max(arr) {\n  var high = arr[0];\n  var i = 0;\n  while (++i < arr.length)\n    if (arr[i] > high)\n      high = arr[i];\n  return high;\n};\n\n\n// unique values of an array\njStat.unique = function unique(arr) {\n  var hash = {}, _arr = [];\n  for(var i = 0; i < arr.length; i++) {\n    if (!hash[arr[i]]) {\n      hash[arr[i]] = true;\n      _arr.push(arr[i]);\n    }\n  }\n  return _arr;\n};\n\n\n// mean value of an array\njStat.mean = function mean(arr) {\n  return jStat.sum(arr) / arr.length;\n};\n\n\n// mean squared error (MSE)\njStat.meansqerr = function meansqerr(arr) {\n  return jStat.sumsqerr(arr) / arr.length;\n};\n\n\n// geometric mean of an array\njStat.geomean = function geomean(arr) {\n  return Math.pow(jStat.product(arr), 1 / arr.length);\n};\n\n\n// median of an array\njStat.median = function median(arr) {\n  var arrlen = arr.length;\n  var _arr = arr.slice().sort(ascNum);\n  // check if array is even or odd, then return the appropriate\n  return !(arrlen & 1)\n    ? (_arr[(arrlen / 2) - 1 ] + _arr[(arrlen / 2)]) / 2\n    : _arr[(arrlen / 2) | 0 ];\n};\n\n\n// cumulative sum of an array\njStat.cumsum = function cumsum(arr) {\n  return jStat.cumreduce(arr, function (a, b) { return a + b; });\n};\n\n\n// cumulative product of an array\njStat.cumprod = function cumprod(arr) {\n  return jStat.cumreduce(arr, function (a, b) { return a * b; });\n};\n\n\n// successive differences of a sequence\njStat.diff = function diff(arr) {\n  var diffs = [];\n  var arrLen = arr.length;\n  var i;\n  for (i = 1; i < arrLen; i++)\n    diffs.push(arr[i] - arr[i - 1]);\n  return diffs;\n};\n\n\n// ranks of an array\njStat.rank = function (arr) {\n  var i;\n  var distinctNumbers = [];\n  var numberCounts = {};\n  for (i = 0; i < arr.length; i++) {\n    var number = arr[i];\n    if (numberCounts[number]) {\n      numberCounts[number]++;\n    } else {\n      numberCounts[number] = 1;\n      distinctNumbers.push(number);\n    }\n  }\n\n  var sortedDistinctNumbers = distinctNumbers.sort(ascNum);\n  var numberRanks = {};\n  var currentRank = 1;\n  for (i = 0; i < sortedDistinctNumbers.length; i++) {\n    var number = sortedDistinctNumbers[i];\n    var count = numberCounts[number];\n    var first = currentRank;\n    var last = currentRank + count - 1;\n    var rank = (first + last) / 2;\n    numberRanks[number] = rank;\n    currentRank += count;\n  }\n\n  return arr.map(function (number) {\n    return numberRanks[number];\n  });\n};\n\n\n// mode of an array\n// if there are multiple modes of an array, return all of them\n// is this the appropriate way of handling it?\njStat.mode = function mode(arr) {\n  var arrLen = arr.length;\n  var _arr = arr.slice().sort(ascNum);\n  var count = 1;\n  var maxCount = 0;\n  var numMaxCount = 0;\n  var mode_arr = [];\n  var i;\n\n  for (i = 0; i < arrLen; i++) {\n    if (_arr[i] === _arr[i + 1]) {\n      count++;\n    } else {\n      if (count > maxCount) {\n        mode_arr = [_arr[i]];\n        maxCount = count;\n        numMaxCount = 0;\n      }\n      // are there multiple max counts\n      else if (count === maxCount) {\n        mode_arr.push(_arr[i]);\n        numMaxCount++;\n      }\n      // resetting count for new value in array\n      count = 1;\n    }\n  }\n\n  return numMaxCount === 0 ? mode_arr[0] : mode_arr;\n};\n\n\n// range of an array\njStat.range = function range(arr) {\n  return jStat.max(arr) - jStat.min(arr);\n};\n\n// variance of an array\n// flag = true indicates sample instead of population\njStat.variance = function variance(arr, flag) {\n  return jStat.sumsqerr(arr) / (arr.length - (flag ? 1 : 0));\n};\n\n// pooled variance of an array of arrays\njStat.pooledvariance = function pooledvariance(arr) {\n  var sumsqerr = arr.reduce(function (a, samples) {return a + jStat.sumsqerr(samples);}, 0);\n  var count = arr.reduce(function (a, samples) {return a + samples.length;}, 0);\n  return sumsqerr / (count - arr.length);\n};\n\n// deviation of an array\njStat.deviation = function (arr) {\n  var mean = jStat.mean(arr);\n  var arrlen = arr.length;\n  var dev = new Array(arrlen);\n  for (var i = 0; i < arrlen; i++) {\n    dev[i] = arr[i] - mean;\n  }\n  return dev;\n};\n\n// standard deviation of an array\n// flag = true indicates sample instead of population\njStat.stdev = function stdev(arr, flag) {\n  return Math.sqrt(jStat.variance(arr, flag));\n};\n\n// pooled standard deviation of an array of arrays\njStat.pooledstdev = function pooledstdev(arr) {\n  return Math.sqrt(jStat.pooledvariance(arr));\n};\n\n// mean deviation (mean absolute deviation) of an array\njStat.meandev = function meandev(arr) {\n  var mean = jStat.mean(arr);\n  var a = [];\n  for (var i = arr.length - 1; i >= 0; i--) {\n    a.push(Math.abs(arr[i] - mean));\n  }\n  return jStat.mean(a);\n};\n\n\n// median deviation (median absolute deviation) of an array\njStat.meddev = function meddev(arr) {\n  var median = jStat.median(arr);\n  var a = [];\n  for (var i = arr.length - 1; i >= 0; i--) {\n    a.push(Math.abs(arr[i] - median));\n  }\n  return jStat.median(a);\n};\n\n\n// coefficient of variation\njStat.coeffvar = function coeffvar(arr) {\n  return jStat.stdev(arr) / jStat.mean(arr);\n};\n\n\n// quartiles of an array\njStat.quartiles = function quartiles(arr) {\n  var arrlen = arr.length;\n  var _arr = arr.slice().sort(ascNum);\n  return [\n    _arr[ Math.round((arrlen) / 4) - 1 ],\n    _arr[ Math.round((arrlen) / 2) - 1 ],\n    _arr[ Math.round((arrlen) * 3 / 4) - 1 ]\n  ];\n};\n\n\n// Arbitary quantiles of an array. Direct port of the scipy.stats\n// implementation by Pierre GF Gerard-Marchant.\njStat.quantiles = function quantiles(arr, quantilesArray, alphap, betap) {\n  var sortedArray = arr.slice().sort(ascNum);\n  var quantileVals = [quantilesArray.length];\n  var n = arr.length;\n  var i, p, m, aleph, k, gamma;\n\n  if (typeof alphap === 'undefined')\n    alphap = 3 / 8;\n  if (typeof betap === 'undefined')\n    betap = 3 / 8;\n\n  for (i = 0; i < quantilesArray.length; i++) {\n    p = quantilesArray[i];\n    m = alphap + p * (1 - alphap - betap);\n    aleph = n * p + m;\n    k = Math.floor(clip(aleph, 1, n - 1));\n    gamma = clip(aleph - k, 0, 1);\n    quantileVals[i] = (1 - gamma) * sortedArray[k - 1] + gamma * sortedArray[k];\n  }\n\n  return quantileVals;\n};\n\n// Return the k-th percentile of values in a range, where k is in the range 0..1, inclusive.\n// Passing true for the exclusive parameter excludes both endpoints of the range.\njStat.percentile = function percentile(arr, k, exclusive) {\n  var _arr = arr.slice().sort(ascNum);\n  var realIndex = k * (_arr.length + (exclusive ? 1 : -1)) + (exclusive ? 0 : 1);\n  var index = parseInt(realIndex);\n  var frac = realIndex - index;\n  if (index + 1 < _arr.length) {\n    return _arr[index - 1] + frac * (_arr[index] - _arr[index - 1]);\n  } else {\n    return _arr[index - 1];\n  }\n}\n\n// The percentile rank of score in a given array. Returns the percentage\n// of all values in the input array that are less than (kind='strict') or\n// less or equal than (kind='weak') score. Default is weak.\njStat.percentileOfScore = function percentileOfScore(arr, score, kind) {\n  var counter = 0;\n  var len = arr.length;\n  var strict = false;\n  var value, i;\n\n  if (kind === 'strict')\n    strict = true;\n\n  for (i = 0; i < len; i++) {\n    value = arr[i];\n    if ((strict && value < score) ||\n        (!strict && value <= score)) {\n      counter++;\n    }\n  }\n\n  return counter / len;\n};\n\n\n// Histogram (bin count) data\njStat.histogram = function histogram(arr, binCnt) {\n  binCnt = binCnt || 4;\n  var first = jStat.min(arr);\n  var binWidth = (jStat.max(arr) - first) / binCnt;\n  var len = arr.length;\n  var bins = [];\n  var i;\n\n  for (i = 0; i < binCnt; i++)\n    bins[i] = 0;\n  for (i = 0; i < len; i++)\n    bins[Math.min(Math.floor(((arr[i] - first) / binWidth)), binCnt - 1)] += 1;\n\n  return bins;\n};\n\n\n// covariance of two arrays\njStat.covariance = function covariance(arr1, arr2) {\n  var u = jStat.mean(arr1);\n  var v = jStat.mean(arr2);\n  var arr1Len = arr1.length;\n  var sq_dev = new Array(arr1Len);\n  var i;\n\n  for (i = 0; i < arr1Len; i++)\n    sq_dev[i] = (arr1[i] - u) * (arr2[i] - v);\n\n  return jStat.sum(sq_dev) / (arr1Len - 1);\n};\n\n\n// (pearson's) population correlation coefficient, rho\njStat.corrcoeff = function corrcoeff(arr1, arr2) {\n  return jStat.covariance(arr1, arr2) /\n      jStat.stdev(arr1, 1) /\n      jStat.stdev(arr2, 1);\n};\n\n  // (spearman's) rank correlation coefficient, sp\njStat.spearmancoeff =  function (arr1, arr2) {\n  arr1 = jStat.rank(arr1);\n  arr2 = jStat.rank(arr2);\n  //return pearson's correlation of the ranks:\n  return jStat.corrcoeff(arr1, arr2);\n}\n\n\n// statistical standardized moments (general form of skew/kurt)\njStat.stanMoment = function stanMoment(arr, n) {\n  var mu = jStat.mean(arr);\n  var sigma = jStat.stdev(arr);\n  var len = arr.length;\n  var skewSum = 0;\n\n  for (var i = 0; i < len; i++)\n    skewSum += Math.pow((arr[i] - mu) / sigma, n);\n\n  return skewSum / arr.length;\n};\n\n// (pearson's) moment coefficient of skewness\njStat.skewness = function skewness(arr) {\n  return jStat.stanMoment(arr, 3);\n};\n\n// (pearson's) (excess) kurtosis\njStat.kurtosis = function kurtosis(arr) {\n  return jStat.stanMoment(arr, 4) - 3;\n};\n\n\nvar jProto = jStat.prototype;\n\n\n// Extend jProto with method for calculating cumulative sums and products.\n// This differs from the similar extension below as cumsum and cumprod should\n// not be run again in the case fullbool === true.\n// If a matrix is passed, automatically assume operation should be done on the\n// columns.\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    // If a matrix is passed, automatically assume operation should be done on\n    // the columns.\n    jProto[passfunc] = function(fullbool, func) {\n      var arr = [];\n      var i = 0;\n      var tmpthis = this;\n      // Assignment reassignation depending on how parameters were passed in.\n      if (isFunction(fullbool)) {\n        func = fullbool;\n        fullbool = false;\n      }\n      // Check if a callback was passed with the function.\n      if (func) {\n        setTimeout(function() {\n          func.call(tmpthis, jProto[passfunc].call(tmpthis, fullbool));\n        });\n        return this;\n      }\n      // Check if matrix and run calculations.\n      if (this.length > 1) {\n        tmpthis = fullbool === true ? this : this.transpose();\n        for (; i < tmpthis.length; i++)\n          arr[i] = jStat[passfunc](tmpthis[i]);\n        return arr;\n      }\n      // Pass fullbool if only vector, not a matrix. for variance and stdev.\n      return jStat[passfunc](this[0], fullbool);\n    };\n  })(funcs[i]);\n})(('cumsum cumprod').split(' '));\n\n\n// Extend jProto with methods which don't require arguments and work on columns.\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    // If a matrix is passed, automatically assume operation should be done on\n    // the columns.\n    jProto[passfunc] = function(fullbool, func) {\n      var arr = [];\n      var i = 0;\n      var tmpthis = this;\n      // Assignment reassignation depending on how parameters were passed in.\n      if (isFunction(fullbool)) {\n        func = fullbool;\n        fullbool = false;\n      }\n      // Check if a callback was passed with the function.\n      if (func) {\n        setTimeout(function() {\n          func.call(tmpthis, jProto[passfunc].call(tmpthis, fullbool));\n        });\n        return this;\n      }\n      // Check if matrix and run calculations.\n      if (this.length > 1) {\n        if (passfunc !== 'sumrow')\n          tmpthis = fullbool === true ? this : this.transpose();\n        for (; i < tmpthis.length; i++)\n          arr[i] = jStat[passfunc](tmpthis[i]);\n        return fullbool === true\n            ? jStat[passfunc](jStat.utils.toVector(arr))\n            : arr;\n      }\n      // Pass fullbool if only vector, not a matrix. for variance and stdev.\n      return jStat[passfunc](this[0], fullbool);\n    };\n  })(funcs[i]);\n})(('sum sumsqrd sumsqerr sumrow product min max unique mean meansqerr ' +\n    'geomean median diff rank mode range variance deviation stdev meandev ' +\n    'meddev coeffvar quartiles histogram skewness kurtosis').split(' '));\n\n\n// Extend jProto with functions that take arguments. Operations on matrices are\n// done on columns.\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jProto[passfunc] = function() {\n      var arr = [];\n      var i = 0;\n      var tmpthis = this;\n      var args = Array.prototype.slice.call(arguments);\n      var callbackFunction;\n\n      // If the last argument is a function, we assume it's a callback; we\n      // strip the callback out and call the function again.\n      if (isFunction(args[args.length - 1])) {\n        callbackFunction = args[args.length - 1];\n        var argsToPass = args.slice(0, args.length - 1);\n\n        setTimeout(function() {\n          callbackFunction.call(tmpthis,\n                                jProto[passfunc].apply(tmpthis, argsToPass));\n        });\n        return this;\n\n      // Otherwise we curry the function args and call normally.\n      } else {\n        callbackFunction = undefined;\n        var curriedFunction = function curriedFunction(vector) {\n          return jStat[passfunc].apply(tmpthis, [vector].concat(args));\n        }\n      }\n\n      // If this is a matrix, run column-by-column.\n      if (this.length > 1) {\n        tmpthis = tmpthis.transpose();\n        for (; i < tmpthis.length; i++)\n          arr[i] = curriedFunction(tmpthis[i]);\n        return arr;\n      }\n\n      // Otherwise run on the vector.\n      return curriedFunction(this[0]);\n    };\n  })(funcs[i]);\n})('quantiles percentileOfScore'.split(' '));\n\n}(jStat, Math));\n// Special functions //\n(function(jStat, Math) {\n\n// Log-gamma function\njStat.gammaln = function gammaln(x) {\n  var j = 0;\n  var cof = [\n    76.18009172947146, -86.50532032941677, 24.01409824083091,\n    -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5\n  ];\n  var ser = 1.000000000190015;\n  var xx, y, tmp;\n  tmp = (y = xx = x) + 5.5;\n  tmp -= (xx + 0.5) * Math.log(tmp);\n  for (; j < 6; j++)\n    ser += cof[j] / ++y;\n  return Math.log(2.5066282746310005 * ser / xx) - tmp;\n};\n\n/*\n * log-gamma function to support poisson distribution sampling. The\n * algorithm comes from SPECFUN by Shanjie Zhang and Jianming Jin and their\n * book \"Computation of Special Functions\", 1996, John Wiley & Sons, Inc.\n */\njStat.loggam = function loggam(x) {\n  var x0, x2, xp, gl, gl0;\n  var k, n;\n\n  var a = [8.333333333333333e-02, -2.777777777777778e-03,\n          7.936507936507937e-04, -5.952380952380952e-04,\n          8.417508417508418e-04, -1.917526917526918e-03,\n          6.410256410256410e-03, -2.955065359477124e-02,\n          1.796443723688307e-01, -1.39243221690590e+00];\n  x0 = x;\n  n = 0;\n  if ((x == 1.0) || (x == 2.0)) {\n      return 0.0;\n  }\n  if (x <= 7.0) {\n      n = Math.floor(7 - x);\n      x0 = x + n;\n  }\n  x2 = 1.0 / (x0 * x0);\n  xp = 2 * Math.PI;\n  gl0 = a[9];\n  for (k = 8; k >= 0; k--) {\n      gl0 *= x2;\n      gl0 += a[k];\n  }\n  gl = gl0 / x0 + 0.5 * Math.log(xp) + (x0 - 0.5) * Math.log(x0) - x0;\n  if (x <= 7.0) {\n      for (k = 1; k <= n; k++) {\n          gl -= Math.log(x0 - 1.0);\n          x0 -= 1.0;\n      }\n  }\n  return gl;\n}\n\n// gamma of x\njStat.gammafn = function gammafn(x) {\n  var p = [-1.716185138865495, 24.76565080557592, -379.80425647094563,\n           629.3311553128184, 866.9662027904133, -31451.272968848367,\n           -36144.413418691176, 66456.14382024054\n  ];\n  var q = [-30.8402300119739, 315.35062697960416, -1015.1563674902192,\n           -3107.771671572311, 22538.118420980151, 4755.8462775278811,\n           -134659.9598649693, -115132.2596755535];\n  var fact = false;\n  var n = 0;\n  var xden = 0;\n  var xnum = 0;\n  var y = x;\n  var i, z, yi, res;\n  if (x > 171.6243769536076) {\n    return Infinity;\n  }\n  if (y <= 0) {\n    res = y % 1 + 3.6e-16;\n    if (res) {\n      fact = (!(y & 1) ? 1 : -1) * Math.PI / Math.sin(Math.PI * res);\n      y = 1 - y;\n    } else {\n      return Infinity;\n    }\n  }\n  yi = y;\n  if (y < 1) {\n    z = y++;\n  } else {\n    z = (y -= n = (y | 0) - 1) - 1;\n  }\n  for (i = 0; i < 8; ++i) {\n    xnum = (xnum + p[i]) * z;\n    xden = xden * z + q[i];\n  }\n  res = xnum / xden + 1;\n  if (yi < y) {\n    res /= yi;\n  } else if (yi > y) {\n    for (i = 0; i < n; ++i) {\n      res *= y;\n      y++;\n    }\n  }\n  if (fact) {\n    res = fact / res;\n  }\n  return res;\n};\n\n\n// lower incomplete gamma function, which is usually typeset with a\n// lower-case greek gamma as the function symbol\njStat.gammap = function gammap(a, x) {\n  return jStat.lowRegGamma(a, x) * jStat.gammafn(a);\n};\n\n\n// The lower regularized incomplete gamma function, usually written P(a,x)\njStat.lowRegGamma = function lowRegGamma(a, x) {\n  var aln = jStat.gammaln(a);\n  var ap = a;\n  var sum = 1 / a;\n  var del = sum;\n  var b = x + 1 - a;\n  var c = 1 / 1.0e-30;\n  var d = 1 / b;\n  var h = d;\n  var i = 1;\n  // calculate maximum number of itterations required for a\n  var ITMAX = -~(Math.log((a >= 1) ? a : 1 / a) * 8.5 + a * 0.4 + 17);\n  var an;\n\n  if (x < 0 || a <= 0) {\n    return NaN;\n  } else if (x < a + 1) {\n    for (; i <= ITMAX; i++) {\n      sum += del *= x / ++ap;\n    }\n    return (sum * Math.exp(-x + a * Math.log(x) - (aln)));\n  }\n\n  for (; i <= ITMAX; i++) {\n    an = -i * (i - a);\n    b += 2;\n    d = an * d + b;\n    c = b + an / c;\n    d = 1 / d;\n    h *= d * c;\n  }\n\n  return (1 - h * Math.exp(-x + a * Math.log(x) - (aln)));\n};\n\n// natural log factorial of n\njStat.factorialln = function factorialln(n) {\n  return n < 0 ? NaN : jStat.gammaln(n + 1);\n};\n\n// factorial of n\njStat.factorial = function factorial(n) {\n  return n < 0 ? NaN : jStat.gammafn(n + 1);\n};\n\n// combinations of n, m\njStat.combination = function combination(n, m) {\n  // make sure n or m don't exceed the upper limit of usable values\n  return (n > 170 || m > 170)\n      ? Math.exp(jStat.combinationln(n, m))\n      : (jStat.factorial(n) / jStat.factorial(m)) / jStat.factorial(n - m);\n};\n\n\njStat.combinationln = function combinationln(n, m){\n  return jStat.factorialln(n) - jStat.factorialln(m) - jStat.factorialln(n - m);\n};\n\n\n// permutations of n, m\njStat.permutation = function permutation(n, m) {\n  return jStat.factorial(n) / jStat.factorial(n - m);\n};\n\n\n// beta function\njStat.betafn = function betafn(x, y) {\n  // ensure arguments are positive\n  if (x <= 0 || y <= 0)\n    return undefined;\n  // make sure x + y doesn't exceed the upper limit of usable values\n  return (x + y > 170)\n      ? Math.exp(jStat.betaln(x, y))\n      : jStat.gammafn(x) * jStat.gammafn(y) / jStat.gammafn(x + y);\n};\n\n\n// natural logarithm of beta function\njStat.betaln = function betaln(x, y) {\n  return jStat.gammaln(x) + jStat.gammaln(y) - jStat.gammaln(x + y);\n};\n\n\n// Evaluates the continued fraction for incomplete beta function by modified\n// Lentz's method.\njStat.betacf = function betacf(x, a, b) {\n  var fpmin = 1e-30;\n  var m = 1;\n  var qab = a + b;\n  var qap = a + 1;\n  var qam = a - 1;\n  var c = 1;\n  var d = 1 - qab * x / qap;\n  var m2, aa, del, h;\n\n  // These q's will be used in factors that occur in the coefficients\n  if (Math.abs(d) < fpmin)\n    d = fpmin;\n  d = 1 / d;\n  h = d;\n\n  for (; m <= 100; m++) {\n    m2 = 2 * m;\n    aa = m * (b - m) * x / ((qam + m2) * (a + m2));\n    // One step (the even one) of the recurrence\n    d = 1 + aa * d;\n    if (Math.abs(d) < fpmin)\n      d = fpmin;\n    c = 1 + aa / c;\n    if (Math.abs(c) < fpmin)\n      c = fpmin;\n    d = 1 / d;\n    h *= d * c;\n    aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));\n    // Next step of the recurrence (the odd one)\n    d = 1 + aa * d;\n    if (Math.abs(d) < fpmin)\n      d = fpmin;\n    c = 1 + aa / c;\n    if (Math.abs(c) < fpmin)\n      c = fpmin;\n    d = 1 / d;\n    del = d * c;\n    h *= del;\n    if (Math.abs(del - 1.0) < 3e-7)\n      break;\n  }\n\n  return h;\n};\n\n\n// Returns the inverse of the lower regularized inomplete gamma function\njStat.gammapinv = function gammapinv(p, a) {\n  var j = 0;\n  var a1 = a - 1;\n  var EPS = 1e-8;\n  var gln = jStat.gammaln(a);\n  var x, err, t, u, pp, lna1, afac;\n\n  if (p >= 1)\n    return Math.max(100, a + 100 * Math.sqrt(a));\n  if (p <= 0)\n    return 0;\n  if (a > 1) {\n    lna1 = Math.log(a1);\n    afac = Math.exp(a1 * (lna1 - 1) - gln);\n    pp = (p < 0.5) ? p : 1 - p;\n    t = Math.sqrt(-2 * Math.log(pp));\n    x = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;\n    if (p < 0.5)\n      x = -x;\n    x = Math.max(1e-3,\n                 a * Math.pow(1 - 1 / (9 * a) - x / (3 * Math.sqrt(a)), 3));\n  } else {\n    t = 1 - a * (0.253 + a * 0.12);\n    if (p < t)\n      x = Math.pow(p / t, 1 / a);\n    else\n      x = 1 - Math.log(1 - (p - t) / (1 - t));\n  }\n\n  for(; j < 12; j++) {\n    if (x <= 0)\n      return 0;\n    err = jStat.lowRegGamma(a, x) - p;\n    if (a > 1)\n      t = afac * Math.exp(-(x - a1) + a1 * (Math.log(x) - lna1));\n    else\n      t = Math.exp(-x + a1 * Math.log(x) - gln);\n    u = err / t;\n    x -= (t = u / (1 - 0.5 * Math.min(1, u * ((a - 1) / x - 1))));\n    if (x <= 0)\n      x = 0.5 * (x + t);\n    if (Math.abs(t) < EPS * x)\n      break;\n  }\n\n  return x;\n};\n\n\n// Returns the error function erf(x)\njStat.erf = function erf(x) {\n  var cof = [-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2,\n             -9.561514786808631e-3, -9.46595344482036e-4, 3.66839497852761e-4,\n             4.2523324806907e-5, -2.0278578112534e-5, -1.624290004647e-6,\n             1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8,\n             6.529054439e-9, 5.059343495e-9, -9.91364156e-10,\n             -2.27365122e-10, 9.6467911e-11, 2.394038e-12,\n             -6.886027e-12, 8.94487e-13, 3.13092e-13,\n             -1.12708e-13, 3.81e-16, 7.106e-15,\n             -1.523e-15, -9.4e-17, 1.21e-16,\n             -2.8e-17];\n  var j = cof.length - 1;\n  var isneg = false;\n  var d = 0;\n  var dd = 0;\n  var t, ty, tmp, res;\n\n  if (x < 0) {\n    x = -x;\n    isneg = true;\n  }\n\n  t = 2 / (2 + x);\n  ty = 4 * t - 2;\n\n  for(; j > 0; j--) {\n    tmp = d;\n    d = ty * d - dd + cof[j];\n    dd = tmp;\n  }\n\n  res = t * Math.exp(-x * x + 0.5 * (cof[0] + ty * d) - dd);\n  return isneg ? res - 1 : 1 - res;\n};\n\n\n// Returns the complmentary error function erfc(x)\njStat.erfc = function erfc(x) {\n  return 1 - jStat.erf(x);\n};\n\n\n// Returns the inverse of the complementary error function\njStat.erfcinv = function erfcinv(p) {\n  var j = 0;\n  var x, err, t, pp;\n  if (p >= 2)\n    return -100;\n  if (p <= 0)\n    return 100;\n  pp = (p < 1) ? p : 2 - p;\n  t = Math.sqrt(-2 * Math.log(pp / 2));\n  x = -0.70711 * ((2.30753 + t * 0.27061) /\n                  (1 + t * (0.99229 + t * 0.04481)) - t);\n  for (; j < 2; j++) {\n    err = jStat.erfc(x) - pp;\n    x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);\n  }\n  return (p < 1) ? x : -x;\n};\n\n\n// Returns the inverse of the incomplete beta function\njStat.ibetainv = function ibetainv(p, a, b) {\n  var EPS = 1e-8;\n  var a1 = a - 1;\n  var b1 = b - 1;\n  var j = 0;\n  var lna, lnb, pp, t, u, err, x, al, h, w, afac;\n  if (p <= 0)\n    return 0;\n  if (p >= 1)\n    return 1;\n  if (a >= 1 && b >= 1) {\n    pp = (p < 0.5) ? p : 1 - p;\n    t = Math.sqrt(-2 * Math.log(pp));\n    x = (2.30753 + t * 0.27061) / (1 + t* (0.99229 + t * 0.04481)) - t;\n    if (p < 0.5)\n      x = -x;\n    al = (x * x - 3) / 6;\n    h = 2 / (1 / (2 * a - 1)  + 1 / (2 * b - 1));\n    w = (x * Math.sqrt(al + h) / h) - (1 / (2 * b - 1) - 1 / (2 * a - 1)) *\n        (al + 5 / 6 - 2 / (3 * h));\n    x = a / (a + b * Math.exp(2 * w));\n  } else {\n    lna = Math.log(a / (a + b));\n    lnb = Math.log(b / (a + b));\n    t = Math.exp(a * lna) / a;\n    u = Math.exp(b * lnb) / b;\n    w = t + u;\n    if (p < t / w)\n      x = Math.pow(a * w * p, 1 / a);\n    else\n      x = 1 - Math.pow(b * w * (1 - p), 1 / b);\n  }\n  afac = -jStat.gammaln(a) - jStat.gammaln(b) + jStat.gammaln(a + b);\n  for(; j < 10; j++) {\n    if (x === 0 || x === 1)\n      return x;\n    err = jStat.ibeta(x, a, b) - p;\n    t = Math.exp(a1 * Math.log(x) + b1 * Math.log(1 - x) + afac);\n    u = err / t;\n    x -= (t = u / (1 - 0.5 * Math.min(1, u * (a1 / x - b1 / (1 - x)))));\n    if (x <= 0)\n      x = 0.5 * (x + t);\n    if (x >= 1)\n      x = 0.5 * (x + t + 1);\n    if (Math.abs(t) < EPS * x && j > 0)\n      break;\n  }\n  return x;\n};\n\n\n// Returns the incomplete beta function I_x(a,b)\njStat.ibeta = function ibeta(x, a, b) {\n  // Factors in front of the continued fraction.\n  var bt = (x === 0 || x === 1) ?  0 :\n    Math.exp(jStat.gammaln(a + b) - jStat.gammaln(a) -\n             jStat.gammaln(b) + a * Math.log(x) + b *\n             Math.log(1 - x));\n  if (x < 0 || x > 1)\n    return false;\n  if (x < (a + 1) / (a + b + 2))\n    // Use continued fraction directly.\n    return bt * jStat.betacf(x, a, b) / a;\n  // else use continued fraction after making the symmetry transformation.\n  return 1 - bt * jStat.betacf(1 - x, b, a) / b;\n};\n\n\n// Returns a normal deviate (mu=0, sigma=1).\n// If n and m are specified it returns a object of normal deviates.\njStat.randn = function randn(n, m) {\n  var u, v, x, y, q;\n  if (!m)\n    m = n;\n  if (n)\n    return jStat.create(n, m, function() { return jStat.randn(); });\n  do {\n    u = jStat._random_fn();\n    v = 1.7156 * (jStat._random_fn() - 0.5);\n    x = u - 0.449871;\n    y = Math.abs(v) + 0.386595;\n    q = x * x + y * (0.19600 * y - 0.25472 * x);\n  } while (q > 0.27597 && (q > 0.27846 || v * v > -4 * Math.log(u) * u * u));\n  return v / u;\n};\n\n\n// Returns a gamma deviate by the method of Marsaglia and Tsang.\njStat.randg = function randg(shape, n, m) {\n  var oalph = shape;\n  var a1, a2, u, v, x, mat;\n  if (!m)\n    m = n;\n  if (!shape)\n    shape = 1;\n  if (n) {\n    mat = jStat.zeros(n,m);\n    mat.alter(function() { return jStat.randg(shape); });\n    return mat;\n  }\n  if (shape < 1)\n    shape += 1;\n  a1 = shape - 1 / 3;\n  a2 = 1 / Math.sqrt(9 * a1);\n  do {\n    do {\n      x = jStat.randn();\n      v = 1 + a2 * x;\n    } while(v <= 0);\n    v = v * v * v;\n    u = jStat._random_fn();\n  } while(u > 1 - 0.331 * Math.pow(x, 4) &&\n          Math.log(u) > 0.5 * x*x + a1 * (1 - v + Math.log(v)));\n  // alpha > 1\n  if (shape == oalph)\n    return a1 * v;\n  // alpha < 1\n  do {\n    u = jStat._random_fn();\n  } while(u === 0);\n  return Math.pow(u, 1 / oalph) * a1 * v;\n};\n\n\n// making use of static methods on the instance\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jStat.fn[passfunc] = function() {\n      return jStat(\n          jStat.map(this, function(value) { return jStat[passfunc](value); }));\n    }\n  })(funcs[i]);\n})('gammaln gammafn factorial factorialln'.split(' '));\n\n\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jStat.fn[passfunc] = function() {\n      return jStat(jStat[passfunc].apply(null, arguments));\n    };\n  })(funcs[i]);\n})('randn'.split(' '));\n\n}(jStat, Math));\n(function(jStat, Math) {\n\n// generate all distribution instance methods\n(function(list) {\n  for (var i = 0; i < list.length; i++) (function(func) {\n    // distribution instance method\n    jStat[func] = function f(a, b, c) {\n      if (!(this instanceof f))\n        return new f(a, b, c);\n      this._a = a;\n      this._b = b;\n      this._c = c;\n      return this;\n    };\n    // distribution method to be used on a jStat instance\n    jStat.fn[func] = function(a, b, c) {\n      var newthis = jStat[func](a, b, c);\n      newthis.data = this;\n      return newthis;\n    };\n    // sample instance method\n    jStat[func].prototype.sample = function(arr) {\n      var a = this._a;\n      var b = this._b;\n      var c = this._c;\n      if (arr)\n        return jStat.alter(arr, function() {\n          return jStat[func].sample(a, b, c);\n        });\n      else\n        return jStat[func].sample(a, b, c);\n    };\n    // generate the pdf, cdf and inv instance methods\n    (function(vals) {\n      for (var i = 0; i < vals.length; i++) (function(fnfunc) {\n        jStat[func].prototype[fnfunc] = function(x) {\n          var a = this._a;\n          var b = this._b;\n          var c = this._c;\n          if (!x && x !== 0)\n            x = this.data;\n          if (typeof x !== 'number') {\n            return jStat.fn.map.call(x, function(x) {\n              return jStat[func][fnfunc](x, a, b, c);\n            });\n          }\n          return jStat[func][fnfunc](x, a, b, c);\n        };\n      })(vals[i]);\n    })('pdf cdf inv'.split(' '));\n    // generate the mean, median, mode and variance instance methods\n    (function(vals) {\n      for (var i = 0; i < vals.length; i++) (function(fnfunc) {\n        jStat[func].prototype[fnfunc] = function() {\n          return jStat[func][fnfunc](this._a, this._b, this._c);\n        };\n      })(vals[i]);\n    })('mean median mode variance'.split(' '));\n  })(list[i]);\n})((\n  'beta centralF cauchy chisquare exponential gamma invgamma kumaraswamy ' +\n  'laplace lognormal noncentralt normal pareto studentt weibull uniform ' +\n  'binomial negbin hypgeom poisson triangular tukey arcsine'\n).split(' '));\n\n\n\n// extend beta function with static methods\njStat.extend(jStat.beta, {\n  pdf: function pdf(x, alpha, beta) {\n    // PDF is zero outside the support\n    if (x > 1 || x < 0)\n      return 0;\n    // PDF is one for the uniform case\n    if (alpha == 1 && beta == 1)\n      return 1;\n\n    if (alpha < 512 && beta < 512) {\n      return (Math.pow(x, alpha - 1) * Math.pow(1 - x, beta - 1)) /\n          jStat.betafn(alpha, beta);\n    } else {\n      return Math.exp((alpha - 1) * Math.log(x) +\n                      (beta - 1) * Math.log(1 - x) -\n                      jStat.betaln(alpha, beta));\n    }\n  },\n\n  cdf: function cdf(x, alpha, beta) {\n    return (x > 1 || x < 0) ? (x > 1) * 1 : jStat.ibeta(x, alpha, beta);\n  },\n\n  inv: function inv(x, alpha, beta) {\n    return jStat.ibetainv(x, alpha, beta);\n  },\n\n  mean: function mean(alpha, beta) {\n    return alpha / (alpha + beta);\n  },\n\n  median: function median(alpha, beta) {\n    return jStat.ibetainv(0.5, alpha, beta);\n  },\n\n  mode: function mode(alpha, beta) {\n    return (alpha - 1 ) / ( alpha + beta - 2);\n  },\n\n  // return a random sample\n  sample: function sample(alpha, beta) {\n    var u = jStat.randg(alpha);\n    return u / (u + jStat.randg(beta));\n  },\n\n  variance: function variance(alpha, beta) {\n    return (alpha * beta) / (Math.pow(alpha + beta, 2) * (alpha + beta + 1));\n  }\n});\n\n// extend F function with static methods\njStat.extend(jStat.centralF, {\n  // This implementation of the pdf function avoids float overflow\n  // See the way that R calculates this value:\n  // https://svn.r-project.org/R/trunk/src/nmath/df.c\n  pdf: function pdf(x, df1, df2) {\n    var p, q, f;\n\n    if (x < 0)\n      return 0;\n\n    if (df1 <= 2) {\n      if (x === 0 && df1 < 2) {\n        return Infinity;\n      }\n      if (x === 0 && df1 === 2) {\n        return 1;\n      }\n      return (1 / jStat.betafn(df1 / 2, df2 / 2)) *\n              Math.pow(df1 / df2, df1 / 2) *\n              Math.pow(x, (df1/2) - 1) *\n              Math.pow((1 + (df1 / df2) * x), -(df1 + df2) / 2);\n    }\n\n    p = (df1 * x) / (df2 + x * df1);\n    q = df2 / (df2 + x * df1);\n    f = df1 * q / 2.0;\n    return f * jStat.binomial.pdf((df1 - 2) / 2, (df1 + df2 - 2) / 2, p);\n  },\n\n  cdf: function cdf(x, df1, df2) {\n    if (x < 0)\n      return 0;\n    return jStat.ibeta((df1 * x) / (df1 * x + df2), df1 / 2, df2 / 2);\n  },\n\n  inv: function inv(x, df1, df2) {\n    return df2 / (df1 * (1 / jStat.ibetainv(x, df1 / 2, df2 / 2) - 1));\n  },\n\n  mean: function mean(df1, df2) {\n    return (df2 > 2) ? df2 / (df2 - 2) : undefined;\n  },\n\n  mode: function mode(df1, df2) {\n    return (df1 > 2) ? (df2 * (df1 - 2)) / (df1 * (df2 + 2)) : undefined;\n  },\n\n  // return a random sample\n  sample: function sample(df1, df2) {\n    var x1 = jStat.randg(df1 / 2) * 2;\n    var x2 = jStat.randg(df2 / 2) * 2;\n    return (x1 / df1) / (x2 / df2);\n  },\n\n  variance: function variance(df1, df2) {\n    if (df2 <= 4)\n      return undefined;\n    return 2 * df2 * df2 * (df1 + df2 - 2) /\n        (df1 * (df2 - 2) * (df2 - 2) * (df2 - 4));\n  }\n});\n\n\n// extend cauchy function with static methods\njStat.extend(jStat.cauchy, {\n  pdf: function pdf(x, local, scale) {\n    if (scale < 0) { return 0; }\n\n    return (scale / (Math.pow(x - local, 2) + Math.pow(scale, 2))) / Math.PI;\n  },\n\n  cdf: function cdf(x, local, scale) {\n    return Math.atan((x - local) / scale) / Math.PI + 0.5;\n  },\n\n  inv: function(p, local, scale) {\n    return local + scale * Math.tan(Math.PI * (p - 0.5));\n  },\n\n  median: function median(local/*, scale*/) {\n    return local;\n  },\n\n  mode: function mode(local/*, scale*/) {\n    return local;\n  },\n\n  sample: function sample(local, scale) {\n    return jStat.randn() *\n        Math.sqrt(1 / (2 * jStat.randg(0.5))) * scale + local;\n  }\n});\n\n\n\n// extend chisquare function with static methods\njStat.extend(jStat.chisquare, {\n  pdf: function pdf(x, dof) {\n    if (x < 0)\n      return 0;\n    return (x === 0 && dof === 2) ? 0.5 :\n        Math.exp((dof / 2 - 1) * Math.log(x) - x / 2 - (dof / 2) *\n                 Math.log(2) - jStat.gammaln(dof / 2));\n  },\n\n  cdf: function cdf(x, dof) {\n    if (x < 0)\n      return 0;\n    return jStat.lowRegGamma(dof / 2, x / 2);\n  },\n\n  inv: function(p, dof) {\n    return 2 * jStat.gammapinv(p, 0.5 * dof);\n  },\n\n  mean : function(dof) {\n    return dof;\n  },\n\n  // TODO: this is an approximation (is there a better way?)\n  median: function median(dof) {\n    return dof * Math.pow(1 - (2 / (9 * dof)), 3);\n  },\n\n  mode: function mode(dof) {\n    return (dof - 2 > 0) ? dof - 2 : 0;\n  },\n\n  sample: function sample(dof) {\n    return jStat.randg(dof / 2) * 2;\n  },\n\n  variance: function variance(dof) {\n    return 2 * dof;\n  }\n});\n\n\n\n// extend exponential function with static methods\njStat.extend(jStat.exponential, {\n  pdf: function pdf(x, rate) {\n    return x < 0 ? 0 : rate * Math.exp(-rate * x);\n  },\n\n  cdf: function cdf(x, rate) {\n    return x < 0 ? 0 : 1 - Math.exp(-rate * x);\n  },\n\n  inv: function(p, rate) {\n    return -Math.log(1 - p) / rate;\n  },\n\n  mean : function(rate) {\n    return 1 / rate;\n  },\n\n  median: function (rate) {\n    return (1 / rate) * Math.log(2);\n  },\n\n  mode: function mode(/*rate*/) {\n    return 0;\n  },\n\n  sample: function sample(rate) {\n    return -1 / rate * Math.log(jStat._random_fn());\n  },\n\n  variance : function(rate) {\n    return Math.pow(rate, -2);\n  }\n});\n\n\n\n// extend gamma function with static methods\njStat.extend(jStat.gamma, {\n  pdf: function pdf(x, shape, scale) {\n    if (x < 0)\n      return 0;\n    return (x === 0 && shape === 1) ? 1 / scale :\n            Math.exp((shape - 1) * Math.log(x) - x / scale -\n                    jStat.gammaln(shape) - shape * Math.log(scale));\n  },\n\n  cdf: function cdf(x, shape, scale) {\n    if (x < 0)\n      return 0;\n    return jStat.lowRegGamma(shape, x / scale);\n  },\n\n  inv: function(p, shape, scale) {\n    return jStat.gammapinv(p, shape) * scale;\n  },\n\n  mean : function(shape, scale) {\n    return shape * scale;\n  },\n\n  mode: function mode(shape, scale) {\n    if(shape > 1) return (shape - 1) * scale;\n    return undefined;\n  },\n\n  sample: function sample(shape, scale) {\n    return jStat.randg(shape) * scale;\n  },\n\n  variance: function variance(shape, scale) {\n    return shape * scale * scale;\n  }\n});\n\n// extend inverse gamma function with static methods\njStat.extend(jStat.invgamma, {\n  pdf: function pdf(x, shape, scale) {\n    if (x <= 0)\n      return 0;\n    return Math.exp(-(shape + 1) * Math.log(x) - scale / x -\n                    jStat.gammaln(shape) + shape * Math.log(scale));\n  },\n\n  cdf: function cdf(x, shape, scale) {\n    if (x <= 0)\n      return 0;\n    return 1 - jStat.lowRegGamma(shape, scale / x);\n  },\n\n  inv: function(p, shape, scale) {\n    return scale / jStat.gammapinv(1 - p, shape);\n  },\n\n  mean : function(shape, scale) {\n    return (shape > 1) ? scale / (shape - 1) : undefined;\n  },\n\n  mode: function mode(shape, scale) {\n    return scale / (shape + 1);\n  },\n\n  sample: function sample(shape, scale) {\n    return scale / jStat.randg(shape);\n  },\n\n  variance: function variance(shape, scale) {\n    if (shape <= 2)\n      return undefined;\n    return scale * scale / ((shape - 1) * (shape - 1) * (shape - 2));\n  }\n});\n\n\n// extend kumaraswamy function with static methods\njStat.extend(jStat.kumaraswamy, {\n  pdf: function pdf(x, alpha, beta) {\n    if (x === 0 && alpha === 1)\n      return beta;\n    else if (x === 1 && beta === 1)\n      return alpha;\n    return Math.exp(Math.log(alpha) + Math.log(beta) + (alpha - 1) *\n                    Math.log(x) + (beta - 1) *\n                    Math.log(1 - Math.pow(x, alpha)));\n  },\n\n  cdf: function cdf(x, alpha, beta) {\n    if (x < 0)\n      return 0;\n    else if (x > 1)\n      return 1;\n    return (1 - Math.pow(1 - Math.pow(x, alpha), beta));\n  },\n\n  inv: function inv(p, alpha, beta) {\n    return Math.pow(1 - Math.pow(1 - p, 1 / beta), 1 / alpha);\n  },\n\n  mean : function(alpha, beta) {\n    return (beta * jStat.gammafn(1 + 1 / alpha) *\n            jStat.gammafn(beta)) / (jStat.gammafn(1 + 1 / alpha + beta));\n  },\n\n  median: function median(alpha, beta) {\n    return Math.pow(1 - Math.pow(2, -1 / beta), 1 / alpha);\n  },\n\n  mode: function mode(alpha, beta) {\n    if (!(alpha >= 1 && beta >= 1 && (alpha !== 1 && beta !== 1)))\n      return undefined;\n    return Math.pow((alpha - 1) / (alpha * beta - 1), 1 / alpha);\n  },\n\n  variance: function variance(/*alpha, beta*/) {\n    throw new Error('variance not yet implemented');\n    // TODO: complete this\n  }\n});\n\n\n\n// extend lognormal function with static methods\njStat.extend(jStat.lognormal, {\n  pdf: function pdf(x, mu, sigma) {\n    if (x <= 0)\n      return 0;\n    return Math.exp(-Math.log(x) - 0.5 * Math.log(2 * Math.PI) -\n                    Math.log(sigma) - Math.pow(Math.log(x) - mu, 2) /\n                    (2 * sigma * sigma));\n  },\n\n  cdf: function cdf(x, mu, sigma) {\n    if (x < 0)\n      return 0;\n    return 0.5 +\n        (0.5 * jStat.erf((Math.log(x) - mu) / Math.sqrt(2 * sigma * sigma)));\n  },\n\n  inv: function(p, mu, sigma) {\n    return Math.exp(-1.41421356237309505 * sigma * jStat.erfcinv(2 * p) + mu);\n  },\n\n  mean: function mean(mu, sigma) {\n    return Math.exp(mu + sigma * sigma / 2);\n  },\n\n  median: function median(mu/*, sigma*/) {\n    return Math.exp(mu);\n  },\n\n  mode: function mode(mu, sigma) {\n    return Math.exp(mu - sigma * sigma);\n  },\n\n  sample: function sample(mu, sigma) {\n    return Math.exp(jStat.randn() * sigma + mu);\n  },\n\n  variance: function variance(mu, sigma) {\n    return (Math.exp(sigma * sigma) - 1) * Math.exp(2 * mu + sigma * sigma);\n  }\n});\n\n\n\n// extend noncentralt function with static methods\njStat.extend(jStat.noncentralt, {\n  pdf: function pdf(x, dof, ncp) {\n    var tol = 1e-14;\n    if (Math.abs(ncp) < tol)  // ncp approx 0; use student-t\n      return jStat.studentt.pdf(x, dof)\n\n    if (Math.abs(x) < tol) {  // different formula for x == 0\n      return Math.exp(jStat.gammaln((dof + 1) / 2) - ncp * ncp / 2 -\n                      0.5 * Math.log(Math.PI * dof) - jStat.gammaln(dof / 2));\n    }\n\n    // formula for x != 0\n    return dof / x *\n        (jStat.noncentralt.cdf(x * Math.sqrt(1 + 2 / dof), dof+2, ncp) -\n         jStat.noncentralt.cdf(x, dof, ncp));\n  },\n\n  cdf: function cdf(x, dof, ncp) {\n    var tol = 1e-14;\n    var min_iterations = 200;\n\n    if (Math.abs(ncp) < tol)  // ncp approx 0; use student-t\n      return jStat.studentt.cdf(x, dof);\n\n    // turn negative x into positive and flip result afterwards\n    var flip = false;\n    if (x < 0) {\n      flip = true;\n      ncp = -ncp;\n    }\n\n    var prob = jStat.normal.cdf(-ncp, 0, 1);\n    var value = tol + 1;\n    // use value at last two steps to determine convergence\n    var lastvalue = value;\n    var y = x * x / (x * x + dof);\n    var j = 0;\n    var p = Math.exp(-ncp * ncp / 2);\n    var q = Math.exp(-ncp * ncp / 2 - 0.5 * Math.log(2) -\n                     jStat.gammaln(3 / 2)) * ncp;\n    while (j < min_iterations || lastvalue > tol || value > tol) {\n      lastvalue = value;\n      if (j > 0) {\n        p *= (ncp * ncp) / (2 * j);\n        q *= (ncp * ncp) / (2 * (j + 1 / 2));\n      }\n      value = p * jStat.beta.cdf(y, j + 0.5, dof / 2) +\n          q * jStat.beta.cdf(y, j+1, dof/2);\n      prob += 0.5 * value;\n      j++;\n    }\n\n    return flip ? (1 - prob) : prob;\n  }\n});\n\n\n// extend normal function with static methods\njStat.extend(jStat.normal, {\n  pdf: function pdf(x, mean, std) {\n    return Math.exp(-0.5 * Math.log(2 * Math.PI) -\n                    Math.log(std) - Math.pow(x - mean, 2) / (2 * std * std));\n  },\n\n  cdf: function cdf(x, mean, std) {\n    return 0.5 * (1 + jStat.erf((x - mean) / Math.sqrt(2 * std * std)));\n  },\n\n  inv: function(p, mean, std) {\n    return -1.41421356237309505 * std * jStat.erfcinv(2 * p) + mean;\n  },\n\n  mean : function(mean/*, std*/) {\n    return mean;\n  },\n\n  median: function median(mean/*, std*/) {\n    return mean;\n  },\n\n  mode: function (mean/*, std*/) {\n    return mean;\n  },\n\n  sample: function sample(mean, std) {\n    return jStat.randn() * std + mean;\n  },\n\n  variance : function(mean, std) {\n    return std * std;\n  }\n});\n\n\n\n// extend pareto function with static methods\njStat.extend(jStat.pareto, {\n  pdf: function pdf(x, scale, shape) {\n    if (x < scale)\n      return 0;\n    return (shape * Math.pow(scale, shape)) / Math.pow(x, shape + 1);\n  },\n\n  cdf: function cdf(x, scale, shape) {\n    if (x < scale)\n      return 0;\n    return 1 - Math.pow(scale / x, shape);\n  },\n\n  inv: function inv(p, scale, shape) {\n    return scale / Math.pow(1 - p, 1 / shape);\n  },\n\n  mean: function mean(scale, shape) {\n    if (shape <= 1)\n      return undefined;\n    return (shape * Math.pow(scale, shape)) / (shape - 1);\n  },\n\n  median: function median(scale, shape) {\n    return scale * (shape * Math.SQRT2);\n  },\n\n  mode: function mode(scale/*, shape*/) {\n    return scale;\n  },\n\n  variance : function(scale, shape) {\n    if (shape <= 2)\n      return undefined;\n    return (scale*scale * shape) / (Math.pow(shape - 1, 2) * (shape - 2));\n  }\n});\n\n\n\n// extend studentt function with static methods\njStat.extend(jStat.studentt, {\n  pdf: function pdf(x, dof) {\n    dof = dof > 1e100 ? 1e100 : dof;\n    return (1/(Math.sqrt(dof) * jStat.betafn(0.5, dof/2))) *\n        Math.pow(1 + ((x * x) / dof), -((dof + 1) / 2));\n  },\n\n  cdf: function cdf(x, dof) {\n    var dof2 = dof / 2;\n    return jStat.ibeta((x + Math.sqrt(x * x + dof)) /\n                       (2 * Math.sqrt(x * x + dof)), dof2, dof2);\n  },\n\n  inv: function(p, dof) {\n    var x = jStat.ibetainv(2 * Math.min(p, 1 - p), 0.5 * dof, 0.5);\n    x = Math.sqrt(dof * (1 - x) / x);\n    return (p > 0.5) ? x : -x;\n  },\n\n  mean: function mean(dof) {\n    return (dof > 1) ? 0 : undefined;\n  },\n\n  median: function median(/*dof*/) {\n    return 0;\n  },\n\n  mode: function mode(/*dof*/) {\n    return 0;\n  },\n\n  sample: function sample(dof) {\n    return jStat.randn() * Math.sqrt(dof / (2 * jStat.randg(dof / 2)));\n  },\n\n  variance: function variance(dof) {\n    return (dof  > 2) ? dof / (dof - 2) : (dof > 1) ? Infinity : undefined;\n  }\n});\n\n\n\n// extend weibull function with static methods\njStat.extend(jStat.weibull, {\n  pdf: function pdf(x, scale, shape) {\n    if (x < 0 || scale < 0 || shape < 0)\n      return 0;\n    return (shape / scale) * Math.pow((x / scale), (shape - 1)) *\n        Math.exp(-(Math.pow((x / scale), shape)));\n  },\n\n  cdf: function cdf(x, scale, shape) {\n    return x < 0 ? 0 : 1 - Math.exp(-Math.pow((x / scale), shape));\n  },\n\n  inv: function(p, scale, shape) {\n    return scale * Math.pow(-Math.log(1 - p), 1 / shape);\n  },\n\n  mean : function(scale, shape) {\n    return scale * jStat.gammafn(1 + 1 / shape);\n  },\n\n  median: function median(scale, shape) {\n    return scale * Math.pow(Math.log(2), 1 / shape);\n  },\n\n  mode: function mode(scale, shape) {\n    if (shape <= 1)\n      return 0;\n    return scale * Math.pow((shape - 1) / shape, 1 / shape);\n  },\n\n  sample: function sample(scale, shape) {\n    return scale * Math.pow(-Math.log(jStat._random_fn()), 1 / shape);\n  },\n\n  variance: function variance(scale, shape) {\n    return scale * scale * jStat.gammafn(1 + 2 / shape) -\n        Math.pow(jStat.weibull.mean(scale, shape), 2);\n  }\n});\n\n\n\n// extend uniform function with static methods\njStat.extend(jStat.uniform, {\n  pdf: function pdf(x, a, b) {\n    return (x < a || x > b) ? 0 : 1 / (b - a);\n  },\n\n  cdf: function cdf(x, a, b) {\n    if (x < a)\n      return 0;\n    else if (x < b)\n      return (x - a) / (b - a);\n    return 1;\n  },\n\n  inv: function(p, a, b) {\n    return a + (p * (b - a));\n  },\n\n  mean: function mean(a, b) {\n    return 0.5 * (a + b);\n  },\n\n  median: function median(a, b) {\n    return jStat.mean(a, b);\n  },\n\n  mode: function mode(/*a, b*/) {\n    throw new Error('mode is not yet implemented');\n  },\n\n  sample: function sample(a, b) {\n    return (a / 2 + b / 2) + (b / 2 - a / 2) * (2 * jStat._random_fn() - 1);\n  },\n\n  variance: function variance(a, b) {\n    return Math.pow(b - a, 2) / 12;\n  }\n});\n\n\n// Got this from http://www.math.ucla.edu/~tom/distributions/binomial.html\nfunction betinc(x, a, b, eps) {\n  var a0 = 0;\n  var b0 = 1;\n  var a1 = 1;\n  var b1 = 1;\n  var m9 = 0;\n  var a2 = 0;\n  var c9;\n\n  while (Math.abs((a1 - a2) / a1) > eps) {\n    a2 = a1;\n    c9 = -(a + m9) * (a + b + m9) * x / (a + 2 * m9) / (a + 2 * m9 + 1);\n    a0 = a1 + c9 * a0;\n    b0 = b1 + c9 * b0;\n    m9 = m9 + 1;\n    c9 = m9 * (b - m9) * x / (a + 2 * m9 - 1) / (a + 2 * m9);\n    a1 = a0 + c9 * a1;\n    b1 = b0 + c9 * b1;\n    a0 = a0 / b1;\n    b0 = b0 / b1;\n    a1 = a1 / b1;\n    b1 = 1;\n  }\n\n  return a1 / a;\n}\n\n\n// extend uniform function with static methods\njStat.extend(jStat.binomial, {\n  pdf: function pdf(k, n, p) {\n    return (p === 0 || p === 1) ?\n      ((n * p) === k ? 1 : 0) :\n      jStat.combination(n, k) * Math.pow(p, k) * Math.pow(1 - p, n - k);\n  },\n\n  cdf: function cdf(x, n, p) {\n    var betacdf;\n    var eps = 1e-10;\n\n    if (x < 0)\n      return 0;\n    if (x >= n)\n      return 1;\n    if (p < 0 || p > 1 || n <= 0)\n      return NaN;\n\n    x = Math.floor(x);\n    var z = p;\n    var a = x + 1;\n    var b = n - x;\n    var s = a + b;\n    var bt = Math.exp(jStat.gammaln(s) - jStat.gammaln(b) -\n                      jStat.gammaln(a) + a * Math.log(z) + b * Math.log(1 - z));\n\n    if (z < (a + 1) / (s + 2))\n      betacdf = bt * betinc(z, a, b, eps);\n    else\n      betacdf = 1 - bt * betinc(1 - z, b, a, eps);\n\n    return Math.round((1 - betacdf) * (1 / eps)) / (1 / eps);\n  }\n});\n\n\n\n// extend uniform function with static methods\njStat.extend(jStat.negbin, {\n  pdf: function pdf(k, r, p) {\n    if (k !== k >>> 0)\n      return false;\n    if (k < 0)\n      return 0;\n    return jStat.combination(k + r - 1, r - 1) *\n        Math.pow(1 - p, k) * Math.pow(p, r);\n  },\n\n  cdf: function cdf(x, r, p) {\n    var sum = 0,\n    k = 0;\n    if (x < 0) return 0;\n    for (; k <= x; k++) {\n      sum += jStat.negbin.pdf(k, r, p);\n    }\n    return sum;\n  }\n});\n\n\n\n// extend uniform function with static methods\njStat.extend(jStat.hypgeom, {\n  pdf: function pdf(k, N, m, n) {\n    // Hypergeometric PDF.\n\n    // A simplification of the CDF algorithm below.\n\n    // k = number of successes drawn\n    // N = population size\n    // m = number of successes in population\n    // n = number of items drawn from population\n\n    if(k !== k | 0) {\n      return false;\n    } else if(k < 0 || k < m - (N - n)) {\n      // It's impossible to have this few successes drawn.\n      return 0;\n    } else if(k > n || k > m) {\n      // It's impossible to have this many successes drawn.\n      return 0;\n    } else if (m * 2 > N) {\n      // More than half the population is successes.\n\n      if(n * 2 > N) {\n        // More than half the population is sampled.\n\n        return jStat.hypgeom.pdf(N - m - n + k, N, N - m, N - n)\n      } else {\n        // Half or less of the population is sampled.\n\n        return jStat.hypgeom.pdf(n - k, N, N - m, n);\n      }\n\n    } else if(n * 2 > N) {\n      // Half or less is successes.\n\n      return jStat.hypgeom.pdf(m - k, N, m, N - n);\n\n    } else if(m < n) {\n      // We want to have the number of things sampled to be less than the\n      // successes available. So swap the definitions of successful and sampled.\n      return jStat.hypgeom.pdf(k, N, n, m);\n    } else {\n      // If we get here, half or less of the population was sampled, half or\n      // less of it was successes, and we had fewer sampled things than\n      // successes. Now we can do this complicated iterative algorithm in an\n      // efficient way.\n\n      // The basic premise of the algorithm is that we partially normalize our\n      // intermediate product to keep it in a numerically good region, and then\n      // finish the normalization at the end.\n\n      // This variable holds the scaled probability of the current number of\n      // successes.\n      var scaledPDF = 1;\n\n      // This keeps track of how much we have normalized.\n      var samplesDone = 0;\n\n      for(var i = 0; i < k; i++) {\n        // For every possible number of successes up to that observed...\n\n        while(scaledPDF > 1 && samplesDone < n) {\n          // Intermediate result is growing too big. Apply some of the\n          // normalization to shrink everything.\n\n          scaledPDF *= 1 - (m / (N - samplesDone));\n\n          // Say we've normalized by this sample already.\n          samplesDone++;\n        }\n\n        // Work out the partially-normalized hypergeometric PDF for the next\n        // number of successes\n        scaledPDF *= (n - i) * (m - i) / ((i + 1) * (N - m - n + i + 1));\n      }\n\n      for(; samplesDone < n; samplesDone++) {\n        // Apply all the rest of the normalization\n        scaledPDF *= 1 - (m / (N - samplesDone));\n      }\n\n      // Bound answer sanely before returning.\n      return Math.min(1, Math.max(0, scaledPDF));\n    }\n  },\n\n  cdf: function cdf(x, N, m, n) {\n    // Hypergeometric CDF.\n\n    // This algorithm is due to Prof. Thomas S. Ferguson, <tom@math.ucla.edu>,\n    // and comes from his hypergeometric test calculator at\n    // <http://www.math.ucla.edu/~tom/distributions/Hypergeometric.html>.\n\n    // x = number of successes drawn\n    // N = population size\n    // m = number of successes in population\n    // n = number of items drawn from population\n\n    if(x < 0 || x < m - (N - n)) {\n      // It's impossible to have this few successes drawn or fewer.\n      return 0;\n    } else if(x >= n || x >= m) {\n      // We will always have this many successes or fewer.\n      return 1;\n    } else if (m * 2 > N) {\n      // More than half the population is successes.\n\n      if(n * 2 > N) {\n        // More than half the population is sampled.\n\n        return jStat.hypgeom.cdf(N - m - n + x, N, N - m, N - n)\n      } else {\n        // Half or less of the population is sampled.\n\n        return 1 - jStat.hypgeom.cdf(n - x - 1, N, N - m, n);\n      }\n\n    } else if(n * 2 > N) {\n      // Half or less is successes.\n\n      return 1 - jStat.hypgeom.cdf(m - x - 1, N, m, N - n);\n\n    } else if(m < n) {\n      // We want to have the number of things sampled to be less than the\n      // successes available. So swap the definitions of successful and sampled.\n      return jStat.hypgeom.cdf(x, N, n, m);\n    } else {\n      // If we get here, half or less of the population was sampled, half or\n      // less of it was successes, and we had fewer sampled things than\n      // successes. Now we can do this complicated iterative algorithm in an\n      // efficient way.\n\n      // The basic premise of the algorithm is that we partially normalize our\n      // intermediate sum to keep it in a numerically good region, and then\n      // finish the normalization at the end.\n\n      // Holds the intermediate, scaled total CDF.\n      var scaledCDF = 1;\n\n      // This variable holds the scaled probability of the current number of\n      // successes.\n      var scaledPDF = 1;\n\n      // This keeps track of how much we have normalized.\n      var samplesDone = 0;\n\n      for(var i = 0; i < x; i++) {\n        // For every possible number of successes up to that observed...\n\n        while(scaledCDF > 1 && samplesDone < n) {\n          // Intermediate result is growing too big. Apply some of the\n          // normalization to shrink everything.\n\n          var factor = 1 - (m / (N - samplesDone));\n\n          scaledPDF *= factor;\n          scaledCDF *= factor;\n\n          // Say we've normalized by this sample already.\n          samplesDone++;\n        }\n\n        // Work out the partially-normalized hypergeometric PDF for the next\n        // number of successes\n        scaledPDF *= (n - i) * (m - i) / ((i + 1) * (N - m - n + i + 1));\n\n        // Add to the CDF answer.\n        scaledCDF += scaledPDF;\n      }\n\n      for(; samplesDone < n; samplesDone++) {\n        // Apply all the rest of the normalization\n        scaledCDF *= 1 - (m / (N - samplesDone));\n      }\n\n      // Bound answer sanely before returning.\n      return Math.min(1, Math.max(0, scaledCDF));\n    }\n  }\n});\n\n\n\n// extend uniform function with static methods\njStat.extend(jStat.poisson, {\n  pdf: function pdf(k, l) {\n    if (l < 0 || (k % 1) !== 0 || k < 0) {\n      return 0;\n    }\n\n    return Math.pow(l, k) * Math.exp(-l) / jStat.factorial(k);\n  },\n\n  cdf: function cdf(x, l) {\n    var sumarr = [],\n    k = 0;\n    if (x < 0) return 0;\n    for (; k <= x; k++) {\n      sumarr.push(jStat.poisson.pdf(k, l));\n    }\n    return jStat.sum(sumarr);\n  },\n\n  mean : function(l) {\n    return l;\n  },\n\n  variance : function(l) {\n    return l;\n  },\n\n  sampleSmall: function sampleSmall(l) {\n    var p = 1, k = 0, L = Math.exp(-l);\n    do {\n      k++;\n      p *= jStat._random_fn();\n    } while (p > L);\n    return k - 1;\n  },\n\n  sampleLarge: function sampleLarge(l) {\n    var lam = l;\n    var k;\n    var U, V, slam, loglam, a, b, invalpha, vr, us;\n\n    slam = Math.sqrt(lam);\n    loglam = Math.log(lam);\n    b = 0.931 + 2.53 * slam;\n    a = -0.059 + 0.02483 * b;\n    invalpha = 1.1239 + 1.1328 / (b - 3.4);\n    vr = 0.9277 - 3.6224 / (b - 2);\n\n    while (1) {\n      U = Math.random() - 0.5;\n      V = Math.random();\n      us = 0.5 - Math.abs(U);\n      k = Math.floor((2 * a / us + b) * U + lam + 0.43);\n      if ((us >= 0.07) && (V <= vr)) {\n          return k;\n      }\n      if ((k < 0) || ((us < 0.013) && (V > us))) {\n          continue;\n      }\n      /* log(V) == log(0.0) ok here */\n      /* if U==0.0 so that us==0.0, log is ok since always returns */\n      if ((Math.log(V) + Math.log(invalpha) - Math.log(a / (us * us) + b)) <= (-lam + k * loglam - jStat.loggam(k + 1))) {\n          return k;\n      }\n    }\n  },\n\n  sample: function sample(l) {\n    if (l < 10)\n      return this.sampleSmall(l);\n    else\n      return this.sampleLarge(l);\n  }\n});\n\n// extend triangular function with static methods\njStat.extend(jStat.triangular, {\n  pdf: function pdf(x, a, b, c) {\n    if (b <= a || c < a || c > b) {\n      return NaN;\n    } else {\n      if (x < a || x > b) {\n        return 0;\n      } else if (x < c) {\n          return (2 * (x - a)) / ((b - a) * (c - a));\n      } else if (x === c) {\n          return (2 / (b - a));\n      } else { // x > c\n          return (2 * (b - x)) / ((b - a) * (b - c));\n      }\n    }\n  },\n\n  cdf: function cdf(x, a, b, c) {\n    if (b <= a || c < a || c > b)\n      return NaN;\n    if (x <= a)\n      return 0;\n    else if (x >= b)\n      return 1;\n    if (x <= c)\n      return Math.pow(x - a, 2) / ((b - a) * (c - a));\n    else // x > c\n      return 1 - Math.pow(b - x, 2) / ((b - a) * (b - c));\n  },\n\n  inv: function inv(p, a, b, c) {\n    if (b <= a || c < a || c > b) {\n      return NaN;\n    } else {\n      if (p <= ((c - a) / (b - a))) {\n        return a + (b - a) * Math.sqrt(p * ((c - a) / (b - a)));\n      } else { // p > ((c - a) / (b - a))\n        return a + (b - a) * (1 - Math.sqrt((1 - p) * (1 - ((c - a) / (b - a)))));\n      }\n    }\n  },\n\n  mean: function mean(a, b, c) {\n    return (a + b + c) / 3;\n  },\n\n  median: function median(a, b, c) {\n    if (c <= (a + b) / 2) {\n      return b - Math.sqrt((b - a) * (b - c)) / Math.sqrt(2);\n    } else if (c > (a + b) / 2) {\n      return a + Math.sqrt((b - a) * (c - a)) / Math.sqrt(2);\n    }\n  },\n\n  mode: function mode(a, b, c) {\n    return c;\n  },\n\n  sample: function sample(a, b, c) {\n    var u = jStat._random_fn();\n    if (u < ((c - a) / (b - a)))\n      return a + Math.sqrt(u * (b - a) * (c - a))\n    return b - Math.sqrt((1 - u) * (b - a) * (b - c));\n  },\n\n  variance: function variance(a, b, c) {\n    return (a * a + b * b + c * c - a * b - a * c - b * c) / 18;\n  }\n});\n\n\n// extend arcsine function with static methods\njStat.extend(jStat.arcsine, {\n  pdf: function pdf(x, a, b) {\n    if (b <= a) return NaN;\n\n    return (x <= a || x >= b) ? 0 :\n      (2 / Math.PI) *\n        Math.pow(Math.pow(b - a, 2) -\n                  Math.pow(2 * x - a - b, 2), -0.5);\n  },\n\n  cdf: function cdf(x, a, b) {\n    if (x < a)\n      return 0;\n    else if (x < b)\n      return (2 / Math.PI) * Math.asin(Math.sqrt((x - a)/(b - a)));\n    return 1;\n  },\n\n  inv: function(p, a, b) {\n    return a + (0.5 - 0.5 * Math.cos(Math.PI * p)) * (b - a);\n  },\n\n  mean: function mean(a, b) {\n    if (b <= a) return NaN;\n    return (a + b) / 2;\n  },\n\n  median: function median(a, b) {\n    if (b <= a) return NaN;\n    return (a + b) / 2;\n  },\n\n  mode: function mode(/*a, b*/) {\n    throw new Error('mode is not yet implemented');\n  },\n\n  sample: function sample(a, b) {\n    return ((a + b) / 2) + ((b - a) / 2) *\n      Math.sin(2 * Math.PI * jStat.uniform.sample(0, 1));\n  },\n\n  variance: function variance(a, b) {\n    if (b <= a) return NaN;\n    return Math.pow(b - a, 2) / 8;\n  }\n});\n\n\nfunction laplaceSign(x) { return x / Math.abs(x); }\n\njStat.extend(jStat.laplace, {\n  pdf: function pdf(x, mu, b) {\n    return (b <= 0) ? 0 : (Math.exp(-Math.abs(x - mu) / b)) / (2 * b);\n  },\n\n  cdf: function cdf(x, mu, b) {\n    if (b <= 0) { return 0; }\n\n    if(x < mu) {\n      return 0.5 * Math.exp((x - mu) / b);\n    } else {\n      return 1 - 0.5 * Math.exp(- (x - mu) / b);\n    }\n  },\n\n  mean: function(mu/*, b*/) {\n    return mu;\n  },\n\n  median: function(mu/*, b*/) {\n    return mu;\n  },\n\n  mode: function(mu/*, b*/) {\n    return mu;\n  },\n\n  variance: function(mu, b) {\n    return 2 * b * b;\n  },\n\n  sample: function sample(mu, b) {\n    var u = jStat._random_fn() - 0.5;\n\n    return mu - (b * laplaceSign(u) * Math.log(1 - (2 * Math.abs(u))));\n  }\n});\n\nfunction tukeyWprob(w, rr, cc) {\n  var nleg = 12;\n  var ihalf = 6;\n\n  var C1 = -30;\n  var C2 = -50;\n  var C3 = 60;\n  var bb   = 8;\n  var wlar = 3;\n  var wincr1 = 2;\n  var wincr2 = 3;\n  var xleg = [\n    0.981560634246719250690549090149,\n    0.904117256370474856678465866119,\n    0.769902674194304687036893833213,\n    0.587317954286617447296702418941,\n    0.367831498998180193752691536644,\n    0.125233408511468915472441369464\n  ];\n  var aleg = [\n    0.047175336386511827194615961485,\n    0.106939325995318430960254718194,\n    0.160078328543346226334652529543,\n    0.203167426723065921749064455810,\n    0.233492536538354808760849898925,\n    0.249147045813402785000562436043\n  ];\n\n  var qsqz = w * 0.5;\n\n  // if w >= 16 then the integral lower bound (occurs for c=20)\n  // is 0.99999999999995 so return a value of 1.\n\n  if (qsqz >= bb)\n    return 1.0;\n\n  // find (f(w/2) - 1) ^ cc\n  // (first term in integral of hartley's form).\n\n  var pr_w = 2 * jStat.normal.cdf(qsqz, 0, 1, 1, 0) - 1; // erf(qsqz / M_SQRT2)\n  // if pr_w ^ cc < 2e-22 then set pr_w = 0\n  if (pr_w >= Math.exp(C2 / cc))\n    pr_w = Math.pow(pr_w, cc);\n  else\n    pr_w = 0.0;\n\n  // if w is large then the second component of the\n  // integral is small, so fewer intervals are needed.\n\n  var wincr;\n  if (w > wlar)\n    wincr = wincr1;\n  else\n    wincr = wincr2;\n\n  // find the integral of second term of hartley's form\n  // for the integral of the range for equal-length\n  // intervals using legendre quadrature.  limits of\n  // integration are from (w/2, 8).  two or three\n  // equal-length intervals are used.\n\n  // blb and bub are lower and upper limits of integration.\n\n  var blb = qsqz;\n  var binc = (bb - qsqz) / wincr;\n  var bub = blb + binc;\n  var einsum = 0.0;\n\n  // integrate over each interval\n\n  var cc1 = cc - 1.0;\n  for (var wi = 1; wi <= wincr; wi++) {\n    var elsum = 0.0;\n    var a = 0.5 * (bub + blb);\n\n    // legendre quadrature with order = nleg\n\n    var b = 0.5 * (bub - blb);\n\n    for (var jj = 1; jj <= nleg; jj++) {\n      var j, xx;\n      if (ihalf < jj) {\n        j = (nleg - jj) + 1;\n        xx = xleg[j-1];\n      } else {\n        j = jj;\n        xx = -xleg[j-1];\n      }\n      var c = b * xx;\n      var ac = a + c;\n\n      // if exp(-qexpo/2) < 9e-14,\n      // then doesn't contribute to integral\n\n      var qexpo = ac * ac;\n      if (qexpo > C3)\n        break;\n\n      var pplus = 2 * jStat.normal.cdf(ac, 0, 1, 1, 0);\n      var pminus= 2 * jStat.normal.cdf(ac, w, 1, 1, 0);\n\n      // if rinsum ^ (cc-1) < 9e-14,\n      // then doesn't contribute to integral\n\n      var rinsum = (pplus * 0.5) - (pminus * 0.5);\n      if (rinsum >= Math.exp(C1 / cc1)) {\n        rinsum = (aleg[j-1] * Math.exp(-(0.5 * qexpo))) * Math.pow(rinsum, cc1);\n        elsum += rinsum;\n      }\n    }\n    elsum *= (((2.0 * b) * cc) / Math.sqrt(2 * Math.PI));\n    einsum += elsum;\n    blb = bub;\n    bub += binc;\n  }\n\n  // if pr_w ^ rr < 9e-14, then return 0\n  pr_w += einsum;\n  if (pr_w <= Math.exp(C1 / rr))\n    return 0;\n\n  pr_w = Math.pow(pr_w, rr);\n  if (pr_w >= 1) // 1 was iMax was eps\n    return 1;\n  return pr_w;\n}\n\nfunction tukeyQinv(p, c, v) {\n  var p0 = 0.322232421088;\n  var q0 = 0.993484626060e-01;\n  var p1 = -1.0;\n  var q1 = 0.588581570495;\n  var p2 = -0.342242088547;\n  var q2 = 0.531103462366;\n  var p3 = -0.204231210125;\n  var q3 = 0.103537752850;\n  var p4 = -0.453642210148e-04;\n  var q4 = 0.38560700634e-02;\n  var c1 = 0.8832;\n  var c2 = 0.2368;\n  var c3 = 1.214;\n  var c4 = 1.208;\n  var c5 = 1.4142;\n  var vmax = 120.0;\n\n  var ps = 0.5 - 0.5 * p;\n  var yi = Math.sqrt(Math.log(1.0 / (ps * ps)));\n  var t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0)\n     / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0);\n  if (v < vmax) t += (t * t * t + t) / v / 4.0;\n  var q = c1 - c2 * t;\n  if (v < vmax) q += -c3 / v + c4 * t / v;\n  return t * (q * Math.log(c - 1.0) + c5);\n}\n\njStat.extend(jStat.tukey, {\n  cdf: function cdf(q, nmeans, df) {\n    // Identical implementation as the R ptukey() function as of commit 68947\n    var rr = 1;\n    var cc = nmeans;\n\n    var nlegq = 16;\n    var ihalfq = 8;\n\n    var eps1 = -30.0;\n    var eps2 = 1.0e-14;\n    var dhaf  = 100.0;\n    var dquar = 800.0;\n    var deigh = 5000.0;\n    var dlarg = 25000.0;\n    var ulen1 = 1.0;\n    var ulen2 = 0.5;\n    var ulen3 = 0.25;\n    var ulen4 = 0.125;\n    var xlegq = [\n      0.989400934991649932596154173450,\n      0.944575023073232576077988415535,\n      0.865631202387831743880467897712,\n      0.755404408355003033895101194847,\n      0.617876244402643748446671764049,\n      0.458016777657227386342419442984,\n      0.281603550779258913230460501460,\n      0.950125098376374401853193354250e-1\n    ];\n    var alegq = [\n      0.271524594117540948517805724560e-1,\n      0.622535239386478928628438369944e-1,\n      0.951585116824927848099251076022e-1,\n      0.124628971255533872052476282192,\n      0.149595988816576732081501730547,\n      0.169156519395002538189312079030,\n      0.182603415044923588866763667969,\n      0.189450610455068496285396723208\n    ];\n\n    if (q <= 0)\n      return 0;\n\n    // df must be > 1\n    // there must be at least two values\n\n    if (df < 2 || rr < 1 || cc < 2) return NaN;\n\n    if (!Number.isFinite(q))\n      return 1;\n\n    if (df > dlarg)\n      return tukeyWprob(q, rr, cc);\n\n    // calculate leading constant\n\n    var f2 = df * 0.5;\n    var f2lf = ((f2 * Math.log(df)) - (df * Math.log(2))) - jStat.gammaln(f2);\n    var f21 = f2 - 1.0;\n\n    // integral is divided into unit, half-unit, quarter-unit, or\n    // eighth-unit length intervals depending on the value of the\n    // degrees of freedom.\n\n    var ff4 = df * 0.25;\n    var ulen;\n    if      (df <= dhaf)  ulen = ulen1;\n    else if (df <= dquar) ulen = ulen2;\n    else if (df <= deigh) ulen = ulen3;\n    else                  ulen = ulen4;\n\n    f2lf += Math.log(ulen);\n\n    // integrate over each subinterval\n\n    var ans = 0.0;\n\n    for (var i = 1; i <= 50; i++) {\n      var otsum = 0.0;\n\n      // legendre quadrature with order = nlegq\n      // nodes (stored in xlegq) are symmetric around zero.\n\n      var twa1 = (2 * i - 1) * ulen;\n\n      for (var jj = 1; jj <= nlegq; jj++) {\n        var j, t1;\n        if (ihalfq < jj) {\n          j = jj - ihalfq - 1;\n          t1 = (f2lf + (f21 * Math.log(twa1 + (xlegq[j] * ulen))))\n              - (((xlegq[j] * ulen) + twa1) * ff4);\n        } else {\n          j = jj - 1;\n          t1 = (f2lf + (f21 * Math.log(twa1 - (xlegq[j] * ulen))))\n              + (((xlegq[j] * ulen) - twa1) * ff4);\n        }\n\n        // if exp(t1) < 9e-14, then doesn't contribute to integral\n        var qsqz;\n        if (t1 >= eps1) {\n          if (ihalfq < jj) {\n            qsqz = q * Math.sqrt(((xlegq[j] * ulen) + twa1) * 0.5);\n          } else {\n            qsqz = q * Math.sqrt(((-(xlegq[j] * ulen)) + twa1) * 0.5);\n          }\n\n          // call wprob to find integral of range portion\n\n          var wprb = tukeyWprob(qsqz, rr, cc);\n          var rotsum = (wprb * alegq[j]) * Math.exp(t1);\n          otsum += rotsum;\n        }\n        // end legendre integral for interval i\n        // L200:\n      }\n\n      // if integral for interval i < 1e-14, then stop.\n      // However, in order to avoid small area under left tail,\n      // at least  1 / ulen  intervals are calculated.\n      if (i * ulen >= 1.0 && otsum <= eps2)\n        break;\n\n      // end of interval i\n      // L330:\n\n      ans += otsum;\n    }\n\n    if (otsum > eps2) { // not converged\n      throw new Error('tukey.cdf failed to converge');\n    }\n    if (ans > 1)\n      ans = 1;\n    return ans;\n  },\n\n  inv: function(p, nmeans, df) {\n    // Identical implementation as the R qtukey() function as of commit 68947\n    var rr = 1;\n    var cc = nmeans;\n\n    var eps = 0.0001;\n    var maxiter = 50;\n\n    // df must be > 1 ; there must be at least two values\n    if (df < 2 || rr < 1 || cc < 2) return NaN;\n\n    if (p < 0 || p > 1) return NaN;\n    if (p === 0) return 0;\n    if (p === 1) return Infinity;\n\n    // Initial value\n\n    var x0 = tukeyQinv(p, cc, df);\n\n    // Find prob(value < x0)\n\n    var valx0 = jStat.tukey.cdf(x0, nmeans, df) - p;\n\n    // Find the second iterate and prob(value < x1).\n    // If the first iterate has probability value\n    // exceeding p then second iterate is 1 less than\n    // first iterate; otherwise it is 1 greater.\n\n    var x1;\n    if (valx0 > 0.0)\n      x1 = Math.max(0.0, x0 - 1.0);\n    else\n      x1 = x0 + 1.0;\n    var valx1 = jStat.tukey.cdf(x1, nmeans, df) - p;\n\n    // Find new iterate\n\n    var ans;\n    for(var iter = 1; iter < maxiter; iter++) {\n      ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0));\n      valx0 = valx1;\n\n      // New iterate must be >= 0\n\n      x0 = x1;\n      if (ans < 0.0) {\n        ans = 0.0;\n        valx1 = -p;\n      }\n      // Find prob(value < new iterate)\n\n      valx1 = jStat.tukey.cdf(ans, nmeans, df) - p;\n      x1 = ans;\n\n      // If the difference between two successive\n      // iterates is less than eps, stop\n\n      var xabs = Math.abs(x1 - x0);\n      if (xabs < eps)\n        return ans;\n    }\n\n    throw new Error('tukey.inv failed to converge');\n  }\n});\n\n}(jStat, Math));\n/* Provides functions for the solution of linear system of equations, integration, extrapolation,\n * interpolation, eigenvalue problems, differential equations and PCA analysis. */\n\n(function(jStat, Math) {\n\nvar push = Array.prototype.push;\nvar isArray = jStat.utils.isArray;\n\nfunction isUsable(arg) {\n  return isArray(arg) || arg instanceof jStat;\n}\n\njStat.extend({\n\n  // add a vector/matrix to a vector/matrix or scalar\n  add: function add(arr, arg) {\n    // check if arg is a vector or scalar\n    if (isUsable(arg)) {\n      if (!isUsable(arg[0])) arg = [ arg ];\n      return jStat.map(arr, function(value, row, col) {\n        return value + arg[row][col];\n      });\n    }\n    return jStat.map(arr, function(value) { return value + arg; });\n  },\n\n  // subtract a vector or scalar from the vector\n  subtract: function subtract(arr, arg) {\n    // check if arg is a vector or scalar\n    if (isUsable(arg)) {\n      if (!isUsable(arg[0])) arg = [ arg ];\n      return jStat.map(arr, function(value, row, col) {\n        return value - arg[row][col] || 0;\n      });\n    }\n    return jStat.map(arr, function(value) { return value - arg; });\n  },\n\n  // matrix division\n  divide: function divide(arr, arg) {\n    if (isUsable(arg)) {\n      if (!isUsable(arg[0])) arg = [ arg ];\n      return jStat.multiply(arr, jStat.inv(arg));\n    }\n    return jStat.map(arr, function(value) { return value / arg; });\n  },\n\n  // matrix multiplication\n  multiply: function multiply(arr, arg) {\n    var row, col, nrescols, sum, nrow, ncol, res, rescols;\n    // eg: arr = 2 arg = 3 -> 6 for res[0][0] statement closure\n    if (arr.length === undefined && arg.length === undefined) {\n      return arr * arg;\n    }\n    nrow = arr.length,\n    ncol = arr[0].length,\n    res = jStat.zeros(nrow, nrescols = (isUsable(arg)) ? arg[0].length : ncol),\n    rescols = 0;\n    if (isUsable(arg)) {\n      for (; rescols < nrescols; rescols++) {\n        for (row = 0; row < nrow; row++) {\n          sum = 0;\n          for (col = 0; col < ncol; col++)\n          sum += arr[row][col] * arg[col][rescols];\n          res[row][rescols] = sum;\n        }\n      }\n      return (nrow === 1 && rescols === 1) ? res[0][0] : res;\n    }\n    return jStat.map(arr, function(value) { return value * arg; });\n  },\n\n  // outer([1,2,3],[4,5,6])\n  // ===\n  // [[1],[2],[3]] times [[4,5,6]]\n  // ->\n  // [[4,5,6],[8,10,12],[12,15,18]]\n  outer:function outer(A, B) {\n    return jStat.multiply(A.map(function(t){ return [t] }), [B]);\n  },\n\n\n  // Returns the dot product of two matricies\n  dot: function dot(arr, arg) {\n    if (!isUsable(arr[0])) arr = [ arr ];\n    if (!isUsable(arg[0])) arg = [ arg ];\n    // convert column to row vector\n    var left = (arr[0].length === 1 && arr.length !== 1) ? jStat.transpose(arr) : arr,\n    right = (arg[0].length === 1 && arg.length !== 1) ? jStat.transpose(arg) : arg,\n    res = [],\n    row = 0,\n    nrow = left.length,\n    ncol = left[0].length,\n    sum, col;\n    for (; row < nrow; row++) {\n      res[row] = [];\n      sum = 0;\n      for (col = 0; col < ncol; col++)\n      sum += left[row][col] * right[row][col];\n      res[row] = sum;\n    }\n    return (res.length === 1) ? res[0] : res;\n  },\n\n  // raise every element by a scalar\n  pow: function pow(arr, arg) {\n    return jStat.map(arr, function(value) { return Math.pow(value, arg); });\n  },\n\n  // exponentiate every element\n  exp: function exp(arr) {\n    return jStat.map(arr, function(value) { return Math.exp(value); });\n  },\n\n  // generate the natural log of every element\n  log: function exp(arr) {\n    return jStat.map(arr, function(value) { return Math.log(value); });\n  },\n\n  // generate the absolute values of the vector\n  abs: function abs(arr) {\n    return jStat.map(arr, function(value) { return Math.abs(value); });\n  },\n\n  // computes the p-norm of the vector\n  // In the case that a matrix is passed, uses the first row as the vector\n  norm: function norm(arr, p) {\n    var nnorm = 0,\n    i = 0;\n    // check the p-value of the norm, and set for most common case\n    if (isNaN(p)) p = 2;\n    // check if multi-dimensional array, and make vector correction\n    if (isUsable(arr[0])) arr = arr[0];\n    // vector norm\n    for (; i < arr.length; i++) {\n      nnorm += Math.pow(Math.abs(arr[i]), p);\n    }\n    return Math.pow(nnorm, 1 / p);\n  },\n\n  // computes the angle between two vectors in rads\n  // In case a matrix is passed, this uses the first row as the vector\n  angle: function angle(arr, arg) {\n    return Math.acos(jStat.dot(arr, arg) / (jStat.norm(arr) * jStat.norm(arg)));\n  },\n\n  // augment one matrix by another\n  // Note: this function returns a matrix, not a jStat object\n  aug: function aug(a, b) {\n    var newarr = [];\n    var i;\n    for (i = 0; i < a.length; i++) {\n      newarr.push(a[i].slice());\n    }\n    for (i = 0; i < newarr.length; i++) {\n      push.apply(newarr[i], b[i]);\n    }\n    return newarr;\n  },\n\n  // The inv() function calculates the inverse of a matrix\n  // Create the inverse by augmenting the matrix by the identity matrix of the\n  // appropriate size, and then use G-J elimination on the augmented matrix.\n  inv: function inv(a) {\n    var rows = a.length;\n    var cols = a[0].length;\n    var b = jStat.identity(rows, cols);\n    var c = jStat.gauss_jordan(a, b);\n    var result = [];\n    var i = 0;\n    var j;\n\n    //We need to copy the inverse portion to a new matrix to rid G-J artifacts\n    for (; i < rows; i++) {\n      result[i] = [];\n      for (j = cols; j < c[0].length; j++)\n        result[i][j - cols] = c[i][j];\n    }\n    return result;\n  },\n\n  // calculate the determinant of a matrix\n  det: function det(a) {\n    var alen = a.length,\n    alend = alen * 2,\n    vals = new Array(alend),\n    rowshift = alen - 1,\n    colshift = alend - 1,\n    mrow = rowshift - alen + 1,\n    mcol = colshift,\n    i = 0,\n    result = 0,\n    j;\n    // check for special 2x2 case\n    if (alen === 2) {\n      return a[0][0] * a[1][1] - a[0][1] * a[1][0];\n    }\n    for (; i < alend; i++) {\n      vals[i] = 1;\n    }\n    for (i = 0; i < alen; i++) {\n      for (j = 0; j < alen; j++) {\n        vals[(mrow < 0) ? mrow + alen : mrow ] *= a[i][j];\n        vals[(mcol < alen) ? mcol + alen : mcol ] *= a[i][j];\n        mrow++;\n        mcol--;\n      }\n      mrow = --rowshift - alen + 1;\n      mcol = --colshift;\n    }\n    for (i = 0; i < alen; i++) {\n      result += vals[i];\n    }\n    for (; i < alend; i++) {\n      result -= vals[i];\n    }\n    return result;\n  },\n\n  gauss_elimination: function gauss_elimination(a, b) {\n    var i = 0,\n    j = 0,\n    n = a.length,\n    m = a[0].length,\n    factor = 1,\n    sum = 0,\n    x = [],\n    maug, pivot, temp, k;\n    a = jStat.aug(a, b);\n    maug = a[0].length;\n    for(i = 0; i < n; i++) {\n      pivot = a[i][i];\n      j = i;\n      for (k = i + 1; k < m; k++) {\n        if (pivot < Math.abs(a[k][i])) {\n          pivot = a[k][i];\n          j = k;\n        }\n      }\n      if (j != i) {\n        for(k = 0; k < maug; k++) {\n          temp = a[i][k];\n          a[i][k] = a[j][k];\n          a[j][k] = temp;\n        }\n      }\n      for (j = i + 1; j < n; j++) {\n        factor = a[j][i] / a[i][i];\n        for(k = i; k < maug; k++) {\n          a[j][k] = a[j][k] - factor * a[i][k];\n        }\n      }\n    }\n    for (i = n - 1; i >= 0; i--) {\n      sum = 0;\n      for (j = i + 1; j<= n - 1; j++) {\n        sum = sum + x[j] * a[i][j];\n      }\n      x[i] =(a[i][maug - 1] - sum) / a[i][i];\n    }\n    return x;\n  },\n\n  gauss_jordan: function gauss_jordan(a, b) {\n    var m = jStat.aug(a, b);\n    var h = m.length;\n    var w = m[0].length;\n    var c = 0;\n    var x, y, y2;\n    // find max pivot\n    for (y = 0; y < h; y++) {\n      var maxrow = y;\n      for (y2 = y+1; y2 < h; y2++) {\n        if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y]))\n          maxrow = y2;\n      }\n      var tmp = m[y];\n      m[y] = m[maxrow];\n      m[maxrow] = tmp\n      for (y2 = y+1; y2 < h; y2++) {\n        c = m[y2][y] / m[y][y];\n        for (x = y; x < w; x++) {\n          m[y2][x] -= m[y][x] * c;\n        }\n      }\n    }\n    // backsubstitute\n    for (y = h-1; y >= 0; y--) {\n      c = m[y][y];\n      for (y2 = 0; y2 < y; y2++) {\n        for (x = w-1; x > y-1; x--) {\n          m[y2][x] -= m[y][x] * m[y2][y] / c;\n        }\n      }\n      m[y][y] /= c;\n      for (x = h; x < w; x++) {\n        m[y][x] /= c;\n      }\n    }\n    return m;\n  },\n\n  // solve equation\n  // Ax=b\n  // A is upper triangular matrix\n  // A=[[1,2,3],[0,4,5],[0,6,7]]\n  // b=[1,2,3]\n  // triaUpSolve(A,b) // -> [2.666,0.1666,1.666]\n  // if you use matrix style\n  // A=[[1,2,3],[0,4,5],[0,6,7]]\n  // b=[[1],[2],[3]]\n  // will return [[2.666],[0.1666],[1.666]]\n  triaUpSolve: function triaUpSolve(A, b) {\n    var size = A[0].length;\n    var x = jStat.zeros(1, size)[0];\n    var parts;\n    var matrix_mode = false;\n\n    if (b[0].length != undefined) {\n      b = b.map(function(i){ return i[0] });\n      matrix_mode = true;\n    }\n\n    jStat.arange(size - 1, -1, -1).forEach(function(i) {\n      parts = jStat.arange(i + 1, size).map(function(j) {\n        return x[j] * A[i][j];\n      });\n      x[i] = (b[i] - jStat.sum(parts)) / A[i][i];\n    });\n\n    if (matrix_mode)\n      return x.map(function(i){ return [i] });\n    return x;\n  },\n\n  triaLowSolve: function triaLowSolve(A, b) {\n    // like to triaUpSolve but A is lower triangular matrix\n    var size = A[0].length;\n    var x = jStat.zeros(1, size)[0];\n    var parts;\n\n    var matrix_mode=false;\n    if (b[0].length != undefined) {\n      b = b.map(function(i){ return i[0] });\n      matrix_mode = true;\n    }\n\n    jStat.arange(size).forEach(function(i) {\n      parts = jStat.arange(i).map(function(j) {\n        return A[i][j] * x[j];\n      });\n      x[i] = (b[i] - jStat.sum(parts)) / A[i][i];\n    })\n\n    if (matrix_mode)\n      return x.map(function(i){ return [i] });\n    return x;\n  },\n\n\n  // A -> [L,U]\n  // A=LU\n  // L is lower triangular matrix\n  // U is upper triangular matrix\n  lu: function lu(A) {\n    var size = A.length;\n    //var L=jStat.diagonal(jStat.ones(1,size)[0]);\n    var L = jStat.identity(size);\n    var R = jStat.zeros(A.length, A[0].length);\n    var parts;\n    jStat.arange(size).forEach(function(t) {\n      R[0][t] = A[0][t];\n    });\n    jStat.arange(1, size).forEach(function(l) {\n      jStat.arange(l).forEach(function(i) {\n        parts = jStat.arange(i).map(function(jj) {\n          return L[l][jj] * R[jj][i];\n        });\n        L[l][i] = (A[l][i] - jStat.sum(parts)) / R[i][i];\n      });\n      jStat.arange(l, size).forEach(function(j) {\n        parts = jStat.arange(l).map(function(jj) {\n          return L[l][jj] * R[jj][j];\n        });\n        R[l][j] = A[parts.length][j] - jStat.sum(parts);\n      });\n    });\n    return [L, R];\n  },\n\n  // A -> T\n  // A=TT'\n  // T is lower triangular matrix\n  cholesky: function cholesky(A) {\n    var size = A.length;\n    var T = jStat.zeros(A.length, A[0].length);\n    var parts;\n    jStat.arange(size).forEach(function(i) {\n      parts = jStat.arange(i).map(function(t) {\n        return Math.pow(T[i][t],2);\n      });\n      T[i][i] = Math.sqrt(A[i][i] - jStat.sum(parts));\n      jStat.arange(i + 1, size).forEach(function(j) {\n        parts = jStat.arange(i).map(function(t) {\n          return T[i][t] * T[j][t];\n        });\n        T[j][i] = (A[i][j] - jStat.sum(parts)) / T[i][i];\n      });\n    });\n    return T;\n  },\n\n\n  gauss_jacobi: function gauss_jacobi(a, b, x, r) {\n    var i = 0;\n    var j = 0;\n    var n = a.length;\n    var l = [];\n    var u = [];\n    var d = [];\n    var xv, c, h, xk;\n    for (; i < n; i++) {\n      l[i] = [];\n      u[i] = [];\n      d[i] = [];\n      for (j = 0; j < n; j++) {\n        if (i > j) {\n          l[i][j] = a[i][j];\n          u[i][j] = d[i][j] = 0;\n        } else if (i < j) {\n          u[i][j] = a[i][j];\n          l[i][j] = d[i][j] = 0;\n        } else {\n          d[i][j] = a[i][j];\n          l[i][j] = u[i][j] = 0;\n        }\n      }\n    }\n    h = jStat.multiply(jStat.multiply(jStat.inv(d), jStat.add(l, u)), -1);\n    c = jStat.multiply(jStat.inv(d), b);\n    xv = x;\n    xk = jStat.add(jStat.multiply(h, x), c);\n    i = 2;\n    while (Math.abs(jStat.norm(jStat.subtract(xk,xv))) > r) {\n      xv = xk;\n      xk = jStat.add(jStat.multiply(h, xv), c);\n      i++;\n    }\n    return xk;\n  },\n\n  gauss_seidel: function gauss_seidel(a, b, x, r) {\n    var i = 0;\n    var n = a.length;\n    var l = [];\n    var u = [];\n    var d = [];\n    var j, xv, c, h, xk;\n    for (; i < n; i++) {\n      l[i] = [];\n      u[i] = [];\n      d[i] = [];\n      for (j = 0; j < n; j++) {\n        if (i > j) {\n          l[i][j] = a[i][j];\n          u[i][j] = d[i][j] = 0;\n        } else if (i < j) {\n          u[i][j] = a[i][j];\n          l[i][j] = d[i][j] = 0;\n        } else {\n          d[i][j] = a[i][j];\n          l[i][j] = u[i][j] = 0;\n        }\n      }\n    }\n    h = jStat.multiply(jStat.multiply(jStat.inv(jStat.add(d, l)), u), -1);\n    c = jStat.multiply(jStat.inv(jStat.add(d, l)), b);\n    xv = x;\n    xk = jStat.add(jStat.multiply(h, x), c);\n    i = 2;\n    while (Math.abs(jStat.norm(jStat.subtract(xk, xv))) > r) {\n      xv = xk;\n      xk = jStat.add(jStat.multiply(h, xv), c);\n      i = i + 1;\n    }\n    return xk;\n  },\n\n  SOR: function SOR(a, b, x, r, w) {\n    var i = 0;\n    var n = a.length;\n    var l = [];\n    var u = [];\n    var d = [];\n    var j, xv, c, h, xk;\n    for (; i < n; i++) {\n      l[i] = [];\n      u[i] = [];\n      d[i] = [];\n      for (j = 0; j < n; j++) {\n        if (i > j) {\n          l[i][j] = a[i][j];\n          u[i][j] = d[i][j] = 0;\n        } else if (i < j) {\n          u[i][j] = a[i][j];\n          l[i][j] = d[i][j] = 0;\n        } else {\n          d[i][j] = a[i][j];\n          l[i][j] = u[i][j] = 0;\n        }\n      }\n    }\n    h = jStat.multiply(jStat.inv(jStat.add(d, jStat.multiply(l, w))),\n                       jStat.subtract(jStat.multiply(d, 1 - w),\n                                      jStat.multiply(u, w)));\n    c = jStat.multiply(jStat.multiply(jStat.inv(jStat.add(d,\n        jStat.multiply(l, w))), b), w);\n    xv = x;\n    xk = jStat.add(jStat.multiply(h, x), c);\n    i = 2;\n    while (Math.abs(jStat.norm(jStat.subtract(xk, xv))) > r) {\n      xv = xk;\n      xk = jStat.add(jStat.multiply(h, xv), c);\n      i++;\n    }\n    return xk;\n  },\n\n  householder: function householder(a) {\n    var m = a.length;\n    var n = a[0].length;\n    var i = 0;\n    var w = [];\n    var p = [];\n    var alpha, r, k, j, factor;\n    for (; i < m - 1; i++) {\n      alpha = 0;\n      for (j = i + 1; j < n; j++)\n      alpha += (a[j][i] * a[j][i]);\n      factor = (a[i + 1][i] > 0) ? -1 : 1;\n      alpha = factor * Math.sqrt(alpha);\n      r = Math.sqrt((((alpha * alpha) - a[i + 1][i] * alpha) / 2));\n      w = jStat.zeros(m, 1);\n      w[i + 1][0] = (a[i + 1][i] - alpha) / (2 * r);\n      for (k = i + 2; k < m; k++) w[k][0] = a[k][i] / (2 * r);\n      p = jStat.subtract(jStat.identity(m, n),\n          jStat.multiply(jStat.multiply(w, jStat.transpose(w)), 2));\n      a = jStat.multiply(p, jStat.multiply(a, p));\n    }\n    return a;\n  },\n\n  // A -> [Q,R]\n  // Q is orthogonal matrix\n  // R is upper triangular\n  QR: (function() {\n    // x -> Q\n    // find a orthogonal matrix Q st.\n    // Qx=y\n    // y is [||x||,0,0,...]\n\n    // quick ref\n    var sum   = jStat.sum;\n    var range = jStat.arange;\n\n    function qr2(x) {\n      // quick impletation\n      // https://www.stat.wisc.edu/~larget/math496/qr.html\n\n      var n = x.length;\n      var p = x[0].length;\n\n      var r = jStat.zeros(p, p);\n      x = jStat.copy(x);\n\n      var i,j,k;\n      for(j = 0; j < p; j++){\n        r[j][j] = Math.sqrt(sum(range(n).map(function(i){\n          return x[i][j] * x[i][j];\n        })));\n        for(i = 0; i < n; i++){\n          x[i][j] = x[i][j] / r[j][j];\n        }\n        for(k = j+1; k < p; k++){\n          r[j][k] = sum(range(n).map(function(i){\n            return x[i][j] * x[i][k];\n          }));\n          for(i = 0; i < n; i++){\n            x[i][k] = x[i][k] - x[i][j]*r[j][k];\n          }\n        }\n      }\n      return [x, r];\n    }\n\n    return qr2;\n  }()),\n\n  lstsq: (function() {\n    // solve least squard problem for Ax=b as QR decomposition way if b is\n    // [[b1],[b2],[b3]] form will return [[x1],[x2],[x3]] array form solution\n    // else b is [b1,b2,b3] form will return [x1,x2,x3] array form solution\n    function R_I(A) {\n      A = jStat.copy(A);\n      var size = A.length;\n      var I = jStat.identity(size);\n      jStat.arange(size - 1, -1, -1).forEach(function(i) {\n        jStat.sliceAssign(\n            I, { row: i }, jStat.divide(jStat.slice(I, { row: i }), A[i][i]));\n        jStat.sliceAssign(\n            A, { row: i }, jStat.divide(jStat.slice(A, { row: i }), A[i][i]));\n        jStat.arange(i).forEach(function(j) {\n          var c = jStat.multiply(A[j][i], -1);\n          var Aj = jStat.slice(A, { row: j });\n          var cAi = jStat.multiply(jStat.slice(A, { row: i }), c);\n          jStat.sliceAssign(A, { row: j }, jStat.add(Aj, cAi));\n          var Ij = jStat.slice(I, { row: j });\n          var cIi = jStat.multiply(jStat.slice(I, { row: i }), c);\n          jStat.sliceAssign(I, { row: j }, jStat.add(Ij, cIi));\n        })\n      });\n      return I;\n    }\n\n    function qr_solve(A, b){\n      var array_mode = false;\n      if (b[0].length === undefined) {\n        // [c1,c2,c3] mode\n        b = b.map(function(x){ return [x] });\n        array_mode = true;\n      }\n      var QR = jStat.QR(A);\n      var Q = QR[0];\n      var R = QR[1];\n      var attrs = A[0].length;\n      var Q1 = jStat.slice(Q,{col:{end:attrs}});\n      var R1 = jStat.slice(R,{row:{end:attrs}});\n      var RI = R_I(R1);\n      var Q2 = jStat.transpose(Q1);\n\n      if(Q2[0].length === undefined){\n        Q2 = [Q2]; // The confusing jStat.multifly implementation threat nature process again.\n      }\n\n      var x = jStat.multiply(jStat.multiply(RI, Q2), b);\n\n      if(x.length === undefined){\n        x = [[x]]; // The confusing jStat.multifly implementation threat nature process again.\n      }\n\n\n      if (array_mode)\n        return x.map(function(i){ return i[0] });\n      return x;\n    }\n\n    return qr_solve;\n  }()),\n\n  jacobi: function jacobi(a) {\n    var condition = 1;\n    var n = a.length;\n    var e = jStat.identity(n, n);\n    var ev = [];\n    var b, i, j, p, q, maxim, theta, s;\n    // condition === 1 only if tolerance is not reached\n    while (condition === 1) {\n      maxim = a[0][1];\n      p = 0;\n      q = 1;\n      for (i = 0; i < n; i++) {\n        for (j = 0; j < n; j++) {\n          if (i != j) {\n            if (maxim < Math.abs(a[i][j])) {\n              maxim = Math.abs(a[i][j]);\n              p = i;\n              q = j;\n            }\n          }\n        }\n      }\n      if (a[p][p] === a[q][q])\n        theta = (a[p][q] > 0) ? Math.PI / 4 : -Math.PI / 4;\n      else\n        theta = Math.atan(2 * a[p][q] / (a[p][p] - a[q][q])) / 2;\n      s = jStat.identity(n, n);\n      s[p][p] = Math.cos(theta);\n      s[p][q] = -Math.sin(theta);\n      s[q][p] = Math.sin(theta);\n      s[q][q] = Math.cos(theta);\n      // eigen vector matrix\n      e = jStat.multiply(e, s);\n      b = jStat.multiply(jStat.multiply(jStat.inv(s), a), s);\n      a = b;\n      condition = 0;\n      for (i = 1; i < n; i++) {\n        for (j = 1; j < n; j++) {\n          if (i != j && Math.abs(a[i][j]) > 0.001) {\n            condition = 1;\n          }\n        }\n      }\n    }\n    for (i = 0; i < n; i++) ev.push(a[i][i]);\n    //returns both the eigenvalue and eigenmatrix\n    return [e, ev];\n  },\n\n  rungekutta: function rungekutta(f, h, p, t_j, u_j, order) {\n    var k1, k2, u_j1, k3, k4;\n    if (order === 2) {\n      while (t_j <= p) {\n        k1 = h * f(t_j, u_j);\n        k2 = h * f(t_j + h, u_j + k1);\n        u_j1 = u_j + (k1 + k2) / 2;\n        u_j = u_j1;\n        t_j = t_j + h;\n      }\n    }\n    if (order === 4) {\n      while (t_j <= p) {\n        k1 = h * f(t_j, u_j);\n        k2 = h * f(t_j + h / 2, u_j + k1 / 2);\n        k3 = h * f(t_j + h / 2, u_j + k2 / 2);\n        k4 = h * f(t_j +h, u_j + k3);\n        u_j1 = u_j + (k1 + 2 * k2 + 2 * k3 + k4) / 6;\n        u_j = u_j1;\n        t_j = t_j + h;\n      }\n    }\n    return u_j;\n  },\n\n  romberg: function romberg(f, a, b, order) {\n    var i = 0;\n    var h = (b - a) / 2;\n    var x = [];\n    var h1 = [];\n    var g = [];\n    var m, a1, j, k, I;\n    while (i < order / 2) {\n      I = f(a);\n      for (j = a, k = 0; j <= b; j = j + h, k++) x[k] = j;\n      m = x.length;\n      for (j = 1; j < m - 1; j++) {\n        I += (((j % 2) !== 0) ? 4 : 2) * f(x[j]);\n      }\n      I = (h / 3) * (I + f(b));\n      g[i] = I;\n      h /= 2;\n      i++;\n    }\n    a1 = g.length;\n    m = 1;\n    while (a1 !== 1) {\n      for (j = 0; j < a1 - 1; j++)\n      h1[j] = ((Math.pow(4, m)) * g[j + 1] - g[j]) / (Math.pow(4, m) - 1);\n      a1 = h1.length;\n      g = h1;\n      h1 = [];\n      m++;\n    }\n    return g;\n  },\n\n  richardson: function richardson(X, f, x, h) {\n    function pos(X, x) {\n      var i = 0;\n      var n = X.length;\n      var p;\n      for (; i < n; i++)\n        if (X[i] === x) p = i;\n      return p;\n    }\n    var h_min = Math.abs(x - X[pos(X, x) + 1]);\n    var i = 0;\n    var g = [];\n    var h1 = [];\n    var y1, y2, m, a, j;\n    while (h >= h_min) {\n      y1 = pos(X, x + h);\n      y2 = pos(X, x);\n      g[i] = (f[y1] - 2 * f[y2] + f[2 * y2 - y1]) / (h * h);\n      h /= 2;\n      i++;\n    }\n    a = g.length;\n    m = 1;\n    while (a != 1) {\n      for (j = 0; j < a - 1; j++)\n        h1[j] = ((Math.pow(4, m)) * g[j + 1] - g[j]) / (Math.pow(4, m) - 1);\n      a = h1.length;\n      g = h1;\n      h1 = [];\n      m++;\n    }\n    return g;\n  },\n\n  simpson: function simpson(f, a, b, n) {\n    var h = (b - a) / n;\n    var I = f(a);\n    var x = [];\n    var j = a;\n    var k = 0;\n    var i = 1;\n    var m;\n    for (; j <= b; j = j + h, k++)\n      x[k] = j;\n    m = x.length;\n    for (; i < m - 1; i++) {\n      I += ((i % 2 !== 0) ? 4 : 2) * f(x[i]);\n    }\n    return (h / 3) * (I + f(b));\n  },\n\n  hermite: function hermite(X, F, dF, value) {\n    var n = X.length;\n    var p = 0;\n    var i = 0;\n    var l = [];\n    var dl = [];\n    var A = [];\n    var B = [];\n    var j;\n    for (; i < n; i++) {\n      l[i] = 1;\n      for (j = 0; j < n; j++) {\n        if (i != j) l[i] *= (value - X[j]) / (X[i] - X[j]);\n      }\n      dl[i] = 0;\n      for (j = 0; j < n; j++) {\n        if (i != j) dl[i] += 1 / (X [i] - X[j]);\n      }\n      A[i] = (1 - 2 * (value - X[i]) * dl[i]) * (l[i] * l[i]);\n      B[i] = (value - X[i]) * (l[i] * l[i]);\n      p += (A[i] * F[i] + B[i] * dF[i]);\n    }\n    return p;\n  },\n\n  lagrange: function lagrange(X, F, value) {\n    var p = 0;\n    var i = 0;\n    var j, l;\n    var n = X.length;\n    for (; i < n; i++) {\n      l = F[i];\n      for (j = 0; j < n; j++) {\n        // calculating the lagrange polynomial L_i\n        if (i != j) l *= (value - X[j]) / (X[i] - X[j]);\n      }\n      // adding the lagrange polynomials found above\n      p += l;\n    }\n    return p;\n  },\n\n  cubic_spline: function cubic_spline(X, F, value) {\n    var n = X.length;\n    var i = 0, j;\n    var A = [];\n    var B = [];\n    var alpha = [];\n    var c = [];\n    var h = [];\n    var b = [];\n    var d = [];\n    for (; i < n - 1; i++)\n      h[i] = X[i + 1] - X[i];\n    alpha[0] = 0;\n    for (i = 1; i < n - 1; i++) {\n      alpha[i] = (3 / h[i]) * (F[i + 1] - F[i]) -\n          (3 / h[i-1]) * (F[i] - F[i-1]);\n    }\n    for (i = 1; i < n - 1; i++) {\n      A[i] = [];\n      B[i] = [];\n      A[i][i-1] = h[i-1];\n      A[i][i] = 2 * (h[i - 1] + h[i]);\n      A[i][i+1] = h[i];\n      B[i][0] = alpha[i];\n    }\n    c = jStat.multiply(jStat.inv(A), B);\n    for (j = 0; j < n - 1; j++) {\n      b[j] = (F[j + 1] - F[j]) / h[j] - h[j] * (c[j + 1][0] + 2 * c[j][0]) / 3;\n      d[j] = (c[j + 1][0] - c[j][0]) / (3 * h[j]);\n    }\n    for (j = 0; j < n; j++) {\n      if (X[j] > value) break;\n    }\n    j -= 1;\n    return F[j] + (value - X[j]) * b[j] + jStat.sq(value-X[j]) *\n        c[j] + (value - X[j]) * jStat.sq(value - X[j]) * d[j];\n  },\n\n  gauss_quadrature: function gauss_quadrature() {\n    throw new Error('gauss_quadrature not yet implemented');\n  },\n\n  PCA: function PCA(X) {\n    var m = X.length;\n    var n = X[0].length;\n    var i = 0;\n    var j, temp1;\n    var u = [];\n    var D = [];\n    var result = [];\n    var temp2 = [];\n    var Y = [];\n    var Bt = [];\n    var B = [];\n    var C = [];\n    var V = [];\n    var Vt = [];\n    for (i = 0; i < m; i++) {\n      u[i] = jStat.sum(X[i]) / n;\n    }\n    for (i = 0; i < n; i++) {\n      B[i] = [];\n      for(j = 0; j < m; j++) {\n        B[i][j] = X[j][i] - u[j];\n      }\n    }\n    B = jStat.transpose(B);\n    for (i = 0; i < m; i++) {\n      C[i] = [];\n      for (j = 0; j < m; j++) {\n        C[i][j] = (jStat.dot([B[i]], [B[j]])) / (n - 1);\n      }\n    }\n    result = jStat.jacobi(C);\n    V = result[0];\n    D = result[1];\n    Vt = jStat.transpose(V);\n    for (i = 0; i < D.length; i++) {\n      for (j = i; j < D.length; j++) {\n        if(D[i] < D[j])  {\n          temp1 = D[i];\n          D[i] = D[j];\n          D[j] = temp1;\n          temp2 = Vt[i];\n          Vt[i] = Vt[j];\n          Vt[j] = temp2;\n        }\n      }\n    }\n    Bt = jStat.transpose(B);\n    for (i = 0; i < m; i++) {\n      Y[i] = [];\n      for (j = 0; j < Bt.length; j++) {\n        Y[i][j] = jStat.dot([Vt[i]], [Bt[j]]);\n      }\n    }\n    return [X, D, Vt, Y];\n  }\n});\n\n// extend jStat.fn with methods that require one argument\n(function(funcs) {\n  for (var i = 0; i < funcs.length; i++) (function(passfunc) {\n    jStat.fn[passfunc] = function(arg, func) {\n      var tmpthis = this;\n      // check for callback\n      if (func) {\n        setTimeout(function() {\n          func.call(tmpthis, jStat.fn[passfunc].call(tmpthis, arg));\n        }, 15);\n        return this;\n      }\n      if (typeof jStat[passfunc](this, arg) === 'number')\n        return jStat[passfunc](this, arg);\n      else\n        return jStat(jStat[passfunc](this, arg));\n    };\n  }(funcs[i]));\n}('add divide multiply subtract dot pow exp log abs norm angle'.split(' ')));\n\n}(jStat, Math));\n(function(jStat, Math) {\n\nvar slice = [].slice;\nvar isNumber = jStat.utils.isNumber;\nvar isArray = jStat.utils.isArray;\n\n// flag==true denotes use of sample standard deviation\n// Z Statistics\njStat.extend({\n  // 2 different parameter lists:\n  // (value, mean, sd)\n  // (value, array, flag)\n  zscore: function zscore() {\n    var args = slice.call(arguments);\n    if (isNumber(args[1])) {\n      return (args[0] - args[1]) / args[2];\n    }\n    return (args[0] - jStat.mean(args[1])) / jStat.stdev(args[1], args[2]);\n  },\n\n  // 3 different paramter lists:\n  // (value, mean, sd, sides)\n  // (zscore, sides)\n  // (value, array, sides, flag)\n  ztest: function ztest() {\n    var args = slice.call(arguments);\n    var z;\n    if (isArray(args[1])) {\n      // (value, array, sides, flag)\n      z = jStat.zscore(args[0],args[1],args[3]);\n      return (args[2] === 1) ?\n        (jStat.normal.cdf(-Math.abs(z), 0, 1)) :\n        (jStat.normal.cdf(-Math.abs(z), 0, 1)*2);\n    } else {\n      if (args.length > 2) {\n        // (value, mean, sd, sides)\n        z = jStat.zscore(args[0],args[1],args[2]);\n        return (args[3] === 1) ?\n          (jStat.normal.cdf(-Math.abs(z),0,1)) :\n          (jStat.normal.cdf(-Math.abs(z),0,1)* 2);\n      } else {\n        // (zscore, sides)\n        z = args[0];\n        return (args[1] === 1) ?\n          (jStat.normal.cdf(-Math.abs(z),0,1)) :\n          (jStat.normal.cdf(-Math.abs(z),0,1)*2);\n      }\n    }\n  }\n});\n\njStat.extend(jStat.fn, {\n  zscore: function zscore(value, flag) {\n    return (value - this.mean()) / this.stdev(flag);\n  },\n\n  ztest: function ztest(value, sides, flag) {\n    var zscore = Math.abs(this.zscore(value, flag));\n    return (sides === 1) ?\n      (jStat.normal.cdf(-zscore, 0, 1)) :\n      (jStat.normal.cdf(-zscore, 0, 1) * 2);\n  }\n});\n\n// T Statistics\njStat.extend({\n  // 2 parameter lists\n  // (value, mean, sd, n)\n  // (value, array)\n  tscore: function tscore() {\n    var args = slice.call(arguments);\n    return (args.length === 4) ?\n      ((args[0] - args[1]) / (args[2] / Math.sqrt(args[3]))) :\n      ((args[0] - jStat.mean(args[1])) /\n       (jStat.stdev(args[1], true) / Math.sqrt(args[1].length)));\n  },\n\n  // 3 different paramter lists:\n  // (value, mean, sd, n, sides)\n  // (tscore, n, sides)\n  // (value, array, sides)\n  ttest: function ttest() {\n    var args = slice.call(arguments);\n    var tscore;\n    if (args.length === 5) {\n      tscore = Math.abs(jStat.tscore(args[0], args[1], args[2], args[3]));\n      return (args[4] === 1) ?\n        (jStat.studentt.cdf(-tscore, args[3]-1)) :\n        (jStat.studentt.cdf(-tscore, args[3]-1)*2);\n    }\n    if (isNumber(args[1])) {\n      tscore = Math.abs(args[0])\n      return (args[2] == 1) ?\n        (jStat.studentt.cdf(-tscore, args[1]-1)) :\n        (jStat.studentt.cdf(-tscore, args[1]-1) * 2);\n    }\n    tscore = Math.abs(jStat.tscore(args[0], args[1]))\n    return (args[2] == 1) ?\n      (jStat.studentt.cdf(-tscore, args[1].length-1)) :\n      (jStat.studentt.cdf(-tscore, args[1].length-1) * 2);\n  }\n});\n\njStat.extend(jStat.fn, {\n  tscore: function tscore(value) {\n    return (value - this.mean()) / (this.stdev(true) / Math.sqrt(this.cols()));\n  },\n\n  ttest: function ttest(value, sides) {\n    return (sides === 1) ?\n      (1 - jStat.studentt.cdf(Math.abs(this.tscore(value)), this.cols()-1)) :\n      (jStat.studentt.cdf(-Math.abs(this.tscore(value)), this.cols()-1)*2);\n  }\n});\n\n// F Statistics\njStat.extend({\n  // Paramter list is as follows:\n  // (array1, array2, array3, ...)\n  // or it is an array of arrays\n  // array of arrays conversion\n  anovafscore: function anovafscore() {\n    var args = slice.call(arguments),\n    expVar, sample, sampMean, sampSampMean, tmpargs, unexpVar, i, j;\n    if (args.length === 1) {\n      tmpargs = new Array(args[0].length);\n      for (i = 0; i < args[0].length; i++) {\n        tmpargs[i] = args[0][i];\n      }\n      args = tmpargs;\n    }\n    // Builds sample array\n    sample = new Array();\n    for (i = 0; i < args.length; i++) {\n      sample = sample.concat(args[i]);\n    }\n    sampMean = jStat.mean(sample);\n    // Computes the explained variance\n    expVar = 0;\n    for (i = 0; i < args.length; i++) {\n      expVar = expVar + args[i].length * Math.pow(jStat.mean(args[i]) - sampMean, 2);\n    }\n    expVar /= (args.length - 1);\n    // Computes unexplained variance\n    unexpVar = 0;\n    for (i = 0; i < args.length; i++) {\n      sampSampMean = jStat.mean(args[i]);\n      for (j = 0; j < args[i].length; j++) {\n        unexpVar += Math.pow(args[i][j] - sampSampMean, 2);\n      }\n    }\n    unexpVar /= (sample.length - args.length);\n    return expVar / unexpVar;\n  },\n\n  // 2 different paramter setups\n  // (array1, array2, array3, ...)\n  // (anovafscore, df1, df2)\n  anovaftest: function anovaftest() {\n    var args = slice.call(arguments),\n    df1, df2, n, i;\n    if (isNumber(args[0])) {\n      return 1 - jStat.centralF.cdf(args[0], args[1], args[2]);\n    }\n    var anovafscore = jStat.anovafscore(args);\n    df1 = args.length - 1;\n    n = 0;\n    for (i = 0; i < args.length; i++) {\n      n = n + args[i].length;\n    }\n    df2 = n - df1 - 1;\n    return 1 - jStat.centralF.cdf(anovafscore, df1, df2);\n  },\n\n  ftest: function ftest(fscore, df1, df2) {\n    return 1 - jStat.centralF.cdf(fscore, df1, df2);\n  }\n});\n\njStat.extend(jStat.fn, {\n  anovafscore: function anovafscore() {\n    return jStat.anovafscore(this.toArray());\n  },\n\n  anovaftes: function anovaftes() {\n    var n = 0;\n    var i;\n    for (i = 0; i < this.length; i++) {\n      n = n + this[i].length;\n    }\n    return jStat.ftest(this.anovafscore(), this.length - 1, n - this.length);\n  }\n});\n\n// Tukey's range test\njStat.extend({\n  // 2 parameter lists\n  // (mean1, mean2, n1, n2, sd)\n  // (array1, array2, sd)\n  qscore: function qscore() {\n    var args = slice.call(arguments);\n    var mean1, mean2, n1, n2, sd;\n    if (isNumber(args[0])) {\n        mean1 = args[0];\n        mean2 = args[1];\n        n1 = args[2];\n        n2 = args[3];\n        sd = args[4];\n    } else {\n        mean1 = jStat.mean(args[0]);\n        mean2 = jStat.mean(args[1]);\n        n1 = args[0].length;\n        n2 = args[1].length;\n        sd = args[2];\n    }\n    return Math.abs(mean1 - mean2) / (sd * Math.sqrt((1 / n1 + 1 / n2) / 2));\n  },\n\n  // 3 different parameter lists:\n  // (qscore, n, k)\n  // (mean1, mean2, n1, n2, sd, n, k)\n  // (array1, array2, sd, n, k)\n  qtest: function qtest() {\n    var args = slice.call(arguments);\n\n    var qscore;\n    if (args.length === 3) {\n      qscore = args[0];\n      args = args.slice(1);\n    } else if (args.length === 7) {\n      qscore = jStat.qscore(args[0], args[1], args[2], args[3], args[4]);\n      args = args.slice(5);\n    } else {\n      qscore = jStat.qscore(args[0], args[1], args[2]);\n      args = args.slice(3);\n    }\n\n    var n = args[0];\n    var k = args[1];\n\n    return 1 - jStat.tukey.cdf(qscore, k, n - k);\n  },\n\n  tukeyhsd: function tukeyhsd(arrays) {\n    var sd = jStat.pooledstdev(arrays);\n    var means = arrays.map(function (arr) {return jStat.mean(arr);});\n    var n = arrays.reduce(function (n, arr) {return n + arr.length;}, 0);\n\n    var results = [];\n    for (var i = 0; i < arrays.length; ++i) {\n        for (var j = i + 1; j < arrays.length; ++j) {\n            var p = jStat.qtest(means[i], means[j], arrays[i].length, arrays[j].length, sd, n, arrays.length);\n            results.push([[i, j], p]);\n        }\n    }\n\n    return results;\n  }\n});\n\n// Error Bounds\njStat.extend({\n  // 2 different parameter setups\n  // (value, alpha, sd, n)\n  // (value, alpha, array)\n  normalci: function normalci() {\n    var args = slice.call(arguments),\n    ans = new Array(2),\n    change;\n    if (args.length === 4) {\n      change = Math.abs(jStat.normal.inv(args[1] / 2, 0, 1) *\n                        args[2] / Math.sqrt(args[3]));\n    } else {\n      change = Math.abs(jStat.normal.inv(args[1] / 2, 0, 1) *\n                        jStat.stdev(args[2]) / Math.sqrt(args[2].length));\n    }\n    ans[0] = args[0] - change;\n    ans[1] = args[0] + change;\n    return ans;\n  },\n\n  // 2 different parameter setups\n  // (value, alpha, sd, n)\n  // (value, alpha, array)\n  tci: function tci() {\n    var args = slice.call(arguments),\n    ans = new Array(2),\n    change;\n    if (args.length === 4) {\n      change = Math.abs(jStat.studentt.inv(args[1] / 2, args[3] - 1) *\n                        args[2] / Math.sqrt(args[3]));\n    } else {\n      change = Math.abs(jStat.studentt.inv(args[1] / 2, args[2].length - 1) *\n                        jStat.stdev(args[2], true) / Math.sqrt(args[2].length));\n    }\n    ans[0] = args[0] - change;\n    ans[1] = args[0] + change;\n    return ans;\n  },\n\n  significant: function significant(pvalue, alpha) {\n    return pvalue < alpha;\n  }\n});\n\njStat.extend(jStat.fn, {\n  normalci: function normalci(value, alpha) {\n    return jStat.normalci(value, alpha, this.toArray());\n  },\n\n  tci: function tci(value, alpha) {\n    return jStat.tci(value, alpha, this.toArray());\n  }\n});\n\n// internal method for calculating the z-score for a difference of proportions test\nfunction differenceOfProportions(p1, n1, p2, n2) {\n  if (p1 > 1 || p2 > 1 || p1 <= 0 || p2 <= 0) {\n    throw new Error(\"Proportions should be greater than 0 and less than 1\")\n  }\n  var pooled = (p1 * n1 + p2 * n2) / (n1 + n2);\n  var se = Math.sqrt(pooled * (1 - pooled) * ((1/n1) + (1/n2)));\n  return (p1 - p2) / se;\n}\n\n// Difference of Proportions\njStat.extend(jStat.fn, {\n  oneSidedDifferenceOfProportions: function oneSidedDifferenceOfProportions(p1, n1, p2, n2) {\n    var z = differenceOfProportions(p1, n1, p2, n2);\n    return jStat.ztest(z, 1);\n  },\n\n  twoSidedDifferenceOfProportions: function twoSidedDifferenceOfProportions(p1, n1, p2, n2) {\n    var z = differenceOfProportions(p1, n1, p2, n2);\n    return jStat.ztest(z, 2);\n  }\n});\n\n}(jStat, Math));\njStat.models = (function(){\n  function sub_regress(exog) {\n    var var_count = exog[0].length;\n    var modelList = jStat.arange(var_count).map(function(endog_index) {\n      var exog_index =\n          jStat.arange(var_count).filter(function(i){return i!==endog_index});\n      return ols(jStat.col(exog, endog_index).map(function(x){ return x[0] }),\n                 jStat.col(exog, exog_index))\n    });\n    return modelList;\n  }\n\n  // do OLS model regress\n  // exog have include const columns ,it will not generate it .In fact, exog is\n  // \"design matrix\" look at\n  //https://en.wikipedia.org/wiki/Design_matrix\n  function ols(endog, exog) {\n    var nobs = endog.length;\n    var df_model = exog[0].length - 1;\n    var df_resid = nobs-df_model - 1;\n    var coef = jStat.lstsq(exog, endog);\n    var predict =\n        jStat.multiply(exog, coef.map(function(x) { return [x] }))\n            .map(function(p) { return p[0] });\n    var resid = jStat.subtract(endog, predict);\n    var ybar = jStat.mean(endog);\n    // constant cause problem\n    // var SST = jStat.sum(endog.map(function(y) {\n    //   return Math.pow(y-ybar,2);\n    // }));\n    var SSE = jStat.sum(predict.map(function(f) {\n      return Math.pow(f - ybar, 2);\n    }));\n    var SSR = jStat.sum(endog.map(function(y, i) {\n      return Math.pow(y - predict[i], 2);\n    }));\n    var SST = SSE + SSR;\n    var R2 = (SSE / SST);\n    return {\n        exog:exog,\n        endog:endog,\n        nobs:nobs,\n        df_model:df_model,\n        df_resid:df_resid,\n        coef:coef,\n        predict:predict,\n        resid:resid,\n        ybar:ybar,\n        SST:SST,\n        SSE:SSE,\n        SSR:SSR,\n        R2:R2\n    };\n  }\n\n  // H0: b_I=0\n  // H1: b_I!=0\n  function t_test(model) {\n    var subModelList = sub_regress(model.exog);\n    //var sigmaHat=jStat.stdev(model.resid);\n    var sigmaHat = Math.sqrt(model.SSR / (model.df_resid));\n    var seBetaHat = subModelList.map(function(mod) {\n      var SST = mod.SST;\n      var R2 = mod.R2;\n      return sigmaHat / Math.sqrt(SST * (1 - R2));\n    });\n    var tStatistic = model.coef.map(function(coef, i) {\n      return (coef - 0) / seBetaHat[i];\n    });\n    var pValue = tStatistic.map(function(t) {\n      var leftppf = jStat.studentt.cdf(t, model.df_resid);\n      return (leftppf > 0.5 ? 1 - leftppf : leftppf) * 2;\n    });\n    var c = jStat.studentt.inv(0.975, model.df_resid);\n    var interval95 = model.coef.map(function(coef, i) {\n      var d = c * seBetaHat[i];\n      return [coef - d, coef + d];\n    })\n    return {\n        se: seBetaHat,\n        t: tStatistic,\n        p: pValue,\n        sigmaHat: sigmaHat,\n        interval95: interval95\n    };\n  }\n\n  function F_test(model) {\n    var F_statistic =\n        (model.R2 / model.df_model) / ((1 - model.R2) / model.df_resid);\n    var fcdf = function(x, n1, n2) {\n      return jStat.beta.cdf(x / (n2 / n1 + x), n1 / 2, n2 / 2)\n    }\n    var pvalue = 1 - fcdf(F_statistic, model.df_model, model.df_resid);\n    return { F_statistic: F_statistic, pvalue: pvalue };\n  }\n\n  function ols_wrap(endog, exog) {\n    var model = ols(endog,exog);\n    var ttest = t_test(model);\n    var ftest = F_test(model);\n    // Provide the Wherry / Ezekiel / McNemar / Cohen Adjusted R^2\n    // Which matches the 'adjusted R^2' provided by R's lm package\n    var adjust_R2 =\n        1 - (1 - model.R2) * ((model.nobs - 1) / (model.df_resid));\n    model.t = ttest;\n    model.f = ftest;\n    model.adjust_R2 = adjust_R2;\n    return model;\n  }\n\n  return { ols: ols_wrap };\n})();\n//To regress, simply build X matrix\n//(append column of 1's) using\n//buildxmatrix and build the Y\n//matrix using buildymatrix\n//(simply the transpose)\n//and run regress.\n\n\n\n//Regressions\n\njStat.extend({\n  buildxmatrix: function buildxmatrix(){\n    //Parameters will be passed in as such\n    //(array1,array2,array3,...)\n    //as (x1,x2,x3,...)\n    //needs to be (1,x1,x2,x3,...)\n    var matrixRows = new Array(arguments.length);\n    for(var i=0;i<arguments.length;i++){\n      var array = [1];\n      matrixRows[i]= array.concat(arguments[i]);\n    }\n    return jStat(matrixRows);\n\n  },\n\n  builddxmatrix: function builddxmatrix() {\n    //Paramters will be passed in as such\n    //([array1,array2,...]\n    var matrixRows = new Array(arguments[0].length);\n    for(var i=0;i<arguments[0].length;i++){\n      var array = [1]\n      matrixRows[i]= array.concat(arguments[0][i]);\n    }\n    return jStat(matrixRows);\n\n  },\n\n  buildjxmatrix: function buildjxmatrix(jMat) {\n    //Builds from jStat Matrix\n    var pass = new Array(jMat.length)\n    for(var i=0;i<jMat.length;i++){\n      pass[i] = jMat[i];\n    }\n    return jStat.builddxmatrix(pass);\n\n  },\n\n  buildymatrix: function buildymatrix(array){\n    return jStat(array).transpose();\n  },\n\n  buildjymatrix: function buildjymatrix(jMat){\n    return jMat.transpose();\n  },\n\n  matrixmult: function matrixmult(A,B){\n    var i, j, k, result, sum;\n    if (A.cols() == B.rows()) {\n      if(B.rows()>1){\n        result = [];\n        for (i = 0; i < A.rows(); i++) {\n          result[i] = [];\n          for (j = 0; j < B.cols(); j++) {\n            sum = 0;\n            for (k = 0; k < A.cols(); k++) {\n              sum += A.toArray()[i][k] * B.toArray()[k][j];\n            }\n            result[i][j] = sum;\n          }\n        }\n        return jStat(result);\n      }\n      result = [];\n      for (i = 0; i < A.rows(); i++) {\n        result[i] = [];\n        for (j = 0; j < B.cols(); j++) {\n          sum = 0;\n          for (k = 0; k < A.cols(); k++) {\n            sum += A.toArray()[i][k] * B.toArray()[j];\n          }\n          result[i][j] = sum;\n        }\n      }\n      return jStat(result);\n    }\n  },\n\n  //regress and regresst to be fixed\n\n  regress: function regress(jMatX,jMatY){\n    //print(\"regressin!\");\n    //print(jMatX.toArray());\n    var innerinv = jStat.xtranspxinv(jMatX);\n    //print(innerinv);\n    var xtransp = jMatX.transpose();\n    var next = jStat.matrixmult(jStat(innerinv),xtransp);\n    return jStat.matrixmult(next,jMatY);\n\n  },\n\n  regresst: function regresst(jMatX,jMatY,sides){\n    var beta = jStat.regress(jMatX,jMatY);\n\n    var compile = {};\n    compile.anova = {};\n    var jMatYBar = jStat.jMatYBar(jMatX, beta);\n    compile.yBar = jMatYBar;\n    var yAverage = jMatY.mean();\n    compile.anova.residuals = jStat.residuals(jMatY, jMatYBar);\n\n    compile.anova.ssr = jStat.ssr(jMatYBar, yAverage);\n    compile.anova.msr = compile.anova.ssr / (jMatX[0].length - 1);\n\n    compile.anova.sse = jStat.sse(jMatY, jMatYBar);\n    compile.anova.mse =\n        compile.anova.sse / (jMatY.length - (jMatX[0].length - 1) - 1);\n\n    compile.anova.sst = jStat.sst(jMatY, yAverage);\n    compile.anova.mst = compile.anova.sst / (jMatY.length - 1);\n\n    compile.anova.r2 = 1 - (compile.anova.sse / compile.anova.sst);\n    if (compile.anova.r2 < 0) compile.anova.r2 = 0;\n\n    compile.anova.fratio = compile.anova.msr / compile.anova.mse;\n    compile.anova.pvalue =\n        jStat.anovaftest(compile.anova.fratio,\n                         jMatX[0].length - 1,\n                         jMatY.length - (jMatX[0].length - 1) - 1);\n\n    compile.anova.rmse = Math.sqrt(compile.anova.mse);\n\n    compile.anova.r2adj = 1 - (compile.anova.mse / compile.anova.mst);\n    if (compile.anova.r2adj < 0) compile.anova.r2adj = 0;\n\n    compile.stats = new Array(jMatX[0].length);\n    var covar = jStat.xtranspxinv(jMatX);\n    var sds, ts, ps;\n\n    for(var i=0; i<beta.length;i++){\n      sds=Math.sqrt(compile.anova.mse * Math.abs(covar[i][i]));\n      ts= Math.abs(beta[i] / sds);\n      ps= jStat.ttest(ts, jMatY.length - jMatX[0].length - 1, sides);\n\n      compile.stats[i]=[beta[i], sds, ts, ps];\n    }\n\n    compile.regress = beta;\n    return compile;\n  },\n\n  xtranspx: function xtranspx(jMatX){\n    return jStat.matrixmult(jMatX.transpose(),jMatX);\n  },\n\n\n  xtranspxinv: function xtranspxinv(jMatX){\n    var inner = jStat.matrixmult(jMatX.transpose(),jMatX);\n    var innerinv = jStat.inv(inner);\n    return innerinv;\n  },\n\n  jMatYBar: function jMatYBar(jMatX, beta) {\n    var yBar = jStat.matrixmult(jMatX, beta);\n    return new jStat(yBar);\n  },\n\n  residuals: function residuals(jMatY, jMatYBar) {\n    return jStat.matrixsubtract(jMatY, jMatYBar);\n  },\n\n  ssr: function ssr(jMatYBar, yAverage) {\n    var ssr = 0;\n    for(var i = 0; i < jMatYBar.length; i++) {\n      ssr += Math.pow(jMatYBar[i] - yAverage, 2);\n    }\n    return ssr;\n  },\n\n  sse: function sse(jMatY, jMatYBar) {\n    var sse = 0;\n    for(var i = 0; i < jMatY.length; i++) {\n      sse += Math.pow(jMatY[i] - jMatYBar[i], 2);\n    }\n    return sse;\n  },\n\n  sst: function sst(jMatY, yAverage) {\n    var sst = 0;\n    for(var i = 0; i < jMatY.length; i++) {\n      sst += Math.pow(jMatY[i] - yAverage, 2);\n    }\n    return sst;\n  },\n\n  matrixsubtract: function matrixsubtract(A,B){\n    var ans = new Array(A.length);\n    for(var i=0;i<A.length;i++){\n      ans[i] = new Array(A[i].length);\n      for(var j=0;j<A[i].length;j++){\n        ans[i][j]=A[i][j]-B[i][j];\n      }\n    }\n    return jStat(ans);\n  }\n});\n  // Make it compatible with previous version.\n  jStat.jStat = jStat;\n\n  return jStat;\n});", "vendor/bigjs/LICENSE": "The MIT License (MIT)\n=====================\n\nCopyright \u00a9 `<2021>` `Michael Mclaughlin`\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \u201cSoftware\u201d), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \u201cAS IS\u201d, WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n", "vendor/bigjs/big.js": "// @ts-nocheck\n/* eslint-disable */\n\n/*\n *  big.js v6.1.1\n *  A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.\n *  Copyright (c) 2021 Michael Mclaughlin\n *  MIT LICENSE\n */\n\n\n/** ************************************ EDITABLE DEFAULTS *****************************************/\n\n\n// The default values below must be integers within the stated ranges.\n\n/*\n   * The maximum number of decimal places (DP) of the results of operations involving division:\n   * div and sqrt, and pow with negative exponents.\n   */\nlet DP = 20,          // 0 to MAX_DP\n\n  /*\n   * The rounding mode (RM) used when rounding to the above decimal places.\n   *\n   *  0  Towards zero (i.e. truncate, no rounding).       (ROUND_DOWN)\n   *  1  To nearest neighbour. If equidistant, round up.  (ROUND_HALF_UP)\n   *  2  To nearest neighbour. If equidistant, to even.   (ROUND_HALF_EVEN)\n   *  3  Away from zero.                                  (ROUND_UP)\n   */\n  RM = 1,             // 0, 1, 2 or 3\n\n  // The maximum value of DP and Big.DP.\n  MAX_DP = 1E6,       // 0 to 1000000\n\n  // The maximum magnitude of the exponent argument to the pow method.\n  MAX_POWER = 1E6,    // 1 to 1000000\n\n  /*\n   * The negative exponent (NE) at and beneath which toString returns exponential notation.\n   * (JavaScript numbers: -7)\n   * -1000000 is the minimum recommended exponent value of a Big.\n   */\n  NE = -7,            // 0 to -1000000\n\n  /*\n   * The positive exponent (PE) at and above which toString returns exponential notation.\n   * (JavaScript numbers: 21)\n   * 1000000 is the maximum recommended exponent value of a Big, but this limit is not enforced.\n   */\n  PE = 21,            // 0 to 1000000\n\n  /*\n   * When true, an error will be thrown if a primitive number is passed to the Big constructor,\n   * or if valueOf is called, or if toNumber is called on a Big which cannot be converted to a\n   * primitive number without a loss of precision.\n   */\n  STRICT = false,     // true or false\n\n\n  /** ************************************************************************************************/\n\n\n  // Error messages.\n  NAME = \"[big.js] \",\n  INVALID = NAME + \"Invalid \",\n  INVALID_DP = INVALID + \"decimal places\",\n  INVALID_RM = INVALID + \"rounding mode\",\n  DIV_BY_ZERO = NAME + \"Division by zero\",\n\n  // The shared prototype object.\n  P = {},\n  UNDEFINED = void 0,\n  NUMERIC = /^-?(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?$/i;\n\n\n/*\n * Create and return a Big constructor.\n */\nfunction _Big_() {\n\n  /*\n   * The Big constructor and exported function.\n   * Create and return a new instance of a Big number object.\n   *\n   * n {number|string|Big} A numeric value.\n   */\n  function Big(n) {\n    let x = this;\n\n    // Enable constructor usage without new.\n    if (!(x instanceof Big)) return n === UNDEFINED ? _Big_() : new Big(n);\n\n    // Duplicate.\n    if (n instanceof Big) {\n      x.s = n.s;\n      x.e = n.e;\n      x.c = n.c.slice();\n    } else {\n      if (typeof n !== \"string\") {\n        if (Big.strict === true) {\n          throw TypeError(INVALID + \"number\");\n        }\n\n        // Minus zero?\n        n = n === 0 && 1 / n < 0 ? \"-0\" : String(n);\n      }\n\n      parse(x, n);\n    }\n\n    // Retain a reference to this Big constructor.\n    // Shadow Big.prototype.constructor which points to Object.\n    x.constructor = Big;\n  }\n\n  Big.prototype = P;\n  Big.DP = DP;\n  Big.RM = RM;\n  Big.NE = NE;\n  Big.PE = PE;\n  Big.strict = STRICT;\n  Big.roundDown = 0;\n  Big.roundHalfUp = 1;\n  Big.roundHalfEven = 2;\n  Big.roundUp = 3;\n\n  return Big;\n}\n\n\n/*\n * Parse the number or string value passed to a Big constructor.\n *\n * x {Big} A Big number instance.\n * n {number|string} A numeric value.\n */\nfunction parse(x, n) {\n  let e, i, nl;\n\n  if (!NUMERIC.test(n)) {\n    throw Error(INVALID + \"number\");\n  }\n\n  // Determine sign.\n  x.s = n.charAt(0) == \"-\" ? (n = n.slice(1), -1) : 1;\n\n  // Decimal point?\n  if ((e = n.indexOf(\".\")) > -1) n = n.replace(\".\", \"\");\n\n  // Exponential form?\n  if ((i = n.search(/e/i)) > 0) {\n\n    // Determine exponent.\n    if (e < 0) e = i;\n    e += +n.slice(i + 1);\n    n = n.substring(0, i);\n  } else if (e < 0) {\n\n    // Integer.\n    e = n.length;\n  }\n\n  nl = n.length;\n\n  // Determine leading zeros.\n  for (i = 0; i < nl && n.charAt(i) == \"0\";) ++i;\n\n  if (i == nl) {\n\n    // Zero.\n    x.c = [x.e = 0];\n  } else {\n\n    // Determine trailing zeros.\n    for (; nl > 0 && n.charAt(--nl) == \"0\";);\n    x.e = e - i - 1;\n    x.c = [];\n\n    // Convert string to array of digits without leading/trailing zeros.\n    for (e = 0; i <= nl;) x.c[e++] = +n.charAt(i++);\n  }\n\n  return x;\n}\n\n\n/*\n * Round Big x to a maximum of sd significant digits using rounding mode rm.\n *\n * x {Big} The Big to round.\n * sd {number} Significant digits: integer, 0 to MAX_DP inclusive.\n * rm {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).\n * [more] {boolean} Whether the result of division was truncated.\n */\nfunction round(x, sd, rm, more) {\n  let xc = x.c;\n\n  if (rm === UNDEFINED) rm = x.constructor.RM;\n  if (rm !== 0 && rm !== 1 && rm !== 2 && rm !== 3) {\n    throw Error(INVALID_RM);\n  }\n\n  if (sd < 1) {\n    more =\n      rm === 3 && (more || !!xc[0]) || sd === 0 && (\n        rm === 1 && xc[0] >= 5 ||\n      rm === 2 && (xc[0] > 5 || xc[0] === 5 && (more || xc[1] !== UNDEFINED))\n      );\n\n    xc.length = 1;\n\n    if (more) {\n\n      // 1, 0.1, 0.01, 0.001, 0.0001 etc.\n      x.e = x.e - sd + 1;\n      xc[0] = 1;\n    } else {\n\n      // Zero.\n      xc[0] = x.e = 0;\n    }\n  } else if (sd < xc.length) {\n\n    // xc[sd] is the digit after the digit that may be rounded up.\n    more =\n      rm === 1 && xc[sd] >= 5 ||\n      rm === 2 && (xc[sd] > 5 || xc[sd] === 5 &&\n        (more || xc[sd + 1] !== UNDEFINED || xc[sd - 1] & 1)) ||\n      rm === 3 && (more || !!xc[0]);\n\n    // Remove any digits after the required precision.\n    xc.length = sd--;\n\n    // Round up?\n    if (more) {\n\n      // Rounding up may mean the previous digit has to be rounded up.\n      for (; ++xc[sd] > 9;) {\n        xc[sd] = 0;\n        if (!sd--) {\n          ++x.e;\n          xc.unshift(1);\n        }\n      }\n    }\n\n    // Remove trailing zeros.\n    for (sd = xc.length; !xc[--sd];) xc.pop();\n  }\n\n  return x;\n}\n\n\n/*\n * Return a string representing the value of Big x in normal or exponential notation.\n * Handles P.toExponential, P.toFixed, P.toJSON, P.toPrecision, P.toString and P.valueOf.\n */\nfunction stringify(x, doExponential, isNonzero) {\n  let e = x.e,\n    s = x.c.join(\"\"),\n    n = s.length;\n\n  // Exponential notation?\n  if (doExponential) {\n    s = s.charAt(0) + (n > 1 ? \".\" + s.slice(1) : \"\") + (e < 0 ? \"e\" : \"e+\") + e;\n\n  // Normal notation.\n  } else if (e < 0) {\n    for (; ++e;) s = \"0\" + s;\n    s = \"0.\" + s;\n  } else if (e > 0) {\n    if (++e > n) {\n      for (e -= n; e--;) s += \"0\";\n    } else if (e < n) {\n      s = s.slice(0, e) + \".\" + s.slice(e);\n    }\n  } else if (n > 1) {\n    s = s.charAt(0) + \".\" + s.slice(1);\n  }\n\n  return x.s < 0 && isNonzero ? \"-\" + s : s;\n}\n\n\n// Prototype/instance methods\n\n\n/*\n * Return a new Big whose value is the absolute value of this Big.\n */\nP.abs = function () {\n  let x = new this.constructor(this);\n  x.s = 1;\n  return x;\n};\n\n\n/*\n * Return 1 if the value of this Big is greater than the value of Big y,\n *       -1 if the value of this Big is less than the value of Big y, or\n *        0 if they have the same value.\n */\nP.cmp = function (y) {\n  let isneg,\n    x = this,\n    xc = x.c,\n    yc = (y = new x.constructor(y)).c,\n    i = x.s,\n    j = y.s,\n    k = x.e,\n    l = y.e;\n\n  // Either zero?\n  if (!xc[0] || !yc[0]) return !xc[0] ? !yc[0] ? 0 : -j : i;\n\n  // Signs differ?\n  if (i != j) return i;\n\n  isneg = i < 0;\n\n  // Compare exponents.\n  if (k != l) return k > l ^ isneg ? 1 : -1;\n\n  j = (k = xc.length) < (l = yc.length) ? k : l;\n\n  // Compare digit by digit.\n  for (i = -1; ++i < j;) {\n    if (xc[i] != yc[i]) return xc[i] > yc[i] ^ isneg ? 1 : -1;\n  }\n\n  // Compare lengths.\n  return k == l ? 0 : k > l ^ isneg ? 1 : -1;\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big divided by the value of Big y, rounded,\n * if necessary, to a maximum of Big.DP decimal places using rounding mode Big.RM.\n */\nP.div = function (y) {\n  let x = this,\n    Big = x.constructor,\n    a = x.c,                  // dividend\n    b = (y = new Big(y)).c,   // divisor\n    k = x.s == y.s ? 1 : -1,\n    dp = Big.DP;\n\n  if (dp !== ~~dp || dp < 0 || dp > MAX_DP) {\n    throw Error(INVALID_DP);\n  }\n\n  // Divisor is zero?\n  if (!b[0]) {\n    throw Error(DIV_BY_ZERO);\n  }\n\n  // Dividend is 0? Return +-0.\n  if (!a[0]) {\n    y.s = k;\n    y.c = [y.e = 0];\n    return y;\n  }\n\n  let bl, bt, n, cmp, ri,\n    bz = b.slice(),\n    ai = bl = b.length,\n    al = a.length,\n    r = a.slice(0, bl),   // remainder\n    rl = r.length,\n    q = y,                // quotient\n    qc = q.c = [],\n    qi = 0,\n    p = dp + (q.e = x.e - y.e) + 1;    // precision of the result\n\n  q.s = k;\n  k = p < 0 ? 0 : p;\n\n  // Create version of divisor with leading zero.\n  bz.unshift(0);\n\n  // Add zeros to make remainder as long as divisor.\n  for (; rl++ < bl;) r.push(0);\n\n  do {\n\n    // n is how many times the divisor goes into current remainder.\n    for (n = 0; n < 10; n++) {\n\n      // Compare divisor and remainder.\n      if (bl != (rl = r.length)) {\n        cmp = bl > rl ? 1 : -1;\n      } else {\n        for (ri = -1, cmp = 0; ++ri < bl;) {\n          if (b[ri] != r[ri]) {\n            cmp = b[ri] > r[ri] ? 1 : -1;\n            break;\n          }\n        }\n      }\n\n      // If divisor < remainder, subtract divisor from remainder.\n      if (cmp < 0) {\n\n        // Remainder can't be more than 1 digit longer than divisor.\n        // Equalise lengths using divisor with extra leading zero?\n        for (bt = rl == bl ? b : bz; rl;) {\n          if (r[--rl] < bt[rl]) {\n            ri = rl;\n            for (; ri && !r[--ri];) r[ri] = 9;\n            --r[ri];\n            r[rl] += 10;\n          }\n          r[rl] -= bt[rl];\n        }\n\n        for (; !r[0];) r.shift();\n      } else {\n        break;\n      }\n    }\n\n    // Add the digit n to the result array.\n    qc[qi++] = cmp ? n : ++n;\n\n    // Update the remainder.\n    if (r[0] && cmp) r[rl] = a[ai] || 0;\n    else r = [a[ai]];\n\n  } while ((ai++ < al || r[0] !== UNDEFINED) && k--);\n\n  // Leading zero? Do not remove if result is simply zero (qi == 1).\n  if (!qc[0] && qi != 1) {\n\n    // There can't be more than one zero.\n    qc.shift();\n    q.e--;\n    p--;\n  }\n\n  // Round?\n  if (qi > p) round(q, p, Big.RM, r[0] !== UNDEFINED);\n\n  return q;\n};\n\n\n/*\n * Return true if the value of this Big is equal to the value of Big y, otherwise return false.\n */\nP.eq = function (y) {\n  return this.cmp(y) === 0;\n};\n\n\n/*\n * Return true if the value of this Big is greater than the value of Big y, otherwise return\n * false.\n */\nP.gt = function (y) {\n  return this.cmp(y) > 0;\n};\n\n\n/*\n * Return true if the value of this Big is greater than or equal to the value of Big y, otherwise\n * return false.\n */\nP.gte = function (y) {\n  return this.cmp(y) > -1;\n};\n\n\n/*\n * Return true if the value of this Big is less than the value of Big y, otherwise return false.\n */\nP.lt = function (y) {\n  return this.cmp(y) < 0;\n};\n\n\n/*\n * Return true if the value of this Big is less than or equal to the value of Big y, otherwise\n * return false.\n */\nP.lte = function (y) {\n  return this.cmp(y) < 1;\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big minus the value of Big y.\n */\nP.minus = P.sub = function (y) {\n  let i, j, t, xlty,\n    x = this,\n    Big = x.constructor,\n    a = x.s,\n    b = (y = new Big(y)).s;\n\n  // Signs differ?\n  if (a != b) {\n    y.s = -b;\n    return x.plus(y);\n  }\n\n  let xc = x.c.slice(),\n    xe = x.e,\n    yc = y.c,\n    ye = y.e;\n\n  // Either zero?\n  if (!xc[0] || !yc[0]) {\n    if (yc[0]) {\n      y.s = -b;\n    } else if (xc[0]) {\n      y = new Big(x);\n    } else {\n      y.s = 1;\n    }\n    return y;\n  }\n\n  // Determine which is the bigger number. Prepend zeros to equalise exponents.\n  if (a = xe - ye) {\n\n    if (xlty = a < 0) {\n      a = -a;\n      t = xc;\n    } else {\n      ye = xe;\n      t = yc;\n    }\n\n    t.reverse();\n    for (b = a; b--;) t.push(0);\n    t.reverse();\n  } else {\n\n    // Exponents equal. Check digit by digit.\n    j = ((xlty = xc.length < yc.length) ? xc : yc).length;\n\n    for (a = b = 0; b < j; b++) {\n      if (xc[b] != yc[b]) {\n        xlty = xc[b] < yc[b];\n        break;\n      }\n    }\n  }\n\n  // x < y? Point xc to the array of the bigger number.\n  if (xlty) {\n    t = xc;\n    xc = yc;\n    yc = t;\n    y.s = -y.s;\n  }\n\n  /*\n   * Append zeros to xc if shorter. No need to add zeros to yc if shorter as subtraction only\n   * needs to start at yc.length.\n   */\n  if ((b = (j = yc.length) - (i = xc.length)) > 0) for (; b--;) xc[i++] = 0;\n\n  // Subtract yc from xc.\n  for (b = i; j > a;) {\n    if (xc[--j] < yc[j]) {\n      for (i = j; i && !xc[--i];) xc[i] = 9;\n      --xc[i];\n      xc[j] += 10;\n    }\n\n    xc[j] -= yc[j];\n  }\n\n  // Remove trailing zeros.\n  for (; xc[--b] === 0;) xc.pop();\n\n  // Remove leading zeros and adjust exponent accordingly.\n  for (; xc[0] === 0;) {\n    xc.shift();\n    --ye;\n  }\n\n  if (!xc[0]) {\n\n    // n - n = +0\n    y.s = 1;\n\n    // Result must be zero.\n    xc = [ye = 0];\n  }\n\n  y.c = xc;\n  y.e = ye;\n\n  return y;\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big modulo the value of Big y.\n */\nP.mod = function (y) {\n  let ygtx,\n    x = this,\n    Big = x.constructor,\n    a = x.s,\n    b = (y = new Big(y)).s;\n\n  if (!y.c[0]) {\n    throw Error(DIV_BY_ZERO);\n  }\n\n  x.s = y.s = 1;\n  ygtx = y.cmp(x) == 1;\n  x.s = a;\n  y.s = b;\n\n  if (ygtx) return new Big(x);\n\n  a = Big.DP;\n  b = Big.RM;\n  Big.DP = Big.RM = 0;\n  x = x.div(y);\n  Big.DP = a;\n  Big.RM = b;\n\n  return this.minus(x.times(y));\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big plus the value of Big y.\n */\nP.plus = P.add = function (y) {\n  let e, k, t,\n    x = this,\n    Big = x.constructor;\n\n  y = new Big(y);\n\n  // Signs differ?\n  if (x.s != y.s) {\n    y.s = -y.s;\n    return x.minus(y);\n  }\n\n  let xe = x.e,\n    xc = x.c,\n    ye = y.e,\n    yc = y.c;\n\n  // Either zero?\n  if (!xc[0] || !yc[0]) {\n    if (!yc[0]) {\n      if (xc[0]) {\n        y = new Big(x);\n      } else {\n        y.s = x.s;\n      }\n    }\n    return y;\n  }\n\n  xc = xc.slice();\n\n  // Prepend zeros to equalise exponents.\n  // Note: reverse faster than unshifts.\n  if (e = xe - ye) {\n    if (e > 0) {\n      ye = xe;\n      t = yc;\n    } else {\n      e = -e;\n      t = xc;\n    }\n\n    t.reverse();\n    for (; e--;) t.push(0);\n    t.reverse();\n  }\n\n  // Point xc to the longer array.\n  if (xc.length - yc.length < 0) {\n    t = yc;\n    yc = xc;\n    xc = t;\n  }\n\n  e = yc.length;\n\n  // Only start adding at yc.length - 1 as the further digits of xc can be left as they are.\n  for (k = 0; e; xc[e] %= 10) k = (xc[--e] = xc[e] + yc[e] + k) / 10 | 0;\n\n  // No need to check for zero, as +x + +y != 0 && -x + -y != 0\n\n  if (k) {\n    xc.unshift(k);\n    ++ye;\n  }\n\n  // Remove trailing zeros.\n  for (e = xc.length; xc[--e] === 0;) xc.pop();\n\n  y.c = xc;\n  y.e = ye;\n\n  return y;\n};\n\n\n/*\n * Return a Big whose value is the value of this Big raised to the power n.\n * If n is negative, round to a maximum of Big.DP decimal places using rounding\n * mode Big.RM.\n *\n * n {number} Integer, -MAX_POWER to MAX_POWER inclusive.\n */\nP.pow = function (n) {\n  let x = this,\n    one = new x.constructor(\"1\"),\n    y = one,\n    isneg = n < 0;\n\n  if (n !== ~~n || n < -MAX_POWER || n > MAX_POWER) {\n    throw Error(INVALID + \"exponent\");\n  }\n\n  if (isneg) n = -n;\n\n  for (;;) {\n    if (n & 1) y = y.times(x);\n    n >>= 1;\n    if (!n) break;\n    x = x.times(x);\n  }\n\n  return isneg ? one.div(y) : y;\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big rounded to a maximum precision of sd\n * significant digits using rounding mode rm, or Big.RM if rm is not specified.\n *\n * sd {number} Significant digits: integer, 1 to MAX_DP inclusive.\n * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).\n */\nP.prec = function (sd, rm) {\n  if (sd !== ~~sd || sd < 1 || sd > MAX_DP) {\n    throw Error(INVALID + \"precision\");\n  }\n  return round(new this.constructor(this), sd, rm);\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big rounded to a maximum of dp decimal places\n * using rounding mode rm, or Big.RM if rm is not specified.\n * If dp is negative, round to an integer which is a multiple of 10**-dp.\n * If dp is not specified, round to 0 decimal places.\n *\n * dp? {number} Integer, -MAX_DP to MAX_DP inclusive.\n * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).\n */\nP.round = function (dp, rm) {\n  if (dp === UNDEFINED) dp = 0;\n  else if (dp !== ~~dp || dp < -MAX_DP || dp > MAX_DP) {\n    throw Error(INVALID_DP);\n  }\n  return round(new this.constructor(this), dp + this.e + 1, rm);\n};\n\n\n/*\n * Return a new Big whose value is the square root of the value of this Big, rounded, if\n * necessary, to a maximum of Big.DP decimal places using rounding mode Big.RM.\n */\nP.sqrt = function () {\n  let r, c, t,\n    x = this,\n    Big = x.constructor,\n    s = x.s,\n    e = x.e,\n    half = new Big(\"0.5\");\n\n  // Zero?\n  if (!x.c[0]) return new Big(x);\n\n  // Negative?\n  if (s < 0) {\n    throw Error(NAME + \"No square root\");\n  }\n\n  // Estimate.\n  s = Math.sqrt(x + \"\");\n\n  // Math.sqrt underflow/overflow?\n  // Re-estimate: pass x coefficient to Math.sqrt as integer, then adjust the result exponent.\n  if (s === 0 || s === 1 / 0) {\n    c = x.c.join(\"\");\n    if (!(c.length + e & 1)) c += \"0\";\n    s = Math.sqrt(c);\n    e = ((e + 1) / 2 | 0) - (e < 0 || e & 1);\n    r = new Big((s == 1 / 0 ? \"5e\" : (s = s.toExponential()).slice(0, s.indexOf(\"e\") + 1)) + e);\n  } else {\n    r = new Big(s + \"\");\n  }\n\n  e = r.e + (Big.DP += 4);\n\n  // Newton-Raphson iteration.\n  do {\n    t = r;\n    r = half.times(t.plus(x.div(t)));\n  } while (t.c.slice(0, e).join(\"\") !== r.c.slice(0, e).join(\"\"));\n\n  return round(r, (Big.DP -= 4) + r.e + 1, Big.RM);\n};\n\n\n/*\n * Return a new Big whose value is the value of this Big times the value of Big y.\n */\nP.times = P.mul = function (y) {\n  let c,\n    x = this,\n    Big = x.constructor,\n    xc = x.c,\n    yc = (y = new Big(y)).c,\n    a = xc.length,\n    b = yc.length,\n    i = x.e,\n    j = y.e;\n\n  // Determine sign of result.\n  y.s = x.s == y.s ? 1 : -1;\n\n  // Return signed 0 if either 0.\n  if (!xc[0] || !yc[0]) {\n    y.c = [y.e = 0];\n    return y;\n  }\n\n  // Initialise exponent of result as x.e + y.e.\n  y.e = i + j;\n\n  // If array xc has fewer digits than yc, swap xc and yc, and lengths.\n  if (a < b) {\n    c = xc;\n    xc = yc;\n    yc = c;\n    j = a;\n    a = b;\n    b = j;\n  }\n\n  // Initialise coefficient array of result with zeros.\n  for (c = new Array(j = a + b); j--;) c[j] = 0;\n\n  // Multiply.\n\n  // i is initially xc.length.\n  for (i = b; i--;) {\n    b = 0;\n\n    // a is yc.length.\n    for (j = a + i; j > i;) {\n\n      // Current sum of products at this digit position, plus carry.\n      b = c[j] + yc[i] * xc[j - i - 1] + b;\n      c[j--] = b % 10;\n\n      // carry\n      b = b / 10 | 0;\n    }\n\n    c[j] = b;\n  }\n\n  // Increment result exponent if there is a final carry, otherwise remove leading zero.\n  if (b) ++y.e;\n  else c.shift();\n\n  // Remove trailing zeros.\n  for (i = c.length; !c[--i];) c.pop();\n  y.c = c;\n\n  return y;\n};\n\n\n/*\n * Return a string representing the value of this Big in exponential notation rounded to dp fixed\n * decimal places using rounding mode rm, or Big.RM if rm is not specified.\n *\n * dp? {number} Decimal places: integer, 0 to MAX_DP inclusive.\n * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).\n */\nP.toExponential = function (dp, rm) {\n  let x = this,\n    n = x.c[0];\n\n  if (dp !== UNDEFINED) {\n    if (dp !== ~~dp || dp < 0 || dp > MAX_DP) {\n      throw Error(INVALID_DP);\n    }\n    x = round(new x.constructor(x), ++dp, rm);\n    for (; x.c.length < dp;) x.c.push(0);\n  }\n\n  return stringify(x, true, !!n);\n};\n\n\n/*\n * Return a string representing the value of this Big in normal notation rounded to dp fixed\n * decimal places using rounding mode rm, or Big.RM if rm is not specified.\n *\n * dp? {number} Decimal places: integer, 0 to MAX_DP inclusive.\n * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).\n *\n * (-0).toFixed(0) is '0', but (-0.1).toFixed(0) is '-0'.\n * (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'.\n */\nP.toFixed = function (dp, rm) {\n  let x = this,\n    n = x.c[0];\n\n  if (dp !== UNDEFINED) {\n    if (dp !== ~~dp || dp < 0 || dp > MAX_DP) {\n      throw Error(INVALID_DP);\n    }\n    x = round(new x.constructor(x), dp + x.e + 1, rm);\n\n    // x.e may have changed if the value is rounded up.\n    for (dp = dp + x.e + 1; x.c.length < dp;) x.c.push(0);\n  }\n\n  return stringify(x, false, !!n);\n};\n\n\n/*\n * Return a string representing the value of this Big.\n * Return exponential notation if this Big has a positive exponent equal to or greater than\n * Big.PE, or a negative exponent equal to or less than Big.NE.\n * Omit the sign for negative zero.\n */\nP.toJSON = P.toString = function () {\n  let x = this,\n    Big = x.constructor;\n  return stringify(x, x.e <= Big.NE || x.e >= Big.PE, !!x.c[0]);\n};\n\n\n/*\n * Return the value of this Big as a primitve number.\n */\nP.toNumber = function () {\n  let n = Number(stringify(this, true, true));\n  if (this.constructor.strict === true && !this.eq(n.toString())) {\n    throw Error(NAME + \"Imprecise conversion\");\n  }\n  return n;\n};\n\n\n/*\n * Return a string representing the value of this Big rounded to sd significant digits using\n * rounding mode rm, or Big.RM if rm is not specified.\n * Use exponential notation if sd is less than the number of digits necessary to represent\n * the integer part of the value in normal notation.\n *\n * sd {number} Significant digits: integer, 1 to MAX_DP inclusive.\n * rm? {number} Rounding mode: 0 (down), 1 (half-up), 2 (half-even) or 3 (up).\n */\nP.toPrecision = function (sd, rm) {\n  let x = this,\n    Big = x.constructor,\n    n = x.c[0];\n\n  if (sd !== UNDEFINED) {\n    if (sd !== ~~sd || sd < 1 || sd > MAX_DP) {\n      throw Error(INVALID + \"precision\");\n    }\n    x = round(new Big(x), sd, rm);\n    for (; x.c.length < sd;) x.c.push(0);\n  }\n\n  return stringify(x, sd <= x.e || x.e <= Big.NE || x.e >= Big.PE, !!n);\n};\n\n\n/*\n * Return a string representing the value of this Big.\n * Return exponential notation if this Big has a positive exponent equal to or greater than\n * Big.PE, or a negative exponent equal to or less than Big.NE.\n * Include the sign for negative zero.\n */\nP.valueOf = function () {\n  let x = this,\n    Big = x.constructor;\n  if (Big.strict === true) {\n    throw Error(NAME + \"valueOf disallowed\");\n  }\n  return stringify(x, x.e <= Big.NE || x.e >= Big.PE, true);\n};\n\n\n// Export\n\n\nexport var Big = _Big_();\n\n// / <reference types=\"https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/types/big.js/index.d.ts\" />\nexport default Big;"}