diff --git a/LICENSE b/LICENSE
deleted file mode 100644
--- a/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2016 Franco Leonardo Bulgarelli
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,674 @@
+                    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>.
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE DeriveGeneric, QuasiQuotes, OverloadedStrings #-}
+
+module Main (main) where
+
+import Language.Mulang.Analyzer (analyse)
+import Language.Mulang.Analyzer.Analysis.Json ()
+import Data.Aeson (eitherDecode, encode)
+import System.Environment (getArgs)
+import Control.Fallible (orFail)
+
+import           Data.List (intercalate)
+import           Version (prettyVersion)
+import           Data.Text.Lazy.Encoding (encodeUtf8)
+import qualified Data.ByteString.Lazy as LBS (putStrLn)
+import qualified Data.Text.Lazy as T (pack)
+import           Data.Text (unpack)
+import           NeatInterpolation (text)
+
+
+main :: IO ()
+main = do
+  argsBody <- fmap parseArgs $ getArgs
+  streamBody <- getContents
+  let body = if argsBody == "-s" then streamBody else argsBody
+  result <- analyseJson body
+  LBS.putStrLn result
+
+analyseJson = fmap encode . analyse . decode . encodeUtf8 . T.pack
+
+parseArgs :: [String] -> String
+parseArgs [jsonBody] = jsonBody
+parseArgs _          = error (intercalate "\n" [prettyVersion, usage])
+
+decode = orFail . eitherDecode
+
+usage = unpack [text|
+        Wrong usage.
+
+         #read from STDIN
+         $ mulang -s
+
+         #read from argument
+         $ mulang '{
+             "sample" : {
+                "tag" : "CodeSample",
+                "language" : "Haskell",
+                "content" : "x = 1"
+             },
+             "spec" : {
+                "expectations" : [
+                   {
+                      "binding" : ":Intransitive:x",
+                      "inspection" : "Uses:*"
+                   }
+                ],
+                "smellsSet" : { "tag" : "NoSmells" }
+             }
+          }'|]
diff --git a/mulang.cabal b/mulang.cabal
--- a/mulang.cabal
+++ b/mulang.cabal
@@ -1,9 +1,9 @@
 name:                mulang
-version:             0.1.0.0
-synopsis:            The Mu Language, a non-computable extended Lambda Calculus
--- description:
-license:             MIT
-license-file:        LICENSE
+version:             3.5.2
+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
 author:              Franco Leonardo Bulgarelli
 maintainer:          franco@mumuki.org
 category:            Language
@@ -11,46 +11,137 @@
 cabal-version:       >=1.10
 
 library
-  build-depends:       base >=4.6 && <4.7
+  hs-source-dirs:      src
   default-language:    Haskell2010
+
+-- TODO recheck this is actuall necessary
   ghc-options:
-      -Wall
-      -fno-warn-missing-signatures
-      -fno-warn-orphans
-      -fno-warn-name-shadowing
-  hs-source-dirs:
-      src
+    -Wall
+    -fno-warn-missing-signatures
+    -fno-warn-unused-do-bind
+    -fno-warn-orphans
+    -fno-warn-name-shadowing
+    -fno-warn-incomplete-patterns
+    -fno-warn-missing-pattern-synonym-signatures
+    -fwarn-tabs
+    -funbox-strict-fields
+
   exposed-modules:
+    Control.Fallible
+    Text.Dictionary
+    Text.SimpleParser
+    Text.Inflections.Tokenizer
     Language.Mulang
-    Language.Mulang.Explorer
-    Language.Mulang.Inspector.Smell
-    Language.Mulang.Inspector.Combiner
+    Language.Mulang.Ast
+    Language.Mulang.Identifier
+    Language.Mulang.Builder
+    Language.Mulang.Generator
+    Language.Mulang.Signature
+    Language.Mulang.DomainLanguage
     Language.Mulang.Inspector
+    Language.Mulang.Inspector.Generic
+    Language.Mulang.Inspector.ObjectOriented
+    Language.Mulang.Inspector.Functional
+    Language.Mulang.Inspector.Logic
+    Language.Mulang.Inspector.Procedural
+    Language.Mulang.Inspector.Combiner
+    Language.Mulang.Inspector.Generic.Duplication
+    Language.Mulang.Inspector.Generic.Smell
+    Language.Mulang.Parsers
     Language.Mulang.Parsers.Haskell
-    Language.Mulang.Parsers.Json
+    Language.Mulang.Parsers.Prolog
+    Language.Mulang.Parsers.Java
+    Language.Mulang.Parsers.JavaScript
+    Language.Mulang.Analyzer
+    Language.Mulang.Analyzer.Analysis
+    Language.Mulang.Analyzer.Analysis.Json
+    Language.Mulang.Analyzer.SampleParser
+    Language.Mulang.Analyzer.ExpectationsAnalyzer
+    Language.Mulang.Analyzer.ExpectationsCompiler
+    Language.Mulang.Analyzer.SignaturesAnalyzer
+    Language.Mulang.Analyzer.SignatureStyleCompiler
+    Language.Mulang.Analyzer.DomainLanguageCompiler
+    Language.Mulang.Analyzer.SmellsAnalyzer
   build-depends:
-    base                      >= 4     && < 5,
-    bytestring                == 0.10.6.0,
-    haskell-src               >= 1     && < 1.1,
-    aeson                     == 0.8.1.1
+    base                      <= 5,
+    bytestring                ,
+    text                      ,
+    unordered-containers      ,
+    containers                ,
+    scientific                ,
+    vector                    ,
+    haskell-src               ,
+    language-java             ,
+    language-javascript       ,
+    aeson                     ,
+    inflections               ,
+    parsec                    ,
+    ParsecTools               ,
+    split                     ,
+    hashable                  ,
+    process
+  build-tools:
+    happy,
+    alex
 
+executable mulang
+  hs-source-dirs:      app
+  main-is:             Main.hs
+  default-language:    Haskell2010
 
+  build-depends:
+    base                      <= 5,
+    bytestring                ,
+    text                      ,
+    aeson                     ,
+    process                   ,
+    neat-interpolation        ,
+    mulang
+  build-tools:
+    happy,
+    alex
+
+  ghc-options:
+    -Wall
+    -fno-warn-missing-signatures
+    -fno-warn-unused-do-bind
+    -fno-warn-orphans
+    -fno-warn-name-shadowing
+    -fno-warn-incomplete-patterns
+    -fno-warn-missing-pattern-synonym-signatures
+    -fwarn-tabs
+    -funbox-strict-fields
+    -threaded
+
 test-suite spec
-  type:
-      exitcode-stdio-1.0
+  hs-source-dirs: spec
+  default-language:    Haskell2010
+
+  type: exitcode-stdio-1.0
   ghc-options:
-      -Wall
-      -fno-warn-missing-signatures
-      -fno-warn-orphans
-      -fno-warn-name-shadowing
-  hs-source-dirs:
-      spec
-  main-is:
-      Spec.hs
+    -Wall
+    -fno-warn-missing-signatures
+    -fno-warn-unused-do-bind
+    -fno-warn-orphans
+    -fno-warn-name-shadowing
+    -fno-warn-incomplete-patterns
+    -fno-warn-missing-pattern-synonym-signatures
+    -fwarn-tabs
+    -funbox-strict-fields
+    -threaded
+  main-is:        Spec.hs
   build-depends:
-    base                      >= 4     && < 5,
-    bytestring                == 0.10.6.0,
-    aeson                     == 0.8.1.1,
-    haskell-src               >= 1     && < 1.1,
-    hspec                     >= 2     && < 3,
+    base                      <= 5,
+    bytestring                ,
+    text                      ,
+    aeson                     ,
+    hspec                     ,
+    neat-interpolation        ,
     mulang
+  build-tools:
+    happy,
+    alex
+
+source-repository head
+  type:     git
+  location: https://github.com/mumuki/mulang
diff --git a/src/Control/Fallible.hs b/src/Control/Fallible.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Fallible.hs
@@ -0,0 +1,28 @@
+module Control.Fallible where
+
+class Fallible f where
+  failure :: f v -> Either v String
+
+instance Show e => Fallible (Either e) where
+  failure (Left e)  = Right . show $ e
+  failure (Right v) = (Left v)
+
+
+orFail :: Fallible f => f v -> v
+orFail f = case failure f of
+            (Left v)  -> v
+            (Right e) -> error e
+
+orNothing :: Fallible f => f v -> Maybe v
+orNothing f = case failure f of
+            (Left v) -> Just v
+            _        -> Nothing
+
+orLeft :: Fallible f => f v -> Either String v
+orLeft f = case failure f of
+            (Right e) -> Left e
+            (Left v)  -> Right v
+
+
+
+
diff --git a/src/Language/Mulang.hs b/src/Language/Mulang.hs
--- a/src/Language/Mulang.hs
+++ b/src/Language/Mulang.hs
@@ -1,97 +1,11 @@
-{-# LANGUAGE DeriveGeneric #-}
-
 module Language.Mulang (
-    Program(..),
-    Declaration(..),
-    Equation(..),
-    Rhs(..),
-    GuardedRhs(..),
-    Expression(..),
-    ComprehensionStatement(..),
-    Alternative(..),
-    GuardedAlternatives(..),
-    GuardedAlternative(..),
-    Pattern(..),
-    LiteralValue(..)
-  ) where
-
-import           GHC.Generics
-
-data Program = Program [Declaration] deriving (Eq, Show, Read, Generic)
-
-type Identifier = String
-
--- declaration or directive
-data Declaration
-         = TypeAlias Identifier
-         | RecordDeclaration Identifier
-         | TypeSignature Identifier
-         | FunctionDeclaration Identifier [Equation]    -- functional, maybe pure,
-                                                        -- optionally guarded,
-                                                        -- optionally pattern matched function
-         | ProcedureDeclaration Identifier              -- classic imperative-style procedure
-         | ConstantDeclaration Identifier Rhs [Declaration]
-  deriving (Eq, Show, Read, Generic)
-
-data Equation = Equation [Pattern] Rhs [Declaration] deriving (Eq, Show, Read, Generic)
-
-data Rhs
-         = UnguardedRhs Expression
-         | GuardedRhss  [GuardedRhs]
-  deriving (Eq, Show, Read, Generic)
-
-data GuardedRhs = GuardedRhs Expression Expression deriving (Eq, Show, Read, Generic)
-
--- expression or statement
--- may have effects
-data Expression
-        = Variable Identifier
-        | Literal LiteralValue
-        | InfixApplication Expression String Expression
-        | Application Expression Expression
-        | Lambda [Pattern] Expression
-        | Let [Declaration] Expression
-        | If Expression Expression Expression
-        | Match Expression [Alternative]
-        | MuTuple [Expression]
-        | MuList [Expression]
-        | Comprehension Expression [ComprehensionStatement]
-        | Sequence [Expression]                   -- sequence of statements
-        | ExpressionOther
-  deriving (Eq, Show, Read, Generic)
-
-data Pattern
-        = VariablePattern String                 -- ^ variable
-        | LiteralPattern String              -- ^ literal constant
-        | InfixApplicationPattern Pattern String Pattern
-        | ApplicationPattern String [Pattern]        -- ^ data constructor and argument
-        | TuplePattern [Pattern]              -- ^ tuple pattern
-        | ListPattern [Pattern]               -- ^ list pattern
-        | AsPattern String Pattern         -- ^ @\@@-pattern
-        | WildcardPattern                   -- ^ wildcard pattern (@_@)
-        | OtherPattern
-  deriving (Eq, Show, Read, Generic)
-
-data ComprehensionStatement
-        = MuGenerator Pattern Expression
-        | MuQualifier Expression
-        | LetStmt [Declaration]
-  deriving (Eq, Show, Read, Generic)
-
-
-data Alternative = Alternative Pattern GuardedAlternatives [Declaration] deriving (Eq, Show, Read, Generic)
-
-data GuardedAlternatives
-        = UnguardedAlternative Expression          -- ^ @->@ /exp/
-        | GuardedAlternatives  [GuardedAlternative] -- ^ /gdpat/
-  deriving (Eq, Show, Read, Generic)
-
-
-data GuardedAlternative = GuardedAlternative Expression Expression deriving (Eq, Show, Read, Generic)
+  module Language.Mulang.Ast,
+  module Language.Mulang.Identifier,
+  module Language.Mulang.Inspector,
+  module Language.Mulang.Generator
+) where
 
