mulang 4.3.0 → 4.4.0
raw patch · 34 files changed
+1724/−993 lines, 34 filesdep +monad-loopsdep +mtl
Dependencies added: monad-loops, mtl
Files
- LICENSE +674/−0
- LICENSE.txt +0/−674
- app/Main.hs +1/−1
- app/Version.hs +1/−1
- mulang.cabal +23/−13
- src/Language/Mulang/Analyzer.hs +38/−15
- src/Language/Mulang/Analyzer/Analysis.hs +39/−18
- src/Language/Mulang/Analyzer/Analysis/Json.hs +8/−2
- src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs +3/−2
- src/Language/Mulang/Analyzer/ExpectationsCompiler.hs +91/−83
- src/Language/Mulang/Analyzer/FragmentParser.hs +33/−0
- src/Language/Mulang/Analyzer/SampleParser.hs +0/−27
- src/Language/Mulang/Analyzer/SmellsAnalyzer.hs +2/−2
- src/Language/Mulang/Analyzer/TestsAnalyzer.hs +20/−0
- src/Language/Mulang/Ast.hs +16/−0
- src/Language/Mulang/Builder.hs +9/−0
- src/Language/Mulang/Identifier.hs +4/−2
- src/Language/Mulang/Inspector.hs +12/−7
- src/Language/Mulang/Inspector/Bound.hs +18/−0
- src/Language/Mulang/Inspector/Combiner.hs +18/−13
- src/Language/Mulang/Inspector/Contextualized.hs +65/−0
- src/Language/Mulang/Inspector/Generic.hs +39/−26
- src/Language/Mulang/Inspector/Logic.hs +5/−4
- src/Language/Mulang/Inspector/ObjectOriented.hs +13/−14
- src/Language/Mulang/Inspector/ObjectOriented/Polymorphism.hs +22/−19
- src/Language/Mulang/Inspector/Primitive.hs +3/−9
- src/Language/Mulang/Inspector/Procedural.hs +3/−2
- src/Language/Mulang/Inspector/Query.hs +20/−0
- src/Language/Mulang/Inspector/Typed.hs +8/−7
- src/Language/Mulang/Interpreter.hs +382/−0
- src/Language/Mulang/Interpreter/Runner.hs +65/−0
- src/Language/Mulang/Parsers/Java.hs +8/−4
- src/Language/Mulang/Parsers/JavaScript.hs +31/−15
- src/Language/Mulang/Parsers/Python.hs +50/−33
+ LICENSE view
@@ -0,0 +1,674 @@+ GNU GENERAL PUBLIC LICENSE+ Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <https://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 <https://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:++ <program> Copyright (C) <year> <name of author>+ 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+<https://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+<https://www.gnu.org/licenses/why-not-lgpl.html>.
− LICENSE.txt
@@ -1,674 +0,0 @@- 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>.
app/Main.hs view
@@ -61,7 +61,7 @@ "spec" : { "expectations" : [ {- "binding" : ":Intransitive:x",+ "binding" : "Intransitive:x", "inspection" : "Uses:*" } ],
app/Version.hs view
@@ -6,7 +6,7 @@ prettyVersion = "Mulang Release " ++ version ++ ", compiled on " ++ compilationTimestamp version :: String-version = "4.3.0"+version = "4.4.0" compilationTimestamp :: String compilationTimestamp = __DATE__ ++ " " ++ __TIME__
mulang.cabal view
@@ -1,9 +1,9 @@ name: mulang-version: 4.3.0+version: 4.4.0 synopsis: An intermediate language designed to perform advanced code analysis description: Mulang is an intermediate language, a combinators library for static code analysis and a multilanguage comand line tool-license: GPL-license-file: LICENSE.txt+license: GPL-3.0+license-file: LICENSE author: Franco Leonardo Bulgarelli maintainer: franco@mumuki.org category: Language@@ -40,17 +40,20 @@ Language.Mulang.Signature Language.Mulang.DomainLanguage Language.Mulang.Inspector- Language.Mulang.Inspector.Primitive+ Language.Mulang.Inspector.Bound+ Language.Mulang.Inspector.Combiner+ Language.Mulang.Inspector.Contextualized+ Language.Mulang.Inspector.Functional Language.Mulang.Inspector.Generic- Language.Mulang.Inspector.Typed+ Language.Mulang.Inspector.Generic.Duplication+ Language.Mulang.Inspector.Generic.Smell+ Language.Mulang.Inspector.Logic Language.Mulang.Inspector.ObjectOriented Language.Mulang.Inspector.ObjectOriented.Polymorphism- Language.Mulang.Inspector.Functional- Language.Mulang.Inspector.Logic+ Language.Mulang.Inspector.Primitive Language.Mulang.Inspector.Procedural- Language.Mulang.Inspector.Combiner- Language.Mulang.Inspector.Generic.Duplication- Language.Mulang.Inspector.Generic.Smell+ Language.Mulang.Inspector.Query+ Language.Mulang.Inspector.Typed Language.Mulang.Parsers Language.Mulang.Parsers.Haskell Language.Mulang.Parsers.Prolog@@ -60,13 +63,17 @@ Language.Mulang.Analyzer Language.Mulang.Analyzer.Analysis Language.Mulang.Analyzer.Analysis.Json- Language.Mulang.Analyzer.SampleParser+ Language.Mulang.Analyzer.DomainLanguageCompiler Language.Mulang.Analyzer.ExpectationsAnalyzer Language.Mulang.Analyzer.ExpectationsCompiler+ Language.Mulang.Analyzer.FragmentParser Language.Mulang.Analyzer.SignaturesAnalyzer Language.Mulang.Analyzer.SignatureStyleCompiler- Language.Mulang.Analyzer.DomainLanguageCompiler Language.Mulang.Analyzer.SmellsAnalyzer+ Language.Mulang.Analyzer.TestsAnalyzer+ Language.Mulang.Interpreter+ Language.Mulang.Interpreter.Runner+ build-depends: base <= 5, bytestring ,@@ -85,6 +92,8 @@ ParsecTools , split , hashable ,+ mtl ,+ monad-loops , process build-tools: happy,@@ -150,7 +159,8 @@ aeson , hspec , neat-interpolation ,- mulang+ mulang ,+ containers build-tools: happy, alex
src/Language/Mulang/Analyzer.hs view
@@ -1,6 +1,8 @@ module Language.Mulang.Analyzer ( noSmells, allSmells,+ noSmellsBut,+ allSmellsBut, emptyDomainLanguage, emptyAnalysisSpec,@@ -10,60 +12,81 @@ expectationsAnalysis, smellsAnalysis, signaturesAnalysis,+ testsAnalysis, + emptyCompletedAnalysisResult,+ analyse, module Language.Mulang.Analyzer.Analysis) where import Language.Mulang import Language.Mulang.Analyzer.Analysis-import Language.Mulang.Analyzer.SampleParser (parseSample)-import Language.Mulang.Analyzer.SignaturesAnalyzer (analyseSignatures)+import Language.Mulang.Analyzer.DomainLanguageCompiler (emptyDomainLanguage, compileDomainLanguage) import Language.Mulang.Analyzer.ExpectationsAnalyzer (analyseExpectations)+import Language.Mulang.Analyzer.FragmentParser (parseFragment)+import Language.Mulang.Analyzer.SignaturesAnalyzer (analyseSignatures) import Language.Mulang.Analyzer.SmellsAnalyzer (analyseSmells)-import Language.Mulang.Analyzer.DomainLanguageCompiler (emptyDomainLanguage, compileDomainLanguage)+import Language.Mulang.Analyzer.TestsAnalyzer (analyseTests) import Data.Maybe (fromMaybe)+ -- -- Builder functions ---noSmells :: SmellsSet-noSmells = NoSmells Nothing -allSmells :: SmellsSet-allSmells = AllSmells Nothing+noSmells :: Maybe SmellsSet+noSmells = Just $ NoSmells Nothing +noSmellsBut :: [Smell] -> Maybe SmellsSet+noSmellsBut = Just . NoSmells . Just++allSmells :: Maybe SmellsSet+allSmells = Just $ AllSmells Nothing++allSmellsBut :: [Smell] -> Maybe SmellsSet+allSmellsBut = Just . AllSmells . Just+ emptyAnalysisSpec :: AnalysisSpec-emptyAnalysisSpec = AnalysisSpec [] noSmells Nothing Nothing Nothing+emptyAnalysisSpec = AnalysisSpec Nothing Nothing Nothing Nothing Nothing Nothing -emptyAnalysis :: Sample -> Analysis+emptyAnalysis :: Fragment -> Analysis emptyAnalysis code = Analysis code emptyAnalysisSpec -domainLanguageAnalysis :: Sample -> DomainLanguage -> Analysis+domainLanguageAnalysis :: Fragment -> DomainLanguage -> Analysis domainLanguageAnalysis code domainLanguage = Analysis code (emptyAnalysisSpec { domainLanguage = Just domainLanguage, smellsSet = allSmells }) -expectationsAnalysis :: Sample -> [Expectation] -> Analysis-expectationsAnalysis code es = Analysis code (emptyAnalysisSpec { expectations = es })+expectationsAnalysis :: Fragment -> [Expectation] -> Analysis+expectationsAnalysis code es = Analysis code (emptyAnalysisSpec { expectations = Just es }) -smellsAnalysis :: Sample -> SmellsSet -> Analysis+smellsAnalysis :: Fragment -> Maybe SmellsSet -> Analysis smellsAnalysis code set = Analysis code (emptyAnalysisSpec { smellsSet = set }) -signaturesAnalysis :: Sample -> SignatureStyle -> Analysis+signaturesAnalysis :: Fragment -> SignatureStyle -> Analysis signaturesAnalysis code style = Analysis code (emptyAnalysisSpec { signatureAnalysisType = Just (StyledSignatures style) }) +testsAnalysis :: Fragment -> TestAnalysisType -> Analysis+testsAnalysis code testAnalysisType = Analysis code (emptyAnalysisSpec { testAnalysisType = Just testAnalysisType })++emptyCompletedAnalysisResult :: AnalysisResult+emptyCompletedAnalysisResult = AnalysisCompleted [] [] [] [] Nothing+ -- -- Analysis running --+ analyse :: Analysis -> IO AnalysisResult-analyse (Analysis sample spec) = analyseSample (parseSample sample)+analyse (Analysis sample spec) = analyseSample (parseFragment sample) where analyseSample (Right ast) = analyseAst ast spec analyseSample (Left message) = return $ AnalysisFailed message analyseAst :: Expression -> AnalysisSpec -> IO AnalysisResult analyseAst ast spec = do language <- compileDomainLanguage (domainLanguage spec)+ testResults <- analyseTests ast (testAnalysisType spec) return $ AnalysisCompleted (analyseExpectations ast (expectations spec)) (analyseSmells ast language (smellsSet spec)) (analyseSignatures ast (signatureAnalysisType spec))+ testResults (analyzeIntermediateLanguage ast spec) analyzeIntermediateLanguage :: Expression -> AnalysisSpec -> Maybe Expression
src/Language/Mulang/Analyzer/Analysis.hs view
@@ -10,8 +10,10 @@ CaseStyle(..), Smell, SignatureAnalysisType(..),+ TestAnalysisType(..),+ InterpreterOptions(..), SignatureStyle(..),- Sample(..),+ Fragment(..), Language(..), AnalysisResult(..),@@ -21,6 +23,7 @@ import Language.Mulang.Ast import Language.Mulang.Builder (NormalizationOptions)+import Language.Mulang.Interpreter.Runner (TestResult) --- -- Common structures@@ -29,33 +32,35 @@ type Smell = String type Inspection = String -data Expectation- = Expectation { binding :: String, inspection :: Inspection } deriving (Show, Eq, Generic)+data Expectation = Expectation {+ binding :: String,+ inspection :: Inspection+} deriving (Show, Eq, Generic) -- -- Analysis input structures -- data Analysis = Analysis {- sample :: Sample,+ sample :: Fragment, spec :: AnalysisSpec } deriving (Show, Eq, Generic) data AnalysisSpec = AnalysisSpec {- expectations :: [Expectation],- smellsSet :: SmellsSet,+ expectations :: Maybe [Expectation],+ smellsSet :: Maybe SmellsSet, signatureAnalysisType :: Maybe SignatureAnalysisType,+ testAnalysisType :: Maybe TestAnalysisType, domainLanguage :: Maybe DomainLanguage, includeIntermediateLanguage :: Maybe Bool } deriving (Show, Eq, Generic) -data DomainLanguage- = DomainLanguage {- dictionaryFilePath :: Maybe FilePath,- caseStyle :: Maybe CaseStyle,- minimumIdentifierSize :: Maybe Int,- jargon :: Maybe [String]- } deriving (Show, Eq, Generic)+data DomainLanguage = DomainLanguage {+ dictionaryFilePath :: Maybe FilePath,+ caseStyle :: Maybe CaseStyle,+ minimumIdentifierSize :: Maybe Int,+ jargon :: Maybe [String]+} deriving (Show, Eq, Generic) data CaseStyle = CamelCase@@ -77,10 +82,24 @@ | HaskellStyle | PrologStyle deriving (Show, Eq, Generic) -data Sample+data Fragment = MulangSample { ast :: Expression, normalizationOptions :: Maybe NormalizationOptions } | CodeSample { language :: Language, content :: Code } deriving (Show, Eq, Generic) +data InterpreterOptions = InterpreterOptions {+ strictReturns :: Maybe Bool,+ strictShortCircuit :: Maybe Bool+} deriving (Show, Eq, Generic)++data TestAnalysisType+ = NoTests+ | EmbeddedTests { interpreterOptions :: Maybe InterpreterOptions }+ | ExternalTests {+ test :: Fragment,+ extra :: Maybe Fragment,+ interpreterOptions :: Maybe InterpreterOptions+ } deriving (Show, Eq, Generic)+ data Language = Json | Java@@ -94,10 +113,12 @@ -- data AnalysisResult- = AnalysisCompleted { expectationResults :: [ExpectationResult],- smells :: [Expectation],- signatures :: [Code],- intermediateLanguage :: Maybe Expression }+ = AnalysisCompleted {+ expectationResults :: [ExpectationResult],+ smells :: [Expectation],+ signatures :: [Code],+ testResults :: [TestResult],+ intermediateLanguage :: Maybe Expression } | AnalysisFailed { reason :: String } deriving (Show, Eq, Generic) data ExpectationResult = ExpectationResult {
src/Language/Mulang/Analyzer/Analysis/Json.hs view
@@ -4,6 +4,7 @@ import Language.Mulang import Language.Mulang.Analyzer.Analysis import Language.Mulang.Builder (NormalizationOptions, SequenceSortMode)+import Language.Mulang.Interpreter.Runner (TestResult, TestStatus) instance FromJSON Analysis instance FromJSON AnalysisSpec@@ -20,7 +21,7 @@ instance FromJSON NormalizationOptions instance FromJSON SequenceSortMode -instance FromJSON Sample+instance FromJSON Fragment instance FromJSON Language instance FromJSON Equation@@ -29,6 +30,9 @@ instance FromJSON Pattern instance FromJSON Statement instance FromJSON Type+instance FromJSON Assertion+instance FromJSON TestAnalysisType+instance FromJSON InterpreterOptions instance ToJSON AnalysisResult instance ToJSON ExpectationResult@@ -41,4 +45,6 @@ instance ToJSON Pattern instance ToJSON Statement instance ToJSON Type-+instance ToJSON Assertion+instance ToJSON TestResult+instance ToJSON TestStatus
src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs view
@@ -1,13 +1,14 @@ module Language.Mulang.Analyzer.ExpectationsAnalyzer ( analyseExpectations) where +import Data.Maybe (fromMaybe) import Language.Mulang import Language.Mulang.Analyzer.Analysis (Expectation, ExpectationResult(..)) import Language.Mulang.Analyzer.ExpectationsCompiler (compileExpectation) -analyseExpectations :: Expression -> [Expectation]-> [ExpectationResult]-analyseExpectations content = map (analyseExpectation content)+analyseExpectations :: Expression -> Maybe [Expectation] -> [ExpectationResult]+analyseExpectations content = map (analyseExpectation content) . (fromMaybe []) analyseExpectation :: Expression -> Expectation -> ExpectationResult analyseExpectation ast e = ExpectationResult e (compileAndEval e)
src/Language/Mulang/Analyzer/ExpectationsCompiler.hs view
@@ -7,38 +7,37 @@ import Data.Maybe (fromMaybe) import Data.List.Split (splitOn) -type Modifiers = (Scope, PredicateModifier)-type Scope = (Inspection -> Inspection)-type PredicateModifier = (IdentifierPredicate -> IdentifierPredicate)+type Modifiers = (ContextualizedModifier, PredicateModifier) compileExpectation :: Expectation -> Inspection compileExpectation = fromMaybe (\_ -> True) . compileMaybe compileMaybe :: Expectation -> Maybe Inspection-compileMaybe (Expectation b i) = do+compileMaybe (Expectation s i) = do let inspectionParts = splitOn ":" i let negator = compileNegator inspectionParts- (scope, predicateModifier) <- compileModifiers (splitOn ":" b)+ (scope, predicateModifier) <- compileModifiers (splitOn ":" s) baseInspection <- compileBaseInspection predicateModifier inspectionParts- return . negator . scope $ baseInspection+ return . negator . decontextualize . scope $ baseInspection compileModifiers :: [String] -> Maybe Modifiers compileModifiers ["*"] = Just (id, id)-compileModifiers ["Intransitive",name] = justScopeFor scopedList name-compileModifiers [name] = justScopeFor transitiveList name+compileModifiers ["Intransitive",name] = justScopeFor contextualizedScopedList name+compileModifiers [name] = justScopeFor contextualizedTransitiveList name compileModifiers _ = Nothing -justScopeFor f name = Just (flip f names, andAlso (except (last names)))+justScopeFor :: ([Identifier] -> ContextualizedModifier) -> Identifier -> Maybe Modifiers+justScopeFor f name = Just (f names, andAlso (except (last names))) where names = splitOn "." name -compileNegator :: [String] -> Scope+compileNegator :: [String] -> Modifier compileNegator ("Not":_) = negative compileNegator _ = id -compileBaseInspection :: PredicateModifier -> [String] -> Maybe (Inspection)+compileBaseInspection :: PredicateModifier -> [String] -> Maybe ContextualizedInspection compileBaseInspection p ("Not":parts) = compileBaseInspection p parts compileBaseInspection p [verb] = compileBaseInspection p [verb, "*"]-compileBaseInspection p [verb, object] = compileInspectionPrimitive verb (compileObject p object)+compileBaseInspection p [verb, object] = fmap ($ (compileObject p object)) (compileInspectionPrimitive verb) compileBaseInspection _ _ = Nothing compileObject :: PredicateModifier -> String -> IdentifierPredicate@@ -50,79 +49,88 @@ compileObject _ name = named name -compileInspectionPrimitive :: String -> IdentifierPredicate -> Maybe Inspection+compileInspectionPrimitive :: String -> Maybe ContextualizedBoundInspection compileInspectionPrimitive = f where- f "Assigns" = binded assigns- f "Calls" = binded calls- f "Declares" = binded declares- f "DeclaresAttribute" = binded declaresAttribute- f "DeclaresClass" = binded declaresClass- f "DeclaresComputation" = binded declaresComputation- f "DeclaresComputationWithArity0" = binded (declaresComputationWithArity 0)- f "DeclaresComputationWithArity1" = binded (declaresComputationWithArity 1)- f "DeclaresComputationWithArity2" = binded (declaresComputationWithArity 2)- f "DeclaresComputationWithArity3" = binded (declaresComputationWithArity 3)- f "DeclaresComputationWithArity4" = binded (declaresComputationWithArity 4)- f "DeclaresComputationWithArity5" = binded (declaresComputationWithArity 5)- f "DeclaresEntryPoint" = binded declaresEntryPoint- f "DeclaresEnumeration" = binded declaresEnumeration- f "DeclaresFact" = binded declaresFact- f "DeclaresFunction" = binded declaresFunction- f "DeclaresInterface" = binded declaresInterface- f "DeclaresMethod" = binded declaresMethod- f "DeclaresObject" = binded declaresObject- f "DeclaresPredicate" = binded declaresPredicate- f "DeclaresProcedure" = binded declaresProcedure- f "DeclaresRecursively" = binded declaresRecursively- f "DeclaresRule" = binded declaresRule- f "DeclaresSuperclass" = binded declaresSuperclass- f "DeclaresTypeAlias" = binded declaresTypeAlias- f "DeclaresTypeSignature" = binded declaresTypeSignature- f "DeclaresVariable" = binded declaresVariable- f "Implements" = binded implements- f "Includes" = binded includes- f "Inherits" = binded inherits- f "Instantiates" = binded instantiates- f "Raises" = binded raises- f "Rescues" = binded rescues- f "TypesParameterAs" = binded typesParameterAs- f "TypesAs" = binded typesAs- f "TypesReturnAs" = binded typesReturnAs- f "Uses" = binded uses- f "UsesAnonymousVariable" = simple usesAnonymousVariable- f "UsesComposition" = simple usesComposition+ f "Assigns" = bound assigns+ f "Calls" = bound calls+ f "Declares" = bound declares+ f "DeclaresAttribute" = bound declaresAttribute+ f "DeclaresClass" = bound declaresClass+ f "DeclaresComputation" = bound declaresComputation+ f "DeclaresComputationWithArity0" = bound (declaresComputationWithArity 0)+ f "DeclaresComputationWithArity1" = bound (declaresComputationWithArity 1)+ f "DeclaresComputationWithArity2" = bound (declaresComputationWithArity 2)+ f "DeclaresComputationWithArity3" = bound (declaresComputationWithArity 3)+ f "DeclaresComputationWithArity4" = bound (declaresComputationWithArity 4)+ f "DeclaresComputationWithArity5" = bound (declaresComputationWithArity 5)+ f "DeclaresEntryPoint" = bound declaresEntryPoint+ f "DeclaresEnumeration" = bound declaresEnumeration+ f "DeclaresFact" = bound declaresFact+ f "DeclaresFunction" = bound declaresFunction+ f "DeclaresInterface" = bound declaresInterface+ f "DeclaresMethod" = bound declaresMethod+ f "DeclaresObject" = bound declaresObject+ f "DeclaresPredicate" = bound declaresPredicate+ f "DeclaresProcedure" = bound declaresProcedure+ f "DeclaresRecursively" = bound declaresRecursively+ f "DeclaresRule" = bound declaresRule+ f "DeclaresSuperclass" = bound declaresSuperclass+ f "DeclaresTypeAlias" = bound declaresTypeAlias+ f "DeclaresTypeSignature" = bound declaresTypeSignature+ f "DeclaresVariable" = bound declaresVariable+ f "Delegates" = contextualizedBound delegates'+ f "Implements" = bound implements+ f "Includes" = bound includes+ f "Inherits" = bound inherits+ f "Instantiates" = bound instantiates+ f "Raises" = bound raises+ f "Rescues" = bound rescues+ f "TypesAs" = bound typesAs+ f "TypesParameterAs" = bound typesParameterAs+ f "TypesReturnAs" = bound typesReturnAs+ f "Uses" = bound uses+ f "UsesAnonymousVariable" = plain usesAnonymousVariable+ f "UsesComposition" = plain usesComposition f "UsesComprehension" = f "UsesForComprehension"- f "UsesConditional" = simple usesConditional- f "UsesDyamicPolymorphism" = simple usesDyamicPolymorphism- f "UsesDynamicMethodOverload" = simple usesDynamicMethodOverload- f "UsesExceptionHandling" = simple usesExceptionHandling- f "UsesExceptions" = simple usesExceptions- f "UsesFindall" = simple usesFindall- f "UsesFor" = simple usesFor- f "UsesForall" = simple usesForall- f "UsesForComprehension" = simple usesForComprehension- f "UsesForeach" = simple usesForEach- f "UsesForLoop" = simple usesForLoop- f "UsesGuards" = simple usesGuards- f "UsesIf" = simple usesIf- f "UsesInheritance" = simple usesInheritance- f "UsesLambda" = simple usesLambda- f "UsesLoop" = simple usesLoop- f "UsesMixins" = simple usesMixins- f "UsesNot" = simple usesNot- f "UsesObjectComposition" = simple usesObjectComposition- f "UsesPatternMatching" = simple usesPatternMatching- f "UsesRepeat" = simple usesRepeat- f "UsesStaticMethodOverload" = simple usesStaticMethodOverload- f "UsesStaticPolymorphism" = simple usesStaticPolymorphism- f "UsesSwitch" = simple usesSwitch- f "UsesTemplateMethod" = simple usesTemplateMethod- f "UsesType" = binded usesType- f "UsesWhile" = simple usesWhile- f "UsesYield" = simple usesYield- f _ = const Nothing+ f "UsesConditional" = plain usesConditional+ f "UsesDyamicPolymorphism" = contextualized usesDyamicPolymorphism'+ f "UsesDynamicMethodOverload" = plain usesDynamicMethodOverload+ f "UsesExceptionHandling" = plain usesExceptionHandling+ f "UsesExceptions" = plain usesExceptions+ f "UsesFindall" = plain usesFindall+ f "UsesFor" = plain usesFor+ f "UsesForall" = plain usesForall+ f "UsesForComprehension" = plain usesForComprehension+ f "UsesForeach" = plain usesForEach+ f "UsesForLoop" = plain usesForLoop+ f "UsesGuards" = plain usesGuards+ f "UsesIf" = plain usesIf+ f "UsesInheritance" = plain usesInheritance+ f "UsesLambda" = plain usesLambda+ f "UsesLoop" = plain usesLoop+ f "UsesMixins" = plain usesMixins+ f "UsesNot" = plain usesNot+ f "UsesObjectComposition" = plain usesObjectComposition+ f "UsesPatternMatching" = plain usesPatternMatching+ f "UsesRepeat" = plain usesRepeat+ f "UsesStaticMethodOverload" = plain usesStaticMethodOverload+ f "UsesStaticPolymorphism" = contextualized usesStaticPolymorphism'+ f "UsesSwitch" = plain usesSwitch+ f "UsesTemplateMethod" = plain usesTemplateMethod+ f "UsesType" = bound usesType+ f "UsesWhile" = plain usesWhile+ f "UsesYield" = plain usesYield+ f _ = Nothing - simple i _ = Just i- binded i b = Just $ i b+ contextualized :: ContextualizedInspection -> Maybe ContextualizedBoundInspection+ contextualized = Just . contextualizedBind + contextualizedBound :: ContextualizedBoundInspection -> Maybe ContextualizedBoundInspection+ contextualizedBound = Just++ plain :: Inspection -> Maybe ContextualizedBoundInspection+ plain = Just . contextualizedBind . contextualize++ bound :: BoundInspection -> Maybe ContextualizedBoundInspection+ bound = Just . boundContextualize
+ src/Language/Mulang/Analyzer/FragmentParser.hs view
@@ -0,0 +1,33 @@+module Language.Mulang.Analyzer.FragmentParser (+ parseFragment,+ parseFragment') where++import Control.Fallible (orFail)++import Language.Mulang+import Language.Mulang.Parsers (EitherParser, maybeToEither)+import Language.Mulang.Parsers.Haskell+import Language.Mulang.Parsers.JavaScript (parseJavaScript)+import Language.Mulang.Parsers.Prolog (parseProlog)+import Language.Mulang.Parsers.Java (parseJava)+import Language.Mulang.Parsers.Python (parsePython)+import Language.Mulang.Analyzer.Analysis (Fragment(..), Language(..))+import Language.Mulang.Builder (normalize, normalizeWith, NormalizationOptions)++parseFragment' :: Fragment -> Expression+parseFragment' = orFail . parseFragment++parseFragment :: Fragment -> Either String Expression+parseFragment (CodeSample language content) = (parserFor language) content+parseFragment (MulangSample ast options) = Right . (normalizerFor options) $ ast++parserFor :: Language -> EitherParser+parserFor Haskell = parseHaskell+parserFor Java = parseJava+parserFor JavaScript = maybeToEither parseJavaScript+parserFor Prolog = parseProlog+parserFor Python = parsePython++normalizerFor :: (Maybe NormalizationOptions) -> (Expression -> Expression)+normalizerFor Nothing = normalize+normalizerFor (Just options) = normalizeWith options
− src/Language/Mulang/Analyzer/SampleParser.hs
@@ -1,27 +0,0 @@-module Language.Mulang.Analyzer.SampleParser (- parseSample) where--import Language.Mulang-import Language.Mulang.Parsers (EitherParser, maybeToEither)-import Language.Mulang.Parsers.Haskell-import Language.Mulang.Parsers.JavaScript (parseJavaScript)-import Language.Mulang.Parsers.Prolog (parseProlog)-import Language.Mulang.Parsers.Java (parseJava)-import Language.Mulang.Parsers.Python (parsePython)-import Language.Mulang.Analyzer.Analysis (Sample(..), Language(..))-import Language.Mulang.Builder (normalize, normalizeWith, NormalizationOptions)--parseSample :: Sample -> Either String Expression-parseSample (CodeSample language content) = (parserFor language) content-parseSample (MulangSample ast options) = Right . (normalizerFor options) $ ast--parserFor :: Language -> EitherParser-parserFor Haskell = parseHaskell-parserFor Java = parseJava-parserFor JavaScript = maybeToEither parseJavaScript-parserFor Prolog = parseProlog-parserFor Python = parsePython--normalizerFor :: (Maybe NormalizationOptions) -> (Expression -> Expression)-normalizerFor Nothing = normalize-normalizerFor (Just options) = normalizeWith options
src/Language/Mulang/Analyzer/SmellsAnalyzer.hs view
@@ -8,8 +8,8 @@ import Data.List import Data.Maybe (fromMaybe) -analyseSmells :: Expression -> DomainLanguage -> SmellsSet -> [Expectation]-analyseSmells ast language set = concatMap (\smell -> detectSmell smell language ast) (smellsFor set)+analyseSmells :: Expression -> DomainLanguage -> Maybe SmellsSet -> [Expectation]+analyseSmells ast language = concatMap (\smell -> detectSmell smell language ast) . smellsFor . fromMaybe (NoSmells Nothing) detectSmell :: Smell -> DomainLanguage -> Expression -> [Expectation] detectSmell smell language = map (exectationFor smell) . detectionFor smell language
+ src/Language/Mulang/Analyzer/TestsAnalyzer.hs view
@@ -0,0 +1,20 @@+module Language.Mulang.Analyzer.TestsAnalyzer (+ analyseTests) where++import Language.Mulang+import Language.Mulang.Analyzer.Analysis (TestAnalysisType(..))+import Language.Mulang.Analyzer.FragmentParser (parseFragment')+import Language.Mulang.Builder (merge)+import Language.Mulang.Interpreter.Runner (runTests, TestResult(..))++import Data.Maybe (fromMaybe)++analyseTests :: Expression -> Maybe TestAnalysisType -> IO [TestResult]+analyseTests e analysis = analyseTests' e (fromMaybe NoTests analysis)++analyseTests' _ NoTests = return []+analyseTests' e (EmbeddedTests _) = runTests e e+analyseTests' e (ExternalTests test extra _) = runTests (merge e extraFragment) testFragment+ where+ testFragment = parseFragment' test+ extraFragment = fromMaybe None . fmap parseFragment' $ extra
src/Language/Mulang/Ast.hs view
@@ -19,6 +19,7 @@ EquationBody(..), Type(..), Expression(..),+ Assertion(..), Statement(..), Pattern(..), Identifier,@@ -187,6 +188,21 @@ -- ^ Generic symbol/atom literal | MuTuple [Expression] | MuList [Expression]+ | TestGroup Expression Expression+ -- ^ Generic test grouping expression such as describe, context, etc.+ | Test Expression Expression+ -- ^ Generic test expression such as it, etc.+ | Assert Bool Assertion+ -- ^ Generic assertion expression such as assert, expect, etc. The first parameter indicates whether the assertion is negated or not+ deriving (Eq, Show, Read, Generic, Ord)++data Assertion+ = Equality Expression Expression+ -- ^ assert equality between two expressions. e.g.: assert.equals(succ(3), 4)+ | Truth Expression+ -- ^ assert truthfulness of boolean expression. e.g.: assert(4 > 3)+ | Failure Expression Expression+ -- ^ assert expression fails with an error. e.g.: assert.throws(function () { throw("this breaks") }, "this breaks") deriving (Eq, Show, Read, Generic, Ord) -- | Mulang Patterns are not expressions, but are aimed to match them.
src/Language/Mulang/Builder.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DeriveGeneric #-} module Language.Mulang.Builder (+ merge, compact, compactMap, compactConcatMap,@@ -41,6 +42,14 @@ compact [] = None compact [e] = e compact es = Sequence es++merge :: Expression -> Expression -> Expression+merge e1 None = e1+merge None e2 = e2+merge (Sequence s1) (Sequence s2) = Sequence (s1 ++ s2)+merge (Sequence s1) e2 = Sequence (s1 ++ [e2])+merge e1 (Sequence s2) = Sequence (e1 : s2)+merge e1 e2 = Sequence [e1, e2] defaultNormalizationOptions :: NormalizationOptions defaultNormalizationOptions = NormalizationOptions {
src/Language/Mulang/Identifier.hs view
@@ -6,7 +6,8 @@ like, named, Identifier,- IdentifierPredicate) where+ IdentifierPredicate,+ PredicateModifier) where import Data.List (isInfixOf) @@ -14,8 +15,9 @@ -- | Mulang does not assume any special naming convention or format type Identifier = String type IdentifierPredicate = Identifier -> Bool+type PredicateModifier = IdentifierPredicate -> IdentifierPredicate -andAlso :: IdentifierPredicate -> IdentifierPredicate -> IdentifierPredicate+andAlso :: IdentifierPredicate -> PredicateModifier andAlso p1 p2 identifier = p1 identifier && p2 identifier anyOf :: [Identifier] -> IdentifierPredicate
src/Language/Mulang/Inspector.hs view
@@ -1,8 +1,10 @@ module Language.Mulang.Inspector ( Inspection,- IdentifierInspection,- module Language.Mulang.Inspector.Generic,+ BoundInspection,+ module Language.Mulang.Inspector.Contextualized, module Language.Mulang.Inspector.Combiner,+ module Language.Mulang.Inspector.Generic,+ module Language.Mulang.Inspector.Query, module Language.Mulang.Inspector.Typed, module Language.Mulang.Inspector.ObjectOriented, module Language.Mulang.Inspector.ObjectOriented.Polymorphism,@@ -10,12 +12,15 @@ module Language.Mulang.Inspector.Logic, module Language.Mulang.Inspector.Procedural) where -import Language.Mulang.Inspector.Primitive (Inspection, IdentifierInspection)-import Language.Mulang.Inspector.Generic-import Language.Mulang.Inspector.Typed import Language.Mulang.Inspector.Combiner-import Language.Mulang.Inspector.ObjectOriented-import Language.Mulang.Inspector.ObjectOriented.Polymorphism+import Language.Mulang.Inspector.Bound (BoundInspection)+import Language.Mulang.Inspector.Contextualized import Language.Mulang.Inspector.Functional+import Language.Mulang.Inspector.Generic import Language.Mulang.Inspector.Logic+import Language.Mulang.Inspector.ObjectOriented+import Language.Mulang.Inspector.ObjectOriented.Polymorphism+import Language.Mulang.Inspector.Primitive (Inspection) import Language.Mulang.Inspector.Procedural+import Language.Mulang.Inspector.Query+import Language.Mulang.Inspector.Typed
+ src/Language/Mulang/Inspector/Bound.hs view
@@ -0,0 +1,18 @@+module Language.Mulang.Inspector.Bound (+ bind,+ containsBoundDeclaration,+ BoundInspection) where++import Language.Mulang.Inspector.Primitive (Inspection)+import Language.Mulang.Identifier (IdentifierPredicate)+import Language.Mulang.Ast (Expression)+import Language.Mulang.Generator (boundDeclarations)+import Data.List.Extra(has)++type BoundInspection = IdentifierPredicate -> Inspection++bind :: Inspection -> BoundInspection+bind = const++containsBoundDeclaration :: (Expression -> Bool) -> BoundInspection+containsBoundDeclaration f b = has f (boundDeclarations b)
src/Language/Mulang/Inspector/Combiner.hs view
@@ -5,32 +5,37 @@ scoped, scopedList, transitive,- transitiveList) where+ transitiveList,+ Modifier) where import Language.Mulang.Ast import Language.Mulang.Generator (transitiveReferencedIdentifiers, declarationsOf, declaredIdentifiers) import Language.Mulang.Inspector.Primitive +type Modifier = Inspection -> Inspection+ detect :: Inspection -> Expression -> [Identifier] detect i expression = filter (`inspection` expression) $ declaredIdentifiers expression- where inspection = scoped i+ where inspection = scoped' i -alternative :: Inspection -> Inspection -> Inspection+alternative :: Inspection -> Modifier alternative i1 i2 expression = i1 expression || i2 expression -negative :: Inspection -> Inspection+negative :: Modifier negative f = not . f -scoped :: Inspection -> Identifier -> Inspection-scoped inspection scope = any inspection . declarationsOf scope+scoped :: Identifier -> Modifier+scoped scope inspection = any inspection . declarationsOf scope -scopedList :: Inspection -> [Identifier] -> Inspection-scopedList i = foldl scoped i . reverse+scopedList :: [Identifier] -> Modifier+scopedList scopes i = foldl scoped' i . reverse $ scopes -transitive :: Inspection -> Identifier -> Inspection-transitive inspection identifier code = any (`scopedInspection` code) . transitiveReferencedIdentifiers identifier $ code- where scopedInspection = scoped inspection+transitive :: Identifier -> Modifier+transitive identifier inspection code = any (`scopedInspection` code) . transitiveReferencedIdentifiers identifier $ code+ where scopedInspection = scoped' inspection -transitiveList :: Inspection -> [Identifier] -> Inspection-transitiveList i identifiers = transitive (scopedList i (init identifiers)) (last identifiers)+transitiveList :: [Identifier] -> Modifier+transitiveList identifiers i = transitive (last identifiers) (scopedList (init identifiers) i)++scoped' = flip scoped
+ src/Language/Mulang/Inspector/Contextualized.hs view
@@ -0,0 +1,65 @@+module Language.Mulang.Inspector.Contextualized (+ decontextualize,+ contextualize,+ contextualized,+ contextualizedBind,+ boundContextualize,+ contextualizedScoped,+ contextualizedScopedList,+ contextualizedTransitive,+ contextualizedTransitiveList,+ ContextualizedInspection,+ ContextualizedModifier,+ ContextualizedBoundInspection) where++import Language.Mulang.Ast+import Language.Mulang.Identifier (IdentifierPredicate)+import Language.Mulang.Inspector.Bound (BoundInspection)+import Language.Mulang.Inspector.Combiner (scoped, scopedList, transitive, transitiveList, Modifier)+import Language.Mulang.Inspector.Primitive (Inspection)++type ContextualizedInspection = Expression -> Inspection+type ContextualizedBoundInspection = IdentifierPredicate -> ContextualizedInspection+type ContextualizedModifier = ContextualizedInspection -> ContextualizedInspection++--+-- Lifts+--++contextualize :: Inspection -> ContextualizedInspection+contextualize = const++-- Generalized version of bind to accept contextualized inspections+contextualizedBind :: ContextualizedInspection -> ContextualizedBoundInspection+contextualizedBind = const++-- Generalized version of contextualize to accept bound inspections+boundContextualize :: BoundInspection -> ContextualizedBoundInspection+boundContextualize i = contextualize . i++--+-- Unlift+--++decontextualize :: ContextualizedInspection -> Inspection+decontextualize inspection = \expression -> inspection expression expression++--+-- Modifiers+--++contextualized :: Modifier -> ContextualizedModifier+contextualized f inspection = \context -> f (inspection context)++contextualizedScoped :: Identifier -> ContextualizedModifier+contextualizedScoped scope = contextualized (scoped scope)++contextualizedScopedList :: [Identifier] -> ContextualizedModifier+contextualizedScopedList scope = contextualized (scopedList scope)++contextualizedTransitive :: Identifier -> ContextualizedModifier+contextualizedTransitive scope = contextualized (transitive scope)++contextualizedTransitiveList :: [Identifier] -> ContextualizedModifier+contextualizedTransitiveList scope = contextualized (transitiveList scope)+
src/Language/Mulang/Inspector/Generic.hs view
@@ -1,39 +1,43 @@ module Language.Mulang.Inspector.Generic (- parses, assigns, calls,- uses,- usesIf,- usesYield,- usesFor, declares,- declaresVariable,- declaresRecursively,- declaresEntryPoint,- declaresFunction, declaresComputation, declaresComputationWithArity, declaresComputationWithArity',- usesAnonymousVariable,+ declaresEntryPoint,+ declaresFunction,+ declaresRecursively,+ declaresVariable,+ delegates,+ delegates',+ parses, raises, rescues,+ uses,+ usesAnonymousVariable,+ usesExceptionHandling, usesExceptions,- usesExceptionHandling) where+ usesFor,+ usesIf,+ usesYield) where import Language.Mulang.Ast+import Language.Mulang.Generator (declaredIdentifiers, expressions, declarations, referencedIdentifiers) import Language.Mulang.Identifier+import Language.Mulang.Inspector.Bound (containsBoundDeclaration, BoundInspection)+import Language.Mulang.Inspector.Contextualized (decontextualize, ContextualizedBoundInspection) import Language.Mulang.Inspector.Primitive-import Language.Mulang.Generator (declaredIdentifiers, referencedIdentifiers)+import Language.Mulang.Inspector.Query (inspect, select) import Data.Maybe (listToMaybe) import Data.List.Extra (has) - -- | Inspection that tells whether an expression is equal to a given piece of code after being parsed parses :: (String -> Expression) -> String -> Inspection parses parser code = (== (parser code)) -assigns :: IdentifierInspection+assigns :: BoundInspection assigns predicate = containsExpression f where f (Assignment name _) = predicate name f (Variable name _) = predicate name@@ -42,16 +46,25 @@ -- | Inspection that tells whether an expression uses the the given target identifier -- in its definition-uses :: IdentifierInspection+uses :: BoundInspection uses p = containsExpression f where f = any p . referencedIdentifiers -calls :: IdentifierInspection+calls :: BoundInspection calls p = containsExpression f where f (Call (Reference id) _ ) = p id f _ = False +delegates :: BoundInspection+delegates = decontextualize . delegates' +delegates' :: ContextualizedBoundInspection+delegates' p context expression = inspect $ do+ (Subroutine name1 _) <- declarations context+ (Call (Reference name2) _) <- expressions expression+ select (name1 == name2)+ select (p name1)+ -- | Inspection that tells whether an expression uses ifs -- in its definition usesIf :: Inspection@@ -71,13 +84,13 @@ -- | Inspection that tells whether a top level declaration exists-declares :: IdentifierInspection+declares :: BoundInspection declares = containsBoundDeclaration f where f (TypeSignature _ _) = False f _ = True -- | Inspection that tells whether an expression is direct recursive-declaresRecursively :: IdentifierInspection+declaresRecursively :: BoundInspection declaresRecursively = containsBoundDeclaration f where f e | (Just name) <- (nameOf e) = uses (named name) e | otherwise = False@@ -86,29 +99,29 @@ nameOf = listToMaybe . declaredIdentifiers -declaresFunction :: IdentifierInspection+declaresFunction :: BoundInspection declaresFunction = containsBoundDeclaration f where f (Function _ _) = True f _ = False -declaresVariable :: IdentifierInspection+declaresVariable :: BoundInspection declaresVariable = containsBoundDeclaration f where f (Variable _ _) = True f _ = False -declaresEntryPoint :: IdentifierInspection+declaresEntryPoint :: BoundInspection declaresEntryPoint = containsBoundDeclaration f where f (EntryPoint _ _) = True f _ = False -- | Inspection that tells whether a top level computation declaration exists-declaresComputation :: IdentifierInspection+declaresComputation :: BoundInspection declaresComputation = declaresComputationWithArity' (const True) -declaresComputationWithArity :: Int -> IdentifierInspection+declaresComputationWithArity :: Int -> BoundInspection declaresComputationWithArity arity = declaresComputationWithArity' (== arity) -declaresComputationWithArity' :: (Int -> Bool) -> IdentifierInspection+declaresComputationWithArity' :: (Int -> Bool) -> BoundInspection declaresComputationWithArity' arityPredicate = containsBoundDeclaration f where f (Subroutine _ es) = any equationArityIs es f (Clause _ args _) = argsHaveArity args@@ -118,7 +131,7 @@ argsHaveArity = arityPredicate.length -raises :: IdentifierInspection+raises :: BoundInspection raises predicate = containsExpression f where f (Raise (New (Reference n) _)) = predicate n f (Raise (Reference n)) = predicate n@@ -129,7 +142,7 @@ where f (Raise _) = True f _ = False -rescues :: IdentifierInspection+rescues :: BoundInspection rescues predicate = containsExpression f where f (Try _ rescues _) = any (matchesType predicate) . map fst $ rescues f _ = False
src/Language/Mulang/Inspector/Logic.hs view
@@ -12,16 +12,17 @@ import Language.Mulang.Ast import Language.Mulang.Identifier-import Language.Mulang.Inspector.Primitive (Inspection, IdentifierInspection, containsExpression, containsBoundDeclaration)+import Language.Mulang.Inspector.Primitive (Inspection, containsExpression)+import Language.Mulang.Inspector.Bound (BoundInspection, containsBoundDeclaration) import Language.Mulang.Inspector.Generic (uses) import Language.Mulang.Inspector.Combiner (alternative) -declaresFact :: IdentifierInspection+declaresFact :: BoundInspection declaresFact = containsBoundDeclaration f where f (Fact _ _) = True f _ = False -declaresRule :: IdentifierInspection+declaresRule :: BoundInspection declaresRule = containsBoundDeclaration f where f (Rule _ _ _) = True f _ = False@@ -56,5 +57,5 @@ f (Exist "is" [(VariablePattern _), _]) = True f _ = False -declaresPredicate :: IdentifierInspection+declaresPredicate :: BoundInspection declaresPredicate pred = alternative (declaresFact pred) (declaresRule pred)
src/Language/Mulang/Inspector/ObjectOriented.hs view
@@ -15,26 +15,25 @@ import Language.Mulang.Ast import Language.Mulang.Identifier-import Language.Mulang.Inspector.Primitive (- Inspection, IdentifierInspection,- containsExpression, containsDeclaration, containsBoundDeclaration)+import Language.Mulang.Inspector.Bound (BoundInspection, containsBoundDeclaration)+import Language.Mulang.Inspector.Primitive (Inspection, containsExpression, containsDeclaration) -implements :: IdentifierInspection+implements :: BoundInspection implements predicate = containsExpression f where f (Implement (Reference name)) = predicate name f _ = False -includes :: IdentifierInspection+includes :: BoundInspection includes predicate = containsExpression f where f (Include (Reference name)) = predicate name f _ = False -inherits :: IdentifierInspection+inherits :: BoundInspection inherits predicate = containsDeclaration f where f (Class _ (Just name) _) = predicate name f _ = False -instantiates :: IdentifierInspection+instantiates :: BoundInspection instantiates predicate = containsExpression f where f (New (Reference name) _) = predicate name f _ = False@@ -45,35 +44,35 @@ usesMixins :: Inspection usesMixins = includes anyone -declaresObject :: IdentifierInspection+declaresObject :: BoundInspection declaresObject = containsBoundDeclaration f where f (Object _ _) = True f _ = False -declaresSuperclass :: IdentifierInspection+declaresSuperclass :: BoundInspection declaresSuperclass = inherits -declaresClass :: IdentifierInspection+declaresClass :: BoundInspection declaresClass = containsBoundDeclaration f where f (Class _ _ _) = True f _ = False -declaresEnumeration :: IdentifierInspection+declaresEnumeration :: BoundInspection declaresEnumeration = containsBoundDeclaration f where f (Enumeration _ _) = True f _ = False -declaresInterface :: IdentifierInspection+declaresInterface :: BoundInspection declaresInterface = containsBoundDeclaration f where f (Interface _ _ _) = True f _ = False -declaresAttribute :: IdentifierInspection+declaresAttribute :: BoundInspection declaresAttribute = containsBoundDeclaration f where f (Attribute _ _) = True f _ = False -declaresMethod :: IdentifierInspection+declaresMethod :: BoundInspection declaresMethod = containsBoundDeclaration f where f (Method _ _) = True f _ = False
src/Language/Mulang/Inspector/ObjectOriented/Polymorphism.hs view
@@ -2,7 +2,9 @@ module Language.Mulang.Inspector.ObjectOriented.Polymorphism ( usesDyamicPolymorphism,+ usesDyamicPolymorphism', usesStaticPolymorphism,+ usesStaticPolymorphism', usesTemplateMethod, usesObjectComposition, usesDynamicMethodOverload,@@ -11,10 +13,11 @@ import Language.Mulang.Ast import Language.Mulang.Identifier import Language.Mulang.Inspector.Primitive (Inspection)+import Language.Mulang.Inspector.Contextualized (ContextualizedInspection, decontextualize)+import Language.Mulang.Inspector.Query (inspect, select, selectCount) import Language.Mulang.Inspector.ObjectOriented (implements, declaresMethod) import Language.Mulang.Inspector.Typed (usesType) -import Control.Monad (MonadPlus, guard) import Language.Mulang.Generator (Generator, declarations, expressions) usesDynamicMethodOverload :: Inspection@@ -22,56 +25,56 @@ klass@(Class _ _ _) <- declarations expression (SimpleMethod n1 (length -> a1) _) <- declarations klass (SimpleMethod n2 (length -> a2) _) <- declarations klass- guard (n1 == n2 && a1 /= a2)+ select (n1 == n2 && a1 /= a2) usesStaticMethodOverload :: Inspection usesStaticMethodOverload expression = inspect $ do klass@(Class _ _ _) <- declarations expression s1@(SubroutineSignature n1 _ _ _) <- declarations klass s2@(SubroutineSignature n2 _ _ _) <- declarations klass- guard (n1 == n2 && s1 /= s2)+ select (n1 == n2 && s1 /= s2) usesObjectComposition :: Inspection usesObjectComposition expression = inspect $ do klass@(Class _ _ _) <- declarations expression (Attribute name1 _) <- declarations klass (Send (Reference name2) _ _) <- expressions klass- guard (name1 == name2)+ select (name1 == name2) usesTemplateMethod :: Inspection usesTemplateMethod expression = inspect $ do klass@(Class _ _ _) <- declarations expression (SimpleSend Self selector _) <- expressions klass- guard (not . declaresMethod (named selector) $ klass)+ select (not . declaresMethod (named selector) $ klass) usesDyamicPolymorphism :: Inspection-usesDyamicPolymorphism expression = inspect $ do+usesDyamicPolymorphism = decontextualize usesDyamicPolymorphism'++usesDyamicPolymorphism' :: ContextualizedInspection+usesDyamicPolymorphism' context expression = inspect $ do (SimpleSend _ selector _) <- expressions expression- guardCount (>1) (methodDeclarationsOf selector expression)+ selectCount (>1) (methodDeclarationsOf selector context) usesStaticPolymorphism :: Inspection-usesStaticPolymorphism expression = inspect $ do- interface@(Interface interfaceId _ _) <- declarations expression+usesStaticPolymorphism = decontextualize usesStaticPolymorphism'++usesStaticPolymorphism' :: ContextualizedInspection+usesStaticPolymorphism' context expression = inspect $ do+ interface@(Interface interfaceId _ _) <- declarations context (SubroutineSignature _ _ _ _) <- declarations interface- guard (usesType (named interfaceId) expression)- guardCount (>1) (implementorsOf interfaceId expression)+ select (usesType (named interfaceId) expression)+ selectCount (>1) (implementorsOf interfaceId context) -- private -inspect :: [a] -> Bool-inspect = not.null--guardCount :: MonadPlus m => (Int -> Bool) -> [a] -> m ()-guardCount condition list = guard (condition . length $ list)- methodDeclarationsOf :: Identifier -> Generator Expression methodDeclarationsOf selector e = do m@(Method s _) <- declarations e- guard (s == selector)+ select (s == selector) return m implementorsOf :: Identifier -> Generator Expression implementorsOf id e = do m@(Class _ _ _) <- declarations e- guard (implements (named id) m)+ select (implements (named id) m) return m
src/Language/Mulang/Inspector/Primitive.hs view
@@ -1,29 +1,23 @@ module Language.Mulang.Inspector.Primitive ( containsExpression, containsDeclaration,- containsBoundDeclaration, containsBody, matchesType,- Inspection,- IdentifierInspection) where+ Inspection) where import Language.Mulang.Ast import Language.Mulang.Identifier (IdentifierPredicate)-import Language.Mulang.Generator (expressions, boundDeclarations, equationBodies, declarations)+import Language.Mulang.Generator (expressions, equationBodies, declarations) import Data.List.Extra (has) -type Inspection = Expression -> Bool-type IdentifierInspection = IdentifierPredicate -> Inspection+type Inspection = Expression -> Bool containsExpression :: (Expression -> Bool) -> Inspection containsExpression f = has f expressions containsBody :: (EquationBody -> Bool)-> Inspection containsBody f = has f equationBodies--containsBoundDeclaration :: (Expression -> Bool) -> IdentifierInspection-containsBoundDeclaration f b = has f (boundDeclarations b) containsDeclaration :: (Expression -> Bool) -> Inspection containsDeclaration f = has f declarations
src/Language/Mulang/Inspector/Procedural.hs view
@@ -8,10 +8,11 @@ declaresProcedure) where import Language.Mulang.Ast-import Language.Mulang.Inspector.Primitive (Inspection, IdentifierInspection, containsExpression, containsBoundDeclaration)+import Language.Mulang.Inspector.Primitive (Inspection, containsExpression)+import Language.Mulang.Inspector.Bound (BoundInspection, containsBoundDeclaration) import Language.Mulang.Inspector.Generic (usesYield) -declaresProcedure :: IdentifierInspection+declaresProcedure :: BoundInspection declaresProcedure = containsBoundDeclaration f where f (Procedure _ _) = True f _ = False
+ src/Language/Mulang/Inspector/Query.hs view
@@ -0,0 +1,20 @@+module Language.Mulang.Inspector.Query (+ inspect,+ select,+ selectCount,+ Query) where++import Control.Monad (guard)++import Language.Mulang.Ast (Expression)++type Query a = [a]++inspect :: Query () -> Bool+inspect = not.null++select :: Bool -> Query ()+select = guard++selectCount :: (Int -> Bool) -> Query Expression -> Query ()+selectCount condition list = select (condition . length $ list)
src/Language/Mulang/Inspector/Typed.hs view
@@ -7,35 +7,36 @@ usesType) where import Language.Mulang.Ast-import Language.Mulang.Inspector.Primitive (IdentifierInspection, containsDeclaration, containsBoundDeclaration)+import Language.Mulang.Inspector.Primitive (containsDeclaration)+import Language.Mulang.Inspector.Bound (BoundInspection, containsBoundDeclaration) -declaresTypeAlias :: IdentifierInspection+declaresTypeAlias :: BoundInspection declaresTypeAlias = containsBoundDeclaration f where f (TypeAlias _ _) = True f _ = False -typesReturnAs :: IdentifierInspection+typesReturnAs :: BoundInspection typesReturnAs predicate = containsDeclaration f where f (SubroutineSignature _ _ name _) = predicate name f _ = False -typesParameterAs :: IdentifierInspection+typesParameterAs :: BoundInspection typesParameterAs predicate = containsDeclaration f where f (SubroutineSignature _ names _ _) = any predicate names f _ = False -typesAs :: IdentifierInspection+typesAs :: BoundInspection typesAs predicate = containsDeclaration f where f (VariableSignature _ name _) = predicate name f _ = False -usesType :: IdentifierInspection+usesType :: BoundInspection usesType predicate = containsDeclaration f where f (VariableSignature _ name _) = predicate name f (SubroutineSignature _ args ret _) = any predicate (ret:args) f _ = False -declaresTypeSignature :: IdentifierInspection+declaresTypeSignature :: BoundInspection declaresTypeSignature = containsBoundDeclaration f where f (TypeSignature _ _) = True f _ = False
+ src/Language/Mulang/Interpreter.hs view
@@ -0,0 +1,382 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Language.Mulang.Interpreter (+ defaultContext,+ dereference,+ dereference',+ eval,+ eval',+ evalExpr,+ evalRaising,+ nullRef,+ ExecutionContext(..),+ Value(..)+) where++import Data.Map.Strict (Map)+import Data.Maybe (fromMaybe, fromJust)+import Data.List (find)+import qualified Data.Map.Strict as Map+import Control.Monad (forM)+import Control.Monad.State.Class+import Control.Monad.Loops+import Control.Monad.State.Strict+import Control.Monad.Cont+import Data.Fixed (mod')++import qualified Language.Mulang as Mu++type Executable m = ContT Reference (StateT ExecutionContext IO) m++type Callback = Reference -> Executable ()++newtype Reference = Reference Int deriving (Show, Eq, Ord)++type ObjectSpace = Map Reference Value++instance Show ExecutionContext where+ show (ExecutionContext globalObjects scopes _ _ _) =+ "ExecutionContext { globalObjects = " ++ show globalObjects ++ ", scopes = " ++ show scopes ++ " }"++data ExecutionContext = ExecutionContext { globalObjects :: ObjectSpace+ , scopes :: [Reference]+ , currentException :: Maybe Reference+ , currentReturnCallback :: Callback+ , currentRaiseCallback :: Callback+ }++data Value = MuString String+ | MuFunction [Reference] Mu.SubroutineBody+ | MuList [Reference]+ -- | The reference is the reference to the localScope+ | MuNumber Double+ | MuBool Bool+ | MuObject (Map String Reference)+ | MuNull+ deriving (Show, Eq)++defaultContext = ExecutionContext+ { globalObjects = Map.singleton (Reference 1) (MuObject Map.empty)+ , scopes = [Reference 1]+ , currentException = Nothing+ , currentRaiseCallback = \r -> do+ v <- dereference r+ error $ "Exception thrown outside try: " ++ show v+ , currentReturnCallback = \_r -> error "Called return from outside a function"+ }++eval' :: ExecutionContext -> Executable Reference -> IO (Reference, ExecutionContext)+eval' ctx ref = runStateT (runContT ref return) ctx++eval :: ExecutionContext -> Mu.Expression -> IO (Reference, ExecutionContext)+eval ctx expr = eval' ctx (evalExpr expr)++evalRaising :: ExecutionContext -> Mu.Expression -> Executable (Reference, Maybe Reference)+evalRaising context expr = do+ resultRef <- callCC $ \raiseCallback -> do+ put (context { currentRaiseCallback = raiseCallback })+ evalExpr expr+ return nullRef+ lastException <- gets currentException+ return (resultRef, lastException)++evalExpressionsWith :: [Mu.Expression] -> ([Value] -> Executable Reference) -> Executable Reference+evalExpressionsWith expressions f = do+ params <- mapM (\e -> evalExpr e >>= dereference) expressions+ f params++evalExpr :: Mu.Expression -> Executable Reference+evalExpr (Mu.Sequence expressions) = last <$> forM expressions evalExpr+evalExpr (Mu.Lambda params body) = do+ executionFrames <- gets scopes+ createReference $+ MuFunction executionFrames [Mu.Equation params (Mu.UnguardedBody body)]++evalExpr (Mu.Subroutine name body) = do+ executionFrames <- gets scopes+ let function = MuFunction executionFrames body+ ref <- createReference function+ unless (null name) (setLocalVariable name ref) -- if function has no name we avoid registering it+ return ref++evalExpr (Mu.Print expression) = do+ parameter :: Value <- evalExpr expression >>= dereference+ liftIO $ print parameter+ return nullRef++evalExpr (Mu.Assert negated (Mu.Truth expression)) =+ evalExpressionsWith [expression] f+ where f [MuBool result]+ | result /= negated = return nullRef+ | otherwise = raiseString $ "Expected " ++ (show . not $ negated) ++ " but got: " ++ show result++evalExpr (Mu.Assert negated (Mu.Equality expected actual)) =+ evalExpressionsWith [expected, actual] f+ where f [v1, v2]+ | muEquals v1 v2 /= negated = return nullRef+ | otherwise = raiseString $ "Expected " ++ show v1 ++ " but got: " ++ show v2++evalExpr (Mu.Application (Mu.Reference ">=") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 >= n2++evalExpr (Mu.Application (Mu.Reference "%") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuNumber $ n1 `mod'` n2+ f params = error $ "Bad parameters, expected two numbers but got " ++ show params++evalExpr (Mu.Application (Mu.Reference ">") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 > n2+ f params = error $ "Bad parameters, expected two bools but got " ++ show params++-- TODO make this evaluation non strict on both parameters+evalExpr (Mu.Application (Mu.Reference "||") expressions) =+ evalExpressionsWith expressions f+ where f [MuBool b1, MuBool b2] = createReference $ MuBool $ b1 || b2+ f params = error $ "Bad parameters, expected two bools but got " ++ show params++-- TODO make this evaluation non strict on both parameters+evalExpr (Mu.Application (Mu.Reference "&&") expressions) =+ evalExpressionsWith expressions f+ where f [MuBool b1, MuBool b2] = createReference $ MuBool $ b1 && b2+ f params = error $ "Bad parameters, expected two bools but got " ++ show params++evalExpr (Mu.Application (Mu.Reference "!") expressions) =+ evalExpressionsWith expressions f+ where f [MuBool b] = createReference $ MuBool $ not b+ f params = error $ "Bad parameters, expected one bool but got " ++ show params++evalExpr (Mu.Application (Mu.Reference "*") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuNumber $ n1 * n2++evalExpr (Mu.Application Mu.Equal expressions) = do+ params <- mapM evalExpr expressions+ let [r1, r2] = params+ muValuesEqual r1 r2++evalExpr (Mu.Application Mu.NotEqual expressions) = do+ evalExpr $ Mu.Application (Mu.Reference "!") [Mu.Application Mu.Equal expressions]++evalExpr (Mu.Application (Mu.Reference "<=") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 <= n2+ f params = raiseString $ "Bad parameters, expected two numbers but got " ++ show params++evalExpr (Mu.Application (Mu.Reference "<") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 < n2+ f params = raiseString $ "Bad parameters, expected two numbers but got " ++ show params++evalExpr (Mu.Application (Mu.Reference "+") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuNumber $ n1 + n2++evalExpr (Mu.Application (Mu.Reference "-") expressions) =+ evalExpressionsWith expressions f+ where f [MuNumber n1, MuNumber n2] = createReference $ MuNumber $ n1 - n2++evalExpr (Mu.MuList expressions) = do+ refs <- forM expressions evalExpr+ createReference $ MuList refs++evalExpr (Mu.New klass expressions) = do+ (MuFunction locals ([Mu.SimpleEquation params body])) <- evalExpr klass >>= dereference+ objReference <- createReference $ MuObject Map.empty+ thisContext <- createReference $ MuObject $ Map.singleton "this" objReference+ paramsContext <- evalParams params expressions+ runFunction (thisContext:paramsContext:locals) body+ return objReference++evalExpr (Mu.Application function expressions) = do+ (MuFunction locals ([Mu.SimpleEquation params body])) <- evalExpr function >>= dereference+ paramsContext <- evalParams params expressions+ returnValue <- runFunction (paramsContext:locals) (body)+ return returnValue++evalExpr (Mu.If cond thenBranch elseBranch) = do+ v <- evalCondition cond+ if v then evalExpr thenBranch else evalExpr elseBranch++evalExpr (Mu.MuNumber n) = createReference $ MuNumber n+evalExpr (Mu.MuNil) = return nullRef+evalExpr (Mu.MuBool b) = createReference $ MuBool b+evalExpr (Mu.MuString s) = createReference $ MuString s+evalExpr (Mu.Return e) = do+ ref <- evalExpr e+ currentReturn <- gets (currentReturnCallback)+ currentReturn ref+ return ref -- Unreachable+evalExpr (Mu.Variable name expr) = do+ r <- evalExpr expr+ setLocalVariable name r+ return r++evalExpr (Mu.While cond expr) = do+ whileM (evalCondition cond) (evalExpr expr)+ return nullRef++evalExpr (Mu.ForLoop beforeExpr cond afterExpr expr) = do+ evalExpr beforeExpr+ whileM (evalCondition cond) $ do+ evalExpr expr+ evalExpr afterExpr+ return nullRef++evalExpr (Mu.Assignment name expr) = do+ valueRef <- evalExpr expr+ frameRef <- findFrameForName' name+ case frameRef of+ Just ref -> updateRef ref (addAttrToObject name valueRef)+ Nothing -> setLocalVariable name valueRef+ return valueRef++evalExpr (Mu.Try expr [( Mu.VariablePattern exName, catchExpr)] finallyExpr) = do+ context <- get+ (resultRef, lastException) <- evalRaising context expr+ modify' (\c ->+ c { currentReturnCallback = currentReturnCallback context+ , currentRaiseCallback = currentRaiseCallback context+ , currentException = Nothing+ })+ case lastException of+ Nothing -> return resultRef+ Just ref -> do+ setLocalVariable exName ref+ evalExpr catchExpr++ evalExpr finallyExpr++evalExpr (Mu.Raise expr) = raiseInternal =<< evalExpr expr++evalExpr (Mu.Reference name) = findReferenceForName name+evalExpr (Mu.None) = return nullRef+evalExpr e = raiseString $ "Unkown expression: " ++ show e++evalCondition :: Mu.Expression -> Executable Bool+evalCondition cond = evalExpr cond >>= dereference >>= muBool+ where+ muBool (MuBool value) = return value+ muBool v = raiseString $ "Boolean expected, got: " ++ show v++evalParams :: [Mu.Pattern] -> [Mu.Expression] -> Executable Reference+evalParams params arguments = do+ evaluatedParams <- forM arguments evalExpr+ let localsAfterParameters = Map.fromList $ zip (getParamNames params) (evaluatedParams ++ repeat nullRef)+ createReference $ MuObject localsAfterParameters++raiseInternal :: Reference -> Executable b+raiseInternal exceptionRef = do+ raiseCallback <- gets currentRaiseCallback+ modify' (\c -> c {currentException = Just exceptionRef})+ raiseCallback exceptionRef+ raiseString "Unreachable" -- the callback above should never allow this to execute++raiseString :: String -> Executable a+raiseString s = do+ raiseInternal =<< (createReference $ MuString s)++muValuesEqual r1 r2+ | r1 == r2 = createReference $ MuBool True+ | otherwise = do+ v1 <- dereference r1+ v2 <- dereference r2+ createReference $ MuBool $ muEquals v1 v2++muEquals (MuBool b1) (MuBool b2) = b1 == b2+muEquals (MuNumber n1) (MuNumber n2) = n1 == n2+muEquals (MuString s1) (MuString s2) = s1 == s2+muEquals MuNull MuNull = True+muEquals _ _ = False++getParamNames :: [Mu.Pattern] -> [String]+getParamNames = fmap (\(Mu.VariablePattern n) -> n)++runFunction :: [Reference] -> Mu.Expression -> Executable Reference+runFunction functionEnv body = do+ context <- get+ returnValue <- callCC $ \(returnCallback) -> do+ put (context { scopes = functionEnv, currentReturnCallback = returnCallback })+ evalExpr body+ return nullRef+ modify' (\c -> c { scopes = scopes context+ , currentReturnCallback = currentReturnCallback context+ , currentRaiseCallback = currentRaiseCallback context+ , currentException = currentException context+ })+ return returnValue++findFrameForName :: String -> Executable Reference+findFrameForName name = do+ maybe (raiseString $ "Reference not found for name '" ++ name ++ "'") return+ =<< findFrameForName' name++findFrameForName' :: String -> Executable (Maybe Reference)+findFrameForName' name = do+ framesRefs <- gets scopes+ frames :: [(Reference, Map String Reference)] <- forM framesRefs $ \ref -> do+ dereference ref >>= \value -> case value of+ (MuObject context) -> return (ref, context)+ v -> error $ "Finding '" ++ name ++ "' the frame I got a non object " ++ show v++ return $ fmap fst . find (Map.member name . snd) $ frames++findReferenceForName :: String -> Executable Reference+findReferenceForName name = do+ ref <- findFrameForName name+ (MuObject context) <- dereference ref+ return $ context Map.! name++getMaxKey :: Map k a -> Maybe k+getMaxKey m = case Map.maxViewWithKey m of+ Just ((k, _a), _) -> Just k+ _ -> Nothing++nullRef = Reference 0++dereference' :: ObjectSpace -> Reference -> Value+dereference' _ (Reference 0) = MuNull+dereference' objectSpace ref = do+ fromMaybe (error $ "Failed to find ref " ++ show ref ++ " in " ++ show objectSpace) .+ Map.lookup ref $+ objectSpace++dereference :: Reference -> Executable Value+dereference ref = do+ objectSpace <- gets globalObjects+ return $ dereference' objectSpace ref++updateGlobalObjects f context =+ context { globalObjects = f $ globalObjects context }++updateLocalVariables f context =+ context { scopes = f $ scopes context }++incrementRef (Reference n) = Reference $ n + 1++createReference :: Value -> Executable Reference+createReference value = do+ nextReferenceId :: Reference <- gets (fromJust . fmap incrementRef . getMaxKey . globalObjects)+ modify (updateGlobalObjects $ Map.insert nextReferenceId value)+ return nextReferenceId++currentFrame :: Executable Reference+currentFrame = gets (head . scopes)++setLocalVariable :: String -> Reference -> Executable ()+setLocalVariable name ref = do+ frame <- currentFrame+ updateRef frame (addAttrToObject name ref)++addAttrToObject :: String -> Reference -> Value -> Value+addAttrToObject k r (MuObject map) = MuObject $ Map.insert k r map+addAttrToObject k _r v = error $ "Tried adding " ++ k ++ " to a non object: " ++ show v++putRef :: Reference -> Value -> Executable ()+putRef ref = modify . updateGlobalObjects . Map.insert ref++updateRef :: Reference -> (Value -> Value) -> Executable ()+updateRef ref f = do+ val <- dereference ref+ putRef ref (f val)
+ src/Language/Mulang/Interpreter/Runner.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE DeriveGeneric #-}++module Language.Mulang.Interpreter.Runner (+ runTests,+ runTestsForDir,+ TestResult(..),+ TestStatus(..)) where++import GHC.Generics++import Control.Monad (forM)+import Control.Monad.State.Strict+import Data.Maybe (fromMaybe, fromJust)+import Data.List (intercalate)++import qualified Language.Mulang.Ast as Mu+import Language.Mulang.Interpreter+import Language.Mulang.Parsers (MaybeParser)++data TestResult+ = TestResult { description :: [String], status :: TestStatus } deriving (Generic, Show, Eq)++data TestStatus+ = Success+ | Failure String+ deriving (Generic, Show, Eq)++data MuTest = MuTest [String] Mu.Expression deriving (Show)++runTestsForDir :: String -> String -> MaybeParser -> IO ()+runTestsForDir solutionPath testPath parse = do+ solution <- fromJust . parse <$> readFile solutionPath+ tests <- fromJust . parse <$> readFile testPath+ results <- runTests solution tests+ forM_ results $ \result -> case result of+ (TestResult desc Success) -> do+ putStrLn $ "PASS : " ++ intercalate " > " desc+ (TestResult desc (Failure reason)) -> do+ putStrLn $ "FAIL : " ++ intercalate " > " desc+ putStrLn $ " " ++ show reason++runTests :: Mu.Expression -> Mu.Expression -> IO [TestResult]+runTests code = runTests' code . getTests++runTests' :: Mu.Expression -> [MuTest] -> IO [TestResult]+runTests' expr tests = do+ (_ref, context) <- eval defaultContext expr+ forM tests $ \(MuTest desc testExpr) -> do+ (exceptionRef, testContext) <- eval' context $ do+ (_, lastException) <- evalRaising context testExpr+ return $ fromMaybe nullRef lastException+ let exception = dereference' (globalObjects testContext) exceptionRef+ case exception of+ MuNull -> return $ TestResult desc Success+ v -> return $ TestResult desc (Failure $ show v)++getTests :: Mu.Expression -> [MuTest]+getTests expr = getAllTestsFromExpr [] expr++getAllTestsFromExpr :: [String] -> Mu.Expression -> [MuTest]+getAllTestsFromExpr _ Mu.None = []+getAllTestsFromExpr s (Mu.Test (Mu.MuString desc) f) = [MuTest (s ++ [desc]) f]+getAllTestsFromExpr s (Mu.TestGroup (Mu.MuString desc) f) = getAllTestsFromExpr (s ++ [desc]) f+getAllTestsFromExpr s (Mu.Sequence expressions) = concatMap (getAllTestsFromExpr s) expressions+getAllTestsFromExpr s e = error $ "Unknown expression: " ++ show e ++ "\nIn " ++ intercalate " > " s
src/Language/Mulang/Parsers/Java.hs view
@@ -3,8 +3,8 @@ module Language.Mulang.Parsers.Java (java, parseJava) where -import Language.Mulang.Ast hiding (While, Return, Equal, Lambda, Try, Switch)-import qualified Language.Mulang.Ast as M (Expression(While, Return, Equal, Lambda, Try, Switch))+import Language.Mulang.Ast hiding (While, Return, Equal, Lambda, Try, Switch, Assert)+import qualified Language.Mulang.Ast as M (Expression(While, Return, Equal, Lambda, Try, Switch, Assert)) import Language.Mulang.Parsers import Language.Mulang.Builder (compact, compactMap, compactConcatMap, normalize) @@ -91,7 +91,6 @@ muStmt (Return exp) = M.Return $ fmapOrNone muExp exp muStmt (ExpStmt exp) = muExp exp muStmt Empty = None-muStmt (Assert exp _) = SimpleSend Self "assert" [muExp exp] muStmt (Synchronized _ block) = muBlock block muStmt (Labeled _ stmt) = muStmt stmt muStmt (Throw exp) = Raise $ muExp exp@@ -165,10 +164,15 @@ muMethodInvocation (MethodCall (Name [Ident "System", Ident "out", Ident "print"]) [expr]) = Print (muExp expr) muMethodInvocation (MethodCall (Name [Ident "System", Ident "out", Ident "printf"]) (expr:_)) = Print (muExp expr) -muMethodInvocation (MethodCall (Name [message]) args) = SimpleSend Self (i message) (map muExp args)+muMethodInvocation (MethodCall (Name [message]) args) = muNormalizeReference $ SimpleSend Self (i message) (map muExp args) muMethodInvocation (MethodCall (Name receptorAndMessage) args) = SimpleSend (Reference (ns . init $ receptorAndMessage)) (i . last $ receptorAndMessage) (map muExp args) muMethodInvocation (PrimaryMethodCall receptor _ selector args) = SimpleSend (muExp receptor) (i selector) (map muExp args) muMethodInvocation e = debug e++muNormalizeReference (SimpleSend Self "assertTrue" [expression]) = M.Assert False $ Truth expression+muNormalizeReference (SimpleSend Self "assertFalse" [expression]) = M.Assert True $ Truth expression+muNormalizeReference (SimpleSend Self "assertEquals" [expected, actual]) = M.Assert False $ Equality expected actual+muNormalizeReference e = e muRefType (ClassRefType clazz) = r clazz muRefType (ArrayType t) = (muType t) ++ "[]"
src/Language/Mulang/Parsers/JavaScript.hs view
@@ -1,7 +1,7 @@ module Language.Mulang.Parsers.JavaScript (js, parseJavaScript) where import Language.Mulang.Ast-import Language.Mulang.Builder (compactMap, normalizeWith, defaultNormalizationOptions, NormalizationOptions(..), SequenceSortMode(..))+import Language.Mulang.Builder (compact, compactMap, normalizeWith, defaultNormalizationOptions, NormalizationOptions(..), SequenceSortMode(..)) import Language.Mulang.Parsers import Language.JavaScript.Parser.Parser (parse)@@ -46,18 +46,33 @@ muJSStatement (JSExpressionStatement (JSIdentifier _ val) _) = Reference val muJSStatement (JSExpressionStatement expression _) = muJSExpression expression muJSStatement (JSAssignStatement (JSIdentifier _ name) op value _) = Assignment name (muJSAssignOp op name (muJSExpression value))-muJSStatement (JSMethodCall (JSMemberDot receptor _ message) _ params _ _) = Send (muJSExpression receptor) (muJSExpression message) (map muJSExpression (muJSCommaList params))-muJSStatement (JSMethodCall ident _ params _ _) = Application (muJSExpression ident) (map muJSExpression (muJSCommaList params))+muJSStatement (JSMethodCall (JSMemberDot receptor _ message) _ params _ _) = normalizeReference $ Send (muJSExpression receptor) (muJSExpression message) (muJSExpressionList params)+muJSStatement (JSMethodCall ident _ params _ _) = normalizeReference $ Application (muJSExpression ident) (muJSExpressionList params) muJSStatement (JSReturn _ maybeExpression _) = Return (maybe None muJSExpression maybeExpression) muJSStatement (JSSwitch _ _ expression _ _ cases _ _) = muSwitch expression . partition isDefault $ cases muJSStatement (JSThrow _ expression _) = Raise (muJSExpression expression) muJSStatement (JSTry _ block catches finally) = Try (muJSBlock block) (map muJSTryCatch catches) (muJSTryFinally finally)-muJSStatement (JSVariable _ list _) = compactMap muJSExpression.muJSCommaList $ list+muJSStatement (JSVariable _ list _) = muJSExpressionFromList list muJSStatement (JSWhile _ _ expression _ statement) = While (muJSExpression expression) (muJSStatement statement) muJSStatement e = debug e -muJSExpressionFromList = compactMap muJSExpression . muJSCommaList+normalizeReference (SimpleSend (Reference "assert") "equals" [expected, actual]) = Assert False $ Equality expected actual+normalizeReference (SimpleSend (Reference "assert") "notEquals" [expected, actual]) = Assert True $ Equality expected actual+normalizeReference (SimpleSend (Reference "assert") "throws" [block, error]) = Assert False $ Failure block error+normalizeReference (Application (Reference "assert") [expression]) = Assert False $ Truth expression+normalizeReference (Application (Reference "describe") [description, Lambda [] e]) = TestGroup description e+normalizeReference (Application (Reference "context") [description, Lambda [] e]) = TestGroup description e+normalizeReference (Application (Reference "it") [description, Lambda [] e]) = Test description e+normalizeReference e = e +mapJSList :: (a -> b) -> JSCommaList a -> [b]+mapJSList f = map f . muJSCommaList++muJSExpressionList = mapJSList muJSExpression+muJSPatternList = mapJSList muPattern++muJSExpressionFromList = compact . muJSExpressionList+ muFor inits conds progs body = ForLoop (muJSExpressionFromList inits) (muJSExpressionFromList conds) (muJSExpressionFromList progs) (muJSStatement body) muForIn (JSIdentifier _ id) generator body = For [Generator (VariablePattern id) (muJSExpression generator)] (muJSStatement body)@@ -68,8 +83,8 @@ muDefault (JSDefault _ _ statements) = compactMap muJSStatement statements -muComputation JSIdentNone params body = Lambda (map muPattern (muJSCommaList params)) (muJSBlock body)-muComputation (JSIdentName _ name) params body = (computationFor (muJSBlock body)) name (muEquation (map muPattern (muJSCommaList params)) (muJSBlock body))+muComputation JSIdentNone params body = Lambda (muJSPatternList params) (muJSBlock body)+muComputation (JSIdentName _ name) params body = (computationFor (muJSBlock body)) name (muEquation (muJSPatternList params) (muJSBlock body)) isDefault:: JSSwitchParts -> Bool isDefault (JSDefault _ _ _) = True@@ -103,7 +118,8 @@ --muJSExpression (JSRegEx _ String) muJSExpression (JSArrayLiteral _ list _) = MuList (muJSArrayList list) muJSExpression (JSAssignExpression (JSIdentifier _ name) op value) = Assignment name (muJSAssignOp op name.muJSExpression $ value)---muJSExpression (JSCallExpression expression _ params _) = Application (muJSExpression expression) (map muJSExpression.muJSCommaList $ expressionList)+muJSExpression (JSMemberExpression (JSMemberDot receptor _ message) _ params _) = Send (muJSExpression receptor) (muJSExpression message) (muJSExpressionList params)+--muJSExpression (JSCallExpression expression _ params _) = Application (muJSExpression expression) (muJSExpressionList expressionList) --muJSExpression (JSCallExpressionDot JSExpression _ JSExpression) -- ^expr, dot, expr --muJSExpression (JSCallExpressionSquare JSExpression _ JSExpression _) -- ^expr, [, expr, ] --muJSExpression (JSCommaExpression JSExpression _ JSExpression) -- ^expression components@@ -112,12 +128,12 @@ muJSExpression (JSExpressionPostfix (JSIdentifier _ name) op) = Assignment name (muJSUnaryOp op name) muJSExpression (JSExpressionTernary condition _ trueVal _ falseVal) = If (muJSExpression condition) (muJSExpression trueVal) (muJSExpression falseVal) muJSExpression (JSFunctionExpression _ ident _ params _ body) = muComputation ident params body---muJSExpression (JSMemberDot JSExpression _ JSExpression) -- ^firstpart, dot, name-muJSExpression (JSMemberExpression id _ params _) = Application (muJSExpression id) (map muJSExpression.muJSCommaList $ params)-muJSExpression (JSMemberNew _ (JSIdentifier _ name) _ args _) = New (Reference name) (map muJSExpression.muJSCommaList $ args)---muJSExpression (JSMemberSquare JSExpression _ JSExpression _) -- ^firstpart, lb, expr, rb+muJSExpression (JSMemberDot receptor _ (JSIdentifier _ message)) = Send (muJSExpression receptor) (Reference message) []+muJSExpression (JSMemberExpression id _ params _) = Application (muJSExpression id) (muJSExpressionList params)+muJSExpression (JSMemberNew _ (JSIdentifier _ name) _ args _) = New (Reference name) (muJSExpressionList args)+muJSExpression (JSMemberSquare receptor _ index _) = Send (muJSExpression receptor) (Reference "[]") [muJSExpression index] muJSExpression (JSNewExpression _ (JSIdentifier _ name)) = New (Reference name) []-muJSExpression (JSObjectLiteral _ propertyList _) = MuObject (compactMap id.map muJSObjectProperty.muJSCommaTrailingList $ propertyList)+muJSExpression (JSObjectLiteral _ propertyList _) = MuObject (compactMap muJSObjectProperty . muJSCommaTrailingList $ propertyList) muJSExpression (JSUnaryExpression (JSUnaryOpNot _) e) = Application (Reference "!") [muJSExpression e] muJSExpression (JSUnaryExpression op (JSIdentifier _ name)) = Assignment name (muJSUnaryOp op name) muJSExpression (JSVarInitExpression (JSIdentifier _ name) initial) = Variable name (muJSVarInitializer initial)@@ -180,7 +196,7 @@ muJSAssignOp' e = debug e muJSTryCatch:: JSTryCatch -> (Pattern, Expression)---muJSTryCatch JSCatch _ _ JSExpression _ JSBlock -- ^catch,lb,ident,rb,block+muJSTryCatch (JSCatch _ _ (JSIdentifier _ name) _ block) = (VariablePattern name, muJSBlock block) --muJSTryCatch JSCatchIf _ _ JSExpression _ JSExpression _ JSBlock -- ^catch,lb,ident,if,expr,rb,block muJSTryCatch e = (WildcardPattern, debug e) @@ -199,7 +215,7 @@ muJSObjectProperty:: JSObjectProperty -> Expression --muJSObjectProperty JSPropertyAccessor JSAccessor JSPropertyName _ [JSExpression] _ JSBlock -- ^(get|set), name, lb, params, rb, block-muJSObjectProperty (JSPropertyNameandValue id _ [JSFunctionExpression _ _ _ params _ block]) = Method (muJSPropertyName id) (muEquation (map muPattern (muJSCommaList params)) (muJSBlock block))+muJSObjectProperty (JSPropertyNameandValue id _ [JSFunctionExpression _ _ _ params _ block]) = Method (muJSPropertyName id) (muEquation (muJSPatternList params) (muJSBlock block)) muJSObjectProperty (JSPropertyNameandValue id _ [expression]) = Variable (muJSPropertyName id) (muJSExpression expression) muJSObjectProperty e = debug e
src/Language/Mulang/Parsers/Python.hs view
@@ -8,7 +8,7 @@ import Language.Python.Common.Token (Token) import Language.Python.Common.AST -import Data.List (intercalate)+import Data.List (intercalate, isPrefixOf) import Data.Maybe (fromMaybe, listToMaybe) import Control.Fallible@@ -32,7 +32,7 @@ muStatement (While cond body _ _) = M.While (muExpr cond) (muSuite body) muStatement (For targets generator body _ _) = M.For [M.Generator (M.TuplePattern (map (M.VariablePattern . muVariable) targets)) (muExpr generator)] (muSuite body) muStatement (Fun name args _ body _) = muComputation (muIdent name) (map muParameter args) (muSuite body)-muStatement (Class name parents body _) = M.Class (muIdent name) (listToMaybe . map muParent $ parents) (muSuite body)+muStatement (Class name parents body _) = muClass (listToMaybe . map muParent $ parents) (muIdent name) (muSuite body) muStatement (Conditional guards els _ ) = foldr muIf (muSuite els) guards muStatement (Assign [to] from _) = M.Assignment (muVariable to) (muExpr from) muStatement (AugmentedAssign to op from _) = M.Assignment (muVariable to) (M.Application (M.Reference . muAssignOp $ op) [M.Reference . muVariable $ to, muExpr from])@@ -73,10 +73,22 @@ muStatement (Exec expr _ _) = muExpr expr muStatement e = M.debug e +muClass (Just "unittest.TestCase") name body = M.TestGroup (M.MuString name) $ normalizeTests body+muClass parent name body = M.Class name parent body +normalizeTests (M.Sequence exprs) = M.Sequence $ map normalizeTest exprs+normalizeTests expr = normalizeTest expr++normalizeTest func@(M.SimpleProcedure name _ body) = if isPrefixOf "test_" name+ then M.Test (M.MuString name) body+ else func+normalizeTest e = e+ muIf (condition, body) otherwise = M.If (muExpr condition) (muSuite body) otherwise -muParent (ArgExpr (Var ident _) _) = muIdent ident+muParent (ArgExpr (Var ident _) _) = muIdent ident+muParent (ArgExpr (Dot (Var var _) attr _) _) = muIdent var ++ "." ++ muIdent attr+muParent _ = undefined muComputation name params body | containsReturn body = M.SimpleFunction name params body | otherwise = M.SimpleProcedure name params body@@ -139,13 +151,16 @@ muList = M.MuList . map muExpr -muCallType (Dot receiver ident _) = muCall (M.Send $ muExpr receiver) ident-muCallType (Var ident _) = muCall M.Application ident+muCallType (Dot _ (Ident "assertEqual" _) _) [a, b] = M.Assert False $ M.Equality a b +muCallType (Dot _ (Ident "assertTrue" _) _) [a] = M.Assert False $ M.Truth a +muCallType (Dot _ (Ident "assertFalse" _) _) [a] = M.Assert True $ M.Truth a+muCallType (Dot receiver ident _) x = muCall (M.Send $ muExpr receiver) ident x+muCallType (Var ident _) x = muCall M.Application ident x muCall callType ident = callType (M.Reference $ muIdent ident) -muApplication op args = M.Application (M.Reference (muOp op)) (map muExpr args)+muApplication op args = M.Application (muOp op) (map muExpr args) muString = M.MuString . intercalate "\n" @@ -167,33 +182,35 @@ --muYieldArg (YieldFrom expr _)(Expr annot) annot -- ^ Yield from a generator (Version 3 only) muYieldArg (YieldExpr expr) = muExpr expr -muOp (And _) = "and"-muOp (Or _) = "or"-muOp (Not _) = "not"-muOp (Exponent _) = "**"-muOp (LessThan _) = "<"-muOp (GreaterThan _) = ">"-muOp (Equality _) = "=="-muOp (GreaterThanEquals _) = ">="-muOp (LessThanEquals _) = "<="-muOp (NotEquals _) = "!="-muOp (NotEqualsV2 _) = "<>" -- Version 2 only.-muOp (In _) = "in"-muOp (Is _) = "is"-muOp (IsNot _) = "is not"-muOp (NotIn _) = "not in"-muOp (BinaryOr _) = "|"-muOp (Xor _) = "^"-muOp (BinaryAnd _) = "&"-muOp (ShiftLeft _) = "<<"-muOp (ShiftRight _) = ">>"-muOp (Multiply _) = "*"-muOp (Plus _) = "+"-muOp (Minus _) = "-"-muOp (Divide _) = "/"-muOp (FloorDivide _) = "//"-muOp (Invert _) = "~"-muOp (Modulo _) = "%"+muOp (Equality _) = M.Equal+muOp (NotEquals _) = M.NotEqual+muOp op = M.Reference $ muOpReference op++muOpReference (And _) = "and"+muOpReference (Or _) = "or"+muOpReference (Not _) = "not"+muOpReference (Exponent _) = "**"+muOpReference (LessThan _) = "<"+muOpReference (GreaterThan _) = ">"+muOpReference (GreaterThanEquals _) = ">="+muOpReference (LessThanEquals _) = "<="+muOpReference (NotEqualsV2 _) = "<>" -- Version 2 only.+muOpReference (In _) = "in"+muOpReference (Is _) = "is"+muOpReference (IsNot _) = "is not"+muOpReference (NotIn _) = "not in"+muOpReference (BinaryOr _) = "|"+muOpReference (Xor _) = "^"+muOpReference (BinaryAnd _) = "&"+muOpReference (ShiftLeft _) = "<<"+muOpReference (ShiftRight _) = ">>"+muOpReference (Multiply _) = "*"+muOpReference (Plus _) = "+"+muOpReference (Minus _) = "-"+muOpReference (Divide _) = "/"+muOpReference (FloorDivide _) = "//"+muOpReference (Invert _) = "~"+muOpReference (Modulo _) = "%" muAssignOp (PlusAssign _) = "+" muAssignOp (MinusAssign _) = "-"