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 +675/−0
- README.md +43/−0
- Setup.hs +19/−0
- dist/build/Language/Lex.hs +384/−0
- dist/build/Language/Par.hs +931/−0
- harmony-commandline/Main.hs +102/−0
- harmony.cabal +127/−0
- src/Data/DiGraph.hs +94/−0
- src/Generation/OutputGenerator.hs +137/−0
- src/Generation/ServiceGenerator.hs +75/−0
- src/Generation/TemplateCompiler.hs +64/−0
- src/LangUtils.hs +85/−0
- src/Language/Abs.hs +67/−0
- src/Language/ErrM.hs +37/−0
- src/Language/Lex.x +187/−0
- src/Language/Par.y +179/−0
- src/TypeCheck/ApiSpec.hs +214/−0
- src/TypeCheck/StaticCheck.hs +229/−0
- templates/client/python/client.tpl +79/−0
- templates/client/python/test.tpl +168/−0
- templates/server/js/package.tpl +10/−0
- templates/server/js/server.tpl +247/−0
- test/HLint.hs +16/−0
- test/Spec.hs +1/−0
+ 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 #-}