-data LiteralValue
-          = MuBool Bool
-          | MuInteger Integer
-          | MuFloat Rational
-          | MuString String
-    deriving (Eq, Show, Read, Generic)
+import Language.Mulang.Ast
+import Language.Mulang.Identifier
+import Language.Mulang.Inspector
+import Language.Mulang.Generator
diff --git a/src/Language/Mulang/Analyzer.hs b/src/Language/Mulang/Analyzer.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer.hs
@@ -0,0 +1,72 @@
+module Language.Mulang.Analyzer (
+  noSmells,
+  allSmells,
+
+  emptyDomainLanguage,
+  emptyAnalysisSpec,
+
+  emptyAnalysis,
+  domainLanguageAnalysis,
+  expectationsAnalysis,
+  smellsAnalysis,
+  signaturesAnalysis,
+
+  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.ExpectationsAnalyzer (analyseExpectations)
+import Language.Mulang.Analyzer.SmellsAnalyzer (analyseSmells)
+import Language.Mulang.Analyzer.DomainLanguageCompiler (emptyDomainLanguage, compileDomainLanguage)
+import Data.Maybe (fromMaybe)
+--
+-- Builder functions
+--
+noSmells :: SmellsSet
+noSmells = NoSmells Nothing
+
+allSmells :: SmellsSet
+allSmells = AllSmells Nothing
+
+emptyAnalysisSpec :: AnalysisSpec
+emptyAnalysisSpec = AnalysisSpec [] noSmells Nothing Nothing Nothing
+
+emptyAnalysis :: Sample -> Analysis
+emptyAnalysis code = Analysis code emptyAnalysisSpec
+
+domainLanguageAnalysis :: Sample -> 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 })
+
+smellsAnalysis :: Sample -> SmellsSet -> Analysis
+smellsAnalysis code set = Analysis code (emptyAnalysisSpec { smellsSet = set })
+
+signaturesAnalysis :: Sample -> SignatureStyle -> Analysis
+signaturesAnalysis code style = Analysis code (emptyAnalysisSpec { signatureAnalysisType = Just (StyledSignatures style) })
+
+--
+-- Analysis running
+--
+analyse :: Analysis -> IO AnalysisResult
+analyse (Analysis sample spec) = analyseSample (parseSample 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)
+  return $ AnalysisCompleted (analyseExpectations ast (expectations spec))
+                             (analyseSmells ast language (smellsSet spec))
+                             (analyseSignatures ast (signatureAnalysisType spec))
+                             (analyzeIntermediateLanguage ast spec)
+
+analyzeIntermediateLanguage :: Expression -> AnalysisSpec -> Maybe Expression
+analyzeIntermediateLanguage ast spec
+  | fromMaybe False (includeIntermediateLanguage spec) = Just ast
+  | otherwise = Nothing
diff --git a/src/Language/Mulang/Analyzer/Analysis.hs b/src/Language/Mulang/Analyzer/Analysis.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/Analysis.hs
@@ -0,0 +1,106 @@
+{-# LANGUAGE DeriveGeneric #-}
+
+module Language.Mulang.Analyzer.Analysis (
+  Expectation(..),
+
+  Analysis(..),
+  AnalysisSpec(..),
+  SmellsSet(..),
+  DomainLanguage(..),
+  CaseStyle(..),
+  Smell,
+  SignatureAnalysisType(..),
+  SignatureStyle(..),
+  Sample(..),
+  Language(..),
+
+  AnalysisResult(..),
+  ExpectationResult(..)) where
+
+import GHC.Generics
+
+import Language.Mulang.Ast
+
+---
+-- Common structures
+--
+
+type Smell = String
+type Inspection = String
+
+data Expectation
+  = Expectation { binding :: String, inspection :: Inspection } deriving (Show, Eq, Generic)
+
+--
+-- Analysis input structures
+--
+
+data Analysis = Analysis {
+  sample :: Sample,
+  spec :: AnalysisSpec
+} deriving (Show, Eq, Generic)
+
+data AnalysisSpec = AnalysisSpec {
+  expectations :: [Expectation],
+  smellsSet :: SmellsSet,
+  signatureAnalysisType :: Maybe SignatureAnalysisType,
+  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 CaseStyle
+  = CamelCase
+  | SnakeCase
+  | RubyCase deriving (Show, Eq, Generic)
+
+data SmellsSet
+  = NoSmells { include :: Maybe [Smell] }
+  | AllSmells { exclude :: Maybe [Smell] } deriving (Show, Eq, Generic)
+
+data SignatureAnalysisType
+  = NoSignatures
+  | DefaultSignatures
+  | StyledSignatures { style :: SignatureStyle } deriving (Show, Eq, Generic)
+
+data SignatureStyle
+  = MulangStyle
+  | UntypedCStyle
+  | HaskellStyle
+  | PrologStyle deriving (Show, Eq, Generic)
+
+data Sample
+  = MulangSample { ast :: Expression }
+  | CodeSample { language :: Language, content :: Code } deriving (Show, Eq, Generic)
+
+data Language
+  =  Json
+  |  Java
+  |  JavaScript
+  |  Prolog
+  |  Haskell deriving (Show, Eq, Generic)
+
+--
+-- Analysis Output structures
+--
+
+data AnalysisResult
+  = AnalysisCompleted { expectationResults :: [ExpectationResult],
+                        smells :: [Expectation],
+                        signatures :: [Code],
+                        intermediateLanguage :: Maybe Expression }
+  | AnalysisFailed { reason :: String } deriving (Show, Eq, Generic)
+
+data ExpectationResult = ExpectationResult {
+  expectation :: Expectation,
+  result :: Bool
+} deriving (Show, Eq, Generic)
+
+
diff --git a/src/Language/Mulang/Analyzer/Analysis/Json.hs b/src/Language/Mulang/Analyzer/Analysis/Json.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/Analysis/Json.hs
@@ -0,0 +1,38 @@
+module Language.Mulang.Analyzer.Analysis.Json () where
+
+import Data.Aeson
+import Language.Mulang
+import Language.Mulang.Analyzer.Analysis
+
+instance FromJSON Analysis
+instance FromJSON AnalysisSpec
+
+instance FromJSON Expectation
+
+instance FromJSON SmellsSet
+instance FromJSON DomainLanguage
+instance FromJSON CaseStyle
+
+instance FromJSON SignatureAnalysisType
+instance FromJSON SignatureStyle
+
+instance FromJSON Sample
+instance FromJSON Language
+
+instance FromJSON Equation
+instance FromJSON EquationBody
+instance FromJSON Expression
+instance FromJSON Pattern
+instance FromJSON ComprehensionStatement
+
+instance ToJSON AnalysisResult
+instance ToJSON ExpectationResult
+
+instance ToJSON Expectation
+
+instance ToJSON Equation
+instance ToJSON EquationBody
+instance ToJSON Expression
+instance ToJSON Pattern
+instance ToJSON ComprehensionStatement
+
diff --git a/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs b/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs
@@ -0,0 +1,31 @@
+module Language.Mulang.Analyzer.DomainLanguageCompiler (
+  emptyDomainLanguage,
+  compileDomainLanguage) where
+
+import           Data.Maybe (fromMaybe)
+import           Language.Mulang.Analyzer.Analysis
+import qualified Language.Mulang.DomainLanguage as DL
+import           Text.Inflections.Tokenizer (camelCase, rubyCase, snakeCase)
+import           Text.Dictionary (fromFile, toDictionary)
+
+
+emptyDomainLanguage :: DomainLanguage
+emptyDomainLanguage = DomainLanguage Nothing Nothing Nothing Nothing
+
+compileDomainLanguage :: Maybe DomainLanguage -> IO DL.DomainLanguage
+compileDomainLanguage Nothing                                 = compileDomainLanguage (Just emptyDomainLanguage)
+compileDomainLanguage (Just (DomainLanguage path style size jargon)) = do
+  dictionary <- compileDictionay path
+  return $ DL.DomainLanguage dictionary (compileStyle style) (compileSize size) (compileJargon jargon)
+
+  where
+    compileDictionay (Just path) = fromFile path
+    compileDictionay _           = return $ toDictionary []
+
+    compileSize = fromMaybe 3
+
+    compileStyle (Just SnakeCase) = snakeCase
+    compileStyle (Just RubyCase)  = rubyCase
+    compileStyle _                = camelCase
+
+    compileJargon = fromMaybe []
diff --git a/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs b/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs
@@ -0,0 +1,15 @@
+module Language.Mulang.Analyzer.ExpectationsAnalyzer (
+  analyseExpectations) where
+
+
+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)
+
+analyseExpectation :: Expression -> Expectation -> ExpectationResult
+analyseExpectation ast e = ExpectationResult e (compileAndEval e)
+  where compileAndEval e = (compileExpectation e) ast
+
diff --git a/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs b/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs
@@ -0,0 +1,111 @@
+module Language.Mulang.Analyzer.ExpectationsCompiler(
+  compileExpectation) where
+
+import Language.Mulang
+import Language.Mulang.Analyzer.Analysis (Expectation(..))
+
+import Data.Maybe (fromMaybe)
+import Data.List.Split (splitOn)
+
+type Modifiers = (Scope, PredicateModifier)
+type Scope = (Inspection -> Inspection)
+type PredicateModifier = (IdentifierPredicate -> IdentifierPredicate)
+
+compileExpectation :: Expectation -> Inspection
+compileExpectation = fromMaybe (\_ -> True) . compileMaybe
+
+compileMaybe :: Expectation -> Maybe Inspection
+compileMaybe (Expectation b i) = do
+  let inspectionParts = splitOn ":" i
+  let negator = compileNegator inspectionParts
+  (scope, predicateModifier) <- compileModifiers (splitOn ":" b)
+  baseInspection             <- compileBaseInspection predicateModifier inspectionParts
+  return . negator . scope $ baseInspection
+
+compileModifiers :: [String] -> Maybe Modifiers
+compileModifiers ["*"]                 = Just (id, id)
+compileModifiers ["Intransitive",name] = justScopeFor scopedList name
+compileModifiers [name]                = justScopeFor transitiveList name
+compileModifiers _                     = Nothing
+
+justScopeFor f name = Just (flip f names, andAlso (except (last names)))
+  where names = splitOn "." name
+
+compileNegator :: [String] -> Scope
+compileNegator ("Not":_) = negative
+compileNegator _         = id
+
+compileBaseInspection :: PredicateModifier -> [String] -> Maybe (Inspection)
+compileBaseInspection p ("Not":parts)         = compileBaseInspection p parts
+compileBaseInspection p [verb]                = compileBaseInspection p [verb, "*"]
+compileBaseInspection p [verb, object]        = compileInspectionPrimitive verb (compileObject p object)
+compileBaseInspection _ _                     = Nothing
+
+compileObject :: PredicateModifier -> String -> IdentifierPredicate
+compileObject p "*"        = p $ anyone
+compileObject p ('~':name) = p $ like name
+compileObject _ ('=':name) = named name
+compileObject _ ('^':name) = except name
+compileObject _ ('[':ns)   | last ns == ']' = anyOf . splitOn "|" . init $ ns
+compileObject _ name       = named name
+
+
+compileInspectionPrimitive :: String -> IdentifierPredicate -> Maybe Inspection
+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 "Uses"                           = binded uses
+  f "UsesAnonymousVariable"          = simple usesAnonymousVariable
+  f "UsesComposition"                = simple usesComposition
+  f "UsesComprehension"              = simple usesComprehension
+  f "UsesConditional"                = simple usesConditional
+  f "UsesExceptionHandling"          = simple usesExceptionHandling
+  f "UsesExceptions"                 = simple usesExceptions
+  f "UsesFindall"                    = simple usesFindall
+  f "UsesForall"                     = simple usesForall
+  f "UsesGuards"                     = simple usesGuards
+  f "UsesIf"                         = simple usesIf
+  f "UsesInheritance"                = simple usesInheritance
+  f "UsesLambda"                     = simple usesLambda
+  f "UsesMixins"                     = simple usesMixins
+  f "UsesNot"                        = simple usesNot
+  f "UsesPatternMatching"            = simple usesPatternMatching
+  f "UsesRepeat"                     = simple usesRepeat
+  f "UsesSwitch"                     = simple usesSwitch
+  f "UsesWhile"                      = simple usesWhile
+  f _                                = const Nothing
+
+  simple i _ = Just i
+  binded i b = Just $ i b
diff --git a/src/Language/Mulang/Analyzer/SampleParser.hs b/src/Language/Mulang/Analyzer/SampleParser.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/SampleParser.hs
@@ -0,0 +1,20 @@
+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.Analyzer.Analysis (Sample(..), Language(..))
+
+parseSample :: Sample -> Either String Expression
+parseSample (CodeSample language content) = (parserFor language) content
+parseSample (MulangSample ast)            = Right ast
+
+parserFor :: Language -> EitherParser
+parserFor Haskell        = parseHaskell
+parserFor Java           = parseJava
+parserFor JavaScript     = maybeToEither parseJavaScript
+parserFor Prolog         = parseProlog
diff --git a/src/Language/Mulang/Analyzer/SignatureStyleCompiler.hs b/src/Language/Mulang/Analyzer/SignatureStyleCompiler.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/SignatureStyleCompiler.hs
@@ -0,0 +1,13 @@
+module Language.Mulang.Analyzer.SignatureStyleCompiler (
+  compileSignatureStyle) where
+
+import Language.Mulang.Signature as Signature (SignatureStyle,
+                                               mulangStyle, untypedCStyle,
+                                               haskellStyle, prologStyle)
+import Language.Mulang.Analyzer.Analysis as Analysis (SignatureStyle(..))
+
+compileSignatureStyle :: Analysis.SignatureStyle -> Signature.SignatureStyle
+compileSignatureStyle MulangStyle = mulangStyle
+compileSignatureStyle UntypedCStyle = untypedCStyle
+compileSignatureStyle HaskellStyle = haskellStyle
+compileSignatureStyle PrologStyle = prologStyle
diff --git a/src/Language/Mulang/Analyzer/SignaturesAnalyzer.hs b/src/Language/Mulang/Analyzer/SignaturesAnalyzer.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/SignaturesAnalyzer.hs
@@ -0,0 +1,15 @@
+module Language.Mulang.Analyzer.SignaturesAnalyzer (
+  analyseSignatures) where
+
+import Language.Mulang
+import Language.Mulang.Signature
+import Language.Mulang.Analyzer.Analysis (SignatureAnalysisType(..))
+import Language.Mulang.Analyzer.SignatureStyleCompiler (compileSignatureStyle)
+import Data.Maybe (fromMaybe)
+
+analyseSignatures :: Expression -> Maybe SignatureAnalysisType -> [Code]
+analyseSignatures e analysis = analyseSignatures' e (fromMaybe NoSignatures analysis)
+
+analyseSignatures' _ NoSignatures             = []
+analyseSignatures' e DefaultSignatures        = codeSignaturesOf e
+analyseSignatures' e (StyledSignatures style) = styledCodeSignaturesOf (compileSignatureStyle style) e
diff --git a/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs b/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs
@@ -0,0 +1,89 @@
+module Language.Mulang.Analyzer.SmellsAnalyzer (
+  analyseSmells) where
+
+import Language.Mulang
+import Language.Mulang.Inspector.Generic.Smell
+import Language.Mulang.DomainLanguage
+import Language.Mulang.Analyzer.Analysis hiding (DomainLanguage)
+import Data.List
+import Data.Maybe (fromMaybe)
+
+analyseSmells :: Expression -> DomainLanguage -> SmellsSet -> [Expectation]
+analyseSmells ast language set = concatMap (\smell -> detectSmell smell language ast) (smellsFor set)
+
+detectSmell :: Smell -> DomainLanguage -> Expression -> [Expectation]
+detectSmell smell language =  map (exectationFor smell) . detectionFor smell language
+
+smellsFor :: SmellsSet -> [Smell]
+smellsFor (NoSmells included)    = fromMaybe [] included
+smellsFor (AllSmells excluded)   = allSmells \\ (fromMaybe [] excluded)
+
+allSmells :: [Smell]
+allSmells = [
+  "DiscardsExceptions",
+  "DoesConsolePrint",
+  "DoesNullTest",
+  "DoesTypeTest",
+  "HasAssignmentReturn",
+  "HasCodeDuplication",
+  "HasLongParameterList",
+  "HasMisspelledIdentifiers",
+  "HasRedundantBooleanComparison",
+  "HasRedundantGuards",
+  "HasRedundantIf",
+  "HasRedundantLambda",
+  "HasRedundantLocalVariableReturn",
+  "HasRedundantParameter",
+  "HasRedundantReduction",
+  "HasTooManyMethods",
+  "HasTooShortIdentifiers",
+  "HasWrongCaseIdentifiers",
+  "IsLongCode",
+  "OverridesEqualOrHashButNotBoth",
+  "ReturnsNull",
+  "UsesCut",
+  "UsesFail",
+  "UsesUnificationOperator" ]
+
+detectionFor :: Smell -> Detection
+detectionFor "DiscardsExceptions"              = simple discardsExceptions
+detectionFor "DoesConsolePrint"                = simple doesConsolePrint
+detectionFor "DoesNullTest"                    = simple doesNullTest
+detectionFor "DoesTypeTest"                    = simple doesTypeTest
+detectionFor "HasAssignmentReturn"             = simple hasAssignmentReturn
+detectionFor "HasCodeDuplication"              = unsupported
+detectionFor "HasLongParameterList"            = simple hasLongParameterList
+detectionFor "HasMisspelledIdentifiers"        = withLanguage hasMisspelledIdentifiers
+detectionFor "HasMisspelledBindings"           = withLanguage hasMisspelledIdentifiers
+detectionFor "HasRedundantBooleanComparison"   = simple hasRedundantBooleanComparison
+detectionFor "HasRedundantGuards"              = simple hasRedundantGuards
+detectionFor "HasRedundantIf"                  = simple hasRedundantIf
+detectionFor "HasRedundantLambda"              = simple hasRedundantLambda
+detectionFor "HasRedundantLocalVariableReturn" = simple hasRedundantLocalVariableReturn
+detectionFor "HasRedundantParameter"           = simple hasRedundantParameter
+detectionFor "HasRedundantReduction"           = simple hasRedundantReduction
+detectionFor "HasTooManyMethods"               = simple hasTooManyMethods
+detectionFor "HasTooShortIdentifiers"          = withLanguage hasTooShortIdentifiers
+detectionFor "HasTooShortBindings"             = withLanguage hasTooShortIdentifiers
+detectionFor "HasWrongCaseIdentifiers"         = withLanguage hasWrongCaseIdentifiers
+detectionFor "HasWrongCaseBinding"             = withLanguage hasWrongCaseIdentifiers
+detectionFor "IsLongCode"                      = unsupported
+detectionFor "OverridesEqualOrHashButNotBoth"  = simple overridesEqualOrHashButNotBoth
+detectionFor "ReturnsNull"                     = simple returnsNull
+detectionFor "UsesCut"                         = simple usesCut
+detectionFor "UsesFail"                        = simple usesFail
+detectionFor "UsesUnificationOperator"         = simple usesUnificationOperator
+detectionFor _                                 = unsupported
+
+type Detection = DomainLanguage -> Expression -> [Identifier]
+unsupported :: Detection
+unsupported _ _ = []
+
+simple :: Inspection -> Detection
+simple inspection _ = detect inspection
+
+withLanguage :: (DomainLanguage -> Inspection) -> Detection
+withLanguage inspection language = detect (inspection language)
+
+exectationFor :: Smell -> Identifier -> Expectation
+exectationFor smell identifier = Expectation identifier smell
diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Ast.hs
@@ -0,0 +1,227 @@
+{-# LANGUAGE DeriveGeneric, PatternSynonyms, ViewPatterns #-}
+
+-- | The Ast module describes a generic, abstract language AST.
+-- |
+-- | Since it only describes the AST, but not many aspects of its semantics, Mulang is non-computable, but just a target
+-- | for code analysis.
+-- |
+-- | Mulang AST itself is the combination of other abstract, paradigmatic languages that express the structures of:
+-- |    * imperative programing
+-- |    * object-oriented programing
+-- |    * functional programing
+-- |    * logic programing
+-- |
+module Language.Mulang.Ast (
+    equationParams,
+    Code,
+    Equation(..),
+    EquationBody(..),
+    Expression(..),
+    ComprehensionStatement(..),
+    Pattern(..),
+    Identifier,
+    pattern SimpleEquation,
+    pattern SimpleFunction,
+    pattern SimpleProcedure,
+    pattern SimpleMethod,
+    pattern SimpleSend,
+    pattern MuTrue,
+    pattern MuFalse,
+    pattern Subroutine,
+    pattern Clause,
+    pattern Call,
+    pattern Params
+  ) where
+
+import           GHC.Generics
+import           Language.Mulang.Identifier (Identifier)
+
+type Code = String
+
+-- | An equation. See @Function@ and @Procedure@ above
+data Equation = Equation [Pattern] EquationBody deriving (Eq, Show, Read, Generic)
+
+data EquationBody
+         = UnguardedBody Expression
+         | GuardedBody  [(Expression, Expression)]
+  deriving (Eq, Show, Read, Generic)
+
+
+-- | Expression is the root element of a Mulang program.
+-- | With the exception of Patterns, nearly everything is an Expression: variable declarations, literals,
+-- | control structures, even object oriented classes declarations.
+-- |
+-- | However, although all those elements can be used as subexpressions and have an dohave an associated value,
+-- | Mulang does not state WHICH is that value.
+data Expression
+    = TypeAlias Identifier
+    -- ^ Functional programming type alias.
+    --   Only the type alias identifier is parsed
+    | Record Identifier
+    -- ^ Imperative / Functional programming struct declaration.
+    --   Only the record name is parsed
+    | TypeSignature Identifier [Identifier] Identifier
+    -- ^ Generic type signature for a computation,
+    --   composed by a name, parameter types and return type
+    | EntryPoint Identifier Expression
+    -- ^ Entry point with its body
+    | Function Identifier [Equation]
+    -- ^ Functional / Imperative programming function declaration.
+    --   It is is composed by an identifier and one or more equations
+    | Procedure Identifier [Equation]
+    -- ^ Imperative programming procedure declaration. It is composed by a name and one or more equations
+    | Method Identifier [Equation]
+    | EqualMethod [Equation]
+    | HashMethod [Equation]
+    | Variable Identifier Expression
+    | Assignment Identifier Expression
+    | Attribute Identifier Expression
+    -- ^ Object oriented programming attribute declaration, composed by an identifier and an initializer
+    | Object Identifier Expression
+    -- ^ Object oriented programming global, named object declaration,
+    --   composed by a name and a body
+    | Class Identifier (Maybe Identifier) Expression
+    -- ^ Object oriented programming global, class declaration,
+    --   composed by a name, an optional superclass, implemented interfaces and a body
+    | Enumeration Identifier [Identifier]
+    -- ^ Imperative named enumeration of values
+    | Interface Identifier [Identifier] Expression
+    -- ^ Object oriented programming global interface or contract declaration,
+    --   composed by a name, superinterfaces and a body
+    | Rule Identifier [Pattern] [Expression]
+    -- ^ Logic programming declaration of a fact, composed by the rue name, rule arguments, and rule body
+    | Fact Identifier [Pattern]
+    -- ^ Logic programming declaration of a fact , composed by the fact name and fact arguments
+    | Exist Identifier [Pattern]
+    -- ^ Logic programming existential cuantification / consult
+    | Not Expression
+    -- ^ Logic programming negation
+    | Findall Expression Expression Expression
+    -- ^ Logic programming findall
+    | Forall Expression Expression
+    -- ^ Logic programming universal cuantification
+    | Reference Identifier
+    -- ^ Generic variable
+    | Application Expression [Expression]
+    -- ^ Generic, non-curried application of a function or procedure, composed by the applied element itself, and the application arguments
+    | Send Expression Expression [Expression]
+    -- ^ Object oriented programming message send, composed by the reciever, selector and arguments
+    | New Identifier [Expression]
+    -- ^ Object oriented instantiation, composed by the class reference and instantiation arguments
+    | Implement Identifier
+    -- ^ Object oriented instantiation, interface implementation
+    | Include Identifier
+    -- ^ Object oriented instantiation, mixin inclusion
+    | Lambda [Pattern] Expression
+    | If Expression Expression Expression
+    | Return Expression
+    | While Expression Expression
+    -- ^ Imperative programming conditional repetition control structure, composed by a condition and a body
+    | Repeat Expression Expression
+    -- ^ Imperative programming fixed repetition control structure, composed by a repetition count expression, and a body
+    | Match Expression [Equation]
+    | Switch Expression [(Expression, Expression)]
+    | Try Expression [(Pattern, Expression)] Expression
+    -- ^ Generic try expression, composed by a body, a list of exception-handling patterns and statments, and a finally expression
+    | Raise Expression
+    -- ^ Generic raise expression, like a throw or raise statament, composed by the raised expression
+    | Print Expression
+    -- ^ Generic print expression
+    | Comprehension Expression [ComprehensionStatement]
+    | Sequence [Expression]
+    -- ^ Generic sequence of statements
+    | Other
+    | Equal
+    | NotEqual
+    | Self
+    | MuNull
+    -- ^ Generic nothing value literal - nil, null, undefined or unit
+    | MuObject Expression
+    -- ^ Object oriented unnamed object literal
+    | MuNumber Double
+    -- ^ Generic number literal
+    | MuBool Bool
+    -- ^ Generic boolean literal
+    | MuString String
+    -- ^ Generic string literal
+    | MuSymbol String
+    -- ^ Generic symbol/atom literal
+    | MuTuple [Expression]
+    | MuList [Expression]
+  deriving (Eq, Show, Read, Generic)
+
+-- | Mulang Patterns are not expressions, but are aimed to match them.
+-- | They are modeled after Haskell, Prolog, Elixir, Scala and Erlang patterns
+data Pattern
+    = VariablePattern String
+    -- ^ variable pattern like @X@
+    | LiteralPattern String
+    -- ^ literal constant pattern like @4@
+    | InfixApplicationPattern Pattern String Pattern
+    -- ^ infix application pattern like @4:X@
+    | ApplicationPattern String [Pattern]
+    -- ^ prefix application pattern like @f _@
+    | TuplePattern [Pattern]
+    -- ^ tuple pattern like @(3, _)@
+    | ListPattern [Pattern]
+    -- ^ list pattern like @[x, y, _]@
+    | FunctorPattern Identifier [Pattern]
+    -- ^ prolog-like functor pattern, like @f(X, 6)@
+    | AsPattern Identifier Pattern
+    | TypePattern Identifier
+    -- ^ @\@@-pattern
+    | WildcardPattern
+    -- ^ wildcard pattern @_@
+    | UnionPattern [Pattern]
+    | OtherPattern
+    -- ^ Other unrecognized pattern
+  deriving (Eq, Show, Read, Generic)
+
+data ComprehensionStatement
+        = MuGenerator Pattern Expression
+        | MuQualifier Expression
+        | LetStmt     Expression
+  deriving (Eq, Show, Read, Generic)
+
+
+pattern SimpleEquation params body = Equation params (UnguardedBody body)
+
+pattern SimpleSend receptor selector args = Send receptor (Reference selector) args
+
+pattern SimpleFunction name params body  = Function  name [SimpleEquation params body]
+pattern SimpleProcedure name params body = Procedure name [SimpleEquation params body]
+pattern SimpleMethod name params body    = Method    name [SimpleEquation params body]
+
+pattern MuTrue  = MuBool True
+pattern MuFalse = MuBool False
+
+pattern Subroutine name equations <- (extractSubroutine -> Just (name, equations))
+pattern Clause name patterns expressions <- (extractClause -> Just (name, patterns, expressions))
+
+pattern Call operation arguments <- (extractCall -> Just (operation, arguments))
+
+pattern Params params <- (extractParams -> Just params)
+
+equationParams :: Equation -> [Pattern]
+equationParams (Equation p _) = p
+
+extractSubroutine :: Expression -> Maybe (Identifier, [Equation])
+extractSubroutine (Function name equations)  = Just (name, equations)
+extractSubroutine (Procedure name equations) = Just (name, equations)
+extractSubroutine (Method name equations)    = Just (name, equations)
+extractSubroutine _                          = Nothing
+
+extractParams :: Expression -> Maybe ([Pattern])
+extractParams (Subroutine _ equations) = Just (equationParams.head $ equations)
+extractParams (Clause _ params _)      = Just params
+extractParams _                        = Nothing
+
+extractCall :: Expression -> Maybe (Expression, [Expression])
+extractCall (Application op args)   = Just (op, args)
+extractCall (Send receptor op args) = Just (op, (receptor:args))
+extractCall _                       = Nothing
+
+extractClause :: Expression -> Maybe (Identifier, [Pattern], [Expression])
+extractClause (Fact name patterns)             = Just (name, patterns, [])
+extractClause (Rule name patterns expressions) = Just (name, patterns, expressions)
+extractClause _                                = Nothing
diff --git a/src/Language/Mulang/Builder.hs b/src/Language/Mulang/Builder.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Builder.hs
@@ -0,0 +1,52 @@
+module Language.Mulang.Builder (compact, compactMap, compactConcatMap, normalize) where
+
+import Language.Mulang.Ast
+
+compactConcatMap :: (a -> [Expression]) -> [a] -> Expression
+compactConcatMap f = compact . concat . map f
+
+compactMap :: (a -> Expression) -> [a] -> Expression
+compactMap f = compact . map f
+
+compact :: [Expression] -> Expression
+compact []  = MuNull
+compact [e] = e
+compact es  = Sequence es
+
+normalize :: Expression -> Expression
+normalize (Variable n (MuObject e))        = Object n (normalizeInObject e)
+normalize (Variable n (Lambda vars e))     = SimpleFunction n vars (normalize e)
+normalize (Variable n e)                   = Variable n (normalize e)
+normalize (Function n equations)           = Function n (map normalizeEquation equations)
+normalize (Procedure n equations)          = Procedure n (map normalizeEquation equations)
+normalize (Fact n args)                    = Fact n args
+normalize (Rule n args es)                 = Rule n args (map normalize es)
+normalize (Method n equations)             = Method n (map normalizeEquation equations)
+normalize (Attribute n e)                  = Attribute n (normalize e)
+normalize (Object n e)                     = Object n (normalizeInObject e)
+normalize (Application (Send r m []) args) = Send (normalize r) (normalize m) (map normalize args)
+normalize (Application e es)               = Application (normalize e) (map normalize es)
+normalize (Send r e es)                    = Send (normalize r) (normalize e) (map normalize es)
+normalize (Lambda ps e2)                   = Lambda ps (normalize e2)
+normalize (If e1 e2 e3)                    = If (normalize e1) (normalize e2) (normalize e3)
+normalize (While e1 e2)                    = While (normalize e1) (normalize e2)
+normalize (Match e1 equations)             = Match (normalize e1) (map normalizeEquation equations)
+normalize (Comprehension e1 stms)          = Comprehension (normalize e1) stms
+normalize (Return e)                       = Return (normalize e)
+normalize (Not e)                          = Not (normalize e)
+normalize (Forall e1 e2)                   = Forall (normalize e1) (normalize e2)
+normalize (Sequence es)                    = Sequence (map normalize es)
+normalize (MuObject e)                     = MuObject (normalize e)
+normalize (MuTuple es)                     = MuTuple (map normalize es)
+normalize (MuList es)                      = MuList (map normalize es)
+normalize e = e
+
+normalizeInObject (Function n eqs)             = Method n (map normalizeEquation eqs)
+normalizeInObject (Variable n (Lambda vars e)) = SimpleMethod n vars (normalize e)
+normalizeInObject (Variable n e)               = Attribute n (normalize e)
+normalizeInObject (Sequence es)                = Sequence (map normalizeInObject es)
+normalizeInObject e                            = normalize e
+
+normalizeEquation :: Equation -> Equation
+normalizeEquation (Equation ps (UnguardedBody e))   = Equation ps (UnguardedBody (normalize e))
+normalizeEquation (Equation ps (GuardedBody b))     = Equation ps (GuardedBody (map (\(c, e) -> (normalize c, normalize e)) b))
diff --git a/src/Language/Mulang/DomainLanguage.hs b/src/Language/Mulang/DomainLanguage.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/DomainLanguage.hs
@@ -0,0 +1,42 @@
+module Language.Mulang.DomainLanguage (
+  hasTooShortIdentifiers,
+  hasWrongCaseIdentifiers,
+  hasMisspelledIdentifiers,
+  DomainLanguage(..)) where
+
+import Language.Mulang.Inspector (Inspection)
+import Language.Mulang.Ast (Expression)
+import Language.Mulang.Generator (mainDeclaredIdentifiers)
+
+import Text.Dictionary (Dictionary, exists)
+
+import Text.Inflections.Tokenizer (CaseStyle, tokenize, canTokenize)
+
+
+data DomainLanguage = DomainLanguage {
+                          dictionary :: Dictionary,
+                          caseStyle :: CaseStyle,
+                          minimumIdentifierSize :: Int,
+                          jargon :: [String] }
+
+type DomainLanguageInspection = DomainLanguage -> Inspection
+
+hasTooShortIdentifiers :: DomainLanguageInspection
+hasTooShortIdentifiers language = any isShort . mainDeclaredIdentifiers
+  where isShort identifier = length identifier < (minimumIdentifierSize language) && notJargonOf identifier language
+
+hasMisspelledIdentifiers :: DomainLanguageInspection
+hasMisspelledIdentifiers language | emptyDictionary language = const False
+hasMisspelledIdentifiers language = any isMisspelled  . wordsOf language
+  where isMisspelled identifier = not (identifier `exists` dictionary language) && notJargonOf identifier language
+
+hasWrongCaseIdentifiers :: DomainLanguageInspection
+hasWrongCaseIdentifiers (DomainLanguage _ style _ _)
+  = any (not . canTokenize style) . mainDeclaredIdentifiers
+
+wordsOf :: DomainLanguage -> Expression -> [String]
+wordsOf (DomainLanguage _ style _ _) = concatMap (tokenize style) . mainDeclaredIdentifiers
+
+emptyDictionary = null . dictionary
+
+notJargonOf identifier language = notElem identifier (jargon language)
diff --git a/src/Language/Mulang/Explorer.hs b/src/Language/Mulang/Explorer.hs
deleted file mode 100644
--- a/src/Language/Mulang/Explorer.hs
+++ /dev/null
@@ -1,92 +0,0 @@
-module Language.Mulang.Explorer (
-  parseDecls,
-  parseBindings,
-  declsOf,
-  rhssOf,
-  bindingsOf,
-  transitiveBindingsOf,
-  expressionsOf,
-  expressionToBinding,
-  Expression(..),
-  Binding) where
-
-import Language.Mulang
-import Data.Maybe (maybeToList)
-import Data.List (nub)
-
-type Binding = String
-
-declName :: Declaration -> String
-declName (TypeSignature b ) = b
-declName (TypeAlias b ) = b
-declName (ConstantDeclaration n _ _) = n
-declName (FunctionDeclaration n _)  = n
-declName _                  = []
-
-declsOf :: Binding -> Program -> [Declaration]
-declsOf binding = filter (isBinding binding) . parseDecls
-
-rhssOf :: Binding -> Program -> [Rhs]
-rhssOf binding = concatMap rhsForBinding . declsOf binding
-
-expressionsOf :: Binding -> Program -> [Expression]
-expressionsOf binding code = do
-  rhs <- rhssOf binding code
-  top <- topExpressions rhs
-  unfoldExpression top
-
-bindingsOf :: Binding -> Program -> [Binding]
-bindingsOf binding code = nub $ do
-          expr <- expressionsOf binding code
-          maybeToList . expressionToBinding $ expr
-
-transitiveBindingsOf :: Binding -> Program -> [Binding]
-transitiveBindingsOf binding code =  expand (`bindingsOf` code) binding
-
-parseDecls :: Program -> [Declaration]
-parseDecls (Program decls) = decls
-
-parseBindings :: Program -> [Binding]
-parseBindings = map declName . parseDecls
-
-expressionToBinding :: Expression -> Maybe Binding
-expressionToBinding (Variable    q) = Just q
-expressionToBinding _                = Nothing
-
--- private
-
-topExpressions :: Rhs -> [Expression]
-topExpressions (UnguardedRhs e) = [e]
-topExpressions (GuardedRhss rhss) = rhss >>= \(GuardedRhs es1 es2) -> [es1, es2]
-
-unfoldExpression :: Expression -> [Expression]
-unfoldExpression expr = expr : concatMap unfoldExpression (subExpressions expr)
-
-subExpressions :: Expression -> [Expression]
-subExpressions (InfixApplication a b c) = [a, (Variable b), c]
-subExpressions (Application a b)        = [a, b]
-subExpressions (Lambda _ a)   = [a]
-subExpressions (MuList as)      = as
-subExpressions (Comprehension a _)   = [a] --TODO
-subExpressions (MuTuple as)      = as
-subExpressions (If a b c)       = [a, b, c]
-subExpressions _ = []
-
-isBinding :: Binding -> Declaration -> Bool
-isBinding binding = (==binding).declName
-
-rhsForBinding :: Declaration -> [Rhs]
-rhsForBinding (ConstantDeclaration _ rhs localDecls) = concatRhs rhs localDecls
-rhsForBinding (FunctionDeclaration _ cases) = cases >>= \(Equation _ rhs localDecls) -> concatRhs rhs localDecls
-rhsForBinding _ = []
-
-concatRhs rhs l = [rhs] ++ concatMap rhsForBinding l
-
-
-expand :: Eq a => (a-> [a]) -> a -> [a]
-expand f x = expand' [] f [x]
-
-expand' _ _ [] = []
-expand' ps f (x:xs) | elem x ps = expand' ps f xs
-                    | otherwise = [x] ++ expand' (x:ps) f (xs ++ f x)
-
diff --git a/src/Language/Mulang/Generator.hs b/src/Language/Mulang/Generator.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Generator.hs
@@ -0,0 +1,139 @@
+module Language.Mulang.Generator (
+  boundDeclarations,
+  declarations,
+  declarationsOf,
+  declaredIdentifiers,
+  mainDeclaredIdentifiers,
+  equationBodies,
+  expressions,
+  referencedIdentifiers,
+  identifierReferences,
+  transitiveReferencedIdentifiers,
+  Generator,
+  Expression(..)) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Identifier
+
+import Data.Maybe (mapMaybe)
+import Data.List (nub)
+
+type Generator a = Expression -> [a]
+
+-- | Returns all the declarations their identifiers -
+-- | classes, methods, functions, records, local and global variables, and so on
+-- |
+-- | For example, in 'f x = g x where x = y', it returns '(f, f x = ...)' and '(x, x = y)'
+declarations :: Generator (Identifier, Expression)
+declarations (Sequence es)          = concatMap declarations es
+declarations e@(Attribute n _)      = [(n, e)]
+declarations e@(Class n _ b)        = (n, e) : declarations b
+declarations e@(Clause n _ es)      = (n, e) : concatMap declarations es
+declarations e@(Enumeration n _)    = [(n, e)]
+declarations e@(Interface n _ b)    = (n, e) : declarations b
+declarations e@(EntryPoint n b)     = (n, e) : declarations b
+declarations e@(Subroutine n b)     = (n, e) : concatMap declarations (equationExpressions b)
+declarations e@(Object n b)         = (n, e) : declarations b
+declarations e@(Clause n _ _)       = [(n, e)]
+declarations e@(Record n)           = [(n, e)]
+declarations e@(TypeAlias n)        = [(n, e)]
+declarations e@(TypeSignature n _ _)= [(n, e)]
+declarations e@(Variable n _)       = [(n, e)]
+declarations _                      = []
+
+-- | Returns all declarations bound to the given identifier predicate
+-- |
+boundDeclarations :: IdentifierPredicate -> Generator Expression
+boundDeclarations f = map snd . filter (f.fst) . declarations
+
+-- | Returns the given expression and all its subexpressions
+-- For example: in 'f x = x + 1', it returns 'f x = x + 1', 'x + 1', 'x' and '1'
+expressions :: Generator Expression
+expressions expr = expr : concatMap expressions (subExpressions expr)
+  where
+    subExpressions :: Generator Expression
+    subExpressions (Assignment _ e)        = [e]
+    subExpressions (Attribute _ v)         = [v]
+    subExpressions (Call op args)          = op:args
+    subExpressions (Class _ _ v)           = [v]
+    subExpressions (Clause _ _ es)         = es
+    subExpressions (Comprehension a _)     = [a] --TODO
+    subExpressions (EntryPoint _ e)        = [e]
+    subExpressions (Forall e1 e2)          = [e1, e2]
+    subExpressions (If a b c)              = [a, b, c]
+    subExpressions (Interface _ _ v)       = [v]
+    subExpressions (Lambda _ a)            = [a]
+    subExpressions (Match e1 equations)    = e1:equationExpressions equations
+    subExpressions (MuList as)             = as
+    subExpressions (MuObject es)           = [es]
+    subExpressions (MuTuple as)            = as
+    subExpressions (New _ es)              = es
+    subExpressions (Not e)                 = [e]
+    subExpressions (Object _ v)            = [v]
+    subExpressions (Repeat e1 e2)          = [e1, e2]
+    subExpressions (Return v)              = [v]
+    subExpressions (Sequence es)           = es
+    subExpressions (Subroutine _ es)       = equationExpressions es
+    subExpressions (Switch e1 list)        = e1 : concatMap (\(x,y) -> [x,y]) list
+    subExpressions (Try t cs f)            = t : map snd cs ++ [f]
+    subExpressions (Variable _ v)          = [v]
+    subExpressions (While e1 e2)           = [e1, e2]
+    subExpressions _                       = []
+
+
+-- | Returns all the referenced identifiers
+-- For example, in 'f (x + 1)', it returns 'f' and 'x'
+referencedIdentifiers :: Generator Identifier
+referencedIdentifiers = nub . identifierReferences
+
+identifierReferences :: Generator Identifier
+identifierReferences = mapMaybe extractReference . expressions
+
+
+-- | Returns all the identifiers transitively referenced by the given one
+-- |
+transitiveReferencedIdentifiers :: Identifier -> Generator Identifier
+transitiveReferencedIdentifiers identifier code =  expand (concatMap referencedIdentifiers . (`declarationsOf` code)) identifier
+  where
+    expand :: Eq a => (a-> [a]) -> a -> [a]
+    expand f x = expand' [] f [x]
+
+    expand' _ _ [] = []
+    expand' ps f (x:xs) | elem x ps = expand' ps f xs
+                        | otherwise = [x] ++ expand' (x:ps) f (xs ++ f x)
+
+
+-- | Returns all the declared identifiers
+-- For example, in 'f x = g x where x = y', it returns 'f' and 'x'
+declaredIdentifiers :: Generator Identifier
+declaredIdentifiers = map fst . declarations
+
+mainDeclaredIdentifiers :: Generator Identifier
+mainDeclaredIdentifiers (Sequence _) = []
+mainDeclaredIdentifiers expression   = take 1 . declaredIdentifiers $ expression
+
+-- | Returns all the body equations of functions, procedures and methods
+equationBodies :: Generator EquationBody
+equationBodies = concatMap (bodiesOf . snd) . declarations
+  where
+    bodiesOf :: Generator EquationBody
+    bodiesOf (Subroutine  _ equations) = equationBodies equations
+    bodiesOf _ = []
+
+    equationBodies = map (\(Equation _ body) -> body)
+
+declarationsOf :: Identifier -> Generator Expression
+declarationsOf b = boundDeclarations (named b)
+
+extractReference :: Expression -> Maybe Identifier
+extractReference (Reference n)        = Just n
+extractReference (Exist n _)          = Just n
+extractReference (New n _)            = Just n
+extractReference (Implement n)        = Just n
+extractReference (Include n)          = Just n
+extractReference _                    = Nothing
+
+equationExpressions = concatMap (\(Equation _ body) -> bodyExpressions body)
+  where
+    bodyExpressions (UnguardedBody e)      = [e]
+    bodyExpressions (GuardedBody b)        = b >>= \(es1, es2) -> [es1, es2]
diff --git a/src/Language/Mulang/Identifier.hs b/src/Language/Mulang/Identifier.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Identifier.hs
@@ -0,0 +1,34 @@
+module Language.Mulang.Identifier (
+  andAlso,
+  anyOf,
+  anyone,
+  except,
+  like,
+  named,
+  Identifier,
+  IdentifierPredicate) where
+
+import  Data.List (isInfixOf)
+
+-- | An identifier
+-- | Mulang does not assume any special naming convention or format
+type Identifier = String
+type IdentifierPredicate = Identifier -> Bool
+
+andAlso :: IdentifierPredicate -> IdentifierPredicate -> IdentifierPredicate
+andAlso p1 p2 identifier = p1 identifier && p2 identifier
+
+anyOf :: [Identifier] -> IdentifierPredicate
+anyOf options identifier = any (== identifier) options
+
+anyone :: IdentifierPredicate
+anyone = const True
+
+except :: String -> IdentifierPredicate
+except = (/=)
+
+like :: String -> IdentifierPredicate
+like = isInfixOf
+
+named :: String -> IdentifierPredicate
+named = (==)
diff --git a/src/Language/Mulang/Inspector.hs b/src/Language/Mulang/Inspector.hs
--- a/src/Language/Mulang/Inspector.hs
+++ b/src/Language/Mulang/Inspector.hs
@@ -1,133 +1,15 @@
 module Language.Mulang.Inspector (
-  hasComposition,
-  hasGuards,
-  hasIf,
-  hasConditional,
-  hasLambda,
-  hasDirectRecursion,
-  hasUsage,
-  hasComprehension,
-  hasBinding,
-  hasFunctionDeclaration,
-  hasArity,
-  hasTypeDeclaration,
-  hasTypeSignature,
-  hasAnonymousVariable,
-  hasExpression,
-  hasDecl,
-  hasRhs,
-  Inspection,
-  GlobalInspection
-  ) where
-
-import  Language.Mulang
-import  Language.Mulang.Explorer
-
-type Inspection = Binding -> Program  -> Bool
-type GlobalInspection = Program  -> Bool
-
--- | Inspection that tells whether a binding uses the composition operator '.'
--- in its definition
-hasComposition :: Inspection
-hasComposition = hasExpression f
-  where f (Variable ".") = True
-        f _ = False
-
--- | Inspection that tells whether a binding uses guards
--- in its definition
-hasGuards :: Inspection
-hasGuards = hasRhs f
-  where f (GuardedRhss _) = True
-        f _ = False
-
--- | Inspection that tells whether a binding uses ifs
--- in its definition
-hasIf :: Inspection
-hasIf = hasExpression f
-  where f (If _ _ _) = True
-        f _ = False
-
--- | Inspection that tells whether a binding uses ifs or guards
--- in its definition
-hasConditional :: Inspection
-hasConditional target code = hasIf target code || hasGuards target code
-
--- | Inspection that tells whether a binding uses a lambda expression
--- in its definition
-hasLambda :: Inspection
-hasLambda = hasExpression f
-  where f (Lambda _ _) = True
-        f _ = False
-
-
--- | Inspection that tells whether a binding is direct recursive
-hasDirectRecursion :: Inspection
-hasDirectRecursion binding = hasUsage binding binding
-
--- | Inspection that tells whether a binding uses the the given target binding
--- in its definition
-hasUsage :: String -> Inspection
-hasUsage target = hasExpression f
-  where f expr | (Just n) <- expressionToBinding expr = n == target
-               | otherwise = False
-
--- | Inspection that tells whether a binding uses
--- comprehensions - list comprehension, for comprehension, do-syntax, etc -
--- in its definitions
-hasComprehension :: Inspection
-hasComprehension = hasExpression f
-  where f (Comprehension _ _) = True
-        f _ = False
-
--- | Inspection that tells whether a top level binding exists
-hasBinding :: Inspection
-hasBinding binding = not.null.rhssOf binding
-
-hasFunctionDeclaration :: Inspection
-hasFunctionDeclaration funBinding = has f (declsOf funBinding)
-  where f (FunctionDeclaration _ _) = True
-        f (ConstantDeclaration _ (UnguardedRhs (Lambda _ _)) _) = True
-        f (ConstantDeclaration _ (UnguardedRhs (Variable _)) _) = True -- not actually always true
-        f _  = False
-
-hasArity :: Int -> Inspection
-hasArity arity funBinding = has f (declsOf funBinding)
-  where f (FunctionDeclaration _ equations) = any equationHasArity equations
-        f (ConstantDeclaration _ (UnguardedRhs (Lambda args _)) _) = argsHaveArity args
-        f _  = False
-
-        equationHasArity = \(Equation args _ _) -> argsHaveArity args
-
-        argsHaveArity args = length args == arity
-
-hasTypeDeclaration :: Inspection
-hasTypeDeclaration binding = hasDecl f
-  where f (TypeAlias name) = binding == name
-        f _                   = False
-
-hasTypeSignature :: Inspection
-hasTypeSignature binding = hasDecl f
-  where f (TypeSignature name)  = binding == name
-        f _                       = False
-
-hasAnonymousVariable :: Inspection
-hasAnonymousVariable binding = has f (declsOf binding)
-  where f (FunctionDeclaration _ equations)    = any (any (== WildcardPattern) . p) equations
-        f _                        = False
-        p (Equation params _ _) = params
-
-hasExpression :: (Expression -> Bool) -> Inspection
-hasExpression f binding = has f (expressionsOf binding)
-
-hasRhs :: (Rhs -> Bool)-> Inspection
-hasRhs f binding = has f (rhssOf binding)
-
-hasDecl :: (Declaration -> Bool) -> GlobalInspection
-hasDecl f = has f parseDecls
-
--- private
-
-has f g = any f . g
-
+  module Language.Mulang.Inspector.Generic,
+  module Language.Mulang.Inspector.Combiner,
+  module Language.Mulang.Inspector.ObjectOriented,
+  module Language.Mulang.Inspector.Functional,
+  module Language.Mulang.Inspector.Logic,
+  module Language.Mulang.Inspector.Procedural) where
 
 
+import Language.Mulang.Inspector.Generic
+import Language.Mulang.Inspector.Combiner
+import Language.Mulang.Inspector.ObjectOriented
+import Language.Mulang.Inspector.Functional
+import Language.Mulang.Inspector.Logic
+import Language.Mulang.Inspector.Procedural
diff --git a/src/Language/Mulang/Inspector/Combiner.hs b/src/Language/Mulang/Inspector/Combiner.hs
--- a/src/Language/Mulang/Inspector/Combiner.hs
+++ b/src/Language/Mulang/Inspector/Combiner.hs
@@ -1,18 +1,36 @@
 module Language.Mulang.Inspector.Combiner (
   detect,
   negative,
-  transitive) where
+  alternative,
+  scoped,
+  scopedList,
+  transitive,
+  transitiveList) where
 
