packages feed

harmony (empty) → 0.1.0.0

raw patch · 24 files changed

+4170/−0 lines, 24 filesdep +BNFCdep +HUnitdep +QuickCheckbuild-type:Customsetup-changed

Dependencies added: BNFC, HUnit, QuickCheck, array, base, containers, derive, directory, harmony, hastache, hlint, hslogger, hspec, mtl, process, text

Files

+ LICENSE view
@@ -0,0 +1,675 @@+GNU GENERAL PUBLIC LICENSE+                       Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++                            Preamble++  The GNU General Public License is a free, copyleft license for+software and other kinds of works.++  The licenses for most software and other practical works are designed+to take away your freedom to share and change the works.  By contrast,+the GNU General Public License is intended to guarantee your freedom to+share and change all versions of a program--to make sure it remains free+software for all its users.  We, the Free Software Foundation, use the+GNU General Public License for most of our software; it applies also to+any other work released this way by its authors.  You can apply it to+your programs, too.++  When we speak of free software, we are referring to freedom, not+price.  Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+them if you wish), that you receive source code or can get it if you+want it, that you can change the software or use pieces of it in new+free programs, and that you know you can do these things.++  To protect your rights, we need to prevent others from denying you+these rights or asking you to surrender the rights.  Therefore, you have+certain responsibilities if you distribute copies of the software, or if+you modify it: responsibilities to respect the freedom of others.++  For example, if you distribute copies of such a program, whether+gratis or for a fee, you must pass on to the recipients the same+freedoms that you received.  You must make sure that they, too, receive+or can get the source code.  And you must show them these terms so they+know their rights.++  Developers that use the GNU GPL protect your rights with two steps:+(1) assert copyright on the software, and (2) offer you this License+giving you legal permission to copy, distribute and/or modify it.++  For the developers' and authors' protection, the GPL clearly explains+that there is no warranty for this free software.  For both users' and+authors' sake, the GPL requires that modified versions be marked as+changed, so that their problems will not be attributed erroneously to+authors of previous versions.++  Some devices are designed to deny users access to install or run+modified versions of the software inside them, although the manufacturer+can do so.  This is fundamentally incompatible with the aim of+protecting users' freedom to change the software.  The systematic+pattern of such abuse occurs in the area of products for individuals to+use, which is precisely where it is most unacceptable.  Therefore, we+have designed this version of the GPL to prohibit the practice for those+products.  If such problems arise substantially in other domains, we+stand ready to extend this provision to those domains in future versions+of the GPL, as needed to protect the freedom of users.++  Finally, every program is threatened constantly by software patents.+States should not allow patents to restrict development and use of+software on general-purpose computers, but in those that do, we wish to+avoid the special danger that patents applied to a free program could+make it effectively proprietary.  To prevent this, the GPL assures that+patents cannot be used to render the program non-free.++  The precise terms and conditions for copying, distribution and+modification follow.++                       TERMS AND CONDITIONS++  0. Definitions.++  "This License" refers to version 3 of the GNU General Public License.++  "Copyright" also means copyright-like laws that apply to other kinds of+works, such as semiconductor masks.++  "The Program" refers to any copyrightable work licensed under this+License.  Each licensee is addressed as "you".  "Licensees" and+"recipients" may be individuals or organizations.++  To "modify" a work means to copy from or adapt all or part of the work+in a fashion requiring copyright permission, other than the making of an+exact copy.  The resulting work is called a "modified version" of the+earlier work or a work "based on" the earlier work.++  A "covered work" means either the unmodified Program or a work based+on the Program.++  To "propagate" a work means to do anything with it that, without+permission, would make you directly or secondarily liable for+infringement under applicable copyright law, except executing it on a+computer or modifying a private copy.  Propagation includes copying,+distribution (with or without modification), making available to the+public, and in some countries other activities as well.++  To "convey" a work means any kind of propagation that enables other+parties to make or receive copies.  Mere interaction with a user through+a computer network, with no transfer of a copy, is not conveying.++  An interactive user interface displays "Appropriate Legal Notices"+to the extent that it includes a convenient and prominently visible+feature that (1) displays an appropriate copyright notice, and (2)+tells the user that there is no warranty for the work (except to the+extent that warranties are provided), that licensees may convey the+work under this License, and how to view a copy of this License.  If+the interface presents a list of user commands or options, such as a+menu, a prominent item in the list meets this criterion.++  1. Source Code.++  The "source code" for a work means the preferred form of the work+for making modifications to it.  "Object code" means any non-source+form of a work.++  A "Standard Interface" means an interface that either is an official+standard defined by a recognized standards body, or, in the case of+interfaces specified for a particular programming language, one that+is widely used among developers working in that language.++  The "System Libraries" of an executable work include anything, other+than the work as a whole, that (a) is included in the normal form of+packaging a Major Component, but which is not part of that Major+Component, and (b) serves only to enable use of the work with that+Major Component, or to implement a Standard Interface for which an+implementation is available to the public in source code form.  A+"Major Component", in this context, means a major essential component+(kernel, window system, and so on) of the specific operating system+(if any) on which the executable work runs, or a compiler used to+produce the work, or an object code interpreter used to run it.++  The "Corresponding Source" for a work in object code form means all+the source code needed to generate, install, and (for an executable+work) run the object code and to modify the work, including scripts to+control those activities.  However, it does not include the work's+System Libraries, or general-purpose tools or generally available free+programs which are used unmodified in performing those activities but+which are not part of the work.  For example, Corresponding Source+includes interface definition files associated with source files for+the work, and the source code for shared libraries and dynamically+linked subprograms that the work is specifically designed to require,+such as by intimate data communication or control flow between those+subprograms and other parts of the work.++  The Corresponding Source need not include anything that users+can regenerate automatically from other parts of the Corresponding+Source.++  The Corresponding Source for a work in source code form is that+same work.++  2. Basic Permissions.++  All rights granted under this License are granted for the term of+copyright on the Program, and are irrevocable provided the stated+conditions are met.  This License explicitly affirms your unlimited+permission to run the unmodified Program.  The output from running a+covered work is covered by this License only if the output, given its+content, constitutes a covered work.  This License acknowledges your+rights of fair use or other equivalent, as provided by copyright law.++  You may make, run and propagate covered works that you do not+convey, without conditions so long as your license otherwise remains+in force.  You may convey covered works to others for the sole purpose+of having them make modifications exclusively for you, or provide you+with facilities for running those works, provided that you comply with+the terms of this License in conveying all material for which you do+not control copyright.  Those thus making or running the covered works+for you must do so exclusively on your behalf, under your direction+and control, on terms that prohibit them from making any copies of+your copyrighted material outside their relationship with you.++  Conveying under any other circumstances is permitted solely under+the conditions stated below.  Sublicensing is not allowed; section 10+makes it unnecessary.++  3. Protecting Users' Legal Rights From Anti-Circumvention Law.++  No covered work shall be deemed part of an effective technological+measure under any applicable law fulfilling obligations under article+11 of the WIPO copyright treaty adopted on 20 December 1996, or+similar laws prohibiting or restricting circumvention of such+measures.++  When you convey a covered work, you waive any legal power to forbid+circumvention of technological measures to the extent such circumvention+is effected by exercising rights under this License with respect to+the covered work, and you disclaim any intention to limit operation or+modification of the work as a means of enforcing, against the work's+users, your or third parties' legal rights to forbid circumvention of+technological measures.++  4. Conveying Verbatim Copies.++  You may convey verbatim copies of the Program's source code as you+receive it, in any medium, provided that you conspicuously and+appropriately publish on each copy an appropriate copyright notice;+keep intact all notices stating that this License and any+non-permissive terms added in accord with section 7 apply to the code;+keep intact all notices of the absence of any warranty; and give all+recipients a copy of this License along with the Program.++  You may charge any price or no price for each copy that you convey,+and you may offer support or warranty protection for a fee.++  5. Conveying Modified Source Versions.++  You may convey a work based on the Program, or the modifications to+produce it from the Program, in the form of source code under the+terms of section 4, provided that you also meet all of these conditions:++    a) The work must carry prominent notices stating that you modified+    it, and giving a relevant date.++    b) The work must carry prominent notices stating that it is+    released under this License and any conditions added under section+    7.  This requirement modifies the requirement in section 4 to+    "keep intact all notices".++    c) You must license the entire work, as a whole, under this+    License to anyone who comes into possession of a copy.  This+    License will therefore apply, along with any applicable section 7+    additional terms, to the whole of the work, and all its parts,+    regardless of how they are packaged.  This License gives no+    permission to license the work in any other way, but it does not+    invalidate such permission if you have separately received it.++    d) If the work has interactive user interfaces, each must display+    Appropriate Legal Notices; however, if the Program has interactive+    interfaces that do not display Appropriate Legal Notices, your+    work need not make them do so.++  A compilation of a covered work with other separate and independent+works, which are not by their nature extensions of the covered work,+and which are not combined with it such as to form a larger program,+in or on a volume of a storage or distribution medium, is called an+"aggregate" if the compilation and its resulting copyright are not+used to limit the access or legal rights of the compilation's users+beyond what the individual works permit.  Inclusion of a covered work+in an aggregate does not cause this License to apply to the other+parts of the aggregate.++  6. Conveying Non-Source Forms.++  You may convey a covered work in object code form under the terms+of sections 4 and 5, provided that you also convey the+machine-readable Corresponding Source under the terms of this License,+in one of these ways:++    a) Convey the object code in, or embodied in, a physical product+    (including a physical distribution medium), accompanied by the+    Corresponding Source fixed on a durable physical medium+    customarily used for software interchange.++    b) Convey the object code in, or embodied in, a physical product+    (including a physical distribution medium), accompanied by a+    written offer, valid for at least three years and valid for as+    long as you offer spare parts or customer support for that product+    model, to give anyone who possesses the object code either (1) a+    copy of the Corresponding Source for all the software in the+    product that is covered by this License, on a durable physical+    medium customarily used for software interchange, for a price no+    more than your reasonable cost of physically performing this+    conveying of source, or (2) access to copy the+    Corresponding Source from a network server at no charge.++    c) Convey individual copies of the object code with a copy of the+    written offer to provide the Corresponding Source.  This+    alternative is allowed only occasionally and noncommercially, and+    only if you received the object code with such an offer, in accord+    with subsection 6b.++    d) Convey the object code by offering access from a designated+    place (gratis or for a charge), and offer equivalent access to the+    Corresponding Source in the same way through the same place at no+    further charge.  You need not require recipients to copy the+    Corresponding Source along with the object code.  If the place to+    copy the object code is a network server, the Corresponding Source+    may be on a different server (operated by you or a third party)+    that supports equivalent copying facilities, provided you maintain+    clear directions next to the object code saying where to find the+    Corresponding Source.  Regardless of what server hosts the+    Corresponding Source, you remain obligated to ensure that it is+    available for as long as needed to satisfy these requirements.++    e) Convey the object code using peer-to-peer transmission, provided+    you inform other peers where the object code and Corresponding+    Source of the work are being offered to the general public at no+    charge under subsection 6d.++  A separable portion of the object code, whose source code is excluded+from the Corresponding Source as a System Library, need not be+included in conveying the object code work.++  A "User Product" is either (1) a "consumer product", which means any+tangible personal property which is normally used for personal, family,+or household purposes, or (2) anything designed or sold for incorporation+into a dwelling.  In determining whether a product is a consumer product,+doubtful cases shall be resolved in favor of coverage.  For a particular+product received by a particular user, "normally used" refers to a+typical or common use of that class of product, regardless of the status+of the particular user or of the way in which the particular user+actually uses, or expects or is expected to use, the product.  A product+is a consumer product regardless of whether the product has substantial+commercial, industrial or non-consumer uses, unless such uses represent+the only significant mode of use of the product.++  "Installation Information" for a User Product means any methods,+procedures, authorization keys, or other information required to install+and execute modified versions of a covered work in that User Product from+a modified version of its Corresponding Source.  The information must+suffice to ensure that the continued functioning of the modified object+code is in no case prevented or interfered with solely because+modification has been made.++  If you convey an object code work under this section in, or with, or+specifically for use in, a User Product, and the conveying occurs as+part of a transaction in which the right of possession and use of the+User Product is transferred to the recipient in perpetuity or for a+fixed term (regardless of how the transaction is characterized), the+Corresponding Source conveyed under this section must be accompanied+by the Installation Information.  But this requirement does not apply+if neither you nor any third party retains the ability to install+modified object code on the User Product (for example, the work has+been installed in ROM).++  The requirement to provide Installation Information does not include a+requirement to continue to provide support service, warranty, or updates+for a work that has been modified or installed by the recipient, or for+the User Product in which it has been modified or installed.  Access to a+network may be denied when the modification itself materially and+adversely affects the operation of the network or violates the rules and+protocols for communication across the network.++  Corresponding Source conveyed, and Installation Information provided,+in accord with this section must be in a format that is publicly+documented (and with an implementation available to the public in+source code form), and must require no special password or key for+unpacking, reading or copying.++  7. Additional Terms.++  "Additional permissions" are terms that supplement the terms of this+License by making exceptions from one or more of its conditions.+Additional permissions that are applicable to the entire Program shall+be treated as though they were included in this License, to the extent+that they are valid under applicable law.  If additional permissions+apply only to part of the Program, that part may be used separately+under those permissions, but the entire Program remains governed by+this License without regard to the additional permissions.++  When you convey a copy of a covered work, you may at your option+remove any additional permissions from that copy, or from any part of+it.  (Additional permissions may be written to require their own+removal in certain cases when you modify the work.)  You may place+additional permissions on material, added by you to a covered work,+for which you have or can give appropriate copyright permission.++  Notwithstanding any other provision of this License, for material you+add to a covered work, you may (if authorized by the copyright holders of+that material) supplement the terms of this License with terms:++    a) Disclaiming warranty or limiting liability differently from the+    terms of sections 15 and 16 of this License; or++    b) Requiring preservation of specified reasonable legal notices or+    author attributions in that material or in the Appropriate Legal+    Notices displayed by works containing it; or++    c) Prohibiting misrepresentation of the origin of that material, or+    requiring that modified versions of such material be marked in+    reasonable ways as different from the original version; or++    d) Limiting the use for publicity purposes of names of licensors or+    authors of the material; or++    e) Declining to grant rights under trademark law for use of some+    trade names, trademarks, or service marks; or++    f) Requiring indemnification of licensors and authors of that+    material by anyone who conveys the material (or modified versions of+    it) with contractual assumptions of liability to the recipient, for+    any liability that these contractual assumptions directly impose on+    those licensors and authors.++  All other non-permissive additional terms are considered "further+restrictions" within the meaning of section 10.  If the Program as you+received it, or any part of it, contains a notice stating that it is+governed by this License along with a term that is a further+restriction, you may remove that term.  If a license document contains+a further restriction but permits relicensing or conveying under this+License, you may add to a covered work material governed by the terms+of that license document, provided that the further restriction does+not survive such relicensing or conveying.++  If you add terms to a covered work in accord with this section, you+must place, in the relevant source files, a statement of the+additional terms that apply to those files, or a notice indicating+where to find the applicable terms.++  Additional terms, permissive or non-permissive, may be stated in the+form of a separately written license, or stated as exceptions;+the above requirements apply either way.++  8. Termination.++  You may not propagate or modify a covered work except as expressly+provided under this License.  Any attempt otherwise to propagate or+modify it is void, and will automatically terminate your rights under+this License (including any patent licenses granted under the third+paragraph of section 11).++  However, if you cease all violation of this License, then your+license from a particular copyright holder is reinstated (a)+provisionally, unless and until the copyright holder explicitly and+finally terminates your license, and (b) permanently, if the copyright+holder fails to notify you of the violation by some reasonable means+prior to 60 days after the cessation.++  Moreover, your license from a particular copyright holder is+reinstated permanently if the copyright holder notifies you of the+violation by some reasonable means, this is the first time you have+received notice of violation of this License (for any work) from that+copyright holder, and you cure the violation prior to 30 days after+your receipt of the notice.++  Termination of your rights under this section does not terminate the+licenses of parties who have received copies or rights from you under+this License.  If your rights have been terminated and not permanently+reinstated, you do not qualify to receive new licenses for the same+material under section 10.++  9. Acceptance Not Required for Having Copies.++  You are not required to accept this License in order to receive or+run a copy of the Program.  Ancillary propagation of a covered work+occurring solely as a consequence of using peer-to-peer transmission+to receive a copy likewise does not require acceptance.  However,+nothing other than this License grants you permission to propagate or+modify any covered work.  These actions infringe copyright if you do+not accept this License.  Therefore, by modifying or propagating a+covered work, you indicate your acceptance of this License to do so.++  10. Automatic Licensing of Downstream Recipients.++  Each time you convey a covered work, the recipient automatically+receives a license from the original licensors, to run, modify and+propagate that work, subject to this License.  You are not responsible+for enforcing compliance by third parties with this License.++  An "entity transaction" is a transaction transferring control of an+organization, or substantially all assets of one, or subdividing an+organization, or merging organizations.  If propagation of a covered+work results from an entity transaction, each party to that+transaction who receives a copy of the work also receives whatever+licenses to the work the party's predecessor in interest had or could+give under the previous paragraph, plus a right to possession of the+Corresponding Source of the work from the predecessor in interest, if+the predecessor has it or can get it with reasonable efforts.++  You may not impose any further restrictions on the exercise of the+rights granted or affirmed under this License.  For example, you may+not impose a license fee, royalty, or other charge for exercise of+rights granted under this License, and you may not initiate litigation+(including a cross-claim or counterclaim in a lawsuit) alleging that+any patent claim is infringed by making, using, selling, offering for+sale, or importing the Program or any portion of it.++  11. Patents.++  A "contributor" is a copyright holder who authorizes use under this+License of the Program or a work on which the Program is based.  The+work thus licensed is called the contributor's "contributor version".++  A contributor's "essential patent claims" are all patent claims+owned or controlled by the contributor, whether already acquired or+hereafter acquired, that would be infringed by some manner, permitted+by this License, of making, using, or selling its contributor version,+but do not include claims that would be infringed only as a+consequence of further modification of the contributor version.  For+purposes of this definition, "control" includes the right to grant+patent sublicenses in a manner consistent with the requirements of+this License.++  Each contributor grants you a non-exclusive, worldwide, royalty-free+patent license under the contributor's essential patent claims, to+make, use, sell, offer for sale, import and otherwise run, modify and+propagate the contents of its contributor version.++  In the following three paragraphs, a "patent license" is any express+agreement or commitment, however denominated, not to enforce a patent+(such as an express permission to practice a patent or covenant not to+sue for patent infringement).  To "grant" such a patent license to a+party means to make such an agreement or commitment not to enforce a+patent against the party.++  If you convey a covered work, knowingly relying on a patent license,+and the Corresponding Source of the work is not available for anyone+to copy, free of charge and under the terms of this License, through a+publicly available network server or other readily accessible means,+then you must either (1) cause the Corresponding Source to be so+available, or (2) arrange to deprive yourself of the benefit of the+patent license for this particular work, or (3) arrange, in a manner+consistent with the requirements of this License, to extend the patent+license to downstream recipients.  "Knowingly relying" means you have+actual knowledge that, but for the patent license, your conveying the+covered work in a country, or your recipient's use of the covered work+in a country, would infringe one or more identifiable patents in that+country that you have reason to believe are valid.++  If, pursuant to or in connection with a single transaction or+arrangement, you convey, or propagate by procuring conveyance of, a+covered work, and grant a patent license to some of the parties+receiving the covered work authorizing them to use, propagate, modify+or convey a specific copy of the covered work, then the patent license+you grant is automatically extended to all recipients of the covered+work and works based on it.++  A patent license is "discriminatory" if it does not include within+the scope of its coverage, prohibits the exercise of, or is+conditioned on the non-exercise of one or more of the rights that are+specifically granted under this License.  You may not convey a covered+work if you are a party to an arrangement with a third party that is+in the business of distributing software, under which you make payment+to the third party based on the extent of your activity of conveying+the work, and under which the third party grants, to any of the+parties who would receive the covered work from you, a discriminatory+patent license (a) in connection with copies of the covered work+conveyed by you (or copies made from those copies), or (b) primarily+for and in connection with specific products or compilations that+contain the covered work, unless you entered into that arrangement,+or that patent license was granted, prior to 28 March 2007.++  Nothing in this License shall be construed as excluding or limiting+any implied license or other defenses to infringement that may+otherwise be available to you under applicable patent law.++  12. No Surrender of Others' Freedom.++  If conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot convey a+covered work so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you may+not convey it at all.  For example, if you agree to terms that obligate you+to collect a royalty for further conveying from those to whom you convey+the Program, the only way you could satisfy both those terms and this+License would be to refrain entirely from conveying the Program.++  13. Use with the GNU Affero General Public License.++  Notwithstanding any other provision of this License, you have+permission to link or combine any covered work with a work licensed+under version 3 of the GNU Affero General Public License into a single+combined work, and to convey the resulting work.  The terms of this+License will continue to apply to the part which is the covered work,+but the special requirements of the GNU Affero General Public License,+section 13, concerning interaction through a network will apply to the+combination as such.++  14. Revised Versions of this License.++  The Free Software Foundation may publish revised and/or new versions of+the GNU General Public License from time to time.  Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++  Each version is given a distinguishing version number.  If the+Program specifies that a certain numbered version of the GNU General+Public License "or any later version" applies to it, you have the+option of following the terms and conditions either of that numbered+version or of any later version published by the Free Software+Foundation.  If the Program does not specify a version number of the+GNU General Public License, you may choose any version ever published+by the Free Software Foundation.++  If the Program specifies that a proxy can decide which future+versions of the GNU General Public License can be used, that proxy's+public statement of acceptance of a version permanently authorizes you+to choose that version for the Program.++  Later license versions may give you additional or different+permissions.  However, no additional obligations are imposed on any+author or copyright holder as a result of your choosing to follow a+later version.++  15. Disclaimer of Warranty.++  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++  16. Limitation of Liability.++  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF+SUCH DAMAGES.++  17. Interpretation of Sections 15 and 16.++  If the disclaimer of warranty and limitation of liability provided+above cannot be given local legal effect according to their terms,+reviewing courts shall apply local law that most closely approximates+an absolute waiver of all civil liability in connection with the+Program, unless a warranty or assumption of liability accompanies a+copy of the Program in return for a fee.++                     END OF TERMS AND CONDITIONS++            How to Apply These Terms to Your New Programs++  If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++  To do so, attach the following notices to the program.  It is safest+to attach them to the start of each source file to most effectively+state the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++    {one line to give the program's name and a brief idea of what it does.}+    Copyright (C) {year}  {name of author}++    This program is free software: you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program.  If not, see <http://www.gnu.org/licenses/>.++Also add information on how to contact you by electronic and paper mail.++  If the program does terminal interaction, make it output a short+notice like this when it starts in an interactive mode:++    {project}  Copyright (C) {year}  {fullname}+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+    This is free software, and you are welcome to redistribute it+    under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License.  Of course, your program's commands+might be different; for a GUI interface, you would use an "about box".++  You should also get your employer (if you work as a programmer) or school,+if any, to sign a "copyright disclaimer" for the program, if necessary.+For more information on this, and how to apply and follow the GNU GPL, see+<http://www.gnu.org/licenses/>.++  The GNU General Public License does not permit incorporating your program+into proprietary programs.  If your program is a subroutine library, you+may consider it more useful to permit linking proprietary applications with+the library.  If this is what you want to do, use the GNU Lesser General+Public License instead of this License.  But first, please read+<http://www.gnu.org/philosophy/why-not-lgpl.html>.+
+ README.md view
@@ -0,0 +1,43 @@+# Harmony+Harmony is a web service specification compiler that generates implementation (server and client) and tests.++## Targets supported+++ Server+  * Node.js (`-sjs`)++ Client (and [Hypothesis](https://github.com/DRMacIver/hypothesis) based tests)+  + Python (`-cpython`)++## Usage++After installing the package (`cabal install`), you will get the `harmony` executable. Afterwards:++    Usage: harmony [OPTION...] input_file+      -c[CLIENTS]     --client[=CLIENTS]         Desired output for the client+      -s[SERVERS]     --server[=SERVERS]         Desired output for the server+      -o[OUTPUT_DIR]  --output_dir[=OUTPUT_DIR]  Output path++Check the [Targets supported](#targets-supported) section to figure out the code related to each target.+## Syntax++The input file should follow the syntax specified in `language_spec/Language.cf`. Example:++    service_name: HouseworkService+    service_version: 1.0.0++    enum Color { RED, BLUE, BLACK }++    struct Task {+       // Primary key+       @PK+       name : String,+       color : Color+    }++    struct Person {+      name: String,+      age: Int,+      tasks: [Task]+    }++    resource Person ("/person")
+ Setup.hs view
@@ -0,0 +1,19 @@+#!/usr/bin/env runhaskell++import Distribution.Simple+import Distribution.Simple.Setup+import Distribution.PackageDescription (HookedBuildInfo, emptyHookedBuildInfo)+import System.Process (system)+import System.Exit (ExitCode (..))+import System.Environment (getArgs)++main = defaultMainWithHooks $ simpleUserHooks { preConf = makeBnfc }++-- Execute bnfc to compile the language specification (see language-spec/Language.cf) before +-- compiling.  +makeBnfc :: Args -> ConfigFlags -> IO HookedBuildInfo+makeBnfc _ _ = do +  bnfcOutput <- system "./make_bnfc.sh"+  case bnfcOutput of+       ExitSuccess -> return emptyHookedBuildInfo+       (ExitFailure code) -> error $ "Error processing the language specification: " ++ show code
+ dist/build/Language/Lex.hs view
@@ -0,0 +1,384 @@+{-# LANGUAGE CPP,MagicHash #-}+{-# LINE 3 "src/Language/Lex.x" #-}++{-# OPTIONS -fno-warn-incomplete-patterns #-}+{-# OPTIONS_GHC -w #-}+module Language.Lex where++++import qualified Data.Bits+import Data.Word (Word8)++#if __GLASGOW_HASKELL__ >= 603+#include "ghcconfig.h"+#elif defined(__GLASGOW_HASKELL__)+#include "config.h"+#endif+#if __GLASGOW_HASKELL__ >= 503+import Data.Array+import Data.Char (ord)+import Data.Array.Base (unsafeAt)+#else+import Array+import Char (ord)+#endif+#if __GLASGOW_HASKELL__ >= 503+import GHC.Exts+#else+import GlaExts+#endif+alex_base :: AlexAddr+alex_base = AlexA# "\xf8\xff\xff\xff\x5b\x00\x00\x00\xac\x00\x00\x00\x2c\x01\x00\x00\xac\x01\x00\x00\xd8\xff\xff\xff\xd7\xff\xff\xff\xac\x02\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x9d\x02\x00\x00\xe3\xff\xff\xff\x73\x03\x00\x00\x00\x00\x00\x00\xdf\x02\x00\x00\xf3\x03\x00\x00\x33\x04\x00\x00\x46\x00\x00\x00\xf3\x04\x00\x00\xb3\x04\x00\x00\x00\x00\x00\x00\xa9\x05\x00\x00\x00\x00\x00\x00\x77\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x06\x00\x00\xcb\x06\x00\x00"#++alex_table :: AlexAddr+alex_table = AlexA# "\x00\x00\x17\x00\x17\x00\x17\x00\x17\x00\x17\x00\x06\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x18\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x18\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x18\x00\x00\x00\x18\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x17\x00\x17\x00\x17\x00\x17\x00\x17\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\x00\x08\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x12\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x03\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\x00\x08\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x12\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x13\x00\x03\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0e\x00\x04\x00\x09\x00\x09\x00\x09\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x10\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#++alex_check :: AlexAddr+alex_check = AlexA# "\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x2e\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x2e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x22\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x28\x00\x29\x00\xff\xff\xff\xff\x2c\x00\xff\xff\xff\xff\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\xff\xff\x5d\x00\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\xff\xff\x7d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x2a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc3\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x2a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2f\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\xff\xff\xff\xff\xc3\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x27\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\x3b\x00\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x5f\x00\x60\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x2a\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\xff\xff\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xff\xff\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\xff\xff\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xff\xff\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x27\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\x3b\x00\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x5f\x00\x60\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xc3\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc3\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#++alex_deflt :: AlexAddr+alex_deflt = AlexA# "\xff\xff\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\xff\xff\x0c\x00\x0c\x00\x0d\x00\x0d\x00\xff\xff\x0c\x00\x14\x00\x14\x00\xff\xff\xff\xff\xff\xff\x15\x00\x15\x00\x15\x00\x15\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#++alex_accept = listArray (0::Int,27) [AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccSkip,AlexAccSkip,AlexAccSkip,AlexAcc (alex_action_3),AlexAcc (alex_action_4),AlexAcc (alex_action_5),AlexAcc (alex_action_6)]+{-# LINE 40 "src/Language/Lex.x" #-}+++tok :: (Posn -> String -> Token) -> (Posn -> String -> Token)+tok f p s = f p s++share :: String -> String+share = id++data Tok =+   TS !String !Int    -- reserved words and symbols+ | TL !String         -- string literals+ | TI !String         -- integer literals+ | TV !String         -- identifiers+ | TD !String         -- double precision float literals+ | TC !String         -- character literals+ | T_VerIdent !String+ | T_RouteIdent !String++ deriving (Eq,Show,Ord)++data Token =+   PT  Posn Tok+ | Err Posn+  deriving (Eq,Show,Ord)++tokenPos :: [Token] -> String+tokenPos (PT (Pn _ l _) _ :_) = "line " ++ show l+tokenPos (Err (Pn _ l _) :_) = "line " ++ show l+tokenPos _ = "end of file"++tokenPosn :: Token -> Posn+tokenPosn (PT p _) = p+tokenPosn (Err p) = p++tokenLineCol :: Token -> (Int, Int)+tokenLineCol = posLineCol . tokenPosn++posLineCol :: Posn -> (Int, Int)+posLineCol (Pn _ l c) = (l,c)++mkPosToken :: Token -> ((Int, Int), String)+mkPosToken t@(PT p _) = (posLineCol p, prToken t)++prToken :: Token -> String+prToken t = case t of+  PT _ (TS s _) -> s+  PT _ (TL s)   -> s+  PT _ (TI s)   -> s+  PT _ (TV s)   -> s+  PT _ (TD s)   -> s+  PT _ (TC s)   -> s+  PT _ (T_VerIdent s) -> s+  PT _ (T_RouteIdent s) -> s+++data BTree = N | B String Tok BTree BTree deriving (Show)++eitherResIdent :: (String -> Tok) -> String -> Tok+eitherResIdent tv s = treeFind resWords+  where+  treeFind N = tv s+  treeFind (B a t left right) | s < a  = treeFind left+                              | s > a  = treeFind right+                              | s == a = t++resWords :: BTree+resWords = b "]" 12 (b "@" 6 (b ")" 3 (b "(" 2 (b "\"" 1 N N) N) (b ":" 5 (b "," 4 N N) N)) (b "Long" 9 (b "Int" 8 (b "Double" 7 N N) N) (b "[" 11 (b "String" 10 N N) N))) (b "service_name" 18 (b "read_only" 15 (b "modules" 14 (b "enum" 13 N N) N) (b "resource" 17 (b "require" 16 N N) N)) (b "{" 21 (b "struct" 20 (b "service_version" 19 N N) N) (b "}" 22 N N)))+   where b s n = let bs = id s+                  in B bs (TS bs n)++unescapeInitTail :: String -> String+unescapeInitTail = id . unesc . tail . id where+  unesc s = case s of+    '\\':c:cs | elem c ['\"', '\\', '\''] -> c : unesc cs+    '\\':'n':cs  -> '\n' : unesc cs+    '\\':'t':cs  -> '\t' : unesc cs+    '"':[]    -> []+    c:cs      -> c : unesc cs+    _         -> []++-------------------------------------------------------------------+-- Alex wrapper code.+-- A modified "posn" wrapper.+-------------------------------------------------------------------++data Posn = Pn !Int !Int !Int+      deriving (Eq, Show,Ord)++alexStartPos :: Posn+alexStartPos = Pn 0 1 1++alexMove :: Posn -> Char -> Posn+alexMove (Pn a l c) '\t' = Pn (a+1)  l     (((c+7) `div` 8)*8+1)+alexMove (Pn a l c) '\n' = Pn (a+1) (l+1)   1+alexMove (Pn a l c) _    = Pn (a+1)  l     (c+1)++type Byte = Word8++type AlexInput = (Posn,     -- current position,+                  Char,     -- previous char+                  [Byte],   -- pending bytes on the current char+                  String)   -- current input string++tokens :: String -> [Token]+tokens str = go (alexStartPos, '\n', [], str)+    where+      go :: AlexInput -> [Token]+      go inp@(pos, _, _, str) =+               case alexScan inp 0 of+                AlexEOF                   -> []+                AlexError (pos, _, _, _)  -> [Err pos]+                AlexSkip  inp' len        -> go inp'+                AlexToken inp' len act    -> act pos (take len str) : (go inp')++alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)+alexGetByte (p, c, (b:bs), s) = Just (b, (p, c, bs, s))+alexGetByte (p, _, [], s) =+  case  s of+    []  -> Nothing+    (c:s) ->+             let p'     = alexMove p c+                 (b:bs) = utf8Encode c+              in p' `seq` Just (b, (p', c, bs, s))++alexInputPrevChar :: AlexInput -> Char+alexInputPrevChar (p, c, bs, s) = c++-- | Encode a Haskell String to a list of Word8 values, in UTF8 format.+utf8Encode :: Char -> [Word8]+utf8Encode = map fromIntegral . go . ord+ where+  go oc+   | oc <= 0x7f       = [oc]++   | oc <= 0x7ff      = [ 0xc0 + (oc `Data.Bits.shiftR` 6)+                        , 0x80 + oc Data.Bits..&. 0x3f+                        ]++   | oc <= 0xffff     = [ 0xe0 + (oc `Data.Bits.shiftR` 12)+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)+                        , 0x80 + oc Data.Bits..&. 0x3f+                        ]+   | otherwise        = [ 0xf0 + (oc `Data.Bits.shiftR` 18)+                        , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)+                        , 0x80 + oc Data.Bits..&. 0x3f+                        ]++alex_action_3 =  tok (\p s -> PT p (eitherResIdent (TV . share) s)) +alex_action_4 =  tok (\p s -> PT p (eitherResIdent (T_VerIdent . share) s)) +alex_action_5 =  tok (\p s -> PT p (eitherResIdent (T_RouteIdent . share) s)) +alex_action_6 =  tok (\p s -> PT p (eitherResIdent (TV . share) s)) +{-# LINE 1 "templates/GenericTemplate.hs" #-}+{-# LINE 1 "templates/GenericTemplate.hs" #-}+{-# LINE 1 "<built-in>" #-}+{-# LINE 1 "templates/GenericTemplate.hs" #-}+-- -----------------------------------------------------------------------------+-- ALEX TEMPLATE+--+-- This code is in the PUBLIC DOMAIN; you may copy it freely and use+-- it for any purpose whatsoever.++-- -----------------------------------------------------------------------------+-- INTERNALS and main scanner engine+++{-# LINE 21 "templates/GenericTemplate.hs" #-}++++++-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.+#if __GLASGOW_HASKELL__ > 706+#define GTE(n,m) (tagToEnum# (n >=# m))+#define EQ(n,m) (tagToEnum# (n ==# m))+#else+#define GTE(n,m) (n >=# m)+#define EQ(n,m) (n ==# m)+#endif++{-# LINE 51 "templates/GenericTemplate.hs" #-}+++data AlexAddr = AlexA# Addr#+-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.+#if __GLASGOW_HASKELL__ < 503+uncheckedShiftL# = shiftL#+#endif++{-# INLINE alexIndexInt16OffAddr #-}+alexIndexInt16OffAddr (AlexA# arr) off =+#ifdef WORDS_BIGENDIAN+  narrow16Int# i+  where+        i    = word2Int# ((high `uncheckedShiftL#` 8#) `or#` low)+        high = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))+        low  = int2Word# (ord# (indexCharOffAddr# arr off'))+        off' = off *# 2#+#else+  indexInt16OffAddr# arr off+#endif++++++{-# INLINE alexIndexInt32OffAddr #-}+alexIndexInt32OffAddr (AlexA# arr) off = +#ifdef WORDS_BIGENDIAN+  narrow32Int# i+  where+   i    = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#`+		     (b2 `uncheckedShiftL#` 16#) `or#`+		     (b1 `uncheckedShiftL#` 8#) `or#` b0)+   b3   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#)))+   b2   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#)))+   b1   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))+   b0   = int2Word# (ord# (indexCharOffAddr# arr off'))+   off' = off *# 4#+#else+  indexInt32OffAddr# arr off+#endif+++++++#if __GLASGOW_HASKELL__ < 503+quickIndex arr i = arr ! i+#else+-- GHC >= 503, unsafeAt is available from Data.Array.Base.+quickIndex = unsafeAt+#endif+++++-- -----------------------------------------------------------------------------+-- Main lexing routines++data AlexReturn a+  = AlexEOF+  | AlexError  !AlexInput+  | AlexSkip   !AlexInput !Int+  | AlexToken  !AlexInput !Int a++-- alexScan :: AlexInput -> StartCode -> AlexReturn a+alexScan input (I# (sc))+  = alexScanUser undefined input (I# (sc))++alexScanUser user input (I# (sc))+  = case alex_scan_tkn user input 0# input sc AlexNone of+	(AlexNone, input') ->+		case alexGetByte input of+			Nothing -> ++++				   AlexEOF+			Just _ ->++++				   AlexError input'++	(AlexLastSkip input'' len, _) ->++++		AlexSkip input'' len++	(AlexLastAcc k input''' len, _) ->++++		AlexToken input''' len k+++-- Push the input through the DFA, remembering the most recent accepting+-- state it encountered.++alex_scan_tkn user orig_input len input s last_acc =+  input `seq` -- strict in the input+  let +	new_acc = (check_accs (alex_accept `quickIndex` (I# (s))))+  in+  new_acc `seq`+  case alexGetByte input of+     Nothing -> (new_acc, input)+     Just (c, new_input) -> ++++      case fromIntegral c of { (I# (ord_c)) ->+        let+                base   = alexIndexInt32OffAddr alex_base s+                offset = (base +# ord_c)+                check  = alexIndexInt16OffAddr alex_check offset+		+                new_s = if GTE(offset,0#) && EQ(check,ord_c)+			  then alexIndexInt16OffAddr alex_table offset+			  else alexIndexInt16OffAddr alex_deflt s+	in+        case new_s of+	    -1# -> (new_acc, input)+		-- on an error, we want to keep the input *before* the+		-- character that failed, not after.+    	    _ -> alex_scan_tkn user orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len)+                                                -- note that the length is increased ONLY if this is the 1st byte in a char encoding)+			new_input new_s new_acc+      }+  where+	check_accs (AlexAccNone) = last_acc+	check_accs (AlexAcc a  ) = AlexLastAcc a input (I# (len))+	check_accs (AlexAccSkip) = AlexLastSkip  input (I# (len))++{-# LINE 198 "templates/GenericTemplate.hs" #-}++data AlexLastAcc a+  = AlexNone+  | AlexLastAcc a !AlexInput !Int+  | AlexLastSkip  !AlexInput !Int++instance Functor AlexLastAcc where+    fmap f AlexNone = AlexNone+    fmap f (AlexLastAcc x y z) = AlexLastAcc (f x) y z+    fmap f (AlexLastSkip x y) = AlexLastSkip x y++data AlexAcc a user+  = AlexAccNone+  | AlexAcc a+  | AlexAccSkip++{-# LINE 242 "templates/GenericTemplate.hs" #-}++-- used by wrappers+iUnbox (I# (i)) = i+
+ dist/build/Language/Par.hs view
@@ -0,0 +1,931 @@+{-# OPTIONS_GHC -w #-}+{-# OPTIONS -fglasgow-exts -cpp #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-overlapping-patterns #-}+module Language.Par where+import Language.Abs+import Language.Lex+import Language.ErrM+import qualified Data.Array as Happy_Data_Array+import qualified GHC.Exts as Happy_GHC_Exts+import Control.Applicative(Applicative(..))+import Control.Monad (ap)++-- parser produced by Happy Version 1.19.5++newtype HappyAbsSyn  = HappyAbsSyn HappyAny+#if __GLASGOW_HASKELL__ >= 607+type HappyAny = Happy_GHC_Exts.Any+#else+type HappyAny = forall a . a+#endif+happyIn22 :: (Ident) -> (HappyAbsSyn )+happyIn22 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn22 #-}+happyOut22 :: (HappyAbsSyn ) -> (Ident)+happyOut22 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut22 #-}+happyIn23 :: (VerIdent) -> (HappyAbsSyn )+happyIn23 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn23 #-}+happyOut23 :: (HappyAbsSyn ) -> (VerIdent)+happyOut23 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut23 #-}+happyIn24 :: (RouteIdent) -> (HappyAbsSyn )+happyIn24 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn24 #-}+happyOut24 :: (HappyAbsSyn ) -> (RouteIdent)+happyOut24 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut24 #-}+happyIn25 :: (Specification) -> (HappyAbsSyn )+happyIn25 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn25 #-}+happyOut25 :: (HappyAbsSyn ) -> (Specification)+happyOut25 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut25 #-}+happyIn26 :: (Name) -> (HappyAbsSyn )+happyIn26 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn26 #-}+happyOut26 :: (HappyAbsSyn ) -> (Name)+happyOut26 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut26 #-}+happyIn27 :: (Version) -> (HappyAbsSyn )+happyIn27 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn27 #-}+happyOut27 :: (HappyAbsSyn ) -> (Version)+happyOut27 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut27 #-}+happyIn28 :: (Modules) -> (HappyAbsSyn )+happyIn28 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn28 #-}+happyOut28 :: (HappyAbsSyn ) -> (Modules)+happyOut28 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut28 #-}+happyIn29 :: (EnumType) -> (HappyAbsSyn )+happyIn29 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn29 #-}+happyOut29 :: (HappyAbsSyn ) -> (EnumType)+happyOut29 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut29 #-}+happyIn30 :: (StructType) -> (HappyAbsSyn )+happyIn30 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn30 #-}+happyOut30 :: (HappyAbsSyn ) -> (StructType)+happyOut30 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut30 #-}+happyIn31 :: (Resource) -> (HappyAbsSyn )+happyIn31 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn31 #-}+happyOut31 :: (HappyAbsSyn ) -> (Resource)+happyOut31 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut31 #-}+happyIn32 :: (Mode) -> (HappyAbsSyn )+happyIn32 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn32 #-}+happyOut32 :: (HappyAbsSyn ) -> (Mode)+happyOut32 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut32 #-}+happyIn33 :: (Field) -> (HappyAbsSyn )+happyIn33 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn33 #-}+happyOut33 :: (HappyAbsSyn ) -> (Field)+happyOut33 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut33 #-}+happyIn34 :: (FType) -> (HappyAbsSyn )+happyIn34 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn34 #-}+happyOut34 :: (HappyAbsSyn ) -> (FType)+happyOut34 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut34 #-}+happyIn35 :: (Annotation) -> (HappyAbsSyn )+happyIn35 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn35 #-}+happyOut35 :: (HappyAbsSyn ) -> (Annotation)+happyOut35 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut35 #-}+happyIn36 :: (EnumVal) -> (HappyAbsSyn )+happyIn36 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn36 #-}+happyOut36 :: (HappyAbsSyn ) -> (EnumVal)+happyOut36 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut36 #-}+happyIn37 :: ([EnumType]) -> (HappyAbsSyn )+happyIn37 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn37 #-}+happyOut37 :: (HappyAbsSyn ) -> ([EnumType])+happyOut37 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut37 #-}+happyIn38 :: ([Field]) -> (HappyAbsSyn )+happyIn38 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn38 #-}+happyOut38 :: (HappyAbsSyn ) -> ([Field])+happyOut38 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut38 #-}+happyIn39 :: ([StructType]) -> (HappyAbsSyn )+happyIn39 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn39 #-}+happyOut39 :: (HappyAbsSyn ) -> ([StructType])+happyOut39 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut39 #-}+happyIn40 :: ([Resource]) -> (HappyAbsSyn )+happyIn40 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn40 #-}+happyOut40 :: (HappyAbsSyn ) -> ([Resource])+happyOut40 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut40 #-}+happyIn41 :: ([EnumVal]) -> (HappyAbsSyn )+happyIn41 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn41 #-}+happyOut41 :: (HappyAbsSyn ) -> ([EnumVal])+happyOut41 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut41 #-}+happyIn42 :: ([Annotation]) -> (HappyAbsSyn )+happyIn42 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn42 #-}+happyOut42 :: (HappyAbsSyn ) -> ([Annotation])+happyOut42 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut42 #-}+happyIn43 :: ([Ident]) -> (HappyAbsSyn )+happyIn43 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyIn43 #-}+happyOut43 :: (HappyAbsSyn ) -> ([Ident])+happyOut43 x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOut43 #-}+happyInTok :: (Token) -> (HappyAbsSyn )+happyInTok x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyInTok #-}+happyOutTok :: (HappyAbsSyn ) -> (Token)+happyOutTok x = Happy_GHC_Exts.unsafeCoerce# x+{-# INLINE happyOutTok #-}+++happyActOffsets :: HappyAddr+happyActOffsets = HappyA# "\x86\x00\x86\x00\x87\x00\x89\x00\x8a\x00\x81\x00\x85\x00\x84\x00\x00\x00\x08\x00\x88\x00\x7d\x00\x00\x00\x00\x00\x7b\x00\x7c\x00\x7a\x00\x00\x00\x7a\x00\x7a\x00\x00\x00\x7a\x00\x78\x00\xff\xff\x00\x00\x77\x00\x76\x00\x74\x00\x72\x00\x73\x00\x75\x00\x71\x00\x70\x00\x6f\x00\x6e\x00\x06\x00\x16\x00\x6e\x00\x6e\x00\x6d\x00\x00\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x6c\x00\x6c\x00\x00\x00\x6c\x00\x6c\x00\x6c\x00\x6b\x00\x69\x00\x6a\x00\x66\x00\x68\x00\x65\x00\x67\x00\x44\x00\x64\x00\x62\x00\x63\x00\x61\x00\x60\x00\x5f\x00\x5a\x00\x00\x00\x00\x00\x5d\x00\x00\x00\x00\x00\x5b\x00\x00\x00\x5e\x00\x00\x00\x58\x00\x00\x00\x00\x00\x5c\x00\x00\x00\x00\x00\x08\x00\x00\x00\x57\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf7\xff\x55\x00\x54\x00\x00\x00\x46\x00\x42\x00\x59\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\x00\x00\x00\x56\x00\x50\x00\x00\x00\x00\x00"#++happyGotoOffsets :: HappyAddr+happyGotoOffsets = HappyA# "\x05\x00\x4f\x00\x53\x00\x51\x00\x4d\x00\x4e\x00\x4c\x00\x48\x00\x3d\x00\x27\x00\x43\x00\x14\x00\x3f\x00\x2c\x00\x3c\x00\x3a\x00\x0e\x00\x3b\x00\x03\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x34\x00\x00\x00\x4b\x00\x31\x00\x00\x00\x4a\x00\x00\x00\x00\x00\x1e\x00\x33\x00\x00\x00\x00\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x26\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x29\x00\x22\x00\x45\x00\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x25\x00\x00\x00\x07\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfb\xff\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x00\x00\x00\x00\xfc\xff\x00\x00\x00\x00"#++happyDefActions :: HappyAddr+happyDefActions = HappyA# "\x00\x00\x00\x00\x00\x00\xe6\xff\x00\x00\x00\x00\x00\x00\xe0\xff\xcc\xff\x00\x00\x00\x00\x00\x00\xd6\xff\xcc\xff\x00\x00\x00\x00\x00\x00\xcc\xff\x00\x00\x00\x00\xec\xff\xca\xff\x00\x00\x00\x00\xd7\xff\xce\xff\x00\x00\xd0\xff\x00\x00\x00\x00\xd2\xff\x00\x00\x00\x00\xd4\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xda\xff\x00\x00\xdb\xff\xdd\xff\xdc\xff\xde\xff\x00\x00\x00\x00\x00\x00\xe1\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe6\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd8\xff\xd5\xff\x00\x00\xcb\xff\xcc\xff\x00\x00\xd1\xff\x00\x00\xcf\xff\x00\x00\xc9\xff\xcd\xff\x00\x00\xcc\xff\xd3\xff\x00\x00\xd9\xff\x00\x00\x00\x00\xe7\xff\xeb\xff\xe8\xff\xd6\xff\x00\x00\x00\x00\x00\x00\xdf\xff\x00\x00\x00\x00\x00\x00\xea\xff\xe3\xff\xe4\xff\xe5\xff\x00\x00\xe9\xff\x00\x00\xe0\xff\xe2\xff"#++happyCheck :: HappyAddr+happyCheck = HappyA# "\xff\xff\x00\x00\x00\x00\x00\x00\x0d\x00\x06\x00\x0a\x00\x00\x00\x03\x00\x04\x00\x0f\x00\x14\x00\x06\x00\x00\x00\x00\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x00\x00\x0e\x00\x15\x00\x15\x00\x15\x00\x1a\x00\x13\x00\x0e\x00\x0e\x00\x17\x00\x00\x00\x17\x00\x13\x00\x13\x00\x0e\x00\x0d\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x06\x00\x10\x00\x02\x00\x0d\x00\x0d\x00\x14\x00\x05\x00\x01\x00\x1a\x00\x0c\x00\x0c\x00\x0c\x00\x07\x00\x08\x00\x0b\x00\x0b\x00\x09\x00\x08\x00\x07\x00\x10\x00\x10\x00\x09\x00\x11\x00\x14\x00\x14\x00\x12\x00\x11\x00\x09\x00\x08\x00\x00\x00\x12\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x12\x00\x11\x00\x0f\x00\x14\x00\x0d\x00\x14\x00\x0a\x00\x04\x00\x07\x00\x09\x00\x08\x00\x06\x00\x05\x00\x03\x00\x01\x00\x19\x00\x16\x00\x01\x00\x1a\x00\x0f\x00\x02\x00\x0c\x00\x05\x00\x11\x00\xff\xff\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\x16\x00\x0b\x00\x05\x00\x05\x00\x17\x00\x17\x00\x15\x00\xff\xff\x10\x00\x04\x00\x15\x00\xff\xff\xff\xff\x13\x00\x0e\x00\x18\x00\x17\x00\x04\x00\xff\xff\xff\xff\xff\xff\x1a\x00\x1a\x00\xff\xff\x17\x00\x1a\x00\x17\x00\x11\x00\x1a\x00\x17\x00\x1a\x00\x14\x00\x17\x00\x1a\x00\x1a\x00\x11\x00\x06\x00\x14\x00\x1a\x00\x17\x00\x1a\x00\x0f\x00\x17\x00\x14\x00\x11\x00\x0d\x00\x12\x00\x10\x00\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#++happyTable :: HappyAddr+happyTable = HappyA# "\x00\x00\x15\x00\x15\x00\x15\x00\x36\x00\x28\x00\x6a\x00\x18\x00\x3c\x00\x3d\x00\x5b\x00\x21\x00\x28\x00\x18\x00\x18\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x18\x00\x19\x00\x5c\x00\x4e\x00\x16\x00\xff\xff\x5d\x00\x19\x00\x19\x00\x15\x00\x46\x00\x15\x00\x4f\x00\x1a\x00\x25\x00\x36\x00\x21\x00\x28\x00\x28\x00\x28\x00\x5a\x00\x5f\x00\x61\x00\x47\x00\x47\x00\x23\x00\x3e\x00\x57\x00\xff\xff\x5e\x00\x43\x00\x29\x00\x45\x00\x1e\x00\x21\x00\x21\x00\x1b\x00\x1e\x00\x45\x00\x52\x00\x22\x00\x1b\x00\x66\x00\x23\x00\x23\x00\x67\x00\x4a\x00\x1b\x00\x1e\x00\x59\x00\x4c\x00\x42\x00\x2f\x00\x44\x00\x49\x00\x4b\x00\x1c\x00\x1f\x00\x24\x00\x17\x00\x26\x00\x23\x00\x30\x00\x3a\x00\x34\x00\x32\x00\x33\x00\x36\x00\x38\x00\x6a\x00\x69\x00\x63\x00\x64\x00\x61\x00\xff\xff\x32\x00\x51\x00\x66\x00\x54\x00\x1e\x00\x00\x00\x00\x00\x55\x00\x00\x00\x00\x00\x00\x00\x65\x00\x57\x00\x40\x00\x41\x00\x15\x00\x15\x00\x52\x00\x00\x00\x38\x00\x49\x00\x56\x00\x00\x00\x00\x00\x3a\x00\x42\x00\x59\x00\x15\x00\x4e\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x15\x00\xff\xff\x15\x00\x1e\x00\xff\xff\x15\x00\xff\xff\x21\x00\x15\x00\xff\xff\xff\xff\x1e\x00\x28\x00\x21\x00\xff\xff\x15\x00\xff\xff\x32\x00\x15\x00\x21\x00\x1e\x00\x36\x00\x3c\x00\x38\x00\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#++happyReduceArr = Happy_Data_Array.array (19, 54) [+	(19 , happyReduce_19),+	(20 , happyReduce_20),+	(21 , happyReduce_21),+	(22 , happyReduce_22),+	(23 , happyReduce_23),+	(24 , happyReduce_24),+	(25 , happyReduce_25),+	(26 , happyReduce_26),+	(27 , happyReduce_27),+	(28 , happyReduce_28),+	(29 , happyReduce_29),+	(30 , happyReduce_30),+	(31 , happyReduce_31),+	(32 , happyReduce_32),+	(33 , happyReduce_33),+	(34 , happyReduce_34),+	(35 , happyReduce_35),+	(36 , happyReduce_36),+	(37 , happyReduce_37),+	(38 , happyReduce_38),+	(39 , happyReduce_39),+	(40 , happyReduce_40),+	(41 , happyReduce_41),+	(42 , happyReduce_42),+	(43 , happyReduce_43),+	(44 , happyReduce_44),+	(45 , happyReduce_45),+	(46 , happyReduce_46),+	(47 , happyReduce_47),+	(48 , happyReduce_48),+	(49 , happyReduce_49),+	(50 , happyReduce_50),+	(51 , happyReduce_51),+	(52 , happyReduce_52),+	(53 , happyReduce_53),+	(54 , happyReduce_54)+	]++happy_n_terms = 27 :: Int+happy_n_nonterms = 22 :: Int++happyReduce_19 = happySpecReduce_1  0# happyReduction_19+happyReduction_19 happy_x_1+	 =  case happyOutTok happy_x_1 of { (PT _ (TV happy_var_1)) -> +	happyIn22+		 (Ident happy_var_1+	)}++happyReduce_20 = happySpecReduce_1  1# happyReduction_20+happyReduction_20 happy_x_1+	 =  case happyOutTok happy_x_1 of { (PT _ (T_VerIdent happy_var_1)) -> +	happyIn23+		 (VerIdent (happy_var_1)+	)}++happyReduce_21 = happySpecReduce_1  2# happyReduction_21+happyReduction_21 happy_x_1+	 =  case happyOutTok happy_x_1 of { (PT _ (T_RouteIdent happy_var_1)) -> +	happyIn24+		 (RouteIdent (happy_var_1)+	)}++happyReduce_22 = happyReduce 6# 3# happyReduction_22+happyReduction_22 (happy_x_6 `HappyStk`+	happy_x_5 `HappyStk`+	happy_x_4 `HappyStk`+	happy_x_3 `HappyStk`+	happy_x_2 `HappyStk`+	happy_x_1 `HappyStk`+	happyRest)+	 = case happyOut26 happy_x_1 of { happy_var_1 -> +	case happyOut27 happy_x_2 of { happy_var_2 -> +	case happyOut28 happy_x_3 of { happy_var_3 -> +	case happyOut37 happy_x_4 of { happy_var_4 -> +	case happyOut39 happy_x_5 of { happy_var_5 -> +	case happyOut40 happy_x_6 of { happy_var_6 -> +	happyIn25+		 (Spec happy_var_1 happy_var_2 happy_var_3 (reverse happy_var_4) happy_var_5 happy_var_6+	) `HappyStk` happyRest}}}}}}++happyReduce_23 = happySpecReduce_3  4# happyReduction_23+happyReduction_23 happy_x_3+	happy_x_2+	happy_x_1+	 =  case happyOut22 happy_x_3 of { happy_var_3 -> +	happyIn26+		 (Nm happy_var_3+	)}++happyReduce_24 = happySpecReduce_3  5# happyReduction_24+happyReduction_24 happy_x_3+	happy_x_2+	happy_x_1+	 =  case happyOut23 happy_x_3 of { happy_var_3 -> +	happyIn27+		 (Ver happy_var_3+	)}++happyReduce_25 = happySpecReduce_0  6# happyReduction_25+happyReduction_25  =  happyIn28+		 (EmptyMods+	)++happyReduce_26 = happyReduce 5# 6# happyReduction_26+happyReduction_26 (happy_x_5 `HappyStk`+	happy_x_4 `HappyStk`+	happy_x_3 `HappyStk`+	happy_x_2 `HappyStk`+	happy_x_1 `HappyStk`+	happyRest)+	 = case happyOut43 happy_x_4 of { happy_var_4 -> +	happyIn28+		 (Mods happy_var_4+	) `HappyStk` happyRest}++happyReduce_27 = happyReduce 5# 7# happyReduction_27+happyReduction_27 (happy_x_5 `HappyStk`+	happy_x_4 `HappyStk`+	happy_x_3 `HappyStk`+	happy_x_2 `HappyStk`+	happy_x_1 `HappyStk`+	happyRest)+	 = case happyOut22 happy_x_2 of { happy_var_2 -> +	case happyOut41 happy_x_4 of { happy_var_4 -> +	happyIn29+		 (DefEnum happy_var_2 happy_var_4+	) `HappyStk` happyRest}}++happyReduce_28 = happyReduce 5# 8# happyReduction_28+happyReduction_28 (happy_x_5 `HappyStk`+	happy_x_4 `HappyStk`+	happy_x_3 `HappyStk`+	happy_x_2 `HappyStk`+	happy_x_1 `HappyStk`+	happyRest)+	 = case happyOut22 happy_x_2 of { happy_var_2 -> +	case happyOut38 happy_x_4 of { happy_var_4 -> +	happyIn30+		 (DefStr happy_var_2 happy_var_4+	) `HappyStk` happyRest}}++happyReduce_29 = happyReduce 8# 9# happyReduction_29+happyReduction_29 (happy_x_8 `HappyStk`+	happy_x_7 `HappyStk`+	happy_x_6 `HappyStk`+	happy_x_5 `HappyStk`+	happy_x_4 `HappyStk`+	happy_x_3 `HappyStk`+	happy_x_2 `HappyStk`+	happy_x_1 `HappyStk`+	happyRest)+	 = case happyOut22 happy_x_2 of { happy_var_2 -> +	case happyOut24 happy_x_5 of { happy_var_5 -> +	case happyOut32 happy_x_8 of { happy_var_8 -> +	happyIn31+		 (Res happy_var_2 happy_var_5 happy_var_8+	) `HappyStk` happyRest}}}++happyReduce_30 = happySpecReduce_1  10# happyReduction_30+happyReduction_30 happy_x_1+	 =  happyIn32+		 (ReadOnly+	)++happyReduce_31 = happySpecReduce_0  10# happyReduction_31+happyReduction_31  =  happyIn32+		 (Write+	)++happyReduce_32 = happyReduce 4# 11# happyReduction_32+happyReduction_32 (happy_x_4 `HappyStk`+	happy_x_3 `HappyStk`+	happy_x_2 `HappyStk`+	happy_x_1 `HappyStk`+	happyRest)+	 = case happyOut42 happy_x_1 of { happy_var_1 -> +	case happyOut22 happy_x_2 of { happy_var_2 -> +	case happyOut34 happy_x_4 of { happy_var_4 -> +	happyIn33+		 (FDef (reverse happy_var_1) happy_var_2 happy_var_4+	) `HappyStk` happyRest}}}++happyReduce_33 = happySpecReduce_1  12# happyReduction_33+happyReduction_33 happy_x_1+	 =  happyIn34+		 (FString+	)++happyReduce_34 = happySpecReduce_1  12# happyReduction_34+happyReduction_34 happy_x_1+	 =  happyIn34+		 (FInt+	)++happyReduce_35 = happySpecReduce_1  12# happyReduction_35+happyReduction_35 happy_x_1+	 =  happyIn34+		 (FLong+	)++happyReduce_36 = happySpecReduce_1  12# happyReduction_36+happyReduction_36 happy_x_1+	 =  happyIn34+		 (FDouble+	)++happyReduce_37 = happySpecReduce_1  12# happyReduction_37+happyReduction_37 happy_x_1+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> +	happyIn34+		 (FDefined happy_var_1+	)}++happyReduce_38 = happySpecReduce_3  12# happyReduction_38+happyReduction_38 happy_x_3+	happy_x_2+	happy_x_1+	 =  case happyOut34 happy_x_2 of { happy_var_2 -> +	happyIn34+		 (FList happy_var_2+	)}++happyReduce_39 = happySpecReduce_2  13# happyReduction_39+happyReduction_39 happy_x_2+	happy_x_1+	 =  case happyOut22 happy_x_2 of { happy_var_2 -> +	happyIn35+		 (Ann happy_var_2+	)}++happyReduce_40 = happySpecReduce_1  14# happyReduction_40+happyReduction_40 happy_x_1+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> +	happyIn36+		 (EnVal happy_var_1+	)}++happyReduce_41 = happySpecReduce_0  15# happyReduction_41+happyReduction_41  =  happyIn37+		 ([]+	)++happyReduce_42 = happySpecReduce_2  15# happyReduction_42+happyReduction_42 happy_x_2+	happy_x_1+	 =  case happyOut37 happy_x_1 of { happy_var_1 -> +	case happyOut29 happy_x_2 of { happy_var_2 -> +	happyIn37+		 (flip (:) happy_var_1 happy_var_2+	)}}++happyReduce_43 = happySpecReduce_1  16# happyReduction_43+happyReduction_43 happy_x_1+	 =  case happyOut33 happy_x_1 of { happy_var_1 -> +	happyIn38+		 ((:[]) happy_var_1+	)}++happyReduce_44 = happySpecReduce_3  16# happyReduction_44+happyReduction_44 happy_x_3+	happy_x_2+	happy_x_1+	 =  case happyOut33 happy_x_1 of { happy_var_1 -> +	case happyOut38 happy_x_3 of { happy_var_3 -> +	happyIn38+		 ((:) happy_var_1 happy_var_3+	)}}++happyReduce_45 = happySpecReduce_1  17# happyReduction_45+happyReduction_45 happy_x_1+	 =  case happyOut30 happy_x_1 of { happy_var_1 -> +	happyIn39+		 ((:[]) happy_var_1+	)}++happyReduce_46 = happySpecReduce_2  17# happyReduction_46+happyReduction_46 happy_x_2+	happy_x_1+	 =  case happyOut30 happy_x_1 of { happy_var_1 -> +	case happyOut39 happy_x_2 of { happy_var_2 -> +	happyIn39+		 ((:) happy_var_1 happy_var_2+	)}}++happyReduce_47 = happySpecReduce_1  18# happyReduction_47+happyReduction_47 happy_x_1+	 =  case happyOut31 happy_x_1 of { happy_var_1 -> +	happyIn40+		 ((:[]) happy_var_1+	)}++happyReduce_48 = happySpecReduce_2  18# happyReduction_48+happyReduction_48 happy_x_2+	happy_x_1+	 =  case happyOut31 happy_x_1 of { happy_var_1 -> +	case happyOut40 happy_x_2 of { happy_var_2 -> +	happyIn40+		 ((:) happy_var_1 happy_var_2+	)}}++happyReduce_49 = happySpecReduce_1  19# happyReduction_49+happyReduction_49 happy_x_1+	 =  case happyOut36 happy_x_1 of { happy_var_1 -> +	happyIn41+		 ((:[]) happy_var_1+	)}++happyReduce_50 = happySpecReduce_3  19# happyReduction_50+happyReduction_50 happy_x_3+	happy_x_2+	happy_x_1+	 =  case happyOut36 happy_x_1 of { happy_var_1 -> +	case happyOut41 happy_x_3 of { happy_var_3 -> +	happyIn41+		 ((:) happy_var_1 happy_var_3+	)}}++happyReduce_51 = happySpecReduce_0  20# happyReduction_51+happyReduction_51  =  happyIn42+		 ([]+	)++happyReduce_52 = happySpecReduce_2  20# happyReduction_52+happyReduction_52 happy_x_2+	happy_x_1+	 =  case happyOut42 happy_x_1 of { happy_var_1 -> +	case happyOut35 happy_x_2 of { happy_var_2 -> +	happyIn42+		 (flip (:) happy_var_1 happy_var_2+	)}}++happyReduce_53 = happySpecReduce_1  21# happyReduction_53+happyReduction_53 happy_x_1+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> +	happyIn43+		 ((:[]) happy_var_1+	)}++happyReduce_54 = happySpecReduce_2  21# happyReduction_54+happyReduction_54 happy_x_2+	happy_x_1+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> +	case happyOut43 happy_x_2 of { happy_var_2 -> +	happyIn43+		 ((:) happy_var_1 happy_var_2+	)}}++happyNewToken action sts stk [] =+	happyDoAction 26# notHappyAtAll action sts stk []++happyNewToken action sts stk (tk:tks) =+	let cont i = happyDoAction i tk action sts stk tks in+	case tk of {+	PT _ (TS _ 1) -> cont 1#;+	PT _ (TS _ 2) -> cont 2#;+	PT _ (TS _ 3) -> cont 3#;+	PT _ (TS _ 4) -> cont 4#;+	PT _ (TS _ 5) -> cont 5#;+	PT _ (TS _ 6) -> cont 6#;+	PT _ (TS _ 7) -> cont 7#;+	PT _ (TS _ 8) -> cont 8#;+	PT _ (TS _ 9) -> cont 9#;+	PT _ (TS _ 10) -> cont 10#;+	PT _ (TS _ 11) -> cont 11#;+	PT _ (TS _ 12) -> cont 12#;+	PT _ (TS _ 13) -> cont 13#;+	PT _ (TS _ 14) -> cont 14#;+	PT _ (TS _ 15) -> cont 15#;+	PT _ (TS _ 16) -> cont 16#;+	PT _ (TS _ 17) -> cont 17#;+	PT _ (TS _ 18) -> cont 18#;+	PT _ (TS _ 19) -> cont 19#;+	PT _ (TS _ 20) -> cont 20#;+	PT _ (TS _ 21) -> cont 21#;+	PT _ (TS _ 22) -> cont 22#;+	PT _ (TV happy_dollar_dollar) -> cont 23#;+	PT _ (T_VerIdent happy_dollar_dollar) -> cont 24#;+	PT _ (T_RouteIdent happy_dollar_dollar) -> cont 25#;+	_ -> happyError' (tk:tks)+	}++happyError_ 26# tk tks = happyError' tks+happyError_ _ tk tks = happyError' (tk:tks)++happyThen :: () => Err a -> (a -> Err b) -> Err b+happyThen = (thenM)+happyReturn :: () => a -> Err a+happyReturn = (returnM)+happyThen1 m k tks = (thenM) m (\a -> k a tks)+happyReturn1 :: () => a -> b -> Err a+happyReturn1 = \a tks -> (returnM) a+happyError' :: () => [(Token)] -> Err a+happyError' = happyError++pSpecification tks = happySomeParser where+  happySomeParser = happyThen (happyParse 0# tks) (\x -> happyReturn (happyOut25 x))++pName tks = happySomeParser where+  happySomeParser = happyThen (happyParse 1# tks) (\x -> happyReturn (happyOut26 x))++pVersion tks = happySomeParser where+  happySomeParser = happyThen (happyParse 2# tks) (\x -> happyReturn (happyOut27 x))++pModules tks = happySomeParser where+  happySomeParser = happyThen (happyParse 3# tks) (\x -> happyReturn (happyOut28 x))++pEnumType tks = happySomeParser where+  happySomeParser = happyThen (happyParse 4# tks) (\x -> happyReturn (happyOut29 x))++pStructType tks = happySomeParser where+  happySomeParser = happyThen (happyParse 5# tks) (\x -> happyReturn (happyOut30 x))++pResource tks = happySomeParser where+  happySomeParser = happyThen (happyParse 6# tks) (\x -> happyReturn (happyOut31 x))++pMode tks = happySomeParser where+  happySomeParser = happyThen (happyParse 7# tks) (\x -> happyReturn (happyOut32 x))++pField tks = happySomeParser where+  happySomeParser = happyThen (happyParse 8# tks) (\x -> happyReturn (happyOut33 x))++pFType tks = happySomeParser where+  happySomeParser = happyThen (happyParse 9# tks) (\x -> happyReturn (happyOut34 x))++pAnnotation tks = happySomeParser where+  happySomeParser = happyThen (happyParse 10# tks) (\x -> happyReturn (happyOut35 x))++pEnumVal tks = happySomeParser where+  happySomeParser = happyThen (happyParse 11# tks) (\x -> happyReturn (happyOut36 x))++pListEnumType tks = happySomeParser where+  happySomeParser = happyThen (happyParse 12# tks) (\x -> happyReturn (happyOut37 x))++pListField tks = happySomeParser where+  happySomeParser = happyThen (happyParse 13# tks) (\x -> happyReturn (happyOut38 x))++pListStructType tks = happySomeParser where+  happySomeParser = happyThen (happyParse 14# tks) (\x -> happyReturn (happyOut39 x))++pListResource tks = happySomeParser where+  happySomeParser = happyThen (happyParse 15# tks) (\x -> happyReturn (happyOut40 x))++pListEnumVal tks = happySomeParser where+  happySomeParser = happyThen (happyParse 16# tks) (\x -> happyReturn (happyOut41 x))++pListAnnotation tks = happySomeParser where+  happySomeParser = happyThen (happyParse 17# tks) (\x -> happyReturn (happyOut42 x))++pListIdent tks = happySomeParser where+  happySomeParser = happyThen (happyParse 18# tks) (\x -> happyReturn (happyOut43 x))++happySeq = happyDontSeq+++returnM :: a -> Err a+returnM = return++thenM :: Err a -> (a -> Err b) -> Err b+thenM = (>>=)++happyError :: [Token] -> Err a+happyError ts =+  Bad $ "syntax error at " ++ tokenPos ts ++ +  case ts of+    [] -> []+    [Err _] -> " due to lexer error"+    _ -> " before " ++ unwords (map (id . prToken) (take 4 ts))++myLexer = tokens+{-# LINE 1 "templates/GenericTemplate.hs" #-}+{-# LINE 1 "templates/GenericTemplate.hs" #-}+{-# LINE 1 "<built-in>" #-}+{-# LINE 1 "templates/GenericTemplate.hs" #-}+-- Id: GenericTemplate.hs,v 1.26 2005/01/14 14:47:22 simonmar Exp +++{-# LINE 13 "templates/GenericTemplate.hs" #-}++++++-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.+#if __GLASGOW_HASKELL__ > 706+#define LT(n,m) ((Happy_GHC_Exts.tagToEnum# (n Happy_GHC_Exts.<# m)) :: Bool)+#define GTE(n,m) ((Happy_GHC_Exts.tagToEnum# (n Happy_GHC_Exts.>=# m)) :: Bool)+#define EQ(n,m) ((Happy_GHC_Exts.tagToEnum# (n Happy_GHC_Exts.==# m)) :: Bool)+#else+#define LT(n,m) (n Happy_GHC_Exts.<# m)+#define GTE(n,m) (n Happy_GHC_Exts.>=# m)+#define EQ(n,m) (n Happy_GHC_Exts.==# m)+#endif++{-# LINE 46 "templates/GenericTemplate.hs" #-}+++data Happy_IntList = HappyCons Happy_GHC_Exts.Int# Happy_IntList+++++++{-# LINE 67 "templates/GenericTemplate.hs" #-}+++{-# LINE 77 "templates/GenericTemplate.hs" #-}+++++++++++infixr 9 `HappyStk`+data HappyStk a = HappyStk a (HappyStk a)++-----------------------------------------------------------------------------+-- starting the parse++happyParse start_state = happyNewToken start_state notHappyAtAll notHappyAtAll++-----------------------------------------------------------------------------+-- Accepting the parse++-- If the current token is 0#, it means we've just accepted a partial+-- parse (a %partial parser).  We must ignore the saved token on the top of+-- the stack in this case.+happyAccept 0# tk st sts (_ `HappyStk` ans `HappyStk` _) =+        happyReturn1 ans+happyAccept j tk st sts (HappyStk ans _) = +        (happyTcHack j (happyTcHack st)) (happyReturn1 ans)++-----------------------------------------------------------------------------+-- Arrays only: do the next action++++happyDoAction i tk st+        = {- nothing -}+          ++          case action of+                0#           -> {- nothing -}+                                     happyFail i tk st+                -1#          -> {- nothing -}+                                     happyAccept i tk st+                n | LT(n,(0# :: Happy_GHC_Exts.Int#)) -> {- nothing -}+                                                   +                                                   (happyReduceArr Happy_Data_Array.! rule) i tk st+                                                   where rule = (Happy_GHC_Exts.I# ((Happy_GHC_Exts.negateInt# ((n Happy_GHC_Exts.+# (1# :: Happy_GHC_Exts.Int#))))))+                n                 -> {- nothing -}+                                     ++                                     happyShift new_state i tk st+                                     where new_state = (n Happy_GHC_Exts.-# (1# :: Happy_GHC_Exts.Int#))+   where off    = indexShortOffAddr happyActOffsets st+         off_i  = (off Happy_GHC_Exts.+# i)+         check  = if GTE(off_i,(0# :: Happy_GHC_Exts.Int#))+                  then EQ(indexShortOffAddr happyCheck off_i, i)+                  else False+         action+          | check     = indexShortOffAddr happyTable off_i+          | otherwise = indexShortOffAddr happyDefActions st+++indexShortOffAddr (HappyA# arr) off =+        Happy_GHC_Exts.narrow16Int# i+  where+        i = Happy_GHC_Exts.word2Int# (Happy_GHC_Exts.or# (Happy_GHC_Exts.uncheckedShiftL# high 8#) low)+        high = Happy_GHC_Exts.int2Word# (Happy_GHC_Exts.ord# (Happy_GHC_Exts.indexCharOffAddr# arr (off' Happy_GHC_Exts.+# 1#)))+        low  = Happy_GHC_Exts.int2Word# (Happy_GHC_Exts.ord# (Happy_GHC_Exts.indexCharOffAddr# arr off'))+        off' = off Happy_GHC_Exts.*# 2#++++++data HappyAddr = HappyA# Happy_GHC_Exts.Addr#+++++-----------------------------------------------------------------------------+-- HappyState data type (not arrays)+++{-# LINE 170 "templates/GenericTemplate.hs" #-}++-----------------------------------------------------------------------------+-- Shifting a token++happyShift new_state 0# tk st sts stk@(x `HappyStk` _) =+     let i = (case Happy_GHC_Exts.unsafeCoerce# x of { (Happy_GHC_Exts.I# (i)) -> i }) in+--     trace "shifting the error token" $+     happyDoAction i tk new_state (HappyCons (st) (sts)) (stk)++happyShift new_state i tk st sts stk =+     happyNewToken new_state (HappyCons (st) (sts)) ((happyInTok (tk))`HappyStk`stk)++-- happyReduce is specialised for the common cases.++happySpecReduce_0 i fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happySpecReduce_0 nt fn j tk st@((action)) sts stk+     = happyGoto nt j tk st (HappyCons (st) (sts)) (fn `HappyStk` stk)++happySpecReduce_1 i fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happySpecReduce_1 nt fn j tk _ sts@((HappyCons (st@(action)) (_))) (v1`HappyStk`stk')+     = let r = fn v1 in+       happySeq r (happyGoto nt j tk st sts (r `HappyStk` stk'))++happySpecReduce_2 i fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happySpecReduce_2 nt fn j tk _ (HappyCons (_) (sts@((HappyCons (st@(action)) (_))))) (v1`HappyStk`v2`HappyStk`stk')+     = let r = fn v1 v2 in+       happySeq r (happyGoto nt j tk st sts (r `HappyStk` stk'))++happySpecReduce_3 i fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happySpecReduce_3 nt fn j tk _ (HappyCons (_) ((HappyCons (_) (sts@((HappyCons (st@(action)) (_))))))) (v1`HappyStk`v2`HappyStk`v3`HappyStk`stk')+     = let r = fn v1 v2 v3 in+       happySeq r (happyGoto nt j tk st sts (r `HappyStk` stk'))++happyReduce k i fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happyReduce k nt fn j tk st sts stk+     = case happyDrop (k Happy_GHC_Exts.-# (1# :: Happy_GHC_Exts.Int#)) sts of+         sts1@((HappyCons (st1@(action)) (_))) ->+                let r = fn stk in  -- it doesn't hurt to always seq here...+                happyDoSeq r (happyGoto nt j tk st1 sts1 r)++happyMonadReduce k nt fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happyMonadReduce k nt fn j tk st sts stk =+      case happyDrop k (HappyCons (st) (sts)) of+        sts1@((HappyCons (st1@(action)) (_))) ->+          let drop_stk = happyDropStk k stk in+          happyThen1 (fn stk tk) (\r -> happyGoto nt j tk st1 sts1 (r `HappyStk` drop_stk))++happyMonad2Reduce k nt fn 0# tk st sts stk+     = happyFail 0# tk st sts stk+happyMonad2Reduce k nt fn j tk st sts stk =+      case happyDrop k (HappyCons (st) (sts)) of+        sts1@((HappyCons (st1@(action)) (_))) ->+         let drop_stk = happyDropStk k stk++             off = indexShortOffAddr happyGotoOffsets st1+             off_i = (off Happy_GHC_Exts.+# nt)+             new_state = indexShortOffAddr happyTable off_i++++          in+          happyThen1 (fn stk tk) (\r -> happyNewToken new_state sts1 (r `HappyStk` drop_stk))++happyDrop 0# l = l+happyDrop n (HappyCons (_) (t)) = happyDrop (n Happy_GHC_Exts.-# (1# :: Happy_GHC_Exts.Int#)) t++happyDropStk 0# l = l+happyDropStk n (x `HappyStk` xs) = happyDropStk (n Happy_GHC_Exts.-# (1#::Happy_GHC_Exts.Int#)) xs++-----------------------------------------------------------------------------+-- Moving to a new state after a reduction+++happyGoto nt j tk st = +   {- nothing -}+   happyDoAction j tk new_state+   where off = indexShortOffAddr happyGotoOffsets st+         off_i = (off Happy_GHC_Exts.+# nt)+         new_state = indexShortOffAddr happyTable off_i+++++-----------------------------------------------------------------------------+-- Error recovery (0# is the error token)++-- parse error if we are in recovery and we fail again+happyFail 0# tk old_st _ stk@(x `HappyStk` _) =+     let i = (case Happy_GHC_Exts.unsafeCoerce# x of { (Happy_GHC_Exts.I# (i)) -> i }) in+--      trace "failing" $ +        happyError_ i tk++{-  We don't need state discarding for our restricted implementation of+    "error".  In fact, it can cause some bogus parses, so I've disabled it+    for now --SDM++-- discard a state+happyFail  0# tk old_st (HappyCons ((action)) (sts)) +                                                (saved_tok `HappyStk` _ `HappyStk` stk) =+--      trace ("discarding state, depth " ++ show (length stk))  $+        happyDoAction 0# tk action sts ((saved_tok`HappyStk`stk))+-}++-- Enter error recovery: generate an error token,+--                       save the old token and carry on.+happyFail  i tk (action) sts stk =+--      trace "entering error recovery" $+        happyDoAction 0# tk action sts ( (Happy_GHC_Exts.unsafeCoerce# (Happy_GHC_Exts.I# (i))) `HappyStk` stk)++-- Internal happy errors:++notHappyAtAll :: a+notHappyAtAll = error "Internal Happy error\n"++-----------------------------------------------------------------------------+-- Hack to get the typechecker to accept our action functions+++happyTcHack :: Happy_GHC_Exts.Int# -> a -> a+happyTcHack x y = y+{-# INLINE happyTcHack #-}+++-----------------------------------------------------------------------------+-- Seq-ing.  If the --strict flag is given, then Happy emits +--      happySeq = happyDoSeq+-- otherwise it emits+--      happySeq = happyDontSeq++happyDoSeq, happyDontSeq :: a -> b -> b+happyDoSeq   a b = a `seq` b+happyDontSeq a b = b++-----------------------------------------------------------------------------+-- Don't inline any functions from the template.  GHC has a nasty habit+-- of deciding to inline happyGoto everywhere, which increases the size of+-- the generated parser quite a bit.+++{-# NOINLINE happyDoAction #-}+{-# NOINLINE happyTable #-}+{-# NOINLINE happyCheck #-}+{-# NOINLINE happyActOffsets #-}+{-# NOINLINE happyGotoOffsets #-}+{-# NOINLINE happyDefActions #-}++{-# NOINLINE happyShift #-}+{-# NOINLINE happySpecReduce_0 #-}+{-# NOINLINE happySpecReduce_1 #-}+{-# NOINLINE happySpecReduce_2 #-}+{-# NOINLINE happySpecReduce_3 #-}+{-# NOINLINE happyReduce #-}+{-# NOINLINE happyMonadReduce #-}+{-# NOINLINE happyGoto #-}+{-# NOINLINE happyFail #-}++-- end of Happy Template.+
+ harmony-commandline/Main.hs view
@@ -0,0 +1,102 @@+module Main where++import           Control.Monad              (forM_, unless)+import           Data.Maybe                 (fromJust)+import qualified Generation.OutputGenerator as OG+import           Language.ErrM+import           Language.Par+import           System.Console.GetOpt+import           System.Environment         (getArgs, getProgName)+import           System.Exit                (ExitCode (ExitFailure), exitWith)+import qualified TypeCheck.ApiSpec          as AS+import qualified TypeCheck.StaticCheck      as SC++-- | Flags of the executable+data Options = Options+  { generationFunctions :: [OG.GenerationFunction]+  , outputDir           :: FilePath+  }++defaultOptions :: Options+defaultOptions = Options+  { generationFunctions = []+  , outputDir = "./harmony_output"+  }++-- | Definition of the flags expected by the executable+options :: [OptDescr (Options -> Options)]+options = [ Option "c" ["client"]+                   (OptArg (\c options -> options { generationFunctions = parseClient c:generationFunctions options})+                           "CLIENTS")+                   "Desired output for the client"+          , Option "s" ["server"]+                   (OptArg (\s options -> options { generationFunctions = parseServer s:generationFunctions options})+                           "SERVERS")+                   "Desired output for the server"+          , Option "o" ["output_dir"]+                   (OptArg (\dir options -> options { outputDir = fromJust dir })+                           "OUTPUT_DIR")+                   "Output path"+          ]++-- | Parse flag input+parseClient, parseServer :: Maybe String -> OG.GenerationFunction+parseClient (Just "js") = OG.generateJSClient+parseClient (Just "python") = OG.generatePythonClient+parseClient (Just other) = error $ "Could not parse client: " ++ other+parseClient Nothing = error "parseClient: not expected Nothing as flag"+parseServer (Just "js") = OG.generateJSServer+parseServer (Just other) = error $ "Could not parse server" ++ other+parseServer Nothing = error "parseServer: not expected Nothing as flag"++-- | Entry point, parses arguments, then the specification file and generates all the desired+-- | outputs.+main :: IO ()+main = do+  (inputFile, outputPath, toGenerateList) <- parseArgs+  contents <- readFile inputFile+  case pSpecification (myLexer contents) of+    Bad err -> ioError (userError err)+    Ok tree -> case SC.staticCheck tree of+                 Bad err -> ioError (userError err)+                 Ok env -> generateOutput env toGenerateList outputPath+  return ()++-- | Parses the arguments and returns a list of targets to generate.+parseArgs :: IO (FilePath, FilePath, [OG.GenerationFunction])+parseArgs = do+  args <- getArgs+  programName <- getProgName++  case getOpt Permute options args of+    (flags, args, []) -> do+      unless (length args == 1)+             (printUsageAndExitWithError Nothing programName options)+      unless (not $ null flags)+             (printUsageAndExitWithError (Just "Select at least a client/server") programName options)+      return (head args, outputDir info, generationFunctions info)+        where+          info :: Options+          info = foldl (flip ($))  defaultOptions flags+    -- TODO: check if this should be another printUsageAndExitWithError call+    (_, _, errs) -> ioError (userError (concat errs ++ usage programName options))++-- | Generate all the output required.+generateOutput :: AS.ApiSpec -> [OG.GenerationFunction] -> FilePath -> IO ()+generateOutput apiSpec genFunctions outputPath = forM_ genFunctions (\f -> f outputPath apiSpec)++-- | Generates the usage message.+usage :: String -> [OptDescr (Options -> Options)] -> String+usage progName = usageInfo header+  where+    header = "Usage: " ++ progName ++ " [OPTION...] input_file"++-- | Prints usage and exits with error.+printUsageAndExitWithError :: Maybe String -> String -> [OptDescr (Options -> Options)] -> IO ()+printUsageAndExitWithError message progName options = do+  case message of+    Just str -> putStrLn $ "ERROR: " ++ str ++ "\n"+    Nothing -> return ()+  putStrLn $ usage progName options+  exitWith (ExitFailure 2)+
+ harmony.cabal view
@@ -0,0 +1,127 @@+name:                harmony++-- The package version.  See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary:      +-+------- breaking API changes+--                   | | +----- non-breaking API additions+--                   | | | +--- code changes with no API change+version:             0.1.0.0++synopsis:            A web service specification compiler that generates implementation and tests.++description:         This application defines a specification language for web services and reads+                     it in order to generate implementation, tests, clients, etc...++license:             GPL-3++license-file:        LICENSE++author:              Santiago Munín++maintainer:          santimunin@gmail.com++bug-reports:         https://github.com/SantiMunin/harmony/issues++category:            Development++build-type:          Custom++data-files:          templates/server/js/package.tpl+                   , templates/server/js/server.tpl+                   , templates/client/python/client.tpl+                   , templates/client/python/test.tpl++extra-source-files:  README.md++cabal-version:       >= 1.18++source-repository head+  type:     git+  location: https://github.com/SantiMunin/harmony++library++  build-depends:       base >=4.7 && <4.8+                     , array+                     , containers+                     , BNFC+                     , hastache+                     , text+                     , mtl+                     , derive+                     , directory+                     , QuickCheck+                     , process+                     , hslogger+  +  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind+  +  hs-source-dirs:      src++  build-tools:         alex+                     , happy++  exposed-modules:     TypeCheck.ApiSpec+                     , TypeCheck.StaticCheck+                     , Generation.OutputGenerator+                     , Generation.ServiceGenerator+                     , Generation.TemplateCompiler+                     , Data.DiGraph+                     , Language.Abs+                     , Language.ErrM+                     , Language.Lex+                     , Language.Par+                     , LangUtils+                     , Paths_harmony++  default-language:    Haskell2010+  +executable harmony++  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind++  hs-source-dirs:      harmony-commandline++  main-is:             Main.hs++  build-depends:       base >= 4.7 && < 4.8+                     , harmony++  default-language:    Haskell2010++test-suite hspec++  type:                exitcode-stdio-1.0++  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind -fno-warn-orphans -fhpc++  hs-source-dirs:      test++  main-is:             Spec.hs++  build-depends:       base >= 4.7 && < 4.8+                     , containers+                     , hspec >= 2.0+                     , QuickCheck+                     , HUnit+                     , harmony+                     , derive+                     , hslogger++  default-language:    Haskell2010++test-suite hlint+  build-depends:       base >= 4.7 && < 4.8+                     , hlint++  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind++  hs-source-dirs:      test+  +  main-is:             HLint.hs++  type:                exitcode-stdio-1.0+  +  default-language:    Haskell2010+
+ src/Data/DiGraph.hs view
@@ -0,0 +1,94 @@+module Data.DiGraph( Graph ()+                   , empty+                   , create+                   , addNode+                   , addAllNodes+                   , addNeighbors+                   , addAllNeighbors+                   , contains+                   , deleteNode+                   , getNeighbors+                   , getNodes+                   , isEmpty+                   , hasCycle+                   , generateInverseDependencyList) where++import qualified Data.Map as M+import qualified Data.Set as S++data (Ord a) => Graph a = Graph { nodes :: S.Set a+                                , next  :: M.Map a (S.Set a)+                                } deriving (Eq, Show)++empty :: Ord a => Graph a+empty = Graph { nodes = S.empty+              , next = M.empty+              }++create :: Ord a => [(a, [a])] -> Graph a+create pairs = addAllNeighbors pairs $ addAllNodes (map fst pairs) empty++addNode :: Ord a => a -> Graph a -> Graph a+addNode v graph = graph { nodes = v `S.insert` nodes graph }++deleteNode :: Ord a => a -> Graph a -> Graph a+deleteNode v graph = graph { nodes = v `S.delete` nodes graph+                           , next = deleteNodeFromNext v $ next graph}+  where+    deleteNodeFromNext v m = rmFromAllSets v $ M.delete v m+    rmFromAllSets v = M.map (S.delete v)++addAllNodes :: Ord a => [a] -> Graph a -> Graph a+addAllNodes nodes graph = foldl (flip addNode) graph nodes++addNeighbors :: Ord a => a -> [a] -> Graph a -> Graph a+addNeighbors v neighboors graph | graph `contains` v = graph { nodes = nodes $ addAllNodes neighboors graph, next = M.insert v (S.fromList neighboors) $ next graph }+                                | otherwise = addNeighbors v neighboors $ addNode v graph++addAllNeighbors :: Ord a => [(a, [a])] -> Graph a -> Graph a+addAllNeighbors pairs graph = foldl (\g (v, next) -> addNeighbors v next g) graph pairs++contains :: Ord a => Graph a -> a -> Bool+contains graph v = v `S.member` nodes graph++getNeighbors :: Ord a => Graph a -> a -> Maybe [a]+getNeighbors graph v = do+  ns <- M.lookup v $ next graph+  let nList = S.toList ns+  if null nList+  then Nothing+  else return nList++getNodes :: Ord a => Graph a -> [a]+getNodes = S.toList . nodes++isEmpty :: Ord a => Graph a -> Bool+isEmpty graph = S.null $ nodes graph++hasCycle :: Ord a => Graph a -> Bool+hasCycle graph | isEmpty graph = False+               | otherwise = any (`go` S.empty) $ getNodes graph+  where+    go node visited | node `S.member` visited = True+                    | otherwise = case getNeighbors graph node of+                                    Nothing -> False+                                    Just next -> any (flip go $ node `S.insert` visited) next++dfs :: Ord a => Graph a -> Maybe a+dfs graph | isEmpty graph = Nothing+          | otherwise = go (head $ getNodes graph) graph+  where+    go :: Ord a => a -> Graph a -> Maybe a+    go node graph =+      case getNeighbors graph node of+        Nothing -> return node+        Just [] -> error "getNeighbors returning \"Just []\" should never happen"+        Just (node':_) -> go node' graph++generateInverseDependencyList :: Ord a => Graph a -> [a]+generateInverseDependencyList graph = go graph []+  where+    go graph accum =+      case dfs graph of+        Nothing -> reverse accum+        Just n -> go (deleteNode n graph) (n:accum)
+ src/Generation/OutputGenerator.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE OverloadedStrings #-}+-- | Contains the generation logic and functions of the different possible outputs.+module Generation.OutputGenerator(GenerationFunction, generateJSServer, generateJSClient, generatePythonClient) where++import           Control.Monad+import           Data.List+import qualified Data.Text.Lazy.IO           as TL+import qualified Generation.ServiceGenerator as SG+import qualified Generation.TemplateCompiler as TC+import           Paths_harmony+import           System.Directory+import           System.Exit                 (ExitCode (..))+import           System.Log.Formatter        ()+import           System.Log.Handler          ()+import           System.Log.Handler.Simple   ()+import           System.Log.Handler.Syslog   ()+import           System.Log.Logger+import           System.Process              (system)+import qualified TypeCheck.ApiSpec           as AS++-- | A template is a source file and a new extension; e.g. ("template.tpl", "js") will result in+--   "template.js" after the template compilation.+type TemplateInfo = (FilePath, String)++-- | All the info necesaary in order to generate a target:+--   * List of regular files (this will be just directly copied)+--   * List of templates that will be compiled+--   * A map from a Harmony type to the target's type+type GenerationInfo = ([FilePath], [TemplateInfo], AS.Type -> String)++-- | A function that generates the target.+type GenerationFunction = FilePath -- ^ Output path+                       -> AS.ApiSpec -- ^ Information of the defined web service+                       -> IO ()++-- | Target generation function.+generateJSServer, generateJSClient, generatePythonClient :: GenerationFunction+generateJSServer = generateOutput (files, templates, fieldMapping) postOpFunc+  where+    files = []+    templates = [ ("templates/server/js/server.tpl", "js")+                , ("templates/server/js/package.tpl", "json")+                ]+    fieldMapping AS.TString = "String"+    fieldMapping AS.TLong = "Number"+    fieldMapping AS.TInt = "Number"+    fieldMapping AS.TDouble = "Number"+    -- An enum is an string with constraints.+    fieldMapping (AS.TEnum _) = "String"+    fieldMapping (AS.TStruct t) = t+    fieldMapping (AS.TList t) = fieldMapping t+    fieldMapping other = error $ "Javascript server generation: Type not recognized -> " ++ show other++generateJSClient = error "Javascript client is not implemented yet"++generatePythonClient = generateOutput (files, templates, fieldMapping) postOpFunc+  where+    files = []+    templates = [ ("templates/client/python/client.tpl", "py")+                , ("templates/client/python/test.tpl", "py")+                ]+    -- These are the generators for the different types used by Hypothesis.+    fieldMapping AS.TString = "strategy([strategy(integers_in_range(65,90)) | strategy(integers_in_range(97, 122))]).map(lambda l: map(chr, l)).map(lambda l: ''.join(l))"+    fieldMapping AS.TInt = "integers_in_range(-1000,1000)"+    fieldMapping AS.TLong = "integers_in_range(-1000,1000)"+    fieldMapping AS.TDouble = "error:PythonNoTypes (Double)"+    fieldMapping (AS.TEnum _) = "error: no directly translation from enum type to Hypothesis type"+    fieldMapping (AS.TStruct name) = name ++ "Data"+    fieldMapping (AS.TList t) = "[" ++ fieldMapping t ++ "]"+    fieldMapping other = error $ "Python client generation: Type not recognized -> " ++ show other++-- | Applies different post processing operations to each file type.+postOpFunc :: String -> FilePath -> IO ()+postOpFunc "js" = applyJsBeautify+postOpFunc "py" = applyYapf+postOpFunc _ = \_ -> return ()++applyJsBeautify :: FilePath -> IO ()+applyJsBeautify path = do+  infoM "Generation.OutputGenerator" $ "Applying js-beautifier to " ++ path+  outcome <- system $ "js-beautify " ++ path ++ " > tempfile && cat tempfile > " ++ path ++ " && rm tempfile"+  case outcome of+    ExitSuccess -> return ()+    (ExitFailure _) ->+      warningM "Generation.OutputGenerator" $ "There was a problem applying the python beautifier, "+              ++ "please check it is installed and in the system's path (if "+              ++ "you ignore this message the Python generated files will not be properly formatted"+++applyYapf :: FilePath -> IO ()+applyYapf path = do+  infoM "Generation.OutputGenerator" $ "Applying yapf to " ++ path+  outcome <- system $ "yapf " ++ path ++ " > tempfile && cat tempfile > " ++ path ++ " && rm tempfile"+  case outcome of+    ExitSuccess -> return ()+    (ExitFailure _) ->+      warningM "Generation.OutputGenerator" $ "There was a problem applying the python beautifier, "+              ++ "please check it is installed and in the system's path (if "+              ++ "you ignore this message the Python generated files will not be properly formatted"++-- | Uses all the information provided by the user (and the input file) and generates+-- the output by compiling the templates and copying all the files to the output directory.+generateOutput :: GenerationInfo -- ^ The information gathered from the user+               -> (String -> FilePath -> IO ()) -- ^ A function that performs a different operation per file extension+               -> FilePath -- ^ Output path+               -> AS.ApiSpec -- ^ The information gathered from the input file (specification)+               -> IO ()+generateOutput (files, templates, fieldMapping) postOpFunc outputPath apiSpec = do+  updateGlobalLogger "Generation.OutputGenerator" (setLevel INFO)+  forM_ files (copy outputPath)+  forM_ templates (generateAndWrite outputPath (SG.generateService apiSpec fieldMapping) postOpFunc)++-- | Copies a file.+copy :: FilePath -- ^ Origin file+     -> FilePath -- ^ Destination path+     -> IO ()+copy origin dest = do+  cabalFilePath <- getDataFileName origin+  copyFile cabalFilePath (dest ++ "/" ++ origin)++-- | Generate a template and writes it to the destination path.+generateAndWrite :: FilePath -- ^ Destination path+                -> TC.Service -- ^ Information for the template+                -> (String -> FilePath -> IO ()) -- ^ A function that performs a different operation per file extension+                -> TemplateInfo -- ^ Information of the template+                -> IO ()+generateAndWrite dest service postOpFunc (templatePath, newExt) = do+  output <- TC.render templatePath service+  createDirectoryIfMissing {- create parent dirs too -} True destDir+  TL.writeFile destFile output+  postOpFunc newExt destFile+  where+    destFileWithoutExt = dest ++ takeWhile (/= '.') (dropWhile (/= '/') templatePath)+    destDir =+      let indices = elemIndices '/' destFile+      in if null indices then "." else take (last indices + 1) destFile+    destFile = destFileWithoutExt ++ "." ++ newExt
+ src/Generation/ServiceGenerator.hs view
@@ -0,0 +1,75 @@+-- | Generation of 'TC.Service' objects from the specification.+module Generation.ServiceGenerator(generateService) where++import qualified Data.Map                    as M+import           Data.Maybe                  (fromJust, fromMaybe, isJust)+import qualified Data.Set                    as S+import qualified Generation.TemplateCompiler as TC+import qualified TypeCheck.ApiSpec           as AS++-- | Transforms an api specification to a service.+generateService :: AS.ApiSpec -- ^ The specification of the web service+                -> (AS.Type -> String) -- ^ A mapping from internal types to target's types+                -> TC.Service+generateService apiSpec fieldMapping =+  TC.Service (AS.name apiSpec)+             (AS.version apiSpec)+             (AS.requiresAuth apiSpec)+             $ map (generateSchema fieldMapping apiSpec . fst) $ AS.structs apiSpec++-- | Generates the information of a resource/struct.+generateSchema :: (AS.Type -> String) -- ^ A mapping from internal types to target's types+               -> AS.ApiSpec -- ^ The specification of the web service+               -> AS.Id -- ^ The name of the struct+               -> TC.Schema+generateSchema fieldMapping apiSpec strId =+  TC.Schema { TC.schemaName = strId+            , TC.schemaRoute = schemaRoute'+            , TC.writable = writable'+            , TC.hasKeyField = hasKeyField+            , TC.keyField = keyField+            , TC.schemaVars = generateVars fieldMapping apiSpec structInfo }+  where+    (schemaRoute', writable') = maybe (Nothing, False) (\(r, w) -> (Just TC.StrValue { TC.value = r }, w)) (M.lookup strId $ AS.resources apiSpec)+    structInfo = fromJust $ lookup strId $ AS.structs apiSpec+    maybeKeyField = AS.getPrimaryKey structInfo+    -- Leave empty if it doesn't exist+    keyField = fromMaybe "" maybeKeyField+    hasKeyField = isJust maybeKeyField++-- | Generates the information of the fields of a 'TC.Schema'.+generateVars :: (AS.Type -> String) -- ^ A mapping from internal types to target's types+             -> AS.ApiSpec -- ^ The specification of the web service+             -> AS.StructInfo -- ^ The information of the struct+             -> [TC.SchemaVar] -- ^ The information of all the fields of the schema+generateVars fieldMapping apiSpec = map getVarFromField+  where+    getVarFromField :: AS.FieldInfo -> TC.SchemaVar+    getVarFromField (AS.FI (n, t, modifs)) = generateSchemaVar n t modifs+    -- TODO(6): implement custom fields+    generateSchemaVar :: AS.Id -> AS.Type -> S.Set AS.Modifier -> TC.SchemaVar+    generateSchemaVar name type' modifs =+      TC.SchemaVar { TC.varName = name+                   , TC.varType = fieldMapping type'+                   , TC.isList = isList type'+                   , TC.isEnum = if isEnum type' then Just $ getValues type' else Nothing+                   , TC.isStruct = isStruct type'+                   , TC.isKey = AS.PrimaryKey `S.member` modifs+                   , TC.isRequired = AS.Required `S.member` modifs+                   , TC.isHidden = AS.Hidden `S.member` modifs+                   , TC.isUnique = AS.Unique `S.member` modifs || AS.PrimaryKey `S.member` modifs+                   , TC.isUserLogin = AS.UserLogin `S.member` modifs+                   }+        where+          getValues (AS.TEnum enumId) = TC.EnumValue $ map TC.StrValue (fromJust $ M.lookup enumId $ AS.enums apiSpec)+          getValues (AS.TList t') = getValues t'+          getValues other = error $ "getValues called on a non-enum type: " ++ show other+          isEnum (AS.TEnum _) = True+          isEnum (AS.TList t') = isEnum t'+          isEnum _ = False+          isList (AS.TList _) = True+          isList _ = False+          isStruct (AS.TStruct _) = True+          isStruct (AS.TList t') = isStruct t'+          isStruct _ = False+
+ src/Generation/TemplateCompiler.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE TemplateHaskell    #-}++-- | Compiles Hastache templates and defines the datatypes to pass information to them.+module Generation.TemplateCompiler where++import           Data.Data+import           Data.DeriveTH+import qualified Data.Text.Lazy        as TL+import           Data.Typeable         ()+import           Paths_harmony+import           Test.QuickCheck+import           Text.Hastache+import           Text.Hastache.Context++-- | An enum value+data StrValue = StrValue { value :: String } deriving (Show, Data, Typeable, Eq)+data EnumValues = EnumValue { values :: [StrValue] } deriving (Show, Data, Typeable, Eq)++-- | A schema variable. It is a field of a struct.+-- <b>DISCLAIMER</b>: there is some redundancy but the focus of this module is to make the templating easy.+data SchemaVar = SchemaVar { varName     :: String+                           , varType     :: String+                           , isList      :: Bool+                           -- Only if it is an enum (varType == String and values not empty)+                           , isEnum      :: Maybe EnumValues+                           , isStruct    :: Bool+                           , isKey       :: Bool+                           , isRequired  :: Bool+                           , isHidden    :: Bool+                           , isUnique    :: Bool+                           , isUserLogin :: Bool+                           } deriving (Show, Data, Typeable, Eq)++-- | A schema is a struct (it has a name, a route, a write mode, etc...).+data Schema = Schema { schemaName  :: String+                     , schemaRoute :: Maybe StrValue+                     , writable    :: Bool+                     , hasKeyField :: Bool+                     , keyField    :: String+                     , schemaVars  :: [SchemaVar] } deriving (Show, Data, Typeable)++-- | A service has a name, a version, and a list of 'Schema'+data Service = Service { name         :: String+                       , version      :: String+                       , requiresAuth :: Bool+                       , schema       :: [Schema] } deriving (Show, Data, Typeable)++-- | Given a template and a service object, render the template.+render:: String -> Service -> IO TL.Text+render templateLoc service =+  do+    template <- getDataFileName templateLoc >>= readFile+    let context = mkGenericContext service in+      hastacheStr defaultConfig (encodeStr template) context+++derive makeArbitrary ''Service+derive makeArbitrary ''StrValue+derive makeArbitrary ''Schema+derive makeArbitrary ''SchemaVar+derive makeArbitrary ''EnumValues+
+ src/LangUtils.hs view
@@ -0,0 +1,85 @@+-- | Contains useful methods to work with the defined types (both from the language+-- specification/bnfc and the 'ApiSpec' module).+module LangUtils where++import qualified Data.Set          as S+import           Language.Abs+import qualified TypeCheck.ApiSpec as AS++-- | Extracts the name of the 'Specification' (AST).+specName :: Specification -- ^ Specification returned by the parser+         -> String -- ^ Name of the specification+specName (Spec (Nm (Ident n)) _ _ _ _ _) = n++-- | Extracts the version of the 'Specification' (AST).+specVersion :: Specification -- ^ Specification returned by the parser+            -> String -- ^ Version of the specification+specVersion (Spec _(Ver (VerIdent v)) _ _ _ _) = v++-- | Extracts the name of an enum.+enumName :: EnumType -- ^ Enum information+         -> String -- ^ Name of the enum type+enumName (DefEnum (Ident name) _) = name++-- | Extracts the values of an enum.+enumVals :: EnumType -- ^ Enum information+         -> [EnumVal] -- ^ List of enum values+enumVals (DefEnum _ vals) = vals++enumValName :: EnumVal -- ^ Enum value information+            -> String -- ^ Identifier of the enum value+enumValName (EnVal (Ident name)) = name++-- | Extracts the name of a struct.+strName :: StructType -- ^ The struct info+        -> String -- ^ The name of the struct+strName (DefStr (Ident name) _) = name++-- | Extracts the fields of a struct.+strFields :: StructType -- ^ Struct info+          -> [Field] -- ^ List of fields of the struct+strFields (DefStr _ fields) = fields++-- | Extracts the name of a resource.+resName :: Resource -- ^ Resource information+        -> String -- ^ Name of the resource+resName (Res (Ident name) _ _) = name++-- | Extracts the route of a resource.+resRoute :: Resource -- ^ Resource information+         -> String -- ^ Route of the resource+resRoute (Res _ (RouteIdent route) _) = route++-- | Extracts the write mode of a resource.+resIsWritable :: Resource -- ^ Resource information+              -> Bool -- ^ True if it is writable, False otherwise+resIsWritable (Res _ _ mode) = mode == Write++-- | Extracts the name of a field.+fieldName :: Field -- ^ Field information+          -> String -- ^ Name of the field+fieldName (FDef _ (Ident name) _) = name++-- | Extracts the annotation of a field.+fieldAnnotations :: Field -- ^ Field information+                 -> [Annotation] -- ^ List of annotations+fieldAnnotations (FDef annotations _ _) = annotations++-- | Extracts the type (defined by the language specification/bnfc) of a field.+fieldType :: Field -- ^ Field information+          -> FType -- ^ Type of the field+fieldType (FDef _ _ ft) = ft++-- | Extracts the type (defined in 'ApiSpec') of a field.+fieldSpecType :: (S.Set String, S.Set String) -- ^ (Struct names, Enum names)+              -> FType -- ^ Field type+              -> AS.Type -- ^ 'ApiSpec' field type+fieldSpecType _ FString = AS.TString+fieldSpecType _ FInt = AS.TInt+fieldSpecType _ FLong = AS.TLong+fieldSpecType _ FDouble = AS.TDouble+fieldSpecType (strs, enums) (FDefined (Ident n)) | n `S.member` enums = AS.TEnum n+                                                 | n `S.member` strs = AS.TStruct n+                                                 | otherwise = error $ "getType: " ++ n ++ " is not defined."+fieldSpecType as (FList type') = AS.TList $ fieldSpecType as type'+
+ src/Language/Abs.hs view
@@ -0,0 +1,67 @@+++module Language.Abs where++-- Haskell module generated by the BNF converter+++++newtype Ident = Ident String deriving (Eq,Ord,Show,Read)+newtype VerIdent = VerIdent String deriving (Eq,Ord,Show,Read)+newtype RouteIdent = RouteIdent String deriving (Eq,Ord,Show,Read)+data Specification =+   Spec Name Version Modules [EnumType] [StructType] [Resource]+  deriving (Eq,Ord,Show,Read)++data Name =+   Nm Ident+  deriving (Eq,Ord,Show,Read)++data Version =+   Ver VerIdent+  deriving (Eq,Ord,Show,Read)++data Modules =+   EmptyMods+ | Mods [Ident]+  deriving (Eq,Ord,Show,Read)++data EnumType =+   DefEnum Ident [EnumVal]+  deriving (Eq,Ord,Show,Read)++data StructType =+   DefStr Ident [Field]+  deriving (Eq,Ord,Show,Read)++data Resource =+   Res Ident RouteIdent Mode+  deriving (Eq,Ord,Show,Read)++data Mode =+   ReadOnly+ | Write+  deriving (Eq,Ord,Show,Read)++data Field =+   FDef [Annotation] Ident FType+  deriving (Eq,Ord,Show,Read)++data FType =+   FString+ | FInt+ | FLong+ | FDouble+ | FDefined Ident+ | FList FType+  deriving (Eq,Ord,Show,Read)++data Annotation =+   Ann Ident+  deriving (Eq,Ord,Show,Read)++data EnumVal =+   EnVal Ident+  deriving (Eq,Ord,Show,Read)+
+ src/Language/ErrM.hs view
@@ -0,0 +1,37 @@+-- BNF Converter: Error Monad+-- Copyright (C) 2004  Author:  Aarne Ranta++-- This file comes with NO WARRANTY and may be used FOR ANY PURPOSE.+module Language.ErrM where++-- the Error monad: like Maybe type with error msgs++import Control.Monad (MonadPlus(..), liftM)+import Control.Applicative (Applicative(..), Alternative(..))++data Err a = Ok a | Bad String+  deriving (Read, Show, Eq, Ord)++instance Monad Err where+  return      = Ok+  fail        = Bad+  Ok a  >>= f = f a+  Bad s >>= _ = Bad s++instance Applicative Err where+  pure = Ok+  (Bad s) <*> _ = Bad s+  (Ok f) <*> o  = liftM f o+++instance Functor Err where+  fmap = liftM++instance MonadPlus Err where+  mzero = Bad "Err.mzero"+  mplus (Bad _) y = y+  mplus x       _ = x++instance Alternative Err where+  empty = mzero+  (<|>) = mplus
+ src/Language/Lex.x view
@@ -0,0 +1,187 @@+-- -*- haskell -*-+-- This Alex file was machine-generated by the BNF converter+{+{-# OPTIONS -fno-warn-incomplete-patterns #-}+{-# OPTIONS_GHC -w #-}+module Language.Lex where++++import qualified Data.Bits+import Data.Word (Word8)+}+++$l = [a-zA-Z\192 - \255] # [\215 \247]    -- isolatin1 letter FIXME+$c = [A-Z\192-\221] # [\215]    -- capital isolatin1 letter FIXME+$s = [a-z\222-\255] # [\247]    -- small isolatin1 letter FIXME+$d = [0-9]                -- digit+$i = [$l $d _ ']          -- identifier character+$u = [\0-\255]          -- universal: any character++@rsyms =    -- symbols and non-identifier-like reserved words+   \: | \[ | \] | \{ | \} | \( | \" | \) | \@ | \,++:-+"//" [.]* ; -- Toss single line comments+"/*" ([$u # \*] | \*+ [$u # [\* \/]])* ("*")+ "/" ;++$white+ ;+@rsyms { tok (\p s -> PT p (eitherResIdent (TV . share) s)) }+$d \. $d \. $d { tok (\p s -> PT p (eitherResIdent (T_VerIdent . share) s)) }+\/ $l + { tok (\p s -> PT p (eitherResIdent (T_RouteIdent . share) s)) }++$l $i*   { tok (\p s -> PT p (eitherResIdent (TV . share) s)) }++++++{++tok :: (Posn -> String -> Token) -> (Posn -> String -> Token)+tok f p s = f p s++share :: String -> String+share = id++data Tok =+   TS !String !Int    -- reserved words and symbols+ | TL !String         -- string literals+ | TI !String         -- integer literals+ | TV !String         -- identifiers+ | TD !String         -- double precision float literals+ | TC !String         -- character literals+ | T_VerIdent !String+ | T_RouteIdent !String++ deriving (Eq,Show,Ord)++data Token =+   PT  Posn Tok+ | Err Posn+  deriving (Eq,Show,Ord)++tokenPos :: [Token] -> String+tokenPos (PT (Pn _ l _) _ :_) = "line " ++ show l+tokenPos (Err (Pn _ l _) :_) = "line " ++ show l+tokenPos _ = "end of file"++tokenPosn :: Token -> Posn+tokenPosn (PT p _) = p+tokenPosn (Err p) = p++tokenLineCol :: Token -> (Int, Int)+tokenLineCol = posLineCol . tokenPosn++posLineCol :: Posn -> (Int, Int)+posLineCol (Pn _ l c) = (l,c)++mkPosToken :: Token -> ((Int, Int), String)+mkPosToken t@(PT p _) = (posLineCol p, prToken t)++prToken :: Token -> String+prToken t = case t of+  PT _ (TS s _) -> s+  PT _ (TL s)   -> s+  PT _ (TI s)   -> s+  PT _ (TV s)   -> s+  PT _ (TD s)   -> s+  PT _ (TC s)   -> s+  PT _ (T_VerIdent s) -> s+  PT _ (T_RouteIdent s) -> s+++data BTree = N | B String Tok BTree BTree deriving (Show)++eitherResIdent :: (String -> Tok) -> String -> Tok+eitherResIdent tv s = treeFind resWords+  where+  treeFind N = tv s+  treeFind (B a t left right) | s < a  = treeFind left+                              | s > a  = treeFind right+                              | s == a = t++resWords :: BTree+resWords = b "]" 12 (b "@" 6 (b ")" 3 (b "(" 2 (b "\"" 1 N N) N) (b ":" 5 (b "," 4 N N) N)) (b "Long" 9 (b "Int" 8 (b "Double" 7 N N) N) (b "[" 11 (b "String" 10 N N) N))) (b "service_name" 18 (b "read_only" 15 (b "modules" 14 (b "enum" 13 N N) N) (b "resource" 17 (b "require" 16 N N) N)) (b "{" 21 (b "struct" 20 (b "service_version" 19 N N) N) (b "}" 22 N N)))+   where b s n = let bs = id s+                  in B bs (TS bs n)++unescapeInitTail :: String -> String+unescapeInitTail = id . unesc . tail . id where+  unesc s = case s of+    '\\':c:cs | elem c ['\"', '\\', '\''] -> c : unesc cs+    '\\':'n':cs  -> '\n' : unesc cs+    '\\':'t':cs  -> '\t' : unesc cs+    '"':[]    -> []+    c:cs      -> c : unesc cs+    _         -> []++-------------------------------------------------------------------+-- Alex wrapper code.+-- A modified "posn" wrapper.+-------------------------------------------------------------------++data Posn = Pn !Int !Int !Int+      deriving (Eq, Show,Ord)++alexStartPos :: Posn+alexStartPos = Pn 0 1 1++alexMove :: Posn -> Char -> Posn+alexMove (Pn a l c) '\t' = Pn (a+1)  l     (((c+7) `div` 8)*8+1)+alexMove (Pn a l c) '\n' = Pn (a+1) (l+1)   1+alexMove (Pn a l c) _    = Pn (a+1)  l     (c+1)++type Byte = Word8++type AlexInput = (Posn,     -- current position,+                  Char,     -- previous char+                  [Byte],   -- pending bytes on the current char+                  String)   -- current input string++tokens :: String -> [Token]+tokens str = go (alexStartPos, '\n', [], str)+    where+      go :: AlexInput -> [Token]+      go inp@(pos, _, _, str) =+               case alexScan inp 0 of+                AlexEOF                   -> []+                AlexError (pos, _, _, _)  -> [Err pos]+                AlexSkip  inp' len        -> go inp'+                AlexToken inp' len act    -> act pos (take len str) : (go inp')++alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)+alexGetByte (p, c, (b:bs), s) = Just (b, (p, c, bs, s))+alexGetByte (p, _, [], s) =+  case  s of+    []  -> Nothing+    (c:s) ->+             let p'     = alexMove p c+                 (b:bs) = utf8Encode c+              in p' `seq` Just (b, (p', c, bs, s))++alexInputPrevChar :: AlexInput -> Char+alexInputPrevChar (p, c, bs, s) = c++-- | Encode a Haskell String to a list of Word8 values, in UTF8 format.+utf8Encode :: Char -> [Word8]+utf8Encode = map fromIntegral . go . ord+ where+  go oc+   | oc <= 0x7f       = [oc]++   | oc <= 0x7ff      = [ 0xc0 + (oc `Data.Bits.shiftR` 6)+                        , 0x80 + oc Data.Bits..&. 0x3f+                        ]++   | oc <= 0xffff     = [ 0xe0 + (oc `Data.Bits.shiftR` 12)+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)+                        , 0x80 + oc Data.Bits..&. 0x3f+                        ]+   | otherwise        = [ 0xf0 + (oc `Data.Bits.shiftR` 18)+                        , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)+                        , 0x80 + oc Data.Bits..&. 0x3f+                        ]+}
+ src/Language/Par.y view
@@ -0,0 +1,179 @@+-- This Happy file was machine-generated by the BNF converter+{+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-overlapping-patterns #-}+module Language.Par where+import Language.Abs+import Language.Lex+import Language.ErrM++}++%name pSpecification Specification+%name pName Name+%name pVersion Version+%name pModules Modules+%name pEnumType EnumType+%name pStructType StructType+%name pResource Resource+%name pMode Mode+%name pField Field+%name pFType FType+%name pAnnotation Annotation+%name pEnumVal EnumVal+%name pListEnumType ListEnumType+%name pListField ListField+%name pListStructType ListStructType+%name pListResource ListResource+%name pListEnumVal ListEnumVal+%name pListAnnotation ListAnnotation+%name pListIdent ListIdent++-- no lexer declaration+%monad { Err } { thenM } { returnM }+%tokentype { Token }++%token+  '\"' { PT _ (TS _ 1) }+  '(' { PT _ (TS _ 2) }+  ')' { PT _ (TS _ 3) }+  ',' { PT _ (TS _ 4) }+  ':' { PT _ (TS _ 5) }+  '@' { PT _ (TS _ 6) }+  'Double' { PT _ (TS _ 7) }+  'Int' { PT _ (TS _ 8) }+  'Long' { PT _ (TS _ 9) }+  'String' { PT _ (TS _ 10) }+  '[' { PT _ (TS _ 11) }+  ']' { PT _ (TS _ 12) }+  'enum' { PT _ (TS _ 13) }+  'modules' { PT _ (TS _ 14) }+  'read_only' { PT _ (TS _ 15) }+  'require' { PT _ (TS _ 16) }+  'resource' { PT _ (TS _ 17) }+  'service_name' { PT _ (TS _ 18) }+  'service_version' { PT _ (TS _ 19) }+  'struct' { PT _ (TS _ 20) }+  '{' { PT _ (TS _ 21) }+  '}' { PT _ (TS _ 22) }++L_ident  { PT _ (TV $$) }+L_VerIdent { PT _ (T_VerIdent $$) }+L_RouteIdent { PT _ (T_RouteIdent $$) }+++%%++Ident   :: { Ident }   : L_ident  { Ident $1 }+VerIdent    :: { VerIdent} : L_VerIdent { VerIdent ($1)}+RouteIdent    :: { RouteIdent} : L_RouteIdent { RouteIdent ($1)}++Specification :: { Specification }+Specification : Name Version Modules ListEnumType ListStructType ListResource { Spec $1 $2 $3 (reverse $4) $5 $6 } +++Name :: { Name }+Name : 'service_name' ':' Ident { Nm $3 } +++Version :: { Version }+Version : 'service_version' ':' VerIdent { Ver $3 } +++Modules :: { Modules }+Modules : {- empty -} { EmptyMods } +  | 'require' 'modules' '[' ListIdent ']' { Mods $4 }+++EnumType :: { EnumType }+EnumType : 'enum' Ident '{' ListEnumVal '}' { DefEnum $2 $4 } +++StructType :: { StructType }+StructType : 'struct' Ident '{' ListField '}' { DefStr $2 $4 } +++Resource :: { Resource }+Resource : 'resource' Ident '(' '\"' RouteIdent '\"' ')' Mode { Res $2 $5 $8 } +++Mode :: { Mode }+Mode : 'read_only' { ReadOnly } +  | {- empty -} { Write }+++Field :: { Field }+Field : ListAnnotation Ident ':' FType { FDef (reverse $1) $2 $4 } +++FType :: { FType }+FType : 'String' { FString } +  | 'Int' { FInt }+  | 'Long' { FLong }+  | 'Double' { FDouble }+  | Ident { FDefined $1 }+  | '[' FType ']' { FList $2 }+++Annotation :: { Annotation }+Annotation : '@' Ident { Ann $2 } +++EnumVal :: { EnumVal }+EnumVal : Ident { EnVal $1 } +++ListEnumType :: { [EnumType] }+ListEnumType : {- empty -} { [] } +  | ListEnumType EnumType { flip (:) $1 $2 }+++ListField :: { [Field] }+ListField : Field { (:[]) $1 } +  | Field ',' ListField { (:) $1 $3 }+++ListStructType :: { [StructType] }+ListStructType : StructType { (:[]) $1 } +  | StructType ListStructType { (:) $1 $2 }+++ListResource :: { [Resource] }+ListResource : Resource { (:[]) $1 } +  | Resource ListResource { (:) $1 $2 }+++ListEnumVal :: { [EnumVal] }+ListEnumVal : EnumVal { (:[]) $1 } +  | EnumVal ',' ListEnumVal { (:) $1 $3 }+++ListAnnotation :: { [Annotation] }+ListAnnotation : {- empty -} { [] } +  | ListAnnotation Annotation { flip (:) $1 $2 }+++ListIdent :: { [Ident] }+ListIdent : Ident { (:[]) $1 } +  | Ident ListIdent { (:) $1 $2 }++++{++returnM :: a -> Err a+returnM = return++thenM :: Err a -> (a -> Err b) -> Err b+thenM = (>>=)++happyError :: [Token] -> Err a+happyError ts =+  Bad $ "syntax error at " ++ tokenPos ts ++ +  case ts of+    [] -> []+    [Err _] -> " due to lexer error"+    _ -> " before " ++ unwords (map (id . prToken) (take 4 ts))++myLexer = tokens+}+
+ src/TypeCheck/ApiSpec.hs view
@@ -0,0 +1,214 @@+{-# LANGUAGE DeriveGeneric   #-}+{-# LANGUAGE TemplateHaskell #-}+-- | Defines an api spec (to be built after the static checking of the AST) and helper methods over+-- it.+module TypeCheck.ApiSpec where++import           Control.Monad   (liftM)+import           Data.DeriveTH+import qualified Data.Map        as M+import qualified Data.Set        as S+import           Test.QuickCheck++-- | Identifier of an enum, struct, field...+type Id = String++-- | The route of a resource.+type Route = String++-- | An enum value.+type EnumValue = String++-- | An enum is a list of values.+type EnumInfo = [EnumValue]++-- | A field modifier.+data Modifier =+    Hidden -- ^ The field will not be returned when read+  | Immutable -- ^ The field cannot be modified+  | Required -- ^ The field can't be absent+  | PrimaryKey -- ^ The field is the primary key (thus 'Unique' as well)+  | Unique -- ^ The field can't have repeated values throughout the collection+  | UserLogin -- ^ The field value will contain the user's login+  deriving (Eq, Ord, Show)++derive makeArbitrary ''Modifier++-- | A field has a type, an identifier and a set of modifiers.+newtype FieldInfo = FI (Id, Type, S.Set Modifier) deriving (Show, Eq, Ord)++-- | A struct is a list of fields.+type StructInfo = [FieldInfo]++-- | A resource has a route and a write mode.+type ResourceInfo = (Route, Writable)++-- | A type can be a primitive one (int, long, double, bool...), an enum, a struct, or a list of+-- another type.+data Type = TInt+          | TLong+          | TFloat+          | TDouble+          | TBool+          | TString+          | TEnum Id+          | TStruct Id+          | TList Type deriving (Eq, Ord, Show)++instance (CoArbitrary Type) where+  coarbitrary = coarbitraryShow++-- | Map from enum id to its info.+type Enums = M.Map Id EnumInfo++-- | Map from struct id to its info.+type Structs = [(Id, StructInfo)]++-- | Map from resource id to the route and the mode.+type Resources = M.Map Id ResourceInfo++-- | Writable is a boolean type.+type Writable = Bool++-- | The spec of an api is a set of enums and structs, along with the resources.+data ApiSpec = AS { name         :: String -- ^ Name of the service+                  , version      :: String -- ^ Version of the service+                  , requiresAuth :: Bool -- ^ Whether it should support authentication or not+                  , enums        :: Enums -- ^ Information about the user defined enums+                  , structs      :: Structs -- ^ Information about the user defined structs+                  , resources    :: Resources -- ^ Information about the resources defined+                  }++derive makeShow ''ApiSpec++-- | Gets the primary key of a struct if it was specified.+getPrimaryKey :: StructInfo -- ^ The info of the struct+              -> Maybe Id -- ^ The result (Nothing if there was no PK defined)+getPrimaryKey structInfo =+  case filter hasPkModifier structInfo of+    [] -> Nothing+    [FI (x, _, _)] -> Just x+    _ -> error "A struct should have at most one specified primary key."+  where+    hasPkModifier (FI (_, _, modifiers)) = PrimaryKey `S.member` modifiers++-- | Finds out if a fieldinfo is relative to a struct+isStructField :: FieldInfo -> Bool+isStructField (FI (_, t, _)) = isStruct t++-- | Find outs if a type is a struct+isStruct :: Type -> Bool+isStruct (TStruct _) = True+isStruct (TList t) = isStruct t+isStruct _ = False++-- | Get the name of a struct+strName :: Type -> String+strName (TStruct t) = t+strName (TList t) = strName t+strName other = error $ "strName of a non struct type (" ++ show other ++ ")"++-- Testing++-- | Generates a non-empty arbitrary 'String'.+nonEmptyString :: Gen String+nonEmptyString = listOf1 arbitrary++-- | Generates an arbitrary 'FieldInfo', making sure that the ids used for enums and structs are valid.+generateRandomFieldInfo :: [Id] -> [Id] -> Gen FieldInfo+generateRandomFieldInfo enumIds structIds =+  do+    id <- nonEmptyString+    t <- generateRandomType enumIds structIds+    modifiers <- listOf arbitrary+    return $ FI (id, t, S.fromList modifiers)+  where+    generateRandomType :: [Id] -> [Id] -> Gen Type+    generateRandomType enumIds structIds = do+      t <- arbitrary++      case t of+           (TStruct _) -> processStruct+           (TEnum _) -> processEnum+           (TList t') | needsEnumId t' ->+                          if null enumIds+                            then generateRandomType enumIds structIds+                            else do+                                newId <- elements enumIds+                                return $ TList $ setNewId newId t'+                      | needsStructId t' ->+                          if null structIds+                            then generateRandomType enumIds structIds+                            else do+                              newId <- elements structIds+                              return $ TList $ setNewId newId t'+                      | otherwise -> return $ TList t'+           other -> return other+      where+        processEnum = if null enumIds+                        then generateRandomType enumIds structIds+                        else liftM TEnum $ elements enumIds+        processStruct =  if null structIds+                          then generateRandomType enumIds structIds+                          else liftM TStruct $ elements structIds+        needsEnumId (TEnum _) = True+        needsEnumId (TList t) = needsEnumId t+        needsEnumId _ = False++        needsStructId (TStruct _) = True+        needsStructId (TList t) = needsStructId t+        needsStructId _ = False++        setNewId newId' (TEnum _) = TEnum newId'+        setNewId newId' (TStruct _) = TStruct newId'+        setNewId newId' (TList t) = TList $ setNewId newId' t+        setNewId _ t = t++instance (Arbitrary ApiSpec) where+  arbitrary = do+    name' <- nonEmptyString+    version' <- nonEmptyString+    enumIds <- listOf nonEmptyString+    enums' <- mapM createEnum enumIds+    structIds <- listOf nonEmptyString+    structs' <- mapM (createStruct enumIds structIds) structIds+    resources' <- mapM (createResource . fst) structs'+    return AS { name = name'+              , version = version'+              , requiresAuth = False+              , enums = M.fromList enums'+              , structs = structs'+              , resources = M.fromList resources'+              }+    where+      createEnum :: Id -> Gen (Id, EnumInfo)+      createEnum id = do+        values <- listOf1 nonEmptyString+        return (id, values)++      createStruct :: [Id] -> [Id] -> Id -> Gen (Id, StructInfo)+      createStruct enumIds structIds thisStructId = do+        rawFields <- listOf1 $ generateRandomFieldInfo enumIds structIds+        shouldHavePk <- arbitrary+        let fields = filterPrimaryKey shouldHavePk rawFields+        return (thisStructId, fields)+        where+          filterPrimaryKey _ [] = []+          filterPrimaryKey True (FI (id, t, mods):fs) | PrimaryKey `S.member` mods = FI (id, t, PrimaryKey `S.delete` mods) : filterPrimaryKey False fs+          filterPrimaryKey True (FI (id, t, mods):fs) = FI (id, t, mods) : filterPrimaryKey True fs+          filterPrimaryKey False (FI (id, t, mods):fs) = FI (id, t, PrimaryKey `S.delete` mods) : filterPrimaryKey False fs++      createResource :: Id -> Gen (Id, ResourceInfo)+      createResource id = do+        route <- nonEmptyString+        writable <- arbitrary+        return (id, (route, writable))++instance (Arbitrary Type) where+  arbitrary = do+    t <- elements [TInt, TLong, TFloat, TDouble, TBool, TString, TEnum "", TStruct "", TList TInt]+    case t of+         TEnum _ -> liftM TEnum nonEmptyString+         TStruct _ -> liftM TStruct nonEmptyString+         TList _ -> liftM TList arbitrary+         other -> return other
+ src/TypeCheck/StaticCheck.hs view
@@ -0,0 +1,229 @@+-- | Static checking of the input file.+module TypeCheck.StaticCheck (staticCheck) where++import           Control.Arrow+import           Control.Monad+import           Control.Monad.State as CMS+import           Data.Char+import qualified Data.DiGraph        as DG+import qualified Data.Foldable       as F+import qualified Data.Map            as M+import           Data.Maybe+import qualified Data.Set            as S+import           Language.Abs+import           Language.ErrM+import           LangUtils+import qualified TypeCheck.ApiSpec   as AS+++type Env = ( S.Set String+           , AS.ApiSpec+           )++type StaticCheck a = StateT Env Err a++-- | List of reserved words.+reservedWords :: [String]+-- TODO(18): complete list+reservedWords = ["Long", "Int", "String", "Resource", "Enum", "Struct"]++-- | Initial environment (all empty).+initialEnv :: Env+initialEnv = (S.empty,+              AS.AS { AS.name = ""+                    , AS.version = ""+                    , AS.requiresAuth = False+                    , AS.enums = M.empty+                    , AS.structs = []+                    , AS.resources = M.empty+                    }+             )++-- | Checks the definition for:+--   * Name clashes+--   * Undefined types+-- and returns a better representation of the api spec.+staticCheck :: Specification -> Err AS.ApiSpec+staticCheck spec@(Spec _ _ modules enums structs resources) = do+  (_, (_, apiSpec)) <- runStateT checkSeq initialEnv+  return apiSpec+  where+    checkSeq = do+      CMS.modify (\(strs, s) -> (strs, s { AS.name = specName spec, AS.version = specVersion spec }))+      let enumNames = getEnumNames enums+          structNames = getStructNames structs+          customTypeNames = enumNames ++ structNames+      checkClashes $ customTypeNames ++ reservedWords++      CMS.modify (\(_, as) -> (S.fromList structNames, as))+      readAndCheckEnums enums+      addStructNames structs+      processModules modules+      readAndCheckStructs structs+      checkResources resources+      sortStructsByDependencyOrder++-- | Looks for name clashes in the definitions.+-- Note that it skips resources as those need to have the same name as some struct.+checkClashes :: [String] -> StaticCheck ()+checkClashes names =+  case findDuplicates names of+    Nothing -> return ()+    Just name ->+      fail $ "Name clash in declaration: "+          ++ name+          ++ " is declared more than once (or it is a reserved word)."++-- | Reads all enums, making sure there are not repeated values.+readAndCheckEnums :: [EnumType] -> StaticCheck ()+readAndCheckEnums es = F.forM_ es checkEnumValues >> F.forM_ es readEnum+  where+    checkEnumValues :: EnumType -> StaticCheck ()+    checkEnumValues (DefEnum _ vals) =+      let duplicates = findDuplicates (map enumValName vals) in+        unless (isNothing duplicates) (fail $ "Enum value defined more than once " ++ fromJust duplicates)+    readEnum :: EnumType -> StaticCheck ()+    readEnum (DefEnum (Ident name) vals) =+      CMS.modify (\(structNames, as) ->+                     (structNames, as { AS.enums = M.insert name (map enumValName vals) (AS.enums as)}))++-- | Adds struct names (without information). Useful to check if a field is valid even if the type is a struct defined afterwards.+addStructNames :: [StructType] -> StaticCheck ()+addStructNames strs = F.forM_ strs addStr+  where+    addStr (DefStr (Ident strName) _) = CMS.modify $ Control.Arrow.first (S.insert strName)++-- | Modifies the environment with the given modules+processModules :: Modules -> StaticCheck ()+processModules EmptyMods = return ()+processModules (Mods moduleDefs) = void (F.forM_ moduleDefs processModule)+  where+    processModule :: Ident -> StaticCheck ()+    processModule (Ident m) | map toLower m == "authentication"  = CMS.modify (\(structNames, as) -> (structNames, as { AS.requiresAuth = True }))+                            | otherwise = fail $ "Error processing module: " ++ show m ++ " is not supported."++-- | Makes sure all the types used in the struct definitions are valid.+readAndCheckStructs :: [StructType] -> StaticCheck ()+readAndCheckStructs strs = do+  F.forM_ strs structOk+  F.forM_ strs readStruct+    where+      structOk :: StructType -> StaticCheck ()+      structOk (DefStr (Ident strName) fields) = do+        names <- getAllNamesFromEnv+        checkAttributeClashes fields (names `S.union` S.fromList reservedWords)+        F.forM_ fields fieldOk+        checkHasPk strName fields++      checkAttributeClashes :: [Field] -> S.Set String -> StaticCheck (S.Set String)+      checkAttributeClashes fields alreadySeen =+        F.foldlM (\names name ->+          if name `S.member` names+          then fail $ "Field " ++ name+                   ++ " is defined twice (or it is a reserved word/custom type name)"+          else return $ name `S.insert` names) alreadySeen (map fieldName fields)++      fieldOk :: Field -> StaticCheck ()+      fieldOk (FDef _ _ (FDefined (Ident name))) = do+        knownTypes <- getAllNamesFromEnv+        unless (name `S.member` knownTypes)+               (fail $ "The type (" ++ name ++ ") was not defined.")+      fieldOk _ = return ()++      checkHasPk :: String -> [Field] -> StaticCheck ()+      checkHasPk strName fields = do+        fieldsWithPk <- filterM (\f -> do+          m <- readAnnotation f+          return (m==AS.PrimaryKey)) $ concatMap fieldAnnotations fields+        --unless (length (filter ((==AS.PrimaryKey) . readAnnotation) $ concatMap fieldAnnotations fields) <= 1)+        unless (length fieldsWithPk <= 1)+               (fail $ strName ++ " Primary Key annotation (@PK) is used more than once")++      readStruct :: StructType -> StaticCheck ()+      readStruct (DefStr (Ident name) fields) = do+        enums <- getEnumNamesFromEnv+        (strs, as) <- CMS.get+        allFields <- mapM (readField (strs, enums)) fields+        CMS.put (strs, as { AS.structs = (name, allFields):AS.structs as})+      readAnnotation :: Annotation -> StaticCheck AS.Modifier+      readAnnotation (Ann (Ident name)) | map toLower name == "hidden" = return AS.Hidden+                                        | map toLower name == "pk" = return AS.PrimaryKey+                                        | map toLower name == "unique" = return AS.Unique+                                        | map toLower name == "immutable" = return AS.Immutable+                                        | map toLower name == "required" = return AS.Required+                                        | map toLower name == "userlogin" = do+                                          as <- CMS.gets snd+                                          if AS.requiresAuth as+                                          then return AS.UserLogin+                                          else fail "The UserLogin annotation requires the module \"Authentication\""+                                        | otherwise = fail $ "Annotation " ++ name ++ " not recognized."+      readField envInfo (FDef anns (Ident n) ft) = do+        allAnnotations <- mapM readAnnotation anns+        return $ AS.FI (n, fieldSpecType envInfo ft, S.fromList allAnnotations)++-- | Gets enum names from the environment.+getEnumNamesFromEnv :: StaticCheck (S.Set String)+getEnumNamesFromEnv = do+  as <- CMS.gets snd+  return $ S.fromList (map fst $ M.toList $ AS.enums as)++-- | Gets the names (identifiers) of all structs and enums (form the environment).+getAllNamesFromEnv :: StaticCheck (S.Set String)+getAllNamesFromEnv = do+  (strNames, as) <- CMS.get+  return $ strNames `S.union` S.fromList (map fst $ M.toList $ AS.enums as)++checkResources :: [Resource] -> StaticCheck ()+checkResources ress = do+  checkDifferentRoutes ress+  F.forM_ ress resourceOk+  F.forM_ ress addResource+  where+    checkDifferentRoutes ress =+      case findDuplicates (map resRoute ress) of+           Nothing -> case findDuplicates (map resName ress) of+                        Nothing -> return ()+                        (Just repeated') -> fail $ "Struct " ++ repeated' ++ " is referred more than once by a resource."+           (Just repeated) -> fail $ "Route " ++ repeated ++ " is defined more than once"+    resourceOk res = do+      definedStructs <- CMS.gets (\(_, as) -> AS.structs as)+      unless (isJust $ lookup (resName res) definedStructs)+             (fail $ "Resource " ++ resName res ++ " does not refer to a defined struct.")+    addResource res = CMS.modify (\(names, as) -> (names, as { AS.resources = M.insert (resName res) (resRoute res, resIsWritable res) (AS.resources as)}))++getEnumNames :: [EnumType] -> [String]+getEnumNames = map enumName++getStructNames :: [StructType] -> [String]+getStructNames = map strName++findDuplicates :: [String] -> Maybe String+findDuplicates list = go list S.empty S.empty+  where+    go [] _ _ = Nothing+    go (x:_) seen _ | lowerCaseStr x `S.member` seen = return x+    go (x:xs) seen repeatedSet = go xs (lowerCaseStr x `S.insert` seen) repeatedSet+    lowerCaseStr :: String -> String+    lowerCaseStr = map toLower++-- | Builds a dependency graph to sort the structs so forall a,b -> if "a" depends on "b", "b" is+-- first in the list. It fails if there is a cycle in the graph.+sortStructsByDependencyOrder :: StaticCheck ()+sortStructsByDependencyOrder = do+  apiSpec <- CMS.gets snd+  let g = createGraph apiSpec+  unless (not $ DG.hasCycle g) (fail "There is a cycle in the struct definitions")+  let priorityList = DG.generateInverseDependencyList g+  let sortedStructs = matchOrder priorityList (AS.structs apiSpec)+  CMS.modify (\(ns, as) -> (ns, as { AS.structs = sortedStructs }))+    where+      createGraph :: AS.ApiSpec -> DG.Graph AS.Id+      createGraph apiSpec = foldl (\g str -> DG.addNeighbors (fst str) (getDeps str) g) DG.empty (AS.structs apiSpec)+        where+          getDeps (_, fields) = map (\(AS.FI (_, t, _)) -> AS.strName t) $ filter AS.isStructField fields+      matchOrder :: Eq a => [a] -> [(a, b)] -> [(a,b)]+      matchOrder pList list = go pList list []+        where+          go :: Eq a => [a] -> [(a, b)] -> [(a, b)] -> [(a, b)]+          go [] _ acc = reverse acc+          go (x:xs) list acc = go xs list ((x, fromJust (lookup x list)):acc)
+ templates/client/python/client.tpl view
@@ -0,0 +1,79 @@+import requests, json+{{#schema}}++class {{schemaName}}:++    def __init__(self, {{#schemaVars}}{{varName}} = None, {{/schemaVars}}):+        self._info = {}+{{#schemaVars}}+{{#isStruct}}+{{#isList}}+        self._info["{{varName}}"] = map((lambda x: x if (isinstance(x, dict) or isinstance(x, list)) else x.toDict()), {{varName}})+{{/isList}}+{{^isList}}+        self._info["{{varName}}"] = {{varName}}.toDict()+{{/isList}}+{{/isStruct}}+{{^isStruct}}+        self._info["{{varName}}"] = {{varName}}+{{/isStruct}}+{{/schemaVars}}++    @staticmethod+    def fromDict(dict):+      return {{schemaName}}({{#schemaVars}}dict["{{varName}}"],{{/schemaVars}})+    +    def toDict(self):+      return self._info++    @staticmethod+    def fromJSON(text):+        return {{schemaName}}.fromDict(json.loads(text))++    def toJSON(self):+        return json.dumps(self._info)+{{#schemaVars}}++    def get_{{varName}}(self):+        return self._info["{{varName}}"]++    def set_{{varName}}(self, {{varName}}):+        self._info["{{varName}}"] = {{varName}}+{{/schemaVars}}+{{/schema}}++{{#requiresAuth}}+def login(url, login, password):+  return requests.post(url + "/u_auth" + "/" + login + "/" + password)++def register(url , login, password):+  return requests.post(url + "/u_auth/register", data=json.dumps({'login' : login, 'password': password}), headers = {'content-type': 'application/json'})+{{/requiresAuth}}++{{#schema}}{{#schemaRoute}}++def get{{schemaName}}_list(url{{#requiresAuth}}, token{{/requiresAuth}}):+    return requests.get(url + "{{&value}}"{{#requiresAuth}}+ "/" + token{{/requiresAuth}})++def get{{schemaName}}(url, item_id{{#requiresAuth}}, token{{/requiresAuth}}):+    return requests.get(url + "{{&value}}" + "/" + item_id{{#requiresAuth}}+ "/" + token{{/requiresAuth}})+{{#writable}}++{{#hasKeyField}}++def put{{schemaName}}(url, item{{#requiresAuth}}, token{{/requiresAuth}}):+    return requests.put(url + "{{&value}}" + "/" + item.get_{{keyField}}(){{#requiresAuth}}+ "/" + token{{/requiresAuth}}, data=item.toJSON(), headers = {'content-type': 'application/json'})+{{/hasKeyField}}++def put{{schemaName}}(url, item_id, item{{#requiresAuth}}, token{{/requiresAuth}}):+    return requests.put(url + "{{&value}}" + "/" + item_id{{#requiresAuth}}+ "/" + token{{/requiresAuth}}, data=item.toJSON(), headers = {'content-type': 'application/json'})+{{^hasKeyField}}++def post{{schemaName}}(url, item{{#requiresAuth}}, token{{/requiresAuth}}):+    return requests.post(url + "{{&value}}"{{#requiresAuth}}+ "/" + token{{/requiresAuth}}, data=item.toJSON(), headers = {'content-type': 'application/json'})+{{/hasKeyField}}++def delete{{schemaName}}(url, item_id{{#requiresAuth}}, token{{/requiresAuth}}):+    return requests.delete(url + "{{&value}}" + "/" + item_id{{#requiresAuth}}+ "/" + token{{/requiresAuth}})+{{/writable}}+{{/schemaRoute}}{{/schema}}
+ templates/client/python/test.tpl view
@@ -0,0 +1,168 @@+from client import *+from hypothesis import *+from hypothesis.searchstrategy.collections import *+from hypothesis.specifiers import * +import unittest+import copy+import sys++def is_valid_id_string(id_string):+  return len(id_string) > 0 \+         and len(id_string) < 20 \+         and all(map(lambda x: (ord(x) >= 65 and ord(x) <= 90) or (ord(x) >= 97 and ord(x) <= 122), id_string))++class ServiceTest(unittest.TestCase):++    def assertEqual(self, item1, item2):+        i1 = copy.deepcopy(item1)+        i2 = copy.deepcopy(item2)+        if type(i1) != type(i2):+            t1 = type(i1).__name__+            t2 = type(i2).__name__+            # str and unicode can be treated as the same type+            if not ((t1 == "unicode" and t2 == "str") or (t1 == "str" and t2 == "unicode")):+                self.fail("Different types ("+ type(i1).__name__ + "," + type(i2).__name__ + ")")+        if isinstance(i1, dict):+            self.assertEquals_dict(i1, i2)+        elif isinstance(i1, list):+            self.assertEquals_list(i1, i2)+        else:  +            super(ServiceTest, self).assertEqual(i1, i2)+ +    def assertEquals_dict(self, d1, d2):+        self.rm_id_key(d1)+        self.rm_id_key(d2)+        super(ServiceTest, self).assertEqual(d1, d2)++    def assertEquals_list(self, l1, l2):+        i1 = map(self.rm_id_key, l1)+        i2 = map(self.rm_id_key, l2)+        i1.sort()+        i2.sort()+        for i in range(len(i1)):+            self.assertEqual(i1[i], i2[i])++    def rm_id_key(self, item):+        if not isinstance(item, dict):+            return item+        if "id" in item:+            item.pop("id", None)+        return item++Settings.default.max_examples = 10000+Settings.default.timeout = 3+Settings.default.average_list_length = 3++{{#schema}}+{{schemaName}}Data = {+{{#schemaVars}}+{{#isEnum}}+  '{{varName}}': {{#isList}}[{{/isList}}sampled_from([{{#values}}"{{value}}", {{/values}}]){{#isList}}]{{/isList}},+{{/isEnum}}+{{^isEnum}}+{{^isKey}}+  '{{varName}}': {{&varType}}, +{{/isKey}}+{{/isEnum}}+{{/schemaVars}}+}+{{/schema}}++{{#schema}}+{{#schemaRoute}}+class Test{{schemaName}}(ServiceTest):+  @given({{#schemaVars}}{{#isKey}}{{&varType}}, {{/isKey}}{{/schemaVars}}{{schemaName}}Data, {{schemaName}}Data{{#requiresAuth}}, strategy([strategy(integers_in_range(65,90)) | strategy(integers_in_range(97, 122))]).map(lambda l: map(chr, l)).map(lambda l: ''.join(l)){{/requiresAuth}})+  def test_insert_edit_delete(self, {{#hasKeyField}}id, {{/hasKeyField}}data, data2{{#requiresAuth}}, userData{{/requiresAuth}}):+{{#schemaVars}}+{{#isUserLogin}}+{{#isKey}}+    assume(is_valid_id_string(userData))+    id = userData+{{/isKey}}+{{^isKey}}+    {{varName}} = userData+{{/isKey}}+{{/isUserLogin}}+{{^isUserLogin}}+{{#isKey}}+    assume(is_valid_id_string(id))+    {{varName}} = id+{{/isKey}}+{{^isKey}}+    {{varName}} = data["{{varName}}"]+{{/isKey}}+{{/isUserLogin}}+{{/schemaVars}}+{{#requiresAuth}}+    assume(is_valid_id_string(userData))+    registerResponse = register(url, userData, userData)+    authResponse = login(url, userData, userData)+    self.assertEqual(authResponse.status_code, 200);+    token = json.loads(authResponse.text)['token']+{{/requiresAuth}}+{{#hasKeyField}}++    putResponse = put{{schemaName}}(url, id, {{schemaName}}({{#schemaVars}}{{^isUserLogin}}{{varName}} = {{varName}},{{/isUserLogin}} {{/schemaVars}}){{#requiresAuth}},token{{/requiresAuth}})+    self.assertEqual(200, putResponse.status_code)+{{/hasKeyField}}+{{^hasKeyField}}+    postResponse = post{{schemaName}}(url, {{schemaName}}({{#schemaVars}}{{^isUserLogin}}{{varName}} = {{varName}},{{/isUserLogin}} {{/schemaVars}}){{#requiresAuth}},token{{/requiresAuth}})+    self.assertEqual(201, postResponse.status_code)+    id = json.loads(postResponse.text)["id"]+{{/hasKeyField}}+{{#schemaVars}}+{{^isKey}}+    self.assertEqual({{varName}}, {{schemaName}}.fromJSON(get{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}}).text).get_{{varName}}())+{{/isKey}}+{{/schemaVars}}++{{#schemaVars}}+{{#isUserLogin}}+    {{varName}} = userData+{{/isUserLogin}}+{{^isUserLogin}}+{{#isKey}}+    {{varName}} = id+{{/isKey}}+{{^isKey}}+    {{varName}} = data["{{varName}}"]+{{/isKey}}+{{/isUserLogin}}+{{/schemaVars}}++    putResponse = put{{schemaName}}(url, id, {{schemaName}}({{#schemaVars}}{{varName}}, {{/schemaVars}}){{#requiresAuth}},token{{/requiresAuth}})+    self.assertEqual(200, putResponse.status_code)+{{#schemaVars}}+{{^isKey}}+    self.assertEqual({{varName}}, {{schemaName}}.fromJSON(get{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}}).text).get_{{varName}}())+{{/isKey}}+{{/schemaVars}}++    deleteResponse = delete{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}})+    self.assertEqual(200, deleteResponse.status_code)++    getAfterDeleteResponse = get{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}})+    self.assertEqual(404, getAfterDeleteResponse.status_code)++{{/schemaRoute}}+{{/schema}}++{{#requiresAuth}}+class LoginTest(ServiceTest):+  @given(strategy([strategy(integers_in_range(65,90)) | strategy(integers_in_range(97, 122))]).map(lambda l: map(chr, l)).map(lambda l: ''.join(l)))+  def login_test(self, userData):+    register = register(url, userData, userData)+    correctLoginResponse = login(url, userData, userData)+    assertEqual(200, correctLoginResponse.status_code)+    assertTrue(len(json.loads(correctLoginResponse.text)['token']) > 0)+    incorrectLoginResponse = login(url, userData, userData + "XYZ")+    assertEqual(401, incorrectLoginResponse.status_code)+{{/requiresAuth}}++if __name__ == '__main__':+    if len(sys.argv) != 2:+        print("Url must be specified. Example: python tests.py http://localhost:3000")+    else:+        url = sys.argv[1]+        del sys.argv[1]+        unittest.main(argv = None)
+ templates/server/js/package.tpl view
@@ -0,0 +1,10 @@+{+  "name": "{{name}}",+  "version" : "{{version}}",+  "dependencies": {+    "express": ">= 4.12.0",+    "body-parser" : "1.12.0",+    "mongoose": "4.0.1"+  },+  "engine": "node 0.12.0"+}
+ templates/server/js/server.tpl view
@@ -0,0 +1,247 @@+var express = require('express'),+    bodyParser = require('body-parser'),+    mongoose = require('mongoose'),+    app = express(),+    args = process.argv.slice(2);++app.use(bodyParser.json());++mongoose.connect(args[1]);++{{#requiresAuth}}+// User registration and authentication+var UserAutoGeneratedSchema = new mongoose.Schema({+  login : { type: String, required: true, unique: true, index: true, dropDupes: true },+  password: { type: String, required: true },+});++UserAutoGeneratedSchema.set('toJSON', {+  transform: function (doc, ret, options) {+    delete ret._id+    delete ret.__v+    delete ret.password+  }+});++var UserAutoGenerated = mongoose.model('UserAutoGenerated', UserAutoGeneratedSchema);++app.post('/u_auth/register', function (req, res) {+  UserAutoGenerated.create(new UserAutoGenerated(req.body), function(err, obj) {+    if (err) {+      console.log("Error registering: ", err);+      res.status(500).send(err);+      return; +    }+    res.status(201).send();+   });+});++app.post('/u_auth/:login/:password', function (req, res) {+  UserAutoGenerated.find({ login: req.params.login }, function(err, result) {+      if (err) {+        console.log(err);+        res.status(500).send(err);+        return;+      }+      if (result.length == 0) {+        res.status(401).send('Invalid credentials');+      } else {+        if (result[0].password != req.params.password) {+          res.status(401).send('Invalid credentials');+        } else {+          var t = generateToken(req.params.login)+          addSession(t, req.params.login, function() {+            res.status(200).json({token: t});+          });+        }+      }+  });+});++var SessionAutoGeneratedSchema = new mongoose.Schema({+  token : { type: String, required: true, unique: true, index: true, dropDupes: true },+  login : { type: String, required: true, unique: true, dropDupes: true }+});++var SessionAutoGenerated = mongoose.model('SessionAutoGenerated', SessionAutoGeneratedSchema);++var addSession = function(newToken, referredLogin, callback) {+ SessionAutoGenerated.update({token : newToken}, {login: referredLogin}, {upsert: true}, callback); +}++var assertSessionCorrect = function(t, res, callback) {+ SessionAutoGenerated.findOne({token: t}, function(err, result) {+   if (err) {+     console.log("Error asserting user token is correct: ", err);+     res.status(500).send(err);+     return;+   }+   if(result == null || result.login == null) {+     console.log("Token " + t + " was not found");+     res.status(401).send("Invalid credentials.");+     return;+  }+   callback(result.login);+ });+}++var generateToken = function(login) {+  //TODO implement+  return login;+}+{{/requiresAuth}}++{{#schema}}+var {{schemaName}}Schema = new mongoose.Schema({+{{#schemaVars}}{{#isList}}+  {{varName}} : { type: [{{#isStruct}}{{varType}}Schema{{/isStruct}}{{^isStruct}}{{varType}}{{/isStruct}}]+               {{/isList}}{{^isList}}+  {{varName}} : { type: {{#isStruct}}{{varType}}Schema{{/isStruct}}{{^isStruct}}{{varType}}{{/isStruct}}+               {{/isList}} {{#isUnique}}, unique : true {{/isUnique}}{{#isKey}}, index: true, dropDupes: true {{/isKey}} {{#isRequired}}, required: true {{/isRequired}} {{#isEnum}}, enum: [{{/isEnum}}{{#isEnum}}{{#values}}'{{value}}',{{/values}}{{/isEnum}}{{#isEnum}}]{{/isEnum}}{{/isStruct}} },+{{/schemaVars}}+});++{{schemaName}}Schema.set('toJSON', {+  transform: function (doc, ret, options) {+    {{^hasKeyField}}ret.id = ret._id{{/hasKeyField}}+    {{#schemaVars}}{{#isHidden}}delete ret.{{varName}};{{/isHidden}}{{/schemaVars}}+    delete ret._id+    delete ret.__v+  }+});++{{^hasKeyField}}+{{schemaName}}Schema.set('toObject', {+  transform : function (doc, ret, options) {+    ret._id = ret.id+    delete ret.id+  }+});+{{/hasKeyField}}++var {{schemaName}} = mongoose.model('{{schemaName}}', {{schemaName}}Schema);++{{/schema}}++{{#schema}}+{{#schemaRoute}}+app.get('{{&value}}{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {+{{#requiresAuth}}+  assertSessionCorrect(req.params.token, res, function(userLogin) {+{{/requiresAuth}}+        {{schemaName}}.find(function(err, result) {+          if (err) {+            res.status(500).send(err);  +          } else {+            res.send(result); +          }   +         });+{{#requiresAuth}}+});+{{/requiresAuth}}+});++app.get('{{&value}}/:id{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {+  {{^hasKeyField}}+  if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) {+    res.status(404).send();+    return;+  }+  {{/hasKeyField}}+{{#requiresAuth}}+  assertSessionCorrect(req.params.token, res, function(userLogin) {+{{/requiresAuth}}+        {{schemaName}}.find({ {{#hasKeyField}}{{keyField}}{{/hasKeyField}}{{^hasKeyField}}_id{{/hasKeyField}}: req.params.id }, function(err, result) {+          if (err) {+            res.status(500).send(err);+            return;+            }+          if (result.length == 0) {+            res.status(404).send('Not Found');+          } else {+            res.send(result[0]);+          }+        });+{{#requiresAuth}}+});+{{/requiresAuth}}+});++{{#writable}}+{{^hasKeyField}}+app.post('{{&value}}{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {+{{#requiresAuth}}+  assertSessionCorrect(req.params.token, res, function(userLogin) {+{{/requiresAuth}}+{{#schemaVars}}+{{#isUserLogin}}+req.body.{{varName}} = userLogin;+{{/isUserLogin}}+{{/schemaVars}}+  {{schemaName}}.create(new {{schemaName}}(req.body), function(err, obj) {+    if (err) {+      res.status(500).send(err);+      return;  +    }+    res+      .status(201)+      .json({id : obj._id});+   });+{{#requiresAuth}}+});+{{/requiresAuth}}+});+{{/hasKeyField}}++app.put('{{&value}}/:id{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {+  {{^hasKeyField}}+  if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) {+    res.status(404).send();+    return;+  }+  {{/hasKeyField}}+{{#requiresAuth}}+  assertSessionCorrect(req.params.token, res, function(userLogin) {+{{/requiresAuth}}+{{#schemaVars}}+{{#isUserLogin}}+req.body.{{varName}} = userLogin;+{{/isUserLogin}}+{{/schemaVars}}+  {{schemaName}}.update({ {{#hasKeyField}}{{keyField}}{{/hasKeyField}}{{^hasKeyField}}_id{{/hasKeyField}} : req.params.id }, req.body, {upsert : true, runValidators : true}, function(err, result) {+    if (err) {+      res.status(500).send(err);+    } else {+      res.status(200).send();+    }+  });+{{#requiresAuth}}+});+{{/requiresAuth}}+});++app.delete('{{&value}}/:id{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {+  {{^hasKeyField}}+  if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) {+    res.status(404).send();+    return;+  }+  {{/hasKeyField}}+{{#requiresAuth}}+  assertSessionCorrect(req.params.token, res, function(userLogin) {+{{/requiresAuth}}+  {{schemaName}}.remove({ {{#hasKeyField}}{{keyField}}{{/hasKeyField}}{{^hasKeyField}}_id{{/hasKeyField}}: req.params.id}, function(err, result) {+      if (err) { +        res.status(500).send(err);+        return;+    }});+    res.status(200).send();+{{#requiresAuth}}+});+{{/requiresAuth}}+});+{{/writable}}+{{/schemaRoute}}+{{/schema}}++app.listen(args[0]);
+ test/HLint.hs view
@@ -0,0 +1,16 @@+module Main (main) where++import           Language.Haskell.HLint (hlint)+import           System.Exit            (exitFailure, exitSuccess)++arguments :: [String]+arguments =+    [ "harmony-commandline"+    , "src"+    , "test"+    ]++main :: IO ()+main = do+    hints <- hlint arguments+    if null hints then exitSuccess else exitFailure
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}