-import Language.Mulang
-import Language.Mulang.Inspector
-import Language.Mulang.Explorer
+import Language.Mulang.Ast
+import Language.Mulang.Generator (transitiveReferencedIdentifiers, declarationsOf, declaredIdentifiers)
+import Language.Mulang.Inspector.Generic
 
-detect :: Inspection -> Program -> [Binding]
-detect inspection code = filter (`inspection` code) $ parseBindings code
+detect :: Inspection -> Expression -> [Identifier]
+detect i expression =
+  filter (`inspection` expression) $ declaredIdentifiers expression
+    where inspection = scoped i
 
+alternative :: Inspection -> Inspection -> Inspection
+alternative i1 i2 expression = i1 expression || i2 expression
+
 negative :: Inspection -> Inspection
-negative f code = not . f code
+negative f = not . f
 
-transitive :: Inspection -> Inspection
-transitive inspection binding code = inspection binding code || inUsage
-  where inUsage = any (`inspection` code) . transitiveBindingsOf binding $ code
+scoped :: Inspection -> Identifier -> Inspection
+scoped inspection scope =  any inspection . declarationsOf scope
+
+scopedList :: Inspection -> [Identifier] -> Inspection
+scopedList i =  foldl scoped i . reverse
+
+transitive :: Inspection -> Identifier -> Inspection
+transitive inspection identifier 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)
diff --git a/src/Language/Mulang/Inspector/Functional.hs b/src/Language/Mulang/Inspector/Functional.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/Functional.hs
@@ -0,0 +1,58 @@
+module Language.Mulang.Inspector.Functional (
+  usesGuards,
+  usesComposition,
+  usesLambda,
+  usesPatternMatching,
+  usesComprehension,
+  usesConditional) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Inspector.Generic
+import Language.Mulang.Inspector.Combiner
+
+usesConditional :: Inspection
+usesConditional = alternative usesIf usesGuards
+
+
+-- | Inspection that tells whether an expression uses the composition operator '.'
+-- in its definition
+usesComposition :: Inspection
+usesComposition = containsExpression f
+  where f (Reference ".") = True
+        f _ = False
+
+-- | Inspection that tells whether an expression uses pattern matching
+-- in its definition
+usesPatternMatching :: Inspection
+usesPatternMatching = containsExpression f
+  where f (Function _ equations) = any nonVariablePattern (patterns equations)
+        f _ = False
+
+        patterns = concatMap (\(Equation ps _) -> ps)
+
+        nonVariablePattern :: Pattern -> Bool
+        nonVariablePattern (VariablePattern _) = False
+        nonVariablePattern _                   = True
+
+
+-- | Inspection that tells whether an expression uses
+-- comprehensions - list comprehension, for comprehension, do-syntax, etc -
+-- in its definitions
+usesComprehension :: Inspection
+usesComprehension = containsExpression f
+  where f (Comprehension _ _) = True
+        f _ = False
+
+-- | Inspection that tells whether an expression uses a lambda expression
+-- in its definition
+usesLambda :: Inspection
+usesLambda = containsExpression f
+  where f (Lambda _ _) = True
+        f _ = False
+
+-- | Inspection that tells whether an expression uses guards
+-- in its definition
+usesGuards :: Inspection
+usesGuards = containsBody f
+  where f (GuardedBody _) = True
+        f _ = False
diff --git a/src/Language/Mulang/Inspector/Generic.hs b/src/Language/Mulang/Inspector/Generic.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/Generic.hs
@@ -0,0 +1,191 @@
+module Language.Mulang.Inspector.Generic (
+  parses,
+  assigns,
+  calls,
+  uses,
+  usesIf,
+  declares,
+  declaresVariable,
+  declaresRecursively,
+  declaresEntryPoint,
+  declaresFunction,
+  declaresComputation,
+  declaresComputationWithArity,
+  declaresComputationWithArity',
+  declaresTypeAlias,
+  declaresTypeSignature,
+  usesAnonymousVariable,
+  raises,
+  rescues,
+  usesExceptions,
+  usesExceptionHandling,
+  containsExpression,
+  containsDeclaration,
+  containsBoundDeclaration,
+  containsBody,
+  matchesType,
+  Inspection,
+  IdentifierInspection) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Identifier
+import Language.Mulang.Generator (expressions, boundDeclarations, equationBodies, declarations, referencedIdentifiers)
+
+import Data.Maybe (listToMaybe)
+
+type Inspection = Expression  -> Bool
+type IdentifierInspection = IdentifierPredicate -> Inspection
+
+-- | 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 predicate = containsExpression f
+  where f (Assignment name _)  = predicate name
+        f (Variable name _)    = predicate name
+        f (Attribute name _)   = predicate name
+        f _                    = False
+
+-- | Inspection that tells whether an expression uses the the given target identifier
+-- in its definition
+uses :: IdentifierInspection
+uses p = containsExpression f
+  where f = any p . referencedIdentifiers
+
+calls :: IdentifierInspection
+calls p = containsExpression f
+  where f (Call (Reference id) _ ) = p id
+        f _                        = False
+
+
+-- | Inspection that tells whether an expression uses ifs
+-- in its definition
+usesIf :: Inspection
+usesIf = containsExpression f
+  where f (If _ _ _) = True
+        f _          = False
+
+-- | Inspection that tells whether a top level declaration exists
+declares :: IdentifierInspection
+declares = containsBoundDeclaration f
+  where f (TypeSignature _ _ _) = False
+        f _                     = True
+
+-- | Inspection that tells whether an expression is direct recursive
+declaresRecursively :: IdentifierInspection
+declaresRecursively = containsBoundDeclaration f
+  where f e | (Just name) <- (nameOf e) = uses (named name) e
+            | otherwise = False
+
+        nameOf :: Expression -> Maybe Identifier
+        nameOf = fmap fst . listToMaybe . declarations
+
+
+declaresFunction :: IdentifierInspection
+declaresFunction = containsBoundDeclaration f
+  where f (Function _ _) = True
+        f _              = False
+
+declaresVariable :: IdentifierInspection
+declaresVariable = containsBoundDeclaration f
+  where f (Variable _ _)  = True
+        f _               = False
+
+declaresEntryPoint :: IdentifierInspection
+declaresEntryPoint = containsBoundDeclaration f
+  where f (EntryPoint _ _)  = True
+        f _                 = False
+
+-- | Inspection that tells whether a top level computation declaration exists
+declaresComputation :: IdentifierInspection
+declaresComputation = declaresComputationWithArity' (const True)
+
+declaresComputationWithArity :: Int -> IdentifierInspection
+declaresComputationWithArity arity = declaresComputationWithArity' (== arity)
+
+declaresComputationWithArity' :: (Int -> Bool) -> IdentifierInspection
+declaresComputationWithArity' arityPredicate = containsBoundDeclaration f
+  where f (Subroutine _ es)       = any equationArityIs es
+        f (Clause _ args _)       = argsHaveArity args
+        f _  = False
+
+        equationArityIs (Equation args _) = argsHaveArity args
+
+        argsHaveArity = arityPredicate.length
+
+declaresTypeAlias :: IdentifierInspection
+declaresTypeAlias = containsBoundDeclaration f
+  where f (TypeAlias _) = True
+        f _             = False
+
+declaresTypeSignature :: IdentifierInspection
+declaresTypeSignature = containsBoundDeclaration f
+  where f (TypeSignature _ _ _) = True
+        f _                     = False
+
+raises :: IdentifierInspection
+raises predicate = containsExpression f
+  where f (Raise (New n _))     = predicate n
+        f (Raise (Reference n)) = predicate n
+        f _                     = False
+
+usesExceptions :: Inspection
+usesExceptions = containsExpression f
+  where f (Raise _)     = True
+        f _             = False
+
+rescues :: IdentifierInspection
+rescues predicate = containsExpression f
+  where f (Try _ rescues _) = any (matchesType predicate) . map fst  $ rescues
+        f _                 = False
+
+usesExceptionHandling :: Inspection
+usesExceptionHandling  = containsExpression f
+  where f (Try _ _ _) = True
+        f _           = False
+
+usesAnonymousVariable :: Inspection
+usesAnonymousVariable = containsExpression f
+  where f (Subroutine _ equations)    = equationContainsWildcard equations
+--TODO        f (Lambda args _)                      = equationContainsWildcard equations
+        f (Clause _ params _)         = paramsContainsWildcard params
+        f _                           = False
+
+        equationContainsWildcard = any (paramsContainsWildcard . equationParams)
+        paramsContainsWildcard = any isOrContainsWildcard
+
+        isOrContainsWildcard (InfixApplicationPattern p1 _ p2) = any isOrContainsWildcard [p1, p2]
+        isOrContainsWildcard (ApplicationPattern _ ps)         = any isOrContainsWildcard ps
+        isOrContainsWildcard (TuplePattern ps)                 = any isOrContainsWildcard ps
+        isOrContainsWildcard (ListPattern ps)                  = any isOrContainsWildcard ps
+        isOrContainsWildcard (FunctorPattern _ ps)             = any isOrContainsWildcard ps
+        isOrContainsWildcard (AsPattern _ p)                   = isOrContainsWildcard p
+        isOrContainsWildcard WildcardPattern                   = True
+        isOrContainsWildcard _                                 = False
+
+
+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 (map snd . declarations)
+
+matchesType :: IdentifierPredicate -> Pattern -> Bool
+matchesType predicate (TypePattern n)               = predicate n
+matchesType predicate (AsPattern _ (TypePattern n)) = predicate n
+matchesType predicate (UnionPattern patterns)       = any (matchesType predicate) patterns
+matchesType _         _                             = False
+
+-- private
+
+has f g = any f . g
+
+
+
diff --git a/src/Language/Mulang/Inspector/Generic/Duplication.hs b/src/Language/Mulang/Inspector/Generic/Duplication.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/Generic/Duplication.hs
@@ -0,0 +1,62 @@
+module Language.Mulang.Inspector.Generic.Duplication (hasCodeDuplication) where
+
+import           Language.Mulang.Ast
+import           Language.Mulang.Inspector
+import           Language.Mulang.Generator (expressions)
+import qualified Data.Hashable as H (hash)
+import           Data.List (nub, subsequences)
+
+hasCodeDuplication :: Inspection
+hasCodeDuplication e =  hasDuplicates $ map hash $ filter (not . isLightweight) $ concat $ stripesOf 2 e
+
+isLightweight :: Inspection
+isLightweight (MuNumber _)              = True
+isLightweight (MuString _)              = True
+isLightweight (MuBool _)                = True
+isLightweight (Reference _)             = True
+isLightweight Self                      = True
+isLightweight MuNull                    = True
+isLightweight Equal                     = True
+isLightweight (Application _ es)        = not $ any isApplication es
+isLightweight (Return e)                = isLightweight e
+isLightweight (Assignment _ e)  = isLightweight e
+isLightweight (Variable _ e) = isLightweight e
+isLightweight _                         = False
+
+isApplication (Application _ _) = True
+isApplication _                 = False
+
+
+hasDuplicates ::Eq a => [a] -> Bool
+hasDuplicates xs = nub xs /= xs
+
+
+hash :: Expression -> Int
+hash (Return e)                    = 1 * (37 + hash e)
+hash (MuNumber e)                  = 2 * H.hash e
+hash (MuString e)                  = 3 * H.hash e
+hash (Reference i)                 = 5 * H.hash i
+hash (MuBool e)                    = 7 * H.hash e
+hash (Application i es)            = 11 * (37 + hash i) * (positionalHash es)
+hash (SimpleFunction _ _ body)     = 13 * (37 + hash body)
+hash Self                          = 15
+hash (SimpleProcedure _ _ body)    = 17 * (37 + hash body)
+hash (Sequence es)                 = 19 * (37 + positionalHash es)
+hash _                             = 1
+
+positionalHash :: [Expression] -> Int
+positionalHash = sum . zipWith hashElement [1..] . reverse
+        where
+          hashElement :: Int -> Expression -> Int
+          hashElement index expression = (31^index) * hash expression
+
+stripesOf :: Int -> Expression -> [[Expression]]
+stripesOf n = concatMap (makeStripes n) . expressions
+
+makeStripes :: Int -> Expression -> [[Expression]]
+makeStripes n (Sequence xs) = stripes n xs
+makeStripes _ e             = [[e]]
+
+stripes :: Int -> [a] -> [[a]]
+stripes n = filter ( (>n) . length) . subsequences
+
diff --git a/src/Language/Mulang/Inspector/Generic/Smell.hs b/src/Language/Mulang/Inspector/Generic/Smell.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/Generic/Smell.hs
@@ -0,0 +1,142 @@
+module Language.Mulang.Inspector.Generic.Smell (
+  hasRedundantBooleanComparison,
+  hasRedundantIf,
+  hasRedundantGuards,
+  hasRedundantLambda,
+  hasRedundantParameter,
+  hasRedundantLocalVariableReturn,
+  hasAssignmentReturn,
+  doesNullTest,
+  doesTypeTest,
+  isLongCode,
+  returnsNull,
+  discardsExceptions,
+  doesConsolePrint,
+  hasLongParameterList,
+  hasTooManyMethods,
+  overridesEqualOrHashButNotBoth) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Inspector
+import Language.Mulang.Generator(identifierReferences)
+
+-- | Inspection that tells whether an identifier has expressions like 'x == True'
+hasRedundantBooleanComparison :: Inspection
+hasRedundantBooleanComparison = compares isBooleanLiteral
+
+doesNullTest :: Inspection
+doesNullTest = compares f
+  where f MuNull = True
+        f _      = False
+
+doesTypeTest :: Inspection
+doesTypeTest = compares f
+  where f (MuString _) = True
+        f _            = False
+
+isLongCode :: Inspection
+isLongCode = containsExpression f
+  where f (Sequence xs)  = (length xs) >= 16
+        f  _             = False
+
+compares :: (Expression -> Bool) -> Inspection
+compares f = containsExpression (any f.comparisonOperands)
+
+comparisonOperands (Call Equal    [a1, a2])   = [a1, a2]
+comparisonOperands (Call NotEqual [a1, a2])   = [a1, a2]
+comparisonOperands _                          = []
+
+returnsNull :: Inspection
+returnsNull = containsExpression f
+  where f (Return MuNull) = True
+        f _               = False
+
+-- | Inspection that tells whether an identifier has an if expression where both branches return
+-- boolean literals
+hasRedundantIf :: Inspection
+hasRedundantIf = containsExpression f
+  where f (If _ (Assignment v1 x) (Assignment v2 y)) = all isBooleanLiteral [x, y] && v1 == v2
+        f (If _ (Variable v1 x) (Variable v2 y))     = all isBooleanLiteral [x, y] && v1 == v2
+        f (If _ (Return x) (Return y))               = all isBooleanLiteral [x, y]
+        f (If _ x y)                                 = all isBooleanLiteral [x, y]
+        f _                                          = False
+
+-- | Inspection that tells whether an identifier has guards where both branches return
+-- boolean literals
+hasRedundantGuards :: Inspection
+hasRedundantGuards = containsBody f -- TODO not true when condition is a pattern
+  where f (GuardedBody [
+            (_, Return x),
+            (Reference "otherwise", Return y)]) = all isBooleanLiteral [x, y]
+        f _ = False
+
+
+-- | Inspection that tells whether an identifier has lambda expressions like '\x -> g x'
+hasRedundantLambda :: Inspection
+hasRedundantLambda = containsExpression f
+  where f (Lambda [VariablePattern (x)] (Return (Call _ [Reference (y)]))) = x == y
+        f _ = False
+
+
+-- | Inspection that tells whether an identifier has parameters that
+-- can be avoided using point-free
+hasRedundantParameter :: Inspection
+hasRedundantParameter = containsExpression f
+  where f function@(SimpleFunction _ params (Return (Application _ args))) | (VariablePattern param) <- last params,
+                                                                             (Reference arg) <- last args = param == arg && showsUpOnlyOnce param (identifierReferences function)
+        f _ = False
+        showsUpOnlyOnce p = (==1).countElem p
+        countElem p = length.filter (==p)
+
+isBooleanLiteral (MuBool _) = True
+isBooleanLiteral _          = False
+
+hasRedundantLocalVariableReturn :: Inspection
+hasRedundantLocalVariableReturn = containsExpression f
+  where f (Sequence [ Variable declaredVariable _,
+                      Return (Reference returnedVariable)]) = returnedVariable == declaredVariable
+        f _                                                 = False
+
+hasAssignmentReturn :: Inspection
+hasAssignmentReturn = containsExpression f
+  where f (Return (Assignment _ _)) = True
+        f (Return (Variable _ _))   = True
+        f _                         = False
+
+discardsExceptions :: Inspection
+discardsExceptions = containsExpression f
+  where f (Try _ [(_, MuNull)] _)  = True
+        f (Try _ [(_, Print _)] _) = True
+        f _                        = False
+
+
+doesConsolePrint :: Inspection
+doesConsolePrint = containsExpression f
+  where f (Print _) = True
+        f _         = False
+
+hasLongParameterList :: Inspection
+hasLongParameterList = containsExpression f
+  where f (Params p) = (>4).length $ p
+        f _ = False
+
+hasTooManyMethods :: Inspection
+hasTooManyMethods = containsExpression f
+  where f (Sequence expressions) = (>15).length.filter isMethod $ expressions
+        f _ = False
+        
+        isMethod (Method _ _) = True
+        isMethod _ = False
+
+overridesEqualOrHashButNotBoth :: Inspection
+overridesEqualOrHashButNotBoth = containsExpression f
+  where f (Sequence expressions) = (any isEqual expressions) /= (any isHash expressions)
+        f (Class _ _ (EqualMethod _)) = True
+        f (Class _ _ (HashMethod _)) = True
+        f _ = False
+
+        isEqual (EqualMethod _) = True
+        isEqual _ = False
+        
+        isHash (HashMethod _) = True
+        isHash _ = False
diff --git a/src/Language/Mulang/Inspector/Logic.hs b/src/Language/Mulang/Inspector/Logic.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/Logic.hs
@@ -0,0 +1,59 @@
+module Language.Mulang.Inspector.Logic (
+  usesNot,
+  usesFindall,
+  usesForall,
+  usesUnificationOperator,
+  hasRedundantReduction,
+  usesCut,
+  usesFail,
+  declaresFact,
+  declaresRule,
+  declaresPredicate) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Identifier
+import Language.Mulang.Inspector.Generic
+import Language.Mulang.Inspector.Combiner
+
+declaresFact :: IdentifierPredicate -> Inspection
+declaresFact = containsBoundDeclaration f
+  where f (Fact _ _) = True
+        f _          = False
+
+declaresRule :: IdentifierPredicate -> Inspection
+declaresRule = containsBoundDeclaration f
+  where f (Rule _ _ _) = True
+        f _            = False
+
+usesNot :: Inspection
+usesNot = containsExpression f
+  where f (Not  _) = True
+        f _ = False
+
+usesFindall :: Inspection
+usesFindall = containsExpression f
+  where f (Findall  _ _ _) = True
+        f _ = False
+
+usesForall :: Inspection
+usesForall = containsExpression f
+  where f (Forall  _ _) = True
+        f _ = False
+
+usesUnificationOperator :: Inspection
+usesUnificationOperator = uses (named "=")
+
+usesCut :: Inspection
+usesCut = uses (named "!")
+
+usesFail :: Inspection
+usesFail = uses (named "fail")
+
+hasRedundantReduction :: Inspection
+hasRedundantReduction = containsExpression f
+  where f (Exist "is" [(VariablePattern _), (ApplicationPattern _ _)]) = False
+        f (Exist "is" [(VariablePattern _), _]) = True
+        f _ = False
+
+declaresPredicate :: IdentifierPredicate -> Inspection
+declaresPredicate pred = alternative (declaresFact pred) (declaresRule pred)
diff --git a/src/Language/Mulang/Inspector/ObjectOriented.hs b/src/Language/Mulang/Inspector/ObjectOriented.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/ObjectOriented.hs
@@ -0,0 +1,77 @@
+module Language.Mulang.Inspector.ObjectOriented (
+  implements,
+  includes,
+  inherits,
+  instantiates,
+  usesInheritance,
+  usesMixins,
+  declaresObject,
+  declaresSuperclass,
+  declaresClass,
+  declaresInterface,
+  declaresEnumeration,
+  declaresAttribute,
+  declaresMethod)  where
+
+import Language.Mulang.Ast
+import Language.Mulang.Identifier
+import Language.Mulang.Inspector.Generic
+
+implements :: IdentifierInspection
+implements predicate = containsExpression f
+  where f (Implement name) = predicate name
+        f _                = False
+
+includes :: IdentifierInspection
+includes predicate = containsExpression f
+  where f (Include name) = predicate name
+        f _              = False
+
+inherits :: IdentifierInspection
+inherits predicate = containsDeclaration f
+  where f (Class _ (Just name) _) = predicate name
+        f _                       = False
+
+instantiates :: IdentifierInspection
+instantiates predicate = containsExpression f
+  where f (New name _) = predicate name
+        f _            = False
+
+usesInheritance :: Inspection
+usesInheritance = declaresSuperclass anyone
+
+usesMixins :: Inspection
+usesMixins = includes anyone
+
+declaresObject :: IdentifierInspection
+declaresObject =  containsBoundDeclaration f
+  where f (Object _ _) = True
+        f _            = False
+
+declaresSuperclass :: IdentifierInspection
+declaresSuperclass = inherits
+
+declaresClass :: IdentifierInspection
+declaresClass =  containsBoundDeclaration f
+  where f (Class _ _ _) = True
+        f _             = False
+
+declaresEnumeration :: IdentifierInspection
+declaresEnumeration =  containsBoundDeclaration f
+  where f (Enumeration _ _) = True
+        f _                 = False
+
+declaresInterface :: IdentifierInspection
+declaresInterface =  containsBoundDeclaration f
+  where f (Interface _ _ _) = True
+        f _                 = False
+
+declaresAttribute :: IdentifierInspection
+declaresAttribute =  containsBoundDeclaration f
+  where f (Attribute _ _) = True
+        f _               = False
+
+declaresMethod :: IdentifierInspection
+declaresMethod =  containsBoundDeclaration f
+  where f (Method _ _) = True
+        f _            = False
diff --git a/src/Language/Mulang/Inspector/Procedural.hs b/src/Language/Mulang/Inspector/Procedural.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Inspector/Procedural.hs
@@ -0,0 +1,36 @@
+module Language.Mulang.Inspector.Procedural (
+  usesRepeat,
+  usesWhile,
+  usesSwitch,
+  declaresProcedure) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Identifier
+import Language.Mulang.Inspector.Generic
+
+declaresProcedure :: IdentifierPredicate -> Inspection
+declaresProcedure = containsBoundDeclaration f
+  where f (Procedure _ _) = True
+        f _                          = False
+
+
+-- | Inspection that tells whether an expression uses while
+-- in its definition
+usesWhile :: Inspection
+usesWhile = containsExpression f
+  where f (While _ _) = True
+        f _ = False
+-- | Inspection that tells whether an expression uses Switch
+-- in its definition
+usesSwitch :: Inspection
+usesSwitch = containsExpression f
+  where f (Switch _ _) = True
+        f _ = False
+
+-- | Inspection that tells whether an expression uses reoeat
+-- in its definition
+usesRepeat :: Inspection
+usesRepeat = containsExpression f
+  where f (Repeat _ _) = True
+        f _ = False
+
diff --git a/src/Language/Mulang/Inspector/Smell.hs b/src/Language/Mulang/Inspector/Smell.hs
deleted file mode 100644
--- a/src/Language/Mulang/Inspector/Smell.hs
+++ /dev/null
@@ -1,54 +0,0 @@
-module Language.Mulang.Inspector.Smell (
-  hasRedundantBooleanComparison,
-  hasRedundantIf,
-  hasRedundantGuards,
-  hasRedundantLambda,
-  hasRedundantParameter) where
-
-import Language.Mulang
-import Language.Mulang.Explorer
-import Language.Mulang.Inspector
-
-
--- | Inspection that tells whether a binding has expressions like 'x == True'
-hasRedundantBooleanComparison :: Inspection
-hasRedundantBooleanComparison = hasExpression f
-  where f (InfixApplication x c y) = any isBooleanLiteral [x, y] && isComp c
-        f _ = False
-
-        isComp c = c == "==" || c == "/="
-
--- | Inspection that tells whether a binding has an if expression where both branches return
--- boolean literals
-hasRedundantIf :: Inspection
-hasRedundantIf = hasExpression f
-  where f (If _ x y) = all isBooleanLiteral [x, y]
-        f _            = False
-
-
--- | Inspection that tells whether a binding has guards where both branches return
--- boolean literals
-hasRedundantGuards :: Inspection
-hasRedundantGuards = hasRhs f -- TODO not true when condition is a pattern
-  where f (GuardedRhss [
-            GuardedRhs _ x,
-            GuardedRhs (Variable "otherwise") y]) = all isBooleanLiteral [x, y]
-        f _ = False
-
-
--- | Inspection that tells whether a binding has lambda expressions like '\x -> g x'
-hasRedundantLambda :: Inspection
-hasRedundantLambda = hasExpression f
-  where f (Lambda [VariablePattern (x)] (Application _ (Variable (y)))) = x == y
-        f _ = False -- TODO consider parenthesis and symbols
-
--- | Inspection that tells whether a binding has parameters that
--- can be avoided using point-free
-hasRedundantParameter :: Inspection
-hasRedundantParameter binding = any f . declsOf binding
-  where f (FunctionDeclaration _ [
-             Equation params (UnguardedRhs (Application _ (Variable arg))) _ ]) | (VariablePattern param) <- last params = param == arg
-        f _ = False
-
-isBooleanLiteral (Literal (MuBool _)) = True
-isBooleanLiteral _                  = False
diff --git a/src/Language/Mulang/Parsers.hs b/src/Language/Mulang/Parsers.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Parsers.hs
@@ -0,0 +1,13 @@
+module Language.Mulang.Parsers
+  (Parser, EitherParser, MaybeParser, maybeToEither) where
+
+import           Language.Mulang.Ast
+import qualified Text.SimpleParser as S (SimpleParser, EitherParser, MaybeParser)
+
+type Parser = S.SimpleParser Expression
+type EitherParser = S.EitherParser Expression
+type MaybeParser = S.MaybeParser Expression
+
+maybeToEither :: MaybeParser -> EitherParser
+maybeToEither parser input | (Just result) <- parser input = Right result
+                           | otherwise = Left "Sample code parsing error"
diff --git a/src/Language/Mulang/Parsers/Haskell.hs b/src/Language/Mulang/Parsers/Haskell.hs
--- a/src/Language/Mulang/Parsers/Haskell.hs
+++ b/src/Language/Mulang/Parsers/Haskell.hs
@@ -1,84 +1,111 @@
-module Language.Mulang.Parsers.Haskell (parseHaskell) where
+module Language.Mulang.Parsers.Haskell (hs, parseHaskell) where
 
-import Language.Mulang
+import Language.Mulang.Ast
+import Language.Mulang.Builder
+import Language.Mulang.Parsers
+
 import Language.Haskell.Syntax
 import Language.Haskell.Parser
 
-import Data.String (IsString(..))
-import Data.Maybe (fromJust)
 import Data.List (intercalate)
 
-instance IsString Program where
-  fromString = fromJust.parseHaskell
+import Control.Fallible
 
-parseHaskell :: String -> Maybe Program
-parseHaskell code | ParseOk ast <- parseModule code = Just (mu ast)
-                  | otherwise = Nothing
+instance Fallible ParseResult where
+  failure (ParseOk v)       = Left v
+  failure (ParseFailed _ m) = Right m
 
-mu :: HsModule -> Program
-mu (HsModule _ _ _ _ decls) = (Program (concatMap muDecls decls))
+hs :: Parser
+hs = orFail . parseHaskell'
+
+parseHaskell :: EitherParser
+parseHaskell = orLeft . parseHaskell'
+
+parseHaskell' :: String -> ParseResult Expression
+parseHaskell' = fmap (normalize . mu) . parseModule . (++"\n")
+
+mu :: HsModule -> Expression
+mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls)
   where
+    mergeDecls decls exp = compact (decls ++ [exp])
+
     muDecls (HsTypeDecl _ name _ _)      = [TypeAlias (muName name)]
-    muDecls (HsDataDecl _ _ name _ _ _ ) = [RecordDeclaration (muName name)]
-    muDecls (HsTypeSig _ names _) = map (\name -> TypeSignature (muName name)) names
+    muDecls (HsDataDecl _ _ name _ _ _ ) = [Record (muName name)]
+    muDecls (HsTypeSig _ names (HsQualType _ t)) = map (muTypeSignature t) names
     muDecls (HsFunBind equations) | (HsMatch _ name _ _ _) <- head equations =
-                                        [FunctionDeclaration (muName name) (map muEquation equations)]
-    muDecls (HsPatBind _ (HsPVar name) rhs decls) = [ConstantDeclaration (muName name) (muRhs rhs) (concatMap muDecls decls)]
+                                        [Function (muName name) (map muEquation equations)]
+    muDecls (HsPatBind _ (HsPVar name) (HsUnGuardedRhs exp) _) = [Variable (muName name) (muExp exp)]
     muDecls _ = []
 
     muEquation :: HsMatch -> Equation
-    muEquation (HsMatch _ _ patterns rhs locals) =
-         Equation (map muPat patterns) (muRhs rhs) (concatMap muDecls locals)
+    muEquation (HsMatch _ _ patterns rhs decls) =
+         Equation (map muPat patterns) (muRhs (concatMap muDecls decls) rhs)
 
-    muRhs (HsUnGuardedRhs exp)          = UnguardedRhs (muExp exp)
-    muRhs (HsGuardedRhss  guards) = GuardedRhss (map muGuardedRhs guards)
+    muRhs decls (HsUnGuardedRhs body)        = UnguardedBody (mergeDecls decls (muBody body))
+    muRhs decls (HsGuardedRhss  guards)      = GuardedBody (map (muGuardedRhs decls) guards )
 
-    muGuardedRhs (HsGuardedRhs _ condition body) = (GuardedRhs (muExp condition) (muExp body))
+    muGuardedRhs decls (HsGuardedRhs _ condition body) = (mergeDecls decls (muExp condition), muBody body)
 
-    muPat (HsPVar name) = VariablePattern (muName name)                 -- ^ variable
-    muPat (HsPLit _) = LiteralPattern ""              -- ^ literal constant
-    --Pattern HsPInfixApp = InfixApplicationPattern Pattern MuQName Pattern
-    --Pattern HsPApp = ApplicationPattern MuQName [Pattern]        -- ^ data constructor and argument
+    muBody = Return . muExp
+
+    muPat (HsPVar name) = VariablePattern (muName name)
+    muPat (HsPLit _) = LiteralPattern ""
+    muPat (HsPInfixApp e1 name e2) = InfixApplicationPattern (muPat e1) (muQName name) (muPat e2)
+    muPat (HsPApp name elements) = ApplicationPattern (muQName name) (map muPat elements)
     muPat (HsPTuple elements) = TuplePattern (map muPat elements)
     muPat (HsPList elements) = ListPattern (map muPat elements)
     muPat (HsPParen pattern) = muPat pattern
-    --Pattern HsPAsPat = AsPattern String Pattern
+    muPat (HsPAsPat name pattern) = AsPattern (muName name) (muPat pattern)
     muPat HsPWildCard = WildcardPattern
     muPat _ = OtherPattern
 
-    muExp (HsVar name) = Variable (muQName name)
-    muExp (HsCon (UnQual (HsIdent "True")))  = Literal (MuBool True)
-    muExp (HsCon (UnQual (HsIdent "False"))) = Literal (MuBool False)
-    muExp (HsCon name)                       = Variable (muQName name)
-    muExp (HsLit lit) = Literal (muLit lit)
-    muExp (HsInfixApp e1 op e2) = InfixApplication (muExp e1) (muQOp op) (muExp e2)  -- ^ infix application
-    muExp (HsApp e1 e2) = Application (muExp e1) (muExp e2)             -- ^ ordinary application
-    muExp (HsNegApp e) = Application (Variable "-") (muExp e)
-    muExp (HsLambda _ args exp) = Lambda (map muPat args) (muExp exp)
+    muExp (HsVar (UnQual (HsIdent "undefined"))) = Raise (MuString "undefined")
+
+    muExp (HsVar name) = muVar (muQName name)
+    muExp (HsCon (UnQual (HsIdent "True")))  = MuTrue
+    muExp (HsCon (UnQual (HsIdent "False"))) = MuFalse
+    muExp (HsCon name)                       = Reference (muQName name)
+    muExp (HsLit lit) = muLit lit
+
+    muExp (HsInfixApp e1 op e2)                                  = Application ((muVar.muQOp) op) [muExp e1, muExp e2]
+    muExp (HsApp (HsVar (UnQual (HsIdent "error"))) e1)          = Raise (muExp e1)
+    muExp (HsApp (HsApp (HsApp (HsApp e1 e2) e3) e4) e5)         = Application (muExp e1) [muExp e2, muExp e3, muExp e4, muExp e5]
+    muExp (HsApp (HsApp (HsApp e1 e2) e3) e4)                    = Application (muExp e1) [muExp e2, muExp e3, muExp e4]
+    muExp (HsApp (HsApp e1 e2) e3)                               = Application (muExp e1) [muExp e2, muExp e3]
+    muExp (HsApp e1 e2)                                          = Application (muExp e1) [muExp e2]
+    muExp (HsLeftSection e1 e2)                                  = Application (muVar $ muQOp e2) [muExp e1]
+    muExp (HsRightSection e1 e2)                                 = Application (muVar $ muQOp e1) [muExp e2]
+    muExp (HsNegApp e) = Application (Reference "-") [muExp e]
+    muExp (HsLambda _ args body) = Lambda (map muPat args) (muBody body)
     --muExp HsLet = Let [Declaration] Expression          -- ^ local declarations with @let@
     muExp (HsIf e1 e2 e3) = If (muExp e1) (muExp e2) (muExp e3)
     --muExp HsMatch = Match Expression [Alternative]          -- ^ @case@ /exp/ @of@ /alts/
     muExp (HsTuple elements) = MuTuple (map muExp elements)               -- ^ tuple Expression
     muExp (HsList elements) = MuList (map muExp elements)
     muExp (HsParen e) = (muExp e)
-    muExp (HsEnumFrom from)              = Application (Variable "enumFrom") (muExp from)
-    muExp (HsEnumFromTo from to)         = Application (Application (Variable "enumFromTo") (muExp from)) (muExp to)
-    muExp (HsEnumFromThen from thn)      = Application (Application (Variable "enumFromThen") (muExp from)) (muExp thn)
-    muExp (HsEnumFromThenTo from thn to) = Application (Application (Application (Variable "enumFromThenTo") (muExp from)) (muExp thn)) (muExp to)
+    muExp (HsEnumFrom from)              = Application (Reference "enumFrom") [(muExp from)]
+    muExp (HsEnumFromTo from to)         = Application (Reference "enumFromTo") [(muExp from), (muExp to)]
+    muExp (HsEnumFromThen from thn)      = Application (Reference "enumFromThen") [(muExp from), (muExp thn)]
+    muExp (HsEnumFromThenTo from thn to) = Application (Reference "enumFromThenTo") [(muExp from), (muExp thn), (muExp to)]
     muExp (HsListComp exp stmts)         = Comprehension (muExp exp) (map muStmt stmts)
     muExp (HsDo stmts) | (HsQualifier exp) <- last stmts  = Comprehension (muExp exp) (map muStmt stmts)
-    muExp _ = ExpressionOther
+    muExp _ = Other
 
-    muLit (HsChar        v) = MuString [v]
-    muLit (HsString      v) = MuString v
-    muLit (HsInt         v) = MuInteger v
-    muLit (HsFrac        v) = MuFloat v
     muLit (HsCharPrim    v) = MuString [v]
     muLit (HsStringPrim  v) = MuString v
-    muLit (HsIntPrim     v) = MuInteger v
-    muLit (HsFloatPrim   v) = MuFloat v
-    muLit (HsDoublePrim  v) = MuFloat v
+    muLit (HsChar        v) = MuString [v]
+    muLit (HsString      v) = MuString v
+    muLit (HsIntPrim     v) = MuNumber . fromIntegral $ v
+    muLit (HsInt         v) = MuNumber . fromIntegral $ v
+    muLit (HsFrac        v) = MuNumber . fromRational $ v
+    muLit (HsFloatPrim   v) = MuNumber . fromRational $ v
+    muLit (HsDoublePrim  v) = MuNumber . fromRational $ v
 
+    muVar :: String -> Expression
+    muVar "==" = Equal
+    muVar "/=" = NotEqual
+    muVar v = Reference v
+
     muName :: HsName -> String
     muName (HsSymbol n) = n
     muName (HsIdent  n) = n
@@ -96,3 +123,17 @@
 
     muStmt (HsGenerator _ pat exp) = MuGenerator (muPat pat) (muExp exp)
     muStmt (HsQualifier exp) = MuQualifier (muExp exp)
+
+    muTypeSignature t name = TypeSignature (muName name) (init topTypes) (last topTypes)
+      where topTypes = muTopTypes t
+
+    muTopTypes (HsTyFun i o) = muType i : muTopTypes o
+    muTopTypes t             = [muType t]
+
+    muType (HsTyFun i o)                              = muType i ++ " -> " ++ muType o
+    muType (HsTyCon name)                             = muQName name
+    muType (HsTyVar name)                             = muName name
+    muType (HsTyTuple ts)                             = "(" ++ (intercalate ", " . map muType $ ts) ++ ")"
+    muType (HsTyApp (HsTyCon (Special HsListCon)) t2) = "[" ++ muType t2 ++ "]"
+    muType (HsTyApp t1 t2)                            = muType t1 ++ " " ++ muType t2
+
diff --git a/src/Language/Mulang/Parsers/Java.hs b/src/Language/Mulang/Parsers/Java.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Parsers/Java.hs
@@ -0,0 +1,184 @@
+{-# LANGUAGE ViewPatterns #-}
+
+
+module Language.Mulang.Parsers.Java (java, parseJava) where
+
+import Language.Mulang.Ast hiding (While, Return, Equal, Lambda, Try)
+import qualified Language.Mulang.Ast as M (Expression(While, Return, Equal, Lambda, Try))
+import Language.Mulang.Parsers
+import Language.Mulang.Builder (compact, compactMap, compactConcatMap)
+
+import Language.Java.Parser
+import Language.Java.Syntax
+
+import Control.Fallible
+
+import Data.Maybe (fromMaybe)
+import Data.List (intercalate)
+import Data.Char (toLower)
+
+java :: Parser
+java = orFail . parseJava'
+
+parseJava :: EitherParser
+parseJava = orLeft . parseJava'
+
+parseJava' = fmap m . j
+
+m (CompilationUnit _ _ typeDecls) = compactMap muTypeDecl $ typeDecls
+
+muTypeDecl (ClassTypeDecl decl)    = muClassTypeDecl decl
+muTypeDecl (InterfaceTypeDecl decl) = muInterfaceTypeDecl decl
+
+muClassTypeDecl (ClassDecl _ name _ superclass interfaces (ClassBody body)) =
+  Class (i name) (fmap muRefType superclass) (compact (map muImplements interfaces ++ concatMap muDecl body))
+muClassTypeDecl (EnumDecl _ name _ (EnumBody constants _))                   =
+  Enumeration (i name) (map muEnumConstant constants)
+
+muImplements interface = Implement $ muRefType interface
+
+muInterfaceTypeDecl (InterfaceDecl _ name _ interfaces (InterfaceBody body)) =
+  Interface (i name) (map muRefType interfaces) (compactConcatMap muMemberDecl body )
+
+muDecl :: Decl -> [Expression]
+muDecl (MemberDecl memberDecl) = muMemberDecl memberDecl
+muDecl (InitDecl _ _)          = return Other
+
+muMemberDecl :: MemberDecl -> [Expression]
+muMemberDecl (FieldDecl _ _type varDecls)                            = map (variableToAttribute.muVarDecl) varDecls
+muMemberDecl (MethodDecl _ _ typ name params _ (MethodBody Nothing)) = return $ TypeSignature (i name) (map muFormalParamType params) (muMaybeType typ)
+muMemberDecl (MethodDecl (elem Static -> True) _ Nothing (Ident "main") [_] _ body)
+                                                                     = return $ EntryPoint "main" (muMethodBody body)
+muMemberDecl (MethodDecl _ _ _ (Ident "equals") params _ body)       = return $ EqualMethod [SimpleEquation (map muFormalParam params) (muMethodBody body)]
+muMemberDecl (MethodDecl _ _ _ (Ident "hashCode") params _ body)     = return $ HashMethod [SimpleEquation (map muFormalParam params) (muMethodBody body)]
+muMemberDecl (MethodDecl _ _ _ name params _ body)                   = return $ SimpleMethod (i name) (map muFormalParam params) (muMethodBody body)
+muMemberDecl (ConstructorDecl _ _ _ _params _ _constructorBody)      = return $ Other
+muMemberDecl (MemberClassDecl decl)                                  = return $ muClassTypeDecl decl
+muMemberDecl (MemberInterfaceDecl decl)                              = return $ muInterfaceTypeDecl decl
+
+muEnumConstant (EnumConstant name _ _) = i name
+
+muFormalParam (FormalParam _ _ _ id)      = VariablePattern (v id)
+muFormalParamType (FormalParam _ typ _ _) = (muType typ)
+
+muBlock (Block statements) = compactConcatMap muBlockStmt statements
+
+muBlockStmt (BlockStmt stmt) = [muStmt stmt]
+muBlockStmt (LocalClass decl) = [muClassTypeDecl decl]
+muBlockStmt (LocalVars _ _type vars) = map muVarDecl vars
+
+muMaybeType Nothing    = "void"
+muMaybeType (Just typ) = muType typ
+
+muType (PrimType t) = muPrimType t
+muType (RefType t)  = muRefType t
+
+muStmt (StmtBlock block)               = muBlock block
+muStmt (IfThen exp ifTrue)             = If (muExp exp) (muStmt ifTrue) MuNull
+muStmt (IfThenElse exp ifTrue ifFalse) = If (muExp exp) (muStmt ifTrue) (muStmt ifFalse)
+muStmt (While cond body)               = M.While (muExp cond) (muStmt body)
+muStmt (Return exp)                    = M.Return $ fmapOrNull muExp exp
+muStmt (ExpStmt exp)                   = muExp exp
+muStmt Empty                           = MuNull
+muStmt (Assert exp _)                  = SimpleSend Self "assert" [muExp exp]
+muStmt (Synchronized _ block)          = muBlock block
+muStmt (Labeled _ stmt)                = muStmt stmt
+muStmt (Throw exp)                     = Raise $ muExp exp
+muStmt (Try block catches finally)     = M.Try (muBlock block) (map muCatch catches) (fmapOrNull muBlock finally)
+--muStmt (EnhancedFor _ _ name gen body) = Other
+--Switch Exp [SwitchBlock]
+muStmt _                               = Other
+
+muExp (Lit lit)                         = muLit lit
+muExp (MethodInv invoke)                = muMethodInvocation invoke
+muExp This                              = Self
+muExp (BinOp arg1 op arg2)              = Send (muExp arg1) (muOp op) [muExp arg2]
+muExp (Cond cond ifTrue ifFalse)        = If (muExp cond) (muExp ifTrue) (muExp ifFalse)
+muExp (ExpName name)                    = muName name
+muExp (Assign lhs EqualA exp)           = Assignment (muLhs lhs) (muExp exp)
+muExp (InstanceCreation _ clazz args _) = New (r clazz) (map muExp args)
+muExp (PreNot exp)                      = SimpleSend (muExp exp) "!" []
+muExp (Lambda params exp)               = M.Lambda (muLambdaParams params) (muLambdaExp exp)
+muExp (MethodRef _ message)             = M.Lambda [VariablePattern "it"] (SimpleSend (Reference "it") (i message) [])
+muExp _                                 = Other
+
+muLambdaExp (LambdaExpression exp) = muExp exp
+muLambdaExp (LambdaBlock block) = muBlock block
+
+muLambdaParams (LambdaSingleParam name)     = [VariablePattern (i name)]
+muLambdaParams (LambdaInferredParams names) = map (VariablePattern . i) names
+muLambdaParams (LambdaFormalParams params)  = map muFormalParam params
+
+muCatch :: Catch -> (Pattern, Expression)
+muCatch (Catch param block) = (TypePattern (muFormalParamType param), muBlock block)
+
+muLhs (NameLhs (Name names)) = ns names
+
+muName (Name names) = Reference . ns $ names
+
+muLit (String s)  = MuString s
+muLit (Char c)    = MuString [c]
+muLit (Int i)     = MuNumber (fromIntegral i)
+muLit (Float d)   = MuNumber d
+muLit (Double d)  = MuNumber d
+muLit (Boolean b) = MuBool   b
+muLit Null        = MuNull
+muLit _           = Other
+
+muOp Mult   = Reference "*"
+muOp Div    = Reference "/"
+muOp Rem    = Reference "rem"
+muOp Add    = Reference "+"
+muOp Sub    = Reference "-"
+muOp LThan  = Reference "<"
+muOp LThanE = Reference "<="
+muOp GThan  = Reference ">"
+muOp GThanE = Reference ">="
+muOp And    = Reference "&&"
+muOp Or     = Reference "||"
+muOp Equal  = M.Equal
+muOp NotEq  = NotEqual
+muOp _      = Other
+
+muVarDecl (VarDecl id init) = Variable (v id) (fmapOrNull muVarInit init)
+
+muMethodBody (MethodBody (Just block)) = muBlock block
+
+muVarInit (InitExp exp) = muExp exp
+muVarInit (InitArray _ArrayInit) = Other
+
+muMethodInvocation (MethodCall (Name [Ident "System", Ident "out", Ident "println"]) [expr])  = Print (muExp expr)
+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 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 _ = Other
+
+muRefType (ClassRefType clazz) = r clazz
+muRefType (ArrayType t)        = (muType t) ++ "[]"
+
+muPrimType = map toLower . dropLast 1 . show
+
+-- Combinators
+
+fmapOrNull f = fromMaybe MuNull . fmap f
+
+-- Helpers
+
+variableToAttribute (Variable id init) = Attribute id init
+
+v (VarId name) = i name
+v (VarDeclArray id) =  (v id) ++ "[]"
+
+i (Ident name) = name
+r (ClassType [(name, _)]) = i name
+
+j = parser compilationUnit
+
+ns = intercalate "." . map i
+
+-- list helpers
+
+dropLast n xs = take (length xs - n) xs
diff --git a/src/Language/Mulang/Parsers/JavaScript.hs b/src/Language/Mulang/Parsers/JavaScript.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Parsers/JavaScript.hs
@@ -0,0 +1,164 @@
+module Language.Mulang.Parsers.JavaScript (js, parseJavaScript) where
+
+import Language.Mulang.Ast
+import Language.Mulang.Builder
+import Language.Mulang.Parsers
+
+import Language.JavaScript.Parser.Parser (parse)
+import Language.JavaScript.Parser.AST
+
+import Data.Either ()
+
+import Control.Fallible
+
+js :: Parser
+js = orFail . parseJavaScript'
+
+parseJavaScript :: MaybeParser
+parseJavaScript = orNothing . parseJavaScript'
+
+parseJavaScript' :: String -> Either String Expression
+parseJavaScript' = fmap (normalize . mu) . (`parse` "src")
+
+mu :: JSNode -> Expression
+mu = compact . muNode . gc
+  where
+    muNode (JSSourceElementsTop statements)                  = [compactMapMu statements]
+    muNode (JSIdentifier "undefined")                        = [MuNull]
+    muNode (JSIdentifier n)                                  = [Reference n]
+    muNode (JSDecimal val)                                   = [MuNumber (read val)]
+    muNode (JSExpression xs)                                 = [compactMapMu xs]
+    muNode (JSLiteral "null")                                = [MuNull]
+    muNode (JSLiteral "true")                                = [MuTrue]
+    muNode (JSLiteral "false")                               = [MuFalse]
+    muNode (JSLiteral _)                                     = []
+    muNode (JSElision _)                                     = []
+    muNode (JSHexInteger v)                                  = muNode (JSStringLiteral '\'' v)
+    muNode (JSOctal v)                                       = muNode (JSStringLiteral '"' v)
+    muNode (JSExpressionPostfix "++" [var] _)                = [muVarAssignment var (muPlus var (MuNumber 1))]
+    muNode (JSExpressionPostfix "--" [var] _)                = [muVarAssignment var (muMinus var (MuNumber 1))]
+    muNode (JSStringLiteral _ v)                             = [MuString v]
+    muNode (JSVariables _ decls _)                           = mapMu decls
+    muNode (JSArrayLiteral _ es _)                           = [MuList (mapMu es)]
+    muNode (JSVarDecl var initial)                           = [muVarDeclaration var initial]
+    muNode (JSWith _ _ _ _ _)                                = [Other]
+    muNode (JSExpressionTernary cond _ true _ false)         = [muIf cond   true false]
+    muNode (JSIf _ _ cond _ true false)                      = [muIf [cond] true false]
+    muNode (JSWhile _ _ cond _ action)                       = [muWhile cond action]
+    muNode (JSBlock _ exps _)                                = [compactMapMu exps]
+    muNode (JSFunctionExpression _ [] _ params _ body)       = [Lambda (muParams params) (mu body)]
+    muNode (JSFunctionExpression _ [name] _ params _ body)   = [muFunction  name params body]
+    muNode (JSReturn _ e _)                                  = [Return (compactMapMu e)]
+    muNode (JSExpressionParen _ e _)                         = [mu e]
+    muNode (JSObjectLiteral _ es _)                          = [MuObject (compactMapMu es)]
+    muNode (JSLabelled _ _ e)                                = [mu e]
+    muNode (JSPropertyNameandValue var _ initial)            = [muVarDeclaration var initial]
+    muNode (JSFunction _ name _ params _ body)               = [muFunction name params body]
+    muNode (JSExpressionBinary op l _ r)                     = [Application (muOp op) [compactMapMu l, compactMapMu r]]
+    muNode (JSMemberDot receptor _ selector)                 = [Send (compactMapMu receptor) (mu selector) []]
+    muNode (JSThrow _ e)                                     = [Raise (mu e)]
+    muNode e                                                 = [Other]
+
+
+
+    mapMu :: [JSNode] -> [Expression]
+    mapMu [] = []
+    mapMu (x:y:xs)   | (JSArguments _ args _) <- gc y =  [Application (mu x) (mapMu args)] ++ mapMu xs
+    mapMu (x:y:z:xs) | (JSOperator (NT (JSLiteral "=") _ _))  <- gc y =  [muVarAssignment x (mu z)] ++ mapMu xs
+                     | (JSOperator (NT (JSLiteral "+=") _ _))  <- gc y =  [muVarAssignment x (muPlus x (mu z))] ++ mapMu xs
+    mapMu (x:xs) = (muNode.gc) x ++ mapMu xs
+
+    muParams :: [JSNode] -> [Pattern]
+    muParams params = concatMap (muPattern.gc) params
+
+    muOp :: String -> Expression
+    muOp "=="  = Equal
+    muOp "===" = Equal
+    muOp "!="  = NotEqual
+    muOp "!==" = NotEqual
+    muOp v    = Reference v
+
+    muPattern (JSLiteral _)    = []
+    muPattern (JSIdentifier i) = [VariablePattern i]
+    muPattern e                = error (show e)
+
+    gc (NN n) = n
+    gc (NT n _ _) = n
+
+    muId = f.gc
+           where f (JSIdentifier id) = id
+
+
+    muEquation params body = [SimpleEquation params body]
+
+    compactMapMu :: [JSNode] -> Expression
+    compactMapMu  = compact . mapMu
+
+    muIf :: [JSNode] -> [JSNode] -> [JSNode] -> Expression
+    muIf cond true false = If (compactMapMu cond) (compactMapMu true) (compactMapMu false)
+
+    muWhile cond action  = While (mu cond) (mu action)
+
+    muVarDeclaration var initial = Variable (muId var) (compactMapMu initial)
+    muVarAssignment  var value  = Assignment (muId var)  value
+
+    muPlus var delta = (Application (Reference "+") [Reference (muId var), delta])
+    muMinus var delta = (Application (Reference "-") [Reference (muId var), delta])
+
+    muFunction :: JSNode -> [JSNode] -> JSNode -> Expression
+    muFunction name params body = muComputation (muId name) (muParams params) (mu body)
+                            where
+                                muComputation name params body = (computationFor body) name (muEquation params body)
+
+                                computationFor :: Expression -> Identifier -> [Equation] -> Expression
+                                computationFor body | containsReturn body = Function
+                                                    | otherwise = Procedure
+
+                                containsReturn :: Expression -> Bool
+                                containsReturn (Return _)    = True
+                                containsReturn (Sequence xs) = any containsReturn xs
+                                containsReturn _             = False
+
+{-JSRegEx String
+optional lb,optional block statements,optional rb
+JSBreak JSNode [JSNode] JSNode
+break, optional identifier, autosemi
+JSCallExpression String [JSNode] [JSNode] [JSNode]
+type : ., (), []; opening [ or ., contents, closing
+JSCase JSNode JSNode JSNode [JSNode]
+case,expr,colon,stmtlist
+JSCatch JSNode JSNode JSNode [JSNode] JSNode JSNode
+catch,lb,ident,[if,expr],rb,block
+JSContinue JSNode [JSNode] JSNode
+continue,optional identifier,autosemi
+JSDefault JSNode JSNode [JSNode]
+default,colon,stmtlist
+JSDoWhile JSNode JSNode JSNode JSNode JSNode JSNode JSNode
+do,stmt,while,lb,expr,rb,autosemi
+JSExpressionPostfix String [JSNode] JSNode
+type, expression, operator
+JSExpressionTernary [JSNode] JSNode [JSNode] JSNode [JSNode]
+cond, ?, trueval, :, falseval
+JSFinally JSNode JSNode
+finally,block
+JSFor JSNode JSNode [JSNode] JSNode [JSNode] JSNode [JSNode] JSNode JSNode
+for,lb,expr,semi,expr,semi,expr,rb.stmt
+JSForIn JSNode JSNode [JSNode] JSNode JSNode JSNode JSNode
+for,lb,expr,in,expr,rb,stmt
+JSForVar JSNode JSNode JSNode [JSNode] JSNode [JSNode] JSNode [JSNode] JSNode JSNode
+for,lb,var,vardecl,semi,expr,semi,expr,rb,stmt
+JSForVarIn JSNode JSNode JSNode JSNode JSNode JSNode JSNode JSNode
+for,lb,var,vardecl,in,expr,rb,stmt
+JSMemberSquare [JSNode] JSNode JSNode JSNode
+firstpart, lb, expr, rb
+JSPropertyAccessor JSNode JSNode JSNode [JSNode] JSNode JSNode
+(get|set), name, lb, params, rb, block
+JSSwitch JSNode JSNode JSNode JSNode JSNode
+switch,lb,expr,rb,caseblock
+JSThrow JSNode JSNode
+throw val
+JSTry JSNode JSNode [JSNode]
+try,block,rest
+JSUnary String JSNode
+type, operator
+ -}
diff --git a/src/Language/Mulang/Parsers/Json.hs b/src/Language/Mulang/Parsers/Json.hs
deleted file mode 100644
--- a/src/Language/Mulang/Parsers/Json.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-module Language.Mulang.Parsers.Json (parseJson) where
-
-import Language.Mulang
-
-import Data.Aeson
-
-import qualified Data.ByteString.Lazy.Char8 as LBS (pack)
-
-parseJson :: String -> Maybe Program
-parseJson  = decode . LBS.pack
-
-instance FromJSON Program
-instance ToJSON Program
-
-instance FromJSON Declaration
-instance ToJSON Declaration
-
-instance FromJSON Equation
-instance ToJSON Equation
-
-instance FromJSON Rhs
-instance ToJSON Rhs
-
-instance FromJSON GuardedRhs
-instance ToJSON GuardedRhs
-
-instance FromJSON Expression
-instance ToJSON Expression
-
-instance FromJSON Pattern
-instance ToJSON Pattern
-
-instance FromJSON ComprehensionStatement
-instance ToJSON ComprehensionStatement
-
-instance FromJSON Alternative
-instance ToJSON Alternative
-
-instance FromJSON GuardedAlternatives
-instance ToJSON GuardedAlternatives
-
-instance FromJSON GuardedAlternative
-instance ToJSON GuardedAlternative
-
-instance FromJSON LiteralValue
-instance ToJSON LiteralValue
diff --git a/src/Language/Mulang/Parsers/Prolog.hs b/src/Language/Mulang/Parsers/Prolog.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Parsers/Prolog.hs
@@ -0,0 +1,161 @@
+{-# LANGUAGE RankNTypes #-}
+
+module Language.Mulang.Parsers.Prolog  (pl, parseProlog) where
+
+import Text.Parsec
+import Text.Parsec.Expr
+import Text.Parsec.Numbers
+
+import Language.Mulang.Ast
+import Language.Mulang.Builder
+import Language.Mulang.Parsers
+
+import Data.Maybe (fromMaybe)
+import Data.Char (isUpper)
+
+import Control.Fallible
+
+type ParsecParser a = forall x . Parsec String x a
+
+pl :: Parser
+pl = orFail . parseProlog'
+
+parseProlog :: EitherParser
+parseProlog = orLeft . parseProlog'
+
+parseProlog' = fmap compact . parse program ""
+
+program :: ParsecParser [Expression]
+program = many predicate
+
+pattern :: ParsecParser Pattern
+pattern = buildExpressionParser optable (term <* spaces)
+  where
+    optable = [ [ Infix (op "^") AssocLeft ],
+                [ Infix (op "*") AssocLeft ],
+                [ Infix (op "/") AssocLeft ],
+                [ Infix (op "+") AssocLeft ],
+                [ Infix (op "-") AssocLeft ] ]
+    term    = try number <|> wildcard <|> tuple <|> (fmap otherToPattern phead)
+
+    otherToPattern (name, []) | isUpper . head $ name = VariablePattern name
+                              | otherwise = LiteralPattern name
+    otherToPattern ("abs", [p])           = ApplicationPattern "abs" [p]
+    otherToPattern ("mod", [p1, p2])      = ApplicationPattern "mod" [p1, p2]
+    otherToPattern ("div", [p1, p2])      = ApplicationPattern "div" [p1, p2]
+    otherToPattern ("rem", [p1, p2])      = ApplicationPattern "rem" [p1, p2]
+    otherToPattern (name, args)           = FunctorPattern name args
+
+op :: String -> ParsecParser (Pattern -> Pattern -> Pattern)
+op symbol = string symbol <* spaces >> return (\x y -> ApplicationPattern symbol [x, y])
+
+tuple :: ParsecParser Pattern
+tuple = fmap compact patternsList
+  where compact [p] = p
+        compact ps  = TuplePattern ps
+
+wildcard :: ParsecParser Pattern
+wildcard = string "_" >> return WildcardPattern
+
+number :: ParsecParser Pattern
+number = fmap (LiteralPattern . show) parseFloat
+
+fact :: ParsecParser Expression
+fact = do
+  (name, args) <- phead
+  end
+  return $ Fact name args
+
+rule :: ParsecParser Expression
+rule = do
+  (name, args) <- phead
+  def
+  consults <- body
+  end
+  return $ Rule name args consults
+
+phead :: ParsecParser (Identifier, [Pattern])
+phead = do
+  name <- identifier
+  args <- optionMaybe patternsList
+  spaces
+  return (name, fromMaybe [] args)
+
+forall :: ParsecParser Expression
+forall = do
+  string "forall"
+  startTuple
+  c1 <- consult
+  separator
+  c2 <- consult
+  endTuple
+  return $ Forall c1 c2
+
+findall :: ParsecParser Expression
+findall = do
+  string "findall"
+  startTuple
+  c1 <- consult
+  separator
+  c2 <- consult
+  separator
+  c3 <- consult
+  endTuple
+  return $ Findall c1 c2 c3
+
+cut :: ParsecParser Expression
+cut = do
+  bang
+  return $ Exist "!" []
+
+pnot :: ParsecParser Expression
+pnot = do
+  c <- operator <|> functor
+  return $ Not c
+  where
+    functor = string "not" >> startTuple >> consult <* endTuple
+    operator = negation >> consult
+
+exist :: ParsecParser Expression
+exist = fmap (\(name, args) -> Exist name args) phead
+
+body :: ParsecParser [Expression]
+body =  sepBy1 consult separator
+
+inlineBody :: ParsecParser Expression
+inlineBody = do
+  startTuple
+  queries <- body
+  endTuple
+  return $ Sequence queries
+
+pinfix :: ParsecParser Expression
+pinfix = do
+  p1 <- pattern
+  spaces
+  operator <- choice . map try . map string $ ["is", "|", ">=", "=<", "\\=", ">", "<", "=:=", "==", "=\\=", ":=", "=..", "=@=", "\\\\=@=", "="]
+  spaces
+  p2 <- pattern
+  return $ Exist operator [p1, p2]
+
+
+consult :: ParsecParser Expression
+consult = choice [try findall, try forall, try pnot, try pinfix, inlineBody, cut, exist]
+
+predicate :: ParsecParser Expression
+predicate = try fact <|> rule
+
+patternsList :: ParsecParser [Pattern]
+patternsList = startTuple >> sepBy1 pattern separator <* endTuple
+
+bang = string "!" >> spaces
+negation = string "\\+" >> spaces
+identifier = many1 letter
+def = string ":-" >> spaces
+startTuple = lparen >> spaces
+endTuple = rparen >> spaces
+separator = (char ',' <|> char ';') >> spaces
+end = char '.' >> spaces
+
+lparen = char '('
+rparen = char ')'
diff --git a/src/Language/Mulang/Signature.hs b/src/Language/Mulang/Signature.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Mulang/Signature.hs
@@ -0,0 +1,116 @@
+module Language.Mulang.Signature (
+  arity,
+  name,
+  nameAndArity,
+  parameterNames,
+  signatureOf,
+  signaturesOf,
+  codeSignaturesOf,
+  styledCodeSignaturesOf,
+  mulangStyle,
+  haskellStyle,
+  prologStyle,
+  untypedCStyle,
+  Signature(..),
+  SignatureStyle) where
+
+import Language.Mulang.Identifier
+import Language.Mulang.Ast
+import Language.Mulang.Generator (declarations)
+
+import Data.List (transpose, intercalate, nub, groupBy)
+import Data.Maybe (fromMaybe, mapMaybe)
+import Control.Monad (msum)
+import Data.Function (on)
+
+type SignatureStyle = [Signature] -> [String]
+
+data Signature = AritySignature Identifier Int
+               | TypedSignature Identifier [Identifier] Identifier
+               | NamedSignature Identifier [Maybe Identifier] deriving (Show, Eq)
+
+
+arity :: Signature -> Int
+arity (AritySignature _ a)    = a
+arity (TypedSignature _ ps _) = length ps
+arity (NamedSignature _ ps)   = length ps
+
+name :: Signature -> Identifier
+name (AritySignature n _)   = n
+name (TypedSignature n _ _) = n
+name (NamedSignature n _)   = n
+
+nameAndArity :: Signature -> (Identifier, Int)
+nameAndArity signature = (name signature, arity signature)
+
+parameterNames :: Signature -> [Maybe Identifier]
+parameterNames (AritySignature _ arity)   = replicate arity Nothing
+parameterNames (TypedSignature _ types _) = map (const Nothing) types
+parameterNames (NamedSignature _ names)   = names
+
+signaturesOf :: Expression -> [Signature]
+signaturesOf = nub . mapMaybe (signatureOf.snd) . declarations
+
+signatureOf :: Expression -> Maybe Signature
+signatureOf (Subroutine name es)          = Just $ NamedSignature name (parameterNamesOf es)
+signatureOf (Clause name args _)          = Just $ AritySignature name (length args)
+signatureOf (TypeSignature name args ret) = Just $ TypedSignature name args ret
+signatureOf (Variable name _)             = Just $ AritySignature name 0
+signatureOf _                             = Nothing
+
+parameterNamesOf :: [Equation] -> [Maybe Identifier]
+parameterNamesOf = map msum . transpose . map (map parameterNameOf . equationParams)
+
+parameterNameOf :: Pattern -> Maybe Identifier
+parameterNameOf (VariablePattern v) = Just v
+parameterNameOf _                   = Nothing
+
+codeSignaturesOf :: Expression -> [Code]
+codeSignaturesOf = styledCodeSignaturesOf mulangStyle
+
+styledCodeSignaturesOf :: SignatureStyle -> Expression -> [Code]
+styledCodeSignaturesOf style = style . signaturesOf
+
+-- Styles
+
+mulangStyle :: SignatureStyle
+mulangStyle = makeLines "--" (return.s)
+  where s :: Signature -> String
+        s (AritySignature name arity)     = name ++ "/" ++ show arity
+        s (NamedSignature name names)     = name ++ "(" ++ (intercalate ", " . makeParamNames $ names) ++ ")"
+        s (TypedSignature name types ret) = name ++ "(" ++ (intercalate ", " types) ++ "): " ++ ret
+
+untypedCStyle :: SignatureStyle
+untypedCStyle = makeLines "//" s
+  where s (AritySignature name 0)     = Just name
+        s (NamedSignature name names) = Just $ name ++ "(" ++ (intercalate ", " . makeParamNames $ names) ++ ")"
+        s _                           = Nothing
+
+haskellStyle :: SignatureStyle
+haskellStyle = groupAndMakeLinesOn "--" name s
+  where s (NamedSignature name names)     = Just $ name ++ " " ++ (intercalate " " . makeParamNames $ names)
+        s (TypedSignature name types ret) = Just $ name ++ " :: " ++ (intercalate " -> " (types ++ [ret]))
+        s (AritySignature name 0)         = Just name
+        s _                               = Nothing
+
+prologStyle :: SignatureStyle
+prologStyle = groupAndMakeLinesOn "%%" nameAndArity s
+  where s (AritySignature name arity) = Just $ name ++ "/" ++ show arity
+        s _                           = Nothing
+
+--Style helper functions
+
+makeParamNames :: [Maybe String] -> [String]
+makeParamNames = map (fromMaybe "?")
+
+makeLines :: String -> (Signature -> Maybe String) -> [Signature] -> [String]
+makeLines comment f = prefixCodeSignaturesWithComment comment . mapMaybe f
+
+groupAndMakeLinesOn :: Eq a => String -> (Signature -> a) -> (Signature -> Maybe String) -> [Signature] -> [String]
+groupAndMakeLinesOn comment groupFunction s = map (intercalate "\n" . makeLines comment s) . groupSignaturesOn groupFunction
+
+prefixCodeSignaturesWithComment :: String -> [String] -> [String]
+prefixCodeSignaturesWithComment comment = map (\s -> comment ++ " " ++ s)
+
+groupSignaturesOn :: Eq a => (Signature -> a) -> [Signature] -> [[Signature]]
+groupSignaturesOn f = groupBy ((==) `on` f)
diff --git a/src/Text/Dictionary.hs b/src/Text/Dictionary.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Dictionary.hs
@@ -0,0 +1,31 @@
+module Text.Dictionary (
+  prepareFile,
+  fromFile,
+  toDictionary,
+  exists,
+  Dictionary) where
+
+import Data.Set (Set, member, fromList, toList, fromDistinctAscList)
+import Data.Char (toLower)
+
+type Dictionary = Set String
+
+prepareFile :: FilePath -> FilePath -> IO ()
+prepareFile old new = edit old new (unlines . uniq . lines . lowercase)
+
+fromFile :: FilePath -> IO Dictionary
+fromFile path = fmap (toDictionary . lines) (readFile path)
+
+toDictionary :: [String] -> Dictionary
+toDictionary = fromDistinctAscList
+
+exists :: String -> Dictionary -> Bool
+exists e = member (lowercase e)
+
+lowercase :: String -> String
+lowercase = map toLower
+
+uniq = toList . fromList
+
+edit :: FilePath -> FilePath -> (String -> String) -> IO ()
+edit old new f = readFile old >>= (return . f) >>= writeFile new
diff --git a/src/Text/Inflections/Tokenizer.hs b/src/Text/Inflections/Tokenizer.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Inflections/Tokenizer.hs
@@ -0,0 +1,43 @@
+module Text.Inflections.Tokenizer (
+  CaseStyle,
+  camelCase,
+  snakeCase,
+  rubyCase,
+  canTokenize,
+  tokenize) where
+
+import Data.Char (toLower, isDigit, isLower)
+import Data.Either (isRight)
+
+import Text.Inflections
+import Text.Inflections.Parse.Types
+import Text.Parsec.Error (ParseError)
+
+import Control.Fallible
+
+type CaseStyle = String -> Either Text.Parsec.Error.ParseError [Text.Inflections.Parse.Types.Word]
+
+camelCase      :: CaseStyle
+camelCase      = parseCamelCase [] . filter (not.isDigit)
+
+snakeCase      :: CaseStyle
+snakeCase      = parseSnakeCase []
+
+rubyCase       :: CaseStyle
+rubyCase  word | (isLower.head) word = snakeCase baseWord
+               | otherwise           = camelCase baseWord
+
+               where baseWord = filter (`notElem` "!?+-=[]<>|&*/") word
+
+canTokenize :: CaseStyle -> String -> Bool
+canTokenize style = isRight . style
+
+tokenize :: CaseStyle -> String -> [String]
+tokenize style s | Just words <- (wordsOrNothing . style) s = concatMap toToken words
+                 | otherwise = []
+                  where toToken = return . map toLower
+
+
+wordsOrNothing = fmap (concatMap c) . orNothing
+                where c (Word w) = [w]
+                      c _        = []
diff --git a/src/Text/SimpleParser.hs b/src/Text/SimpleParser.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/SimpleParser.hs
@@ -0,0 +1,8 @@
+module Text.SimpleParser (
+  SimpleParser,
+  MaybeParser,
+  EitherParser) where
+
+type SimpleParser a = String -> a
+type MaybeParser a = String -> Maybe a
+type EitherParser a = String -> Either String a
