diff --git a/mulang.cabal b/mulang.cabal
index 3bc2e2c03..12bb0ba94 100644
--- a/mulang.cabal
+++ b/mulang.cabal
@@ -36,6 +36,7 @@ library
     Language.Mulang.Ast
     Language.Mulang.Identifier
     Language.Mulang.Builder
+    Language.Mulang.Unbuilder
     Language.Mulang.Generator
     Language.Mulang.Signature
     Language.Mulang.DomainLanguage
@@ -58,13 +59,23 @@ library
     Language.Mulang.Inspector.Typed
     Language.Mulang.Parsers
     Language.Mulang.Parsers.Haskell
-    Language.Mulang.Parsers.Prolog
     Language.Mulang.Parsers.Java
     Language.Mulang.Parsers.JavaScript
+    Language.Mulang.Parsers.Prolog
     Language.Mulang.Parsers.Python
+    Language.Mulang.Operators
+    Language.Mulang.Operators.Haskell
+    Language.Mulang.Operators.Java
+    Language.Mulang.Operators.Python
+    Language.Mulang.Operators.Ruby
+    Language.Mulang.Unparsers
+    Language.Mulang.Unparsers.Java
+    Language.Mulang.Unparsers.Python
+    Language.Mulang.Unparsers.Ruby
     Language.Mulang.Analyzer
     Language.Mulang.Analyzer.Analysis
     Language.Mulang.Analyzer.Analysis.Json
+    Language.Mulang.Analyzer.Autocorrector
     Language.Mulang.Analyzer.DomainLanguageCompiler
     Language.Mulang.Analyzer.ExpectationsAnalyzer
     Language.Mulang.Analyzer.ExpectationsCompiler
@@ -73,6 +84,7 @@ library
     Language.Mulang.Analyzer.SignatureStyleCompiler
     Language.Mulang.Analyzer.SmellsAnalyzer
     Language.Mulang.Analyzer.TestsAnalyzer
+    Language.Mulang.Analyzer.Synthesizer
     Language.Mulang.Interpreter
     Language.Mulang.Interpreter.Runner
 
diff --git a/spec/AutocorrectorSpec.hs b/spec/AutocorrectorSpec.hs
new file mode 100644
index 000000000..27b85907a
--- /dev/null
+++ b/spec/AutocorrectorSpec.hs
@@ -0,0 +1,136 @@
+module AutocorrectorSpec (spec) where
+
+import           Test.Hspec
+import           Language.Mulang.Analyzer.Autocorrector
+import           Language.Mulang.Analyzer.Analysis hiding (spec)
+import qualified Language.Mulang.Analyzer.Analysis as A
+import           Data.Maybe (fromJust)
+
+run language = head . fromJust . expectations . A.spec . autocorrect . expectationsAnalysis (CodeSample language "foo") . (:[])
+
+spec :: Spec
+spec = do
+  describe "correct primitive usages" $ do
+    it "corrects haskell otherwise negated" $ do
+      run Haskell (Expectation "*" "Not:Uses:otherwise")  `shouldBe` (Expectation "*" "Not:UsesOtherwise")
+
+    it "corrects haskell otherwise" $ do
+      run Haskell (Expectation "*" "Uses:otherwise")  `shouldBe` (Expectation "*" "UsesOtherwise")
+
+    it "corrects haskell and" $ do
+      run Haskell (Expectation "*" "Uses:and") `shouldBe` (Expectation "*" "Uses:and")
+      run Haskell (Expectation "*" "Uses:&&") `shouldBe` (Expectation "*" "UsesAnd")
+
+    it "corrects haskell or" $ do
+      run Haskell (Expectation "*" "Uses:or") `shouldBe` (Expectation "*" "Uses:or")
+      run Haskell (Expectation "*" "Uses:||")`shouldBe` (Expectation "*" "UsesOr")
+
+    it "corrects haskell not" $ do
+      run Haskell (Expectation "*" "Uses:not") `shouldBe` (Expectation "*" "UsesNegation")
+      run Haskell (Expectation "*" "Uses:!")  `shouldBe` (Expectation "*" "Uses:!")
+
+    it "corrects java and" $ do
+      run Java (Expectation "*" "Uses:and") `shouldBe` (Expectation "*" "Uses:and")
+      run Java (Expectation "*"  "Uses:&&") `shouldBe` (Expectation "*" "UsesAnd")
+
+    it "corrects python and" $ do
+      run Python (Expectation "*" "Uses:and") `shouldBe` (Expectation "*" "UsesAnd")
+      run Python (Expectation "*"  "Uses:&&") `shouldBe` (Expectation "*" "Uses:&&")
+
+    it "corrects ruby and" $ do
+      run Ruby (Expectation "*" "Uses:and") `shouldBe` (Expectation "*" "UsesAnd")
+      run Ruby (Expectation "*"  "Uses:&&") `shouldBe` (Expectation "*" "UsesAnd")
+
+  describe "correct primitive declarations" $ do
+    it "corrects haskell otherwise negated" $ do
+      run Haskell (Expectation "*" "Not:Declares:otherwise")  `shouldBe` (Expectation "*" "Not:DeclaresOtherwise")
+
+    it "corrects haskell otherwise" $ do
+      run Haskell (Expectation "*" "Declares:otherwise")  `shouldBe` (Expectation "*" "DeclaresOtherwise")
+
+    it "corrects haskell and" $ do
+      run Haskell (Expectation "*" "Declares:and") `shouldBe` (Expectation "*" "Declares:and")
+      run Haskell (Expectation "*" "Declares:&&") `shouldBe` (Expectation "*" "DeclaresAnd")
+
+    it "corrects haskell or" $ do
+      run Haskell (Expectation "*" "Declares:or") `shouldBe` (Expectation "*" "Declares:or")
+      run Haskell (Expectation "*" "Declares:||")`shouldBe` (Expectation "*" "DeclaresOr")
+
+    it "corrects haskell not" $ do
+      run Haskell (Expectation "*" "Declares:not") `shouldBe` (Expectation "*" "DeclaresNegation")
+      run Haskell (Expectation "*" "Declares:!")  `shouldBe` (Expectation "*" "Declares:!")
+
+    it "corrects java and" $ do
+      run Java (Expectation "*" "Declares:and") `shouldBe` (Expectation "*" "Declares:and")
+      run Java (Expectation "*"  "Declares:&&") `shouldBe` (Expectation "*" "DeclaresAnd")
+
+    it "corrects python and" $ do
+      run Python (Expectation "*" "Declares:and") `shouldBe` (Expectation "*" "DeclaresAnd")
+      run Python (Expectation "*"  "Declares:&&") `shouldBe` (Expectation "*" "Declares:&&")
+
+    it "corrects ruby and" $ do
+      run Ruby (Expectation "*" "Declares:and") `shouldBe` (Expectation "*" "DeclaresAnd")
+      run Ruby (Expectation "*"  "Declares:&&") `shouldBe` (Expectation "*" "DeclaresAnd")
+
+  describe "corrects keyword usages" $ do
+    it "corrects haskell type usage with negation" $ do
+      run Haskell (Expectation "*" "Not:Uses:type") `shouldBe` (Expectation "*" "Not:DeclaresTypeAlias")
+
+    it "corrects haskell type usage" $ do
+      run Haskell (Expectation "*" "Uses:type") `shouldBe` (Expectation "*" "DeclaresTypeAlias")
+
+    it "corrects java if usage" $ do
+      run Java (Expectation "*" "Uses:if") `shouldBe` (Expectation "*"  "UsesIf")
+
+    it "corrects java class usage" $ do
+      run Java (Expectation "*" "Uses:class") `shouldBe` (Expectation "*" "DeclaresClass")
+
+    it "corrects java interface usage" $ do
+      run Java (Expectation "*" "Uses:interface") `shouldBe` (Expectation "*" "DeclaresInterface")
+
+    it "corrects java for usage" $ do
+      run Java (Expectation "*" "Uses:for") `shouldBe` (Expectation "*" "UsesForLoop")
+
+    it "corrects python def usage" $ do
+      run Python (Expectation "*" "Uses:def") `shouldBe` (Expectation "*" "DeclaresComputation")
+
+    it "corrects ruby class usage" $ do
+      run Ruby (Expectation "*" "Uses:class") `shouldBe` (Expectation "*" "DeclaresClass")
+
+    it "corrects ruby include usage" $ do
+      run Ruby (Expectation "*" "Uses:include") `shouldBe` (Expectation "*" "Includes")
+
+    it "corrects ruby def usage" $ do
+      run Ruby (Expectation "*" "Uses:def") `shouldBe` (Expectation "*" "DeclaresComputation")
+
+
+  describe "corrects keyword declarations" $ do
+    it "corrects haskell type declaration with negation" $ do
+      run Haskell (Expectation "*" "Not:Declares:type") `shouldBe` (Expectation "*" "Not:DeclaresTypeAlias")
+
+    it "corrects haskell type declaration" $ do
+      run Haskell (Expectation "*" "Declares:type") `shouldBe` (Expectation "*" "DeclaresTypeAlias")
+
+    it "corrects java if declaration" $ do
+      run Java (Expectation "*" "Declares:if") `shouldBe` (Expectation "*"  "UsesIf")
+
+    it "corrects java class declaration" $ do
+      run Java (Expectation "*" "Declares:class") `shouldBe` (Expectation "*" "DeclaresClass")
+
+    it "corrects java interface declaration" $ do
+      run Java (Expectation "*" "Declares:interface") `shouldBe` (Expectation "*" "DeclaresInterface")
+
+    it "corrects java for declaration" $ do
+      run Java (Expectation "*" "Declares:for") `shouldBe` (Expectation "*" "UsesForLoop")
+
+    it "corrects python def declaration" $ do
+      run Python (Expectation "*" "Declares:def") `shouldBe` (Expectation "*" "DeclaresComputation")
+
+    it "corrects ruby class declaration" $ do
+      run Ruby (Expectation "*" "Declares:class") `shouldBe` (Expectation "*" "DeclaresClass")
+
+    it "corrects ruby include declaration" $ do
+      run Ruby (Expectation "*" "Declares:include") `shouldBe` (Expectation "*" "Includes")
+
+    it "corrects ruby def declaration" $ do
+      run Ruby (Expectation "*" "Declares:def") `shouldBe` (Expectation "*" "DeclaresComputation")
diff --git a/spec/ExpectationsAnalyzerSpec.hs b/spec/ExpectationsAnalyzerSpec.hs
index e538fc0d5..c11dc7331 100644
--- a/spec/ExpectationsAnalyzerSpec.hs
+++ b/spec/ExpectationsAnalyzerSpec.hs
@@ -18,122 +18,144 @@ spec = describe "ExpectationsAnalyzer" $ do
     let ydeclares = Expectation "*" "Declares:y"
     (runAst None [ydeclares]) `shouldReturn` (result [failed ydeclares] [])
 
-  describe "Advanced expectations" $ do
-    it "evaluates unknown basic expectations" $ do
-      let hasTurtle = Expectation "x" "HasTurtle"
-      (run Haskell "x = 2" [hasTurtle]) `shouldReturn` (result [passed hasTurtle] [])
-
-    it "evaluates unknown basic negated expectations" $ do
-      let notHasTurtle = Expectation "x" "Not:HasTurtle"
-      (run Haskell "x = 2" [notHasTurtle]) `shouldReturn` (result [passed notHasTurtle] [])
-
-    it "evaluates empty expectations" $ do
-      (run Haskell "x = 2" []) `shouldReturn` (result [] [])
-
-    it "evaluates present named expectations" $ do
-      let ydeclares = Expectation "*" "Declares:y"
-      let xdeclares = Expectation "*" "Declares:x"
-      (run Haskell "x = 2" [ydeclares, xdeclares]) `shouldReturn` (result [failed ydeclares, passed xdeclares] [])
-
-    it "evaluates present expectations" $ do
-      let declaresF = Expectation "*" "DeclaresFunction"
-      let declaresT = Expectation "*" "DeclaresTypeAlias"
-      (run Haskell "f x = 2" [declaresF, declaresT]) `shouldReturn` (result [passed declaresF, failed declaresT] [])
-
-  describe "Basic expectations" $ do
-    it "can be negated" $ do
-      let notDeclaresX = Expectation "*" "Not:Declares:x"
-      let notDeclaresY = Expectation "*" "Not:Declares:y"
-      (run Haskell "x = \"¡\"" [notDeclaresY, notDeclaresX]) `shouldReturn` (result [
-                                                                          passed notDeclaresY, failed notDeclaresX] [])
-    it "works with Declares" $ do
-      let xdeclares = Expectation "*" "Declares:x"
-      let ydeclares = Expectation "*" "Declares:y"
-      (run Haskell "x = 2" [ydeclares, xdeclares]) `shouldReturn` (result [failed ydeclares, passed xdeclares] [])
-
-    it "works with Uses" $ do
-      let usesy = Expectation "x" "Uses:y"
-      let usesz = Expectation "x" "Uses:z"
-      (run Haskell "x = y * 10" [usesy, usesz]) `shouldReturn` (result [passed usesy, failed usesz] [])
-
-    it "works with DeclaresComputationWithArity" $ do
-      let hasArity2 = Expectation "*" "DeclaresComputationWithArity2:foo"
-      let hasArity3 = Expectation "*" "DeclaresComputationWithArity3:foo"
-      (run Prolog "foo(x, y)." [hasArity2, hasArity3]) `shouldReturn` (result [passed hasArity2, failed hasArity3] [])
-
-    it "works with DeclaresTypeSignature" $ do
-      let declaresTypeSignature = Expectation "*" "DeclaresTypeSignature:f"
-      (run Haskell "f x y = y + x" [declaresTypeSignature]) `shouldReturn` (result [failed declaresTypeSignature] [])
-      (run Haskell "f :: Int -> Int -> Int \nf x y = y + x" [declaresTypeSignature]) `shouldReturn` (result [passed declaresTypeSignature] [])
-
-    it "works with DeclaresTypeAlias" $ do
-      let hasTypeAlias = Expectation "*" "DeclaresTypeAlias:Words"
-      (run Haskell "type Works = [String]" [hasTypeAlias]) `shouldReturn` (result [failed hasTypeAlias] [])
-      (run Haskell "data Words = Words" [hasTypeAlias]) `shouldReturn` (result [failed hasTypeAlias] [])
-      (run Haskell "type Words = [String]" [hasTypeAlias]) `shouldReturn` (result [passed hasTypeAlias] [])
-
-    it "works with UsesIf" $ do
-      let hasIf = Expectation "min" "UsesIf"
-      (run Haskell "min x y = True" [hasIf]) `shouldReturn` (result [failed hasIf] [])
-      (run Haskell "min x y = if x < y then x else y" [hasIf]) `shouldReturn` (result [passed hasIf] [])
-
-    it "works with UsesGuards" $ do
-      let hasGuards = Expectation "min" "UsesGuards"
-      (run Haskell "min x y = x" [hasGuards]) `shouldReturn` (result [failed hasGuards] [])
-      (run Haskell "min x y | x < y = x | otherwise = y" [hasGuards]) `shouldReturn` (result [passed hasGuards] [])
-
-    it "works with UsesAnonymousVariable" $ do
-      let hasAnonymousVariable = Expectation "c" "UsesAnonymousVariable"
-      (run Haskell "c x = 14" [hasAnonymousVariable]) `shouldReturn` (result [failed hasAnonymousVariable] [])
-      (run Haskell "c _ = 14" [hasAnonymousVariable]) `shouldReturn` (result [passed hasAnonymousVariable] [])
-
-    it "works with UsesComposition" $ do
-      let hasComposition = Expectation "h" "UsesComposition"
-      (run Haskell "h = f" [hasComposition]) `shouldReturn` (result [failed hasComposition] [])
-      (run Haskell "h = f . g" [hasComposition]) `shouldReturn` (result [passed hasComposition] [])
-
-    it "works with UsesForComprehension" $ do
-      let hasComprehension = Expectation "x" "UsesForComprehension"
-      (run Haskell "x = [m | m <- t]" [hasComprehension]) `shouldReturn` (result [passed hasComprehension] [])
-
-    it "works with UsesForLoop" $ do
-      let hasForLoop = Expectation "f" "UsesForLoop"
-      (run JavaScript "function f() { var x; for (x = 0; x < 10; x++) { x; } }" [hasForLoop]) `shouldReturn` (result [passed hasForLoop] [])
-
-    it "works with UsesConditional" $ do
-      let hasConditional = Expectation "min" "UsesConditional"
-      (run JavaScript "function min(x, y) { if (x < y) { return x } else { return y } }" [hasConditional]) `shouldReturn` (result [
-                                                                                                            passed hasConditional] [])
-
-    it "works with UsesWhile" $ do
-      let hasWhile = Expectation "f" "UsesWhile"
-      (run JavaScript "function f() { var x = 5; while (x < 10) { x++ } }" [hasWhile]) `shouldReturn` (result [passed hasWhile] [])
-
-    it "works with HasForall" $ do
-      let hasForall = Expectation "f" "HasForall"
-      (run Prolog "f(X) :- isElement(Usuario), forall(isRelated(X, Y), complies(Y))." [hasForall]) `shouldReturn` (result [
-                                                                                                            passed hasForall] [])
-
-    it "works with UsesFindall" $ do
-      let hasFindall = Expectation "baz" "UsesFindall"
-      (run Prolog "baz(X):- bar(X, Y)." [hasFindall]) `shouldReturn` (result [failed hasFindall] [])
-      (run Prolog "baz(X):- findall(Y, bar(X, Y), Z)." [hasFindall]) `shouldReturn` (result [passed hasFindall] [])
-
-    it "works with UsesLambda" $ do
-      let hasLambda = Expectation "f" "UsesLambda"
-      (run Haskell "f = map id" [hasLambda]) `shouldReturn` (result [failed hasLambda] [])
-      (run Haskell "f = map $ \\x -> x + 1" [hasLambda]) `shouldReturn` (result [passed hasLambda] [])
-
-    it "works with DeclaresRecursively" $ do
-      let hasDirectRecursion = Expectation "*" "DeclaresRecursively:f"
-      (run Haskell "f x = if x < 5 then g (x - 1) else 2" [hasDirectRecursion]) `shouldReturn` (result [failed hasDirectRecursion] [])
-      (run Haskell "f x = if x < 5 then f (x - 1) else 2" [hasDirectRecursion]) `shouldReturn` (result [passed hasDirectRecursion] [])
-
-    it "works with UsesNot" $ do
-      let hasNot = Expectation "foo" "UsesNot"
-      (run Prolog "foo(X) :- bar(X)." [hasNot]) `shouldReturn` (result [failed hasNot] [])
-      (run Prolog "foo(X) :- not(bar(X))." [hasNot]) `shouldReturn` (result [passed hasNot] [])
-
-    it "properly reports parsing errors" $ do
-      let hasNot = Expectation "foo" "UsesNot"
-      (run Haskell " foo " [hasNot]) `shouldReturn` (AnalysisFailed "Parse error")
+  it "evaluates unknown basic expectations" $ do
+    let hasTurtle = Expectation "x" "HasTurtle"
+    (run Haskell "x = 2" [hasTurtle]) `shouldReturn` (result [passed hasTurtle] [])
+
+  it "evaluates unknown basic negated expectations" $ do
+    let notHasTurtle = Expectation "x" "Not:HasTurtle"
+    (run Haskell "x = 2" [notHasTurtle]) `shouldReturn` (result [passed notHasTurtle] [])
+
+  it "evaluates empty expectations" $ do
+    (run Haskell "x = 2" []) `shouldReturn` (result [] [])
+
+  it "evaluates present named expectations" $ do
+    let ydeclares = Expectation "*" "Declares:y"
+    let xdeclares = Expectation "*" "Declares:x"
+    (run Haskell "x = 2" [ydeclares, xdeclares]) `shouldReturn` (result [failed ydeclares, passed xdeclares] [])
+
+  it "evaluates present expectations" $ do
+    let declaresF = Expectation "*" "DeclaresFunction"
+    let declaresT = Expectation "*" "DeclaresTypeAlias"
+    (run Haskell "f x = 2" [declaresF, declaresT]) `shouldReturn` (result [passed declaresF, failed declaresT] [])
+
+  it "can be negated" $ do
+    let notDeclaresX = Expectation "*" "Not:Declares:x"
+    let notDeclaresY = Expectation "*" "Not:Declares:y"
+    (run Haskell "x = \"¡\"" [notDeclaresY, notDeclaresX]) `shouldReturn` (result [
+                                                                        passed notDeclaresY, failed notDeclaresX] [])
+  it "works with Declares" $ do
+    let xdeclares = Expectation "*" "Declares:x"
+    let ydeclares = Expectation "*" "Declares:y"
+    (run Haskell "x = 2" [ydeclares, xdeclares]) `shouldReturn` (result [failed ydeclares, passed xdeclares] [])
+
+  it "works with Uses" $ do
+    let usesy = Expectation "x" "Uses:y"
+    let usesz = Expectation "x" "Uses:z"
+    (run Haskell "x = y * 10" [usesy, usesz]) `shouldReturn` (result [passed usesy, failed usesz] [])
+
+  it "works with DeclaresComputationWithArity" $ do
+    let hasArity2 = Expectation "*" "DeclaresComputationWithArity2:foo"
+    let hasArity3 = Expectation "*" "DeclaresComputationWithArity3:foo"
+    (run Prolog "foo(x, y)." [hasArity2, hasArity3]) `shouldReturn` (result [passed hasArity2, failed hasArity3] [])
+
+  it "works with DeclaresTypeSignature" $ do
+    let declaresTypeSignature = Expectation "*" "DeclaresTypeSignature:f"
+    (run Haskell "f x y = y + x" [declaresTypeSignature]) `shouldReturn` (result [failed declaresTypeSignature] [])
+    (run Haskell "f :: Int -> Int -> Int \nf x y = y + x" [declaresTypeSignature]) `shouldReturn` (result [passed declaresTypeSignature] [])
+
+  it "works with DeclaresTypeAlias" $ do
+    let hasTypeAlias = Expectation "*" "DeclaresTypeAlias:Words"
+    (run Haskell "type Works = [String]" [hasTypeAlias]) `shouldReturn` (result [failed hasTypeAlias] [])
+    (run Haskell "data Words = Words" [hasTypeAlias]) `shouldReturn` (result [failed hasTypeAlias] [])
+    (run Haskell "type Words = [String]" [hasTypeAlias]) `shouldReturn` (result [passed hasTypeAlias] [])
+
+  it "works with UsesIf" $ do
+    let hasIf = Expectation "min" "UsesIf"
+    (run Haskell "min x y = True" [hasIf]) `shouldReturn` (result [failed hasIf] [])
+    (run Haskell "min x y = if x < y then x else y" [hasIf]) `shouldReturn` (result [passed hasIf] [])
+
+  it "works with UsesGuards" $ do
+    let hasGuards = Expectation "min" "UsesGuards"
+    (run Haskell "min x y = x" [hasGuards]) `shouldReturn` (result [failed hasGuards] [])
+    (run Haskell "min x y | x < y = x | otherwise = y" [hasGuards]) `shouldReturn` (result [passed hasGuards] [])
+
+  it "works with UsesAnonymousVariable" $ do
+    let hasAnonymousVariable = Expectation "c" "UsesAnonymousVariable"
+    (run Haskell "c x = 14" [hasAnonymousVariable]) `shouldReturn` (result [failed hasAnonymousVariable] [])
+    (run Haskell "c _ = 14" [hasAnonymousVariable]) `shouldReturn` (result [passed hasAnonymousVariable] [])
+
+  it "works with UsesComposition" $ do
+    let hasComposition = Expectation "h" "UsesComposition"
+    (run Haskell "h = f" [hasComposition]) `shouldReturn` (result [failed hasComposition] [])
+    (run Haskell "h = f . g" [hasComposition]) `shouldReturn` (result [passed hasComposition] [])
+
+  it "works with UsesForComprehension" $ do
+    let hasComprehension = Expectation "x" "UsesForComprehension"
+    (run Haskell "x = [m | m <- t]" [hasComprehension]) `shouldReturn` (result [passed hasComprehension] [])
+
+  it "works with UsesForLoop" $ do
+    let hasForLoop = Expectation "f" "UsesForLoop"
+    (run JavaScript "function f() { var x; for (x = 0; x < 10; x++) { x; } }" [hasForLoop]) `shouldReturn` (result [passed hasForLoop] [])
+
+  it "works with UsesConditional" $ do
+    let hasConditional = Expectation "min" "UsesConditional"
+    (run JavaScript "function min(x, y) { if (x < y) { return x } else { return y } }" [hasConditional]) `shouldReturn` (result [
+                                                                                                          passed hasConditional] [])
+
+  it "works with UsesWhile" $ do
+    let hasWhile = Expectation "f" "UsesWhile"
+    (run JavaScript "function f() { var x = 5; while (x < 10) { x++ } }" [hasWhile]) `shouldReturn` (result [passed hasWhile] [])
+
+  it "works with HasForall" $ do
+    let hasForall = Expectation "f" "HasForall"
+    (run Prolog "f(X) :- isElement(Usuario), forall(isRelated(X, Y), complies(Y))." [hasForall]) `shouldReturn` (result [
+                                                                                                          passed hasForall] [])
+
+  it "works with UsesFindall" $ do
+    let hasFindall = Expectation "baz" "UsesFindall"
+    (run Prolog "baz(X):- bar(X, Y)." [hasFindall]) `shouldReturn` (result [failed hasFindall] [])
+    (run Prolog "baz(X):- findall(Y, bar(X, Y), Z)." [hasFindall]) `shouldReturn` (result [passed hasFindall] [])
+
+  it "works with UsesLambda" $ do
+    let hasLambda = Expectation "f" "UsesLambda"
+    (run Haskell "f = map id" [hasLambda]) `shouldReturn` (result [failed hasLambda] [])
+    (run Haskell "f = map $ \\x -> x + 1" [hasLambda]) `shouldReturn` (result [passed hasLambda] [])
+
+  it "works with DeclaresRecursively" $ do
+    let hasDirectRecursion = Expectation "*" "DeclaresRecursively:f"
+    (run Haskell "f x = if x < 5 then g (x - 1) else 2" [hasDirectRecursion]) `shouldReturn` (result [failed hasDirectRecursion] [])
+    (run Haskell "f x = if x < 5 then f (x - 1) else 2" [hasDirectRecursion]) `shouldReturn` (result [passed hasDirectRecursion] [])
+
+  it "works with UsesNot" $ do
+    let hasNot = Expectation "foo" "UsesNot"
+    (run Prolog "foo(X) :- bar(X)." [hasNot]) `shouldReturn` (result [failed hasNot] [])
+    (run Prolog "foo(X) :- not(bar(X))." [hasNot]) `shouldReturn` (result [passed hasNot] [])
+
+  it "properly reports parsing errors" $ do
+    let hasNot = Expectation "foo" "UsesNot"
+    (run Haskell " foo " [hasNot]) `shouldReturn` (AnalysisFailed "Parse error")
+
+  it "works with keyword-based expectation synthesis of declares" $ do
+    let usesType = Expectation "*" "Uses:type"
+    let declaresTypeAlias = Expectation "*" "DeclaresTypeAlias"
+    run Haskell "type X = Int" [usesType] `shouldReturn` (result [passed declaresTypeAlias] [])
+
+  it "works with keyword-based expectation synthesis of uses" $ do
+    let usesType = Expectation "*" "Uses:type"
+    let declaresTypeAlias = Expectation "*" "DeclaresTypeAlias"
+    run Haskell "type X = Int" [usesType] `shouldReturn` (result [passed declaresTypeAlias] [])
+
+  it "works with operator-based expectation synthesis of declares" $ do
+    let declaresNot = Expectation "*" "Declares:not"
+    let usesNegation = Expectation "*" "DeclaresNegation"
+    run Haskell "x = not True" [declaresNot] `shouldReturn` (result [failed usesNegation] [])
+
+  it "works with operator-based expectation synthesis of uses" $ do
+    let usesNot = Expectation "*" "Uses:not"
+    let usesNegation = Expectation "*" "UsesNegation"
+    run Haskell "x = not True" [usesNot] `shouldReturn` (result [passed usesNegation] [])
+
+  it "works with operators" $ do
+    let usesNegation = Expectation "*" "UsesNegation"
+    run Haskell "x = not True" [usesNegation] `shouldReturn` (result [passed usesNegation] [])
diff --git a/spec/ExpectationsCompilerSpec.hs b/spec/ExpectationsCompilerSpec.hs
index 73701636c..9a3f83dbf 100644
--- a/spec/ExpectationsCompilerSpec.hs
+++ b/spec/ExpectationsCompilerSpec.hs
@@ -227,6 +227,10 @@ spec = do
     run (java "class Foo implements Bar {}") "Foo" "Implements:Bar" `shouldBe` True
     run (java "class Foo implements Bar {}") "Foo" "Implements:Baz" `shouldBe` False
 
+  it "works with Print" $ do
+    run (java "public class Foo { public static void main() { } }") "*" "UsesPrint" `shouldBe` False
+    run (java "public class Foo { public static void main() { System.out.println((5).equals(6)); } }") "*" "UsesPrint" `shouldBe` True
+
   it "works with Inherits" $ do
     run (java "class Foo extends Bar {}") "Foo" "Inherits:Bar" `shouldBe` True
     run (java "class Foo extends Bar {}") "Foo" "Inherits:Baz" `shouldBe` False
@@ -235,3 +239,22 @@ spec = do
     run (java "class Foo implements Bar {}") "Foo" "Implements:[Bar|Baz|Foobar]" `shouldBe` True
     run (java "class Foo implements Baz {}") "Foo" "Implements:[Bar|Baz|Foobar]" `shouldBe` True
     run (java "class Foo implements Foobaz {}") "Foo" "Implements:[Bar|Baz|Foobar]" `shouldBe` False
+
+  it "works with primitive operators in js" $ do
+    run (js "x == 4") "*" "UsesEqual" `shouldBe` True
+    run (js "x != 4") "*" "UsesEqual" `shouldBe` False
+
+  it "works with primitive operators in hs" $ do
+    run (hs "x = x . y") "*" "UsesForwardComposition" `shouldBe` False
+    run (hs "x = x . y") "*" "UsesBackwardComposition" `shouldBe` True
+
+  it "works with primitive operators usages in java" $ do
+    run (java "public class Foo { public static void main() { System.out.println((5).equals(6)); } }") "*" "UsesHash" `shouldBe` False
+    run (java "public class Foo { public static void main() { System.out.println((5).equals(6)); } }") "*" "UsesEqual" `shouldBe` True
+
+  it "works with primitive operators declarations in java" $ do
+    run (java "public class Foo { public boolean equals(Object other) { return false; } }") "*" "DeclaresEqual" `shouldBe` True
+    run (java "public class Foo { public boolean equals(Object other) { return false; } }") "*" "DeclaresHash" `shouldBe` False
+
+  it "does not mix keywords with inspections" $ do
+    run (hs "type X = Int") "*" "Uses:type" `shouldBe` False
diff --git a/spec/GeneratorSpec.hs b/spec/GeneratorSpec.hs
index ebc5303f6..386aa0e99 100644
--- a/spec/GeneratorSpec.hs
+++ b/spec/GeneratorSpec.hs
@@ -16,7 +16,7 @@ spec = do
   describe "referencedIdentifiers" $ do
     it "answers referenced identifiers" $ do
       let code = hs "f x =  (:[]) . m x y . g h 2"
-      (referencedIdentifiers code) `shouldBe` [".", "flip", ":", "m","x","y", "g","h"]
+      (referencedIdentifiers code) `shouldBe` ["flip", ":", "m","x","y", "g","h"]
 
   describe "transitiveReferencedIdentifiers" $ do
     it "answers transitive referenced identifiers" $ do
diff --git a/spec/InspectorSpec.hs b/spec/InspectorSpec.hs
index 72faa772b..9bd477431 100644
--- a/spec/InspectorSpec.hs
+++ b/spec/InspectorSpec.hs
@@ -416,6 +416,20 @@ spec = do
     it "is False when using a matcher that does not match" $ do
       (callsMatching (with "1") anyone) (hs "f = g 2") `shouldBe` False
 
+  describe "usesBooleanLogic" $ do
+    it "is when it is used" $ do
+      usesBooleanLogic (hs "f x y = x || y")   `shouldBe` True
+      usesBooleanLogic (hs "f x y = x && y")   `shouldBe` True
+      usesBooleanLogic (hs "f x y = not x")    `shouldBe` True
+      usesBooleanLogic (hs "f x y = (not) x")  `shouldBe` True
+      usesBooleanLogic (hs "f x y = (&&) x y") `shouldBe` True
+
+    it "is is not used otherwise" $ do
+      usesBooleanLogic (hs "f x y = x + y") `shouldBe` False
+      usesBooleanLogic (hs "f x y = x")     `shouldBe` False
+      usesBooleanLogic (hs "f x y = and x") `shouldBe` False
+      usesBooleanLogic (hs "f x y = or x")  `shouldBe` False
+
   describe "usesExceptions" $ do
     it "is True when a raise is used, java" $ do
       usesExceptions (java "class Sample { void aMethod() { throw new RuntimeException(); } }") `shouldBe` True
@@ -465,8 +479,11 @@ spec = do
     it "is True when required function is used as argument" $ do
       uses (named "m") (hs "y x = x m") `shouldBe` True
 
+    it "is False with primitives" $ do
+      uses (named "&&") (hs "y x = x && z") `shouldBe` False
+
     it "is True when required function is used as operator" $ do
-      uses (named "&&" )(hs "y x = x && z") `shouldBe` True
+      uses (named "<>") (hs "y x = x <> z") `shouldBe` True
 
     it "is False when required function is not used in constant" $ do
       uses (named "m") (hs "y = 3") `shouldBe` False
@@ -566,6 +583,32 @@ spec = do
       transitive "p" (uses (named "m")) (js "var o = {g: function(){ m }}\n\
                                         \var p = {n: function() { o.g() }}") `shouldBe` True
 
+  describe "usesPrimitive, hs" $ do
+    it "is True when required primitive is used on application" $ do
+      usesPrimitive And (hs "y x = x && z") `shouldBe` True
+      usesPrimitive BackwardComposition (hs "y x = x . z") `shouldBe` True
+      usesPrimitive Negation (hs "y x = not z") `shouldBe` True
+
+    it "is True when required primitive is used as argument" $ do
+      usesPrimitive And (hs "y x = f (&&) y z") `shouldBe` True
+
+    it "is False when primitive is just apparently used" $ do
+      usesPrimitive And (hs "y x = and x") `shouldBe` False
+
+    it "is False when primitive is not used" $ do
+      usesPrimitive Negation (hs "y x = m x") `shouldBe` False
+
+  describe "usesPrimitive, js" $ do
+    it "is True when required primitive is used on application" $ do
+      usesPrimitive And (js "x && z") `shouldBe` True
+      usesPrimitive Negation (js "function () { return !z }") `shouldBe` True
+
+    it "is False when primitive is just apparently used" $ do
+      usesPrimitive Or (js "or(x)") `shouldBe` False
+
+    it "is False when primitive is not used" $ do
+      usesPrimitive ForwardComposition (js "f(g(x))") `shouldBe` False
+
   describe "declaresComputation" $ do
     describe "with constants" $ do
       it "is False when exists" $ do
diff --git a/spec/JavaScriptSpec.hs b/spec/JavaScriptSpec.hs
index 3ceff0bad..da6a3649e 100644
--- a/spec/JavaScriptSpec.hs
+++ b/spec/JavaScriptSpec.hs
@@ -93,10 +93,10 @@ spec = do
       js "true" `shouldBe` MuTrue
 
     it "handles negation" $ do
-      js "!true" `shouldBe` (Application (Reference "!") [MuTrue])
+      js "!true" `shouldBe` (Application (Primitive Negation) [MuTrue])
 
     it "handles boolean binary operations" $ do
-      js "true || false " `shouldBe` (Application (Reference "||") [MuTrue, MuFalse])
+      js "true || false " `shouldBe` (Application (Primitive Or) [MuTrue, MuFalse])
 
     it "handles lambdas" $ do
       js "(function(x, y) { 1 })" `shouldBe` (Lambda [VariablePattern "x", VariablePattern "y"] (MuNumber 1))
diff --git a/spec/JavaSpec.hs b/spec/JavaSpec.hs
index 709c79c82..1759f8c1b 100644
--- a/spec/JavaSpec.hs
+++ b/spec/JavaSpec.hs
@@ -12,7 +12,6 @@ import           NeatInterpolation (text)
 run :: Text -> Expression
 run = java . unpack
 
-
 spec :: Spec
 spec = do
   describe "parse" $ do
@@ -71,7 +70,7 @@ spec = do
             class Foo {
                public  A hello(A a) {}
             }|] `shouldBe` Class "Foo" Nothing (Sequence [
-                              SubroutineSignature "hello" ["A"] "A" [],
+                              SubroutineSignature "hello" ["A"] "A" ["A"],
                               (SimpleMethod "hello" [VariablePattern "a"] None)])
 
     it "parses Methods with type arguments and type constraints" $ do
@@ -79,7 +78,7 @@ spec = do
             class Foo {
                public  A hello(A a) {}
             }|] `shouldBe` Class "Foo" Nothing (Sequence [
-                              SubroutineSignature "hello" ["A"] "A" [],
+                              SubroutineSignature "hello" ["A"] "A" ["A"],
                               (SimpleMethod "hello" [VariablePattern "a"] None)])
 
     it "parses Empty Returns" $ do
@@ -124,7 +123,7 @@ spec = do
              public boolean hello() { return !true; }
           }|] `shouldBe` Class "Foo" Nothing (Sequence [
                           SubroutineSignature "hello" [] "boolean" [],
-                          (SimpleMethod "hello" [] (Return (SimpleSend MuTrue "!" [])))])
+                          (SimpleMethod "hello" [] (Return (PrimitiveSend MuTrue Negation [])))])
 
     it "parses Chars In Returns" $ do
       run [text|class Foo {
@@ -133,6 +132,15 @@ spec = do
                           SubroutineSignature "hello" [] "char" [],
                           (SimpleMethod "hello" [] (Return (MuChar 'f')))])
 
+    it "parses equals methods invocations" $ do
+      run [text|public class Foo {
+            public static void main() {
+              System.out.println((5).equals(6));
+            }
+          }|] `shouldBe` Class "Foo" Nothing (Sequence [
+                          SubroutineSignature "main" [] "void" [],
+                          (SimpleMethod "main" [] (Print (PrimitiveSend (MuNumber 5) Equal [MuNumber 6])))])
+
     it "parses Parameters" $ do
       run "public class Foo extends Bar { int succ(int y) {} }" `shouldBe` Class "Foo" (Just "Bar") (Sequence [
                                                                               SubroutineSignature "succ" ["int"] "int" [],
@@ -262,7 +270,7 @@ spec = do
           }|] `shouldBe` Class "Foo" Nothing (Sequence [
                            SubroutineSignature "hello" ["String"] "void" [],
                            SimpleMethod "hello" [VariablePattern "x"] (
-                             If (Send (Reference "x") Equal [MuString "foo"])
+                             If (Send (Reference "x") (Primitive Equal) [MuString "foo"])
                               None
                               None)])
 
@@ -273,7 +281,7 @@ spec = do
           }|] `shouldBe` Class "Foo" Nothing (Sequence [
                             SubroutineSignature "hello" ["String"] "void" [],
                             (SimpleMethod "hello" [VariablePattern "x"] (
-                            If (Send (Reference "x") NotEqual [MuString "foo"])
+                            If (Send (Reference "x") (Primitive NotEqual) [MuString "foo"])
                               None
                               None))])
 
diff --git a/spec/PythonSpec.hs b/spec/PythonSpec.hs
index 090c1c911..a7fabc05d 100644
--- a/spec/PythonSpec.hs
+++ b/spec/PythonSpec.hs
@@ -69,7 +69,7 @@ spec = do
       py "1;2;3" `shouldBe` Sequence [MuNumber 1, MuNumber 2, MuNumber 3]
 
     it "parses unary operators" $ do
-      py "not True" `shouldBe` (Application (Reference "not") [MuBool True])
+      py "not True" `shouldBe` (Application (Primitive Negation) [MuBool True])
 
     it "parses classes" $ do
       py "class DerivedClassName: pass" `shouldBe` Class "DerivedClassName" Nothing None
diff --git a/spec/SmellSpec.hs b/spec/SmellSpec.hs
index ab7c6a6e3..64e84aebd 100644
--- a/spec/SmellSpec.hs
+++ b/spec/SmellSpec.hs
@@ -83,13 +83,13 @@ spec = do
       hasRedundantBooleanComparison (hs "f x = True") `shouldBe` False
 
     it "is True when comparing self with a boolean, using a message" $ do
-      hasRedundantBooleanComparison (Send Self Equal [MuBool True]) `shouldBe` True
+      hasRedundantBooleanComparison (PrimitiveSend Self Equal [MuBool True]) `shouldBe` True
 
     it "is True when comparing a boolean with a reference, using a message" $ do
-      hasRedundantBooleanComparison (Send (MuBool False) NotEqual [Reference "x"]) `shouldBe` True
+      hasRedundantBooleanComparison (PrimitiveSend (MuBool False) NotEqual [Reference "x"]) `shouldBe` True
 
     it "is False when comparing references" $ do
-      hasRedundantBooleanComparison (Send (Reference "y") Equal [Reference "x"]) `shouldBe` False
+      hasRedundantBooleanComparison (PrimitiveSend (Reference "y") Equal [Reference "x"]) `shouldBe` False
 
   describe "hasRedundantLocalVariableReturn" $ do
     it "is True when local variable is not necessary" $ do
@@ -191,6 +191,23 @@ spec = do
     it "is False when there is no guard" $ do
       hasRedundantGuards (hs "x = False") `shouldBe` False
 
+  describe "shouldUseOtherwise" $ do
+    it "is True when there are two guards and last one is a True" $ do
+      shouldUseOtherwise (hs "f x | c x = True\n\
+                             \    | True = False") `shouldBe` True
+
+    it "is True when there are three guards and last one is a True" $ do
+      shouldUseOtherwise (hs "f x | c x = True\n\
+                             \    | g x = False\n\
+                             \    | True = False") `shouldBe` True
+
+    it "is True when last guard is an otherwsie" $ do
+      shouldUseOtherwise (hs "f x | c x = True\n\
+                             \    | otherwise = False") `shouldBe` False
+
+    it "is False when there no guards" $ do
+      shouldUseOtherwise (hs "f x = True") `shouldBe` False
+
   describe "discardsExceptions" $ do
     it "is True when there is an empty catch" $ do
       discardsExceptions (javaStatement "try { new Bar().baz(); } catch (Exception e) { /*TODO handle exception*/ }") `shouldBe` True
diff --git a/spec/SmellsAnalyzerSpec.hs b/spec/SmellsAnalyzerSpec.hs
index c976ad72a..a95bfb8a1 100644
--- a/spec/SmellsAnalyzerSpec.hs
+++ b/spec/SmellsAnalyzerSpec.hs
@@ -11,20 +11,27 @@ runExcept language content smells = analyse (smellsAnalysis (CodeSample language
 runOnly language content smells = analyse (smellsAnalysis (CodeSample language content) (noSmellsBut smells))
 
 spec = describe "SmellsAnalyzer" $ do
-  describe "Using domain language and nested structures" $ do
+  it "Using domain language and nested structures" $ do
     let runRuby sample = analyse (domainLanguageAnalysis (MulangSample sample Nothing) (DomainLanguage Nothing (Just RubyCase) (Just 3) Nothing))
-    it "works with empty set" $ do
-      (runRuby (Sequence [
-        (Object "Foo_Bar" (Sequence [
-          (SimpleMethod "y" [] None),
-          (SimpleMethod "aB" [] None),
-          (SimpleMethod "fooBar" [] None)])),
-        (Object "Foo" None)])) `shouldReturn` (result [
-                                                    Expectation "y" "HasTooShortIdentifiers",
-                                                    Expectation "aB" "HasTooShortIdentifiers",
-                                                    Expectation "Foo_Bar" "HasWrongCaseIdentifiers",
-                                                    Expectation "aB" "HasWrongCaseIdentifiers",
-                                                    Expectation "fooBar" "HasWrongCaseIdentifiers"])
+    (runRuby (Sequence [
+      (Object "Foo_Bar" (Sequence [
+        (SimpleMethod "y" [] None),
+        (SimpleMethod "aB" [] None),
+        (SimpleMethod "fooBar" [] None)])),
+      (Object "Foo" None)])) `shouldReturn` (result [
+                                                  Expectation "y" "HasTooShortIdentifiers",
+                                                  Expectation "aB" "HasTooShortIdentifiers",
+                                                  Expectation "Foo_Bar" "HasWrongCaseIdentifiers",
+                                                  Expectation "aB" "HasWrongCaseIdentifiers",
+                                                  Expectation "fooBar" "HasWrongCaseIdentifiers"])
+
+  it "works inferring domain language" $ do
+    let runPython sample = runExcept Python3 sample []
+    runPython "def fooBar():\n\tpass\n\ndef foo_baz():\n\tpass\n\n" `shouldReturn` (result [Expectation "fooBar" "HasWrongCaseIdentifiers"])
+
+  it "works inferring caseStyl" $ do
+    let runPython sample = analyse (domainLanguageAnalysis (CodeSample Python3 sample) (DomainLanguage Nothing Nothing (Just 3) Nothing))
+    runPython "def fooBar():\n\tpass\n\ndef foo_baz():\n\tpass\n\n" `shouldReturn` (result [Expectation "fooBar" "HasWrongCaseIdentifiers"])
 
   describe "Using exclusion" $ do
     it "works with empty set, in java" $ do
diff --git a/spec/UnjavaSpec.hs b/spec/UnjavaSpec.hs
new file mode 100644
index 000000000..706b45df2
--- /dev/null
+++ b/spec/UnjavaSpec.hs
@@ -0,0 +1,97 @@
+{-# LANGUAGE QuasiQuotes, OverloadedStrings #-}
+
+module UnjavaSpec (spec) where
+
+import           Test.Hspec
+import           Language.Mulang
+import           Language.Mulang.Parsers.Java (java)
+import           Language.Mulang.Unparsers.Java (unparseJava)
+
+shouldRoundTrip expression =  (java.unparseJava) expression `shouldBe` expression
+
+spec :: Spec
+spec = do
+  let wrapStatement expr = (Class "Sample" Nothing
+                              (Sequence [
+                                SubroutineSignature "sample" [] "void" [],
+                                SimpleMethod "sample" [] expr
+                              ]))
+  let wrapExpression expr = wrapStatement (Return expr)
+
+  describe "unparse" $ do
+    let itWorksWith expr expectedCode = it (show expr) (unparseJava expr `shouldBe` expectedCode)
+    let itWorksWithJavaExpression expr expectedCode = it (show expr) (unparseJava (wrapExpression expr) `shouldBe` expectedCode)
+    let itWorksWithJavaStatement expr expectedCode = it (show expr) (unparseJava (wrapStatement expr) `shouldBe` expectedCode)
+
+    itWorksWithJavaExpression (MuNumber 1.5) "public class Sample { \tpublic void sample (  ) { return 1.5 ; }\n }"
+    itWorksWithJavaStatement ((Assignment "x" (Send (Reference "x") (Reference "+") [MuNumber 8]))) "public class Sample { \tpublic void sample (  ) { x = (x + 8) ; }\n }"
+    itWorksWithJavaStatement (Sequence [Print (MuString "hello"), Print (MuString "world")]) "public class Sample { \tpublic void sample (  ) { System.out.println(\"hello\");\n\tSystem.out.println(\"world\");\n\t }\n }"
+    itWorksWithJavaStatement (Sequence [Print (MuString "hello"), SimpleSend Self "foo" []]) "public class Sample { \tpublic void sample (  ) { System.out.println(\"hello\");\n\tthis.foo();\n\t }\n }"
+
+    itWorksWithJavaStatement (While MuTrue None) "public class Sample { \tpublic void sample (  ) { while ( true ) {  } }\n }"
+    itWorksWithJavaStatement (While MuTrue (SimpleSend Self "foo" [])) "public class Sample { \tpublic void sample (  ) { while ( true ) { \tthis.foo();\n\t } }\n }"
+
+  describe "roundTrip" $ do
+    let itWorksWith expr = it (show expr) (shouldRoundTrip expr)
+    let itWorksWithJavaExpression expr = it (show expr) (shouldRoundTrip (wrapExpression expr))
+    let itWorksWithJavaStatement expr = it (show expr) (shouldRoundTrip (wrapStatement expr))
+
+    describe "literals" $ do
+      itWorksWithJavaExpression (MuNumber 1.5)
+      itWorksWithJavaExpression (MuNumber 1)
+      itWorksWithJavaExpression MuTrue
+      itWorksWithJavaExpression (MuString "some string")
+
+    itWorksWithJavaStatement (Assignment "one" (MuNumber 1))
+    itWorksWithJavaExpression ((Reference "x"))
+    itWorksWithJavaExpression ((Send Self (Reference "f") [MuNumber 2]))
+    itWorksWithJavaExpression ((Send (Reference "o") (Reference "f") [(MuNumber 2)]))
+    itWorksWithJavaStatement ((Assignment "x" (Send (Reference "x") (Reference "+") [MuNumber 8])))
+    itWorksWithJavaExpression ((Send (Reference "x") (Reference "+") [Reference "y"]))
+    itWorksWithJavaStatement (Sequence [Print (MuString "hello"), Print (MuString "world")])
+    itWorksWithJavaStatement (Sequence [Print (MuString "hello"), SimpleSend Self "foo" []])
+    itWorksWithJavaExpression ((Send MuTrue (Primitive Negation) []))
+
+    describe "classes" $ do
+      itWorksWith (Class "DerivedClassName" Nothing None)
+      itWorksWith (Class "DerivedClassName" (Just "BaseClassName") None)
+      itWorksWith (Class "Foo" Nothing None)
+      itWorksWith (Class "Foo" (Just "Bar") None)
+
+    --itWorksWithJavaStatement (If MuTrue (MuNumber 1) (If MuFalse (MuNumber 2) (MuNumber 3)))
+    -- itWorksWith (Class "Sample" Nothing (SimpleMethod "foo" [VariablePattern "param"] (Print (Reference "param"))))
+    itWorksWithJavaStatement (While MuTrue None)
+    -- itWorksWithJavaStatement (For [Generator (TuplePattern [VariablePattern "x"]) (Application (Reference "range") [MuNumber 0, MuNumber 3])] None)
+    -- itWorksWithJavaStatement (Raise (Application (Reference "Exception") [MuString "something"]))
+
+    -- describe "lambdas" $ do
+    --   itWorksWith $ (Lambda [VariablePattern "x"] (MuNumber 1))
+    --   itWorksWith $ (Lambda [] (Reference "foo"))
+
+    describe "boolean operations" $ do
+      let muand x y = (Send x (Primitive And) [y])
+      let muor  x y = (Send x (Primitive Or) [y])
+      let muneg x = (Send x (Primitive Negation) [])
+
+      itWorksWithJavaExpression $ (Reference "a") `muand` (Reference "b")
+      itWorksWithJavaExpression $ (Reference "a") `muor` (Reference "b")
+      itWorksWithJavaExpression $ (muneg (Reference "a")) `muor` (Reference "b")
+      itWorksWithJavaExpression $ muneg ((Reference "a") `muor` (Reference "b"))
+      itWorksWithJavaExpression $ muneg ((Reference "a") `muand` (Reference "b")) `muor` (Reference "c")
+      itWorksWithJavaExpression $ (Reference "a") `muand` ((Reference "b") `muor` (Reference "c"))
+
+    describe "interface" $ do
+      itWorksWith (Interface "Foo" [] None)
+      itWorksWith (Interface "Foo" [] (SubroutineSignature "foo" [] "void" []))
+      itWorksWith (Interface "Foo" [] (SubroutineSignature "foo" [] "A" ["A"]))
+      itWorksWith (Interface "Foo" [] (SubroutineSignature "foo" [] "int" []))
+      itWorksWith (Interface "Foo" [] (Sequence [
+                                  SubroutineSignature "foo" [] "void" [],
+                                    SubroutineSignature "bar" [] "int" []]))
+      itWorksWith (Interface "Foo" [] (SubroutineSignature "foo" ["String", "int"] "void" []))
+      itWorksWith (Interface "Foo" ["Bar", "Baz"] None)
+
+      -- shouldRoundTrip (Class "Foo" Nothing (Sequence [
+      --                    TypeSignature "hello" (ParameterizedType [] "void" []),
+      --                    SimpleMethod "hello" [] None
+      --                 ]))
diff --git a/spec/UnpythonSpec.hs b/spec/UnpythonSpec.hs
new file mode 100644
index 000000000..4fa089784
--- /dev/null
+++ b/spec/UnpythonSpec.hs
@@ -0,0 +1,104 @@
+module UnpythonSpec (spec) where
+
+import           Test.Hspec
+import           Language.Mulang
+
+import           Language.Mulang.Parsers.Python (py)
+import           Language.Mulang.Unparsers.Python (unparsePython)
+
+shouldRoundTrip expression =  (py.unparsePython) expression `shouldBe` expression
+
+spec :: Spec
+spec = do
+  describe "roundTrip" $ do
+    let itWorksWith expr = it (show expr) (shouldRoundTrip expr)
+
+    describe "literals" $ do
+      itWorksWith $ (MuNumber 1.5)
+      itWorksWith $ (MuNumber 1)
+      itWorksWith $ MuTrue
+      itWorksWith $ (MuString "some string")
+      itWorksWith $ (MuList [MuNumber 1, MuNumber 2, MuNumber 3])
+      itWorksWith $ (MuList [MuNumber 1, MuNumber 2, MuNumber 3])
+
+    itWorksWith $ (Assignment "one" (MuNumber 1))
+    itWorksWith $ ((Reference "x"))
+    itWorksWith $ ((Application (Reference "f") [MuNumber 2]))
+    itWorksWith $ ((Send (Reference "o") (Reference "f") [(MuNumber 2)]))
+    itWorksWith $ ((Assignment "x" (Application (Reference "+") [Reference "x",MuNumber 8])))
+    itWorksWith $ ((Application (Reference "+") [Reference "x",Reference "y"]))
+    itWorksWith $ (Sequence [MuNumber 1, MuNumber 2, MuNumber 3])
+    itWorksWith $ ((Application (Primitive Negation) [MuTrue]))
+
+    describe "classes" $ do
+      itWorksWith $ (Class "DerivedClassName" Nothing None)
+      itWorksWith $ (Class "DerivedClassName" (Just "BaseClassName") None)
+
+    itWorksWith $ (If MuTrue (MuNumber 1) (If MuFalse (MuNumber 2) (MuNumber 3)))
+    itWorksWith $ (SimpleFunction "foo" [] (Return (MuNumber 1)))
+    itWorksWith $ (SimpleProcedure "foo" [VariablePattern "param"] (Print (Reference "param")))
+    itWorksWith $ (While MuTrue None)
+    itWorksWith $ (For [Generator (TuplePattern [VariablePattern "x"]) (Application (Reference "range") [MuNumber 0, MuNumber 3])] None)
+    itWorksWith $ (Raise None)
+    itWorksWith $ (Raise (Application (Reference "Exception") [MuString "something"]))
+
+    describe "lambdas" $ do
+      itWorksWith $ (Lambda [VariablePattern "x"] (MuNumber 1))
+      itWorksWith $ (Lambda [] (Reference "foo"))
+
+    itWorksWith $ (MuTuple [MuNumber 1, MuString "something"])
+    itWorksWith $ (Yield (MuNumber 1))
+
+    describe "boolean operations" $ do
+      let muand x y = (Application (Primitive And) [x, y])
+      let muor  x y = (Application (Primitive Or) [x, y])
+      let muneg x = (Application (Primitive Negation) [x])
+
+      itWorksWith $ (Reference "a") `muand` (Reference "b")
+      itWorksWith $ (Reference "a") `muor` (Reference "b")
+      itWorksWith $ (muneg (Reference "a")) `muor` (Reference "b")
+      itWorksWith $ muneg ((Reference "a") `muor` (Reference "b"))
+      itWorksWith $ muneg ((Reference "a") `muand` (Reference "b")) `muor` (Reference "c")
+      itWorksWith $ (Reference "a") `muand` ((Reference "b") `muor` (Reference "c"))
+
+  describe "unparsePython" $ do
+    let itWorksWith expr expectedCode = it (show expr) (unparsePython expr `shouldBe` expectedCode)
+
+    describe "literals" $ do
+      itWorksWith (MuNumber 1) "1"
+      itWorksWith (MuNumber 1.5) "1.5"
+      itWorksWith (MuNumber 1) "1"
+      itWorksWith MuTrue "True"
+      itWorksWith (MuString "some string") "\"some string\""
+      itWorksWith (MuList [MuNumber 1, MuNumber 2, MuNumber 3]) "[1,2,3]"
+      itWorksWith MuNil "None"
+
+    itWorksWith (Assignment "one" (MuNumber 1)) "one = 1"
+    itWorksWith ((Reference "x")) "x"
+    itWorksWith ((Application (Reference "f") [MuNumber 2])) "f(2)"
+    itWorksWith ((Send (Reference "o") (Reference "f") [(MuNumber 2)])) "o.f(2)"
+    itWorksWith ((Assignment "x" (Application (Reference "+") [Reference "x",MuNumber 8]))) "x = (x + 8)"
+    itWorksWith ((Application (Reference "+") [Reference "x",Reference "y"])) "(x + y)"
+    itWorksWith (Sequence [MuNumber 1, MuNumber 2, MuNumber 3]) "1\n2\n3\n"
+    itWorksWith ((Application (Primitive Negation) [MuTrue])) "(not True)"
+
+    describe "clases" $ do
+      itWorksWith (Class "DerivedClassName" Nothing None) "class DerivedClassName:\n\tpass\n"
+      itWorksWith (Class "DerivedClassName" (Just "BaseClassName") None) "class DerivedClassName(BaseClassName):\n\tpass\n"
+
+    describe "defs" $ do
+      itWorksWith (SimpleFunction "foo" [] (Return (MuNumber 1))) "def foo():\n\treturn 1\n"
+      itWorksWith (SimpleProcedure "foo" [VariablePattern "param"] (Print (Reference "param"))) "def foo(param):\n\tprint(param)\n"
+
+    itWorksWith (While MuTrue None) "while True:\n\tpass\n"
+    itWorksWith (For [Generator (TuplePattern [VariablePattern "x"]) (Application (Reference "range") [MuNumber 0, MuNumber 3])] None) "for x in range(0,3): pass"
+    itWorksWith (Raise None) "raise"
+    itWorksWith (Raise (Application (Reference "Exception") [MuString "something"])) "raise Exception(\"something\")"
+
+    describe "lambdas" $ do
+      itWorksWith (Lambda [VariablePattern "x"] (Reference "x")) "lambda x: x"
+      itWorksWith (Lambda [VariablePattern "x", VariablePattern "y"] (MuNumber 1)) "lambda x,y: 1"
+      itWorksWith (Lambda [] MuNil) "lambda : None"
+
+    itWorksWith (MuTuple [MuNumber 1, MuString "something"]) "(1,\"something\")"
+    itWorksWith (Yield (MuNumber 1)) "yield 1"
diff --git a/spec/UnrubySpec.hs b/spec/UnrubySpec.hs
new file mode 100644
index 000000000..139d279b2
--- /dev/null
+++ b/spec/UnrubySpec.hs
@@ -0,0 +1,68 @@
+module UnrubySpec (spec) where
+
+import           Test.Hspec
+import           Language.Mulang
+
+import           Language.Mulang.Unparsers.Ruby (unparseRuby)
+
+spec :: Spec
+spec = do
+  describe "unparseRuby" $ do
+    let itWorksWith expr expectedCode = it (show expr) (unparseRuby expr `shouldBe` expectedCode)
+
+    describe "literals" $ do
+      itWorksWith (MuNumber 1.5) "1.5"
+      itWorksWith (MuNumber 1) "1"
+      itWorksWith MuTrue "true"
+      itWorksWith MuFalse "false"
+      itWorksWith (MuString "some string") "\"some string\""
+      itWorksWith (MuList [MuNumber 1, MuNumber 2, MuNumber 3]) "[1,2,3]"
+      itWorksWith MuNil "nil"
+
+    itWorksWith (Assignment "one" (MuNumber 1)) "one = 1"
+    itWorksWith ((Reference "x")) "x"
+    itWorksWith ((Application (Reference "f") [MuNumber 2])) "f(2)"
+    itWorksWith ((Send (Reference "o") (Reference "f") [(MuNumber 2)])) "o.f(2)"
+    itWorksWith ((Assignment "x" (Application (Reference "+") [Reference "x",MuNumber 8]))) "x = (x + 8)"
+    itWorksWith ((Application (Reference "+") [Reference "x",Reference "y"])) "(x + y)"
+    itWorksWith (Sequence [MuNumber 1, MuNumber 2, MuNumber 3]) "1\n2\n3\n"
+    itWorksWith ((Application (Primitive Negation) [MuTrue])) "(!true)"
+
+    describe "classes" $ do
+      itWorksWith (Class "DerivedClassName" Nothing None) "class DerivedClassName\nend\n"
+      itWorksWith (Class "DerivedClassName" (Just "BaseClassName") None) "class DerivedClassName < BaseClassName\nend\n"
+
+    itWorksWith (If MuTrue (MuNumber 1) (MuNumber 3)) "if true\n\t1\nelse\n\t3\nend\n"
+
+    describe "functions and procedures" $ do
+      itWorksWith (SimpleFunction "foo" [] (Return (MuNumber 1))) "def foo()\n\treturn 1\nend\n"
+      itWorksWith (SimpleFunction "foo" [VariablePattern "x"] (Return (Reference "x"))) "def foo(x)\n\treturn x\nend\n"
+      itWorksWith (SimpleProcedure "foo" [] (Print (Reference "param"))) "def foo()\n\tputs(param)\nend\n"
+      itWorksWith (SimpleProcedure "foo" [VariablePattern "param"] (Print (Reference "param"))) "def foo(param)\n\tputs(param)\nend\n"
+
+    describe "while" $ do
+      itWorksWith (While MuTrue None) "while true\nend\n"
+      itWorksWith (While MuTrue (Print (MuString "hi"))) "while true\n\tputs(\"hi\")\nend\n"
+
+    describe "raise" $ do
+      itWorksWith (Raise None) "raise"
+      itWorksWith (Raise (MuString "something")) "raise \"something\""
+
+    describe "lambda" $ do
+      itWorksWith (Lambda [VariablePattern "x"] (Reference "x")) "lambda { |x| x }"
+      itWorksWith (Lambda [VariablePattern "x", VariablePattern "y"] (MuNumber 1)) "lambda { |x,y| 1 }"
+      itWorksWith (Lambda [] MuNil) "lambda { || nil }"
+
+    itWorksWith (Yield (MuNumber 1)) "yield 1"
+
+    describe "boolean operations" $ do
+      let muand x y = (Application (Primitive And) [x, y])
+      let muor  x y = (Application (Primitive Or) [x, y])
+      let muneg x = (Application (Primitive Negation) [x])
+
+      itWorksWith ((Reference "a") `muand` (Reference "b")) "(a && b)"
+      itWorksWith ((Reference "a") `muor` (Reference "b")) "(a || b)"
+      itWorksWith ((muneg (Reference "a")) `muor` (Reference "b")) "((!a) || b)"
+      itWorksWith (muneg ((Reference "a") `muor` (Reference "b"))) "(!(a || b))"
+      itWorksWith (muneg ((Reference "a") `muand` (Reference "b")) `muor` (Reference "c")) "((!(a && b)) || c)"
+      itWorksWith ((Reference "a") `muand` ((Reference "b") `muor` (Reference "c"))) "(a && (b || c))"
diff --git a/src/Language/Mulang/Analyzer.hs b/src/Language/Mulang/Analyzer.hs
index afd436c25..800ac3436 100644
--- a/src/Language/Mulang/Analyzer.hs
+++ b/src/Language/Mulang/Analyzer.hs
@@ -1,90 +1,36 @@
 module Language.Mulang.Analyzer (
-  noSmells,
-  allSmells,
-  noSmellsBut,
-  allSmellsBut,
-
-  emptyDomainLanguage,
-  emptyAnalysisSpec,
-
-  emptyAnalysis,
-  domainLanguageAnalysis,
-  expectationsAnalysis,
-  smellsAnalysis,
-  signaturesAnalysis,
-  testsAnalysis,
-
-  emptyCompletedAnalysisResult,
-
   analyse,
-
   module Language.Mulang.Analyzer.Analysis) where
 
 import Language.Mulang
-import Language.Mulang.Analyzer.Analysis
-import Language.Mulang.Analyzer.DomainLanguageCompiler (emptyDomainLanguage, compileDomainLanguage)
+import Language.Mulang.Analyzer.Analysis hiding (Inspection)
+import Language.Mulang.Analyzer.DomainLanguageCompiler (compileDomainLanguage)
 import Language.Mulang.Analyzer.ExpectationsAnalyzer (analyseExpectations)
 import Language.Mulang.Analyzer.FragmentParser (parseFragment)
 import Language.Mulang.Analyzer.SignaturesAnalyzer  (analyseSignatures)
 import Language.Mulang.Analyzer.SmellsAnalyzer (analyseSmells)
 import Language.Mulang.Analyzer.TestsAnalyzer  (analyseTests)
+import Language.Mulang.Analyzer.Autocorrector  (autocorrect)
 import Data.Maybe (fromMaybe)
 
---
--- Builder functions
---
-
-noSmells :: Maybe SmellsSet
-noSmells = Just $ NoSmells Nothing
-
-noSmellsBut :: [Smell] -> Maybe SmellsSet
-noSmellsBut = Just . NoSmells . Just
-
-allSmells :: Maybe SmellsSet
-allSmells = Just $ AllSmells Nothing
-
-allSmellsBut :: [Smell] -> Maybe SmellsSet
-allSmellsBut = Just . AllSmells . Just
-
-emptyAnalysisSpec :: AnalysisSpec
-emptyAnalysisSpec = AnalysisSpec Nothing Nothing Nothing Nothing Nothing Nothing
-
-emptyAnalysis :: Fragment -> Analysis
-emptyAnalysis code = Analysis code emptyAnalysisSpec
-
-domainLanguageAnalysis :: Fragment -> DomainLanguage -> Analysis
-domainLanguageAnalysis code domainLanguage = Analysis code (emptyAnalysisSpec { domainLanguage = Just domainLanguage, smellsSet = allSmells })
-
-expectationsAnalysis :: Fragment -> [Expectation] -> Analysis
-expectationsAnalysis code es = Analysis code (emptyAnalysisSpec { expectations = Just es })
-
-smellsAnalysis :: Fragment -> Maybe SmellsSet -> Analysis
-smellsAnalysis code set = Analysis code (emptyAnalysisSpec { smellsSet = set })
-
-signaturesAnalysis :: Fragment -> SignatureStyle -> Analysis
-signaturesAnalysis code style = Analysis code (emptyAnalysisSpec { signatureAnalysisType = Just (StyledSignatures style) })
-
-testsAnalysis :: Fragment -> TestAnalysisType -> Analysis
-testsAnalysis code testAnalysisType = Analysis code (emptyAnalysisSpec { testAnalysisType = Just testAnalysisType })
-
-emptyCompletedAnalysisResult :: AnalysisResult
-emptyCompletedAnalysisResult = AnalysisCompleted [] [] [] [] Nothing
 
 --
 -- Analysis running
 --
 
-analyse :: Analysis -> IO AnalysisResult
-analyse (Analysis sample spec) = analyseSample (parseFragment sample)
+analyse, analyse' :: Analysis -> IO AnalysisResult
+analyse = analyse' . autocorrect
+
+analyse' (Analysis sample spec) = analyseSample . parseFragment $ sample
   where analyseSample (Right ast)    = analyseAst ast spec
         analyseSample (Left message) = return $ AnalysisFailed message
 
 analyseAst :: Expression -> AnalysisSpec -> IO AnalysisResult
 analyseAst ast spec = do
-  language <- compileDomainLanguage (domainLanguage spec)
+  domaingLang <- compileDomainLanguage (domainLanguage spec)
   testResults <- analyseTests ast (testAnalysisType spec)
   return $ AnalysisCompleted (analyseExpectations ast (expectations spec))
-                             (analyseSmells ast language (smellsSet spec))
+                             (analyseSmells ast domaingLang (smellsSet spec))
                              (analyseSignatures ast (signatureAnalysisType spec))
                              testResults
                              (analyzeIntermediateLanguage ast spec)
diff --git a/src/Language/Mulang/Analyzer/Analysis.hs b/src/Language/Mulang/Analyzer/Analysis.hs
index 87f5e26c9..d435a2ad7 100644
--- a/src/Language/Mulang/Analyzer/Analysis.hs
+++ b/src/Language/Mulang/Analyzer/Analysis.hs
@@ -1,20 +1,39 @@
 {-# LANGUAGE DeriveGeneric #-}
 
 module Language.Mulang.Analyzer.Analysis (
+  noSmells,
+  allSmells,
+  noSmellsBut,
+  allSmellsBut,
+
+  emptyDomainLanguage,
+  emptyAnalysisSpec,
+
+  emptyAnalysis,
+  domainLanguageAnalysis,
+  expectationsAnalysis,
+  smellsAnalysis,
+  signaturesAnalysis,
+  testsAnalysis,
+
+  emptyCompletedAnalysisResult,
+
   Expectation(..),
 
   Analysis(..),
   AnalysisSpec(..),
-  SmellsSet(..),
-  DomainLanguage(..),
+  AutocorrectionRules,
   CaseStyle(..),
-  Smell,
-  SignatureAnalysisType(..),
-  TestAnalysisType(..),
-  InterpreterOptions(..),
-  SignatureStyle(..),
+  DomainLanguage(..),
   Fragment(..),
+  Inspection,
+  InterpreterOptions(..),
   Language(..),
+  SignatureAnalysisType(..),
+  SignatureStyle(..),
+  Smell,
+  SmellsSet(..),
+  TestAnalysisType(..),
 
   AnalysisResult(..),
   ExpectationResult(..)) where
@@ -24,6 +43,7 @@ import GHC.Generics
 import Language.Mulang.Ast
 import Language.Mulang.Builder (NormalizationOptions)
 import Language.Mulang.Interpreter.Runner (TestResult)
+import Data.Map.Strict (Map)
 
 ---
 -- Common structures
@@ -31,6 +51,7 @@ import Language.Mulang.Interpreter.Runner (TestResult)
 
 type Smell = String
 type Inspection = String
+type AutocorrectionRules = Map Inspection Inspection
 
 data Expectation = Expectation {
   binding :: String,
@@ -52,7 +73,9 @@ data AnalysisSpec = AnalysisSpec {
   signatureAnalysisType :: Maybe SignatureAnalysisType,
   testAnalysisType :: Maybe TestAnalysisType,
   domainLanguage :: Maybe DomainLanguage,
-  includeIntermediateLanguage :: Maybe Bool
+  includeIntermediateLanguage :: Maybe Bool,
+  originalLanguage :: Maybe Language,
+  autocorrectionRules :: Maybe AutocorrectionRules
 } deriving (Show, Eq, Generic)
 
 data DomainLanguage = DomainLanguage {
@@ -108,7 +131,10 @@ data Language
   |  Haskell
   |  Python
   |  Python2
-  |  Python3 deriving (Show, Eq, Generic)
+  |  Python3
+  |  Ruby
+  |  Php
+  deriving (Show, Eq, Generic)
 
 --
 -- Analysis Output structures
@@ -128,4 +154,45 @@ data ExpectationResult = ExpectationResult {
   result :: Bool
 } deriving (Show, Eq, Generic)
 
+--
+-- Builder functions
+--
+
+noSmells :: Maybe SmellsSet
+noSmells = Just $ NoSmells Nothing
+
+noSmellsBut :: [Smell] -> Maybe SmellsSet
+noSmellsBut = Just . NoSmells . Just
+
+allSmells :: Maybe SmellsSet
+allSmells = Just $ AllSmells Nothing
+
+allSmellsBut :: [Smell] -> Maybe SmellsSet
+allSmellsBut = Just . AllSmells . Just
+
+emptyAnalysisSpec :: AnalysisSpec
+emptyAnalysisSpec = AnalysisSpec Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
+
+emptyAnalysis :: Fragment -> Analysis
+emptyAnalysis code = Analysis code emptyAnalysisSpec
+
+domainLanguageAnalysis :: Fragment -> DomainLanguage -> Analysis
+domainLanguageAnalysis code domainLanguage = Analysis code (emptyAnalysisSpec { domainLanguage = Just domainLanguage, smellsSet = allSmells })
+
+expectationsAnalysis :: Fragment -> [Expectation] -> Analysis
+expectationsAnalysis code es = Analysis code (emptyAnalysisSpec { expectations = Just es })
+
+smellsAnalysis :: Fragment -> Maybe SmellsSet -> Analysis
+smellsAnalysis code set = Analysis code (emptyAnalysisSpec { smellsSet = set })
+
+signaturesAnalysis :: Fragment -> SignatureStyle -> Analysis
+signaturesAnalysis code style = Analysis code (emptyAnalysisSpec { signatureAnalysisType = Just (StyledSignatures style) })
+
+testsAnalysis :: Fragment -> TestAnalysisType -> Analysis
+testsAnalysis code testAnalysisType = Analysis code (emptyAnalysisSpec { testAnalysisType = Just testAnalysisType })
+
+emptyCompletedAnalysisResult :: AnalysisResult
+emptyCompletedAnalysisResult = AnalysisCompleted [] [] [] [] Nothing
 
+emptyDomainLanguage :: DomainLanguage
+emptyDomainLanguage = DomainLanguage Nothing Nothing Nothing Nothing
diff --git a/src/Language/Mulang/Analyzer/Analysis/Json.hs b/src/Language/Mulang/Analyzer/Analysis/Json.hs
index 5217329fc..3710e5aba 100644
--- a/src/Language/Mulang/Analyzer/Analysis/Json.hs
+++ b/src/Language/Mulang/Analyzer/Analysis/Json.hs
@@ -33,6 +33,7 @@ instance FromJSON Type
 instance FromJSON Assertion
 instance FromJSON TestAnalysisType
 instance FromJSON InterpreterOptions
+instance FromJSON Operator
 
 instance ToJSON AnalysisResult
 instance ToJSON ExpectationResult
@@ -48,3 +49,4 @@ instance ToJSON Type
 instance ToJSON Assertion
 instance ToJSON TestResult
 instance ToJSON TestStatus
+instance ToJSON Operator
diff --git a/src/Language/Mulang/Analyzer/Autocorrector.hs b/src/Language/Mulang/Analyzer/Autocorrector.hs
new file mode 100644
index 000000000..5ce998bb2
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/Autocorrector.hs
@@ -0,0 +1,132 @@
+module Language.Mulang.Analyzer.Autocorrector (autocorrect) where
+
+import           Language.Mulang.Analyzer.Analysis
+import           Language.Mulang.Analyzer.Synthesizer (generateOperatorEncodingRules, generateInspectionEncodingRules)
+
+import           Language.Mulang.Operators (Token, OperatorsTable, buildOperatorsTable)
+import           Language.Mulang.Operators.Haskell (haskellTokensTable)
+import           Language.Mulang.Operators.Ruby (rubyTokensTable)
+import           Language.Mulang.Operators.Java (javaTokensTable)
+import           Language.Mulang.Operators.Python (pythonTokensTable)
+
+import           Data.Maybe (fromMaybe, fromJust)
+import qualified Data.Map.Strict as Map
+
+
+-- | Computes a derived Analysis infering missing values from context
+--
+-- It performs the following corrections:
+--
+--  1. fills originalLanguage when it is not present but can be inferred from the code sample
+--  2. fills the autocorrectionRules when they are not present but can be inferred from the originalLanguage
+--  3. aguments the autocorrectionRules with operators-based rules when they can be inferred from the originalLanguage
+--  4. corrects the expectations' inspections using the autocorrectionRules
+--  5. fills the domainLanguage rules when it is not present but can be inferred from the originalLanguage
+--  6. fills the domainLanguage's caseStyle when it is not present but can be inferred from the originalLanguage
+autocorrect :: Analysis -> Analysis
+autocorrect (Analysis f s@(AnalysisSpec { originalLanguage = Just _ })) = Analysis f (autocorrectSpec s)
+autocorrect (Analysis f@(CodeSample { language = l } ) s)               = autocorrect (Analysis f s { originalLanguage = Just l }) -- (1)
+autocorrect a                                                           = a
+
+autocorrectSpec :: AnalysisSpec -> AnalysisSpec
+autocorrectSpec s = runFixes [rulesFix, rulesAgumentationFix, expectationsFix, emptyDomainLanguageFix, domainLanguageCaseStyleFix]
+  where
+    runFixes = foldl combine s . map ($ (justOriginalLanguage s))
+    combine s f | Just s' <- f s = s'
+                | otherwise = s
+
+-- Fixes
+
+type Fix = Language -> AnalysisSpec -> Maybe AnalysisSpec
+
+rulesFix :: Fix  -- (2)
+rulesFix l s = do
+  AnalysisSpec { autocorrectionRules = Nothing } <- Just s
+  return s { autocorrectionRules = Just (inferAutocorrectionRules l) }
+
+rulesAgumentationFix :: Fix -- (3)
+rulesAgumentationFix l s = do
+  AnalysisSpec { autocorrectionRules = Just rules } <- Just s
+  return s { autocorrectionRules = Just (augmentRules rules (inferOperatorsTable l)) }
+  where
+    augmentRules :: AutocorrectionRules -> OperatorsTable -> AutocorrectionRules
+    augmentRules rules tokens = Map.fromList (Map.toList rules ++ (concatMap generateOperatorEncodingRules . Map.toList) tokens)
+
+expectationsFix :: Fix -- (4)
+expectationsFix _ s = do
+  AnalysisSpec { expectations = Just es } <- Just s
+  return s { expectations = Just (map autocorrectExpectation es) }
+  where
+    autocorrectExpectation :: Expectation -> Expectation
+    autocorrectExpectation (Expectation b i) = Expectation b . fromMaybe i . Map.lookup i . justAutocorrectionRules $ s
+
+emptyDomainLanguageFix :: Fix  -- (5)
+emptyDomainLanguageFix _ s = do
+  AnalysisSpec { domainLanguage = Nothing } <- Just s
+  return s { domainLanguage = Just emptyDomainLanguage }
+
+domainLanguageCaseStyleFix :: Fix -- (6)
+domainLanguageCaseStyleFix l s = do
+  AnalysisSpec { domainLanguage = Just dl } <- Just s
+  DomainLanguage { caseStyle = Nothing } <- Just dl
+  return s { domainLanguage = Just (dl { caseStyle = Just (inferCaseStyle l) }) }
+
+-- Inferences
+
+type Inference a = Language -> a
+
+inferOperatorsTable :: Inference OperatorsTable
+inferOperatorsTable = buildOperatorsTable . table
+  where
+    table Haskell = haskellTokensTable
+    table Java    = javaTokensTable
+    table Ruby    = rubyTokensTable
+    table Python  = pythonTokensTable
+    table Python2 = pythonTokensTable
+    table Python3 = pythonTokensTable
+    table _       = Map.empty
+
+inferCaseStyle :: Inference CaseStyle
+inferCaseStyle Python  = RubyCase
+inferCaseStyle Python2 = RubyCase
+inferCaseStyle Python3 = RubyCase
+inferCaseStyle Ruby    = RubyCase
+inferCaseStyle _       = CamelCase
+
+inferAutocorrectionRules :: Inference AutocorrectionRules
+inferAutocorrectionRules = buildRules . rules
+  where
+    buildRules :: [(Token, Inspection)] -> AutocorrectionRules
+    buildRules = Map.fromList . concatMap generateInspectionEncodingRules
+
+    rules Haskell = [
+        ("type", "DeclaresTypeAlias"),
+        ("if", "UsesIf")
+      ]
+    rules Java = [
+        ("if", "UsesIf"),
+        ("class", "DeclaresClass"),
+        ("interface", "DeclaresInterface"),
+        ("for", "UsesForLoop")
+      ]
+    rules Ruby = [
+        ("if", "UsesIf"),
+        ("class", "DeclaresClass"),
+        ("def", "DeclaresComputation"),
+        ("for", "UsesForeach"),
+        ("include",  "Includes")
+      ]
+    rules Python = [
+        ("if", "UsesIf"),
+        ("class", "DeclaresClass"),
+        ("def", "DeclaresComputation"),
+        ("for", "UsesForeach")
+      ]
+    rules Python2 = rules Python
+    rules Python3 = rules Python
+    rules _ = []
+
+-- Misc
+
+justOriginalLanguage = fromJust . originalLanguage
+justAutocorrectionRules = fromJust . autocorrectionRules
diff --git a/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs b/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs
index 79a1acb99..e2a58be9a 100644
--- a/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs
+++ b/src/Language/Mulang/Analyzer/DomainLanguageCompiler.hs
@@ -1,5 +1,4 @@
 module Language.Mulang.Analyzer.DomainLanguageCompiler (
-  emptyDomainLanguage,
   compileDomainLanguage) where
 
 import           Data.Maybe (fromMaybe)
@@ -9,9 +8,6 @@ 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
diff --git a/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs b/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs
index f94c280ef..8a86e1e5d 100644
--- a/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs
+++ b/src/Language/Mulang/Analyzer/ExpectationsAnalyzer.hs
@@ -4,7 +4,7 @@ module Language.Mulang.Analyzer.ExpectationsAnalyzer (
 import Data.Maybe (fromMaybe)
 
 import Language.Mulang
-import Language.Mulang.Analyzer.Analysis (Expectation, ExpectationResult(..))
+import Language.Mulang.Analyzer.Analysis (Language, Expectation, ExpectationResult(..))
 import Language.Mulang.Analyzer.ExpectationsCompiler (compileExpectation)
 
 analyseExpectations :: Expression -> Maybe [Expectation] -> [ExpectationResult]
diff --git a/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs b/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs
index f09fc75ef..c5020da25 100644
--- a/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs
+++ b/src/Language/Mulang/Analyzer/ExpectationsCompiler.hs
@@ -1,8 +1,11 @@
+{-# LANGUAGE ViewPatterns #-}
+
 module Language.Mulang.Analyzer.ExpectationsCompiler(
   compileExpectation) where
 
 import Language.Mulang
 import Language.Mulang.Analyzer.Analysis (Expectation(..))
+import Language.Mulang.Analyzer.Synthesizer (decodeUsageInspection, decodeDeclarationInspection)
 
 import Data.Maybe (fromMaybe)
 import Data.List.Split (splitOn)
@@ -35,12 +38,16 @@ compileNegator ("Not":_) = negative
 compileNegator _         = id
 
 compileBaseInspection :: PredicateModifier -> [String] -> Maybe ContextualizedInspection
-compileBaseInspection p ("Not":parts)                 = compileBaseInspection p parts
-compileBaseInspection p [verb]                        = compileBaseInspection p [verb, "*"]
-compileBaseInspection p [verb, object]                = compileBaseInspection p [verb, object, "With"]
-compileBaseInspection p (verb:"With":args)            = compileBaseInspection p (verb:"*":"With":args)
-compileBaseInspection p (verb:object:"With":args)     = fmap ($ (compileObject p object)) (compileInspectionPrimitive (verb:args))
-compileBaseInspection _ _                             = Nothing
+compileBaseInspection p ("Not":parts)               = compileBaseInspection p parts
+compileBaseInspection p parts                       = compileAffirmativeInspection p parts
+
+compileAffirmativeInspection :: PredicateModifier -> [String] -> Maybe ContextualizedInspection
+compileAffirmativeInspection p [verb]                        = compileAffirmativeInspection p [verb, "*"]
+compileAffirmativeInspection p [verb, object]                = compileAffirmativeInspection p [verb, object, "With"]
+compileAffirmativeInspection p (verb:"With":args)            = compileAffirmativeInspection p (verb:"*":"With":args)
+compileAffirmativeInspection p (verb:object:"With":args)     = fmap ($ (compileObject p object)) (compileInspectionPrimitive (verb:args))
+compileAffirmativeInspection _ _                             = Nothing
+
 
 compileObject :: PredicateModifier -> String -> IdentifierPredicate
 compileObject p "*"        = p $ anyone
@@ -89,12 +96,13 @@ compileInspectionPrimitive = f
   f ["Instantiates"]                   = bound instantiates
   f ["Raises"]                         = bound raises
   f ["Rescues"]                        = bound rescues
+  f ["Returns", value]                 = plain (returnsMatching (with value))
   f ["TypesAs"]                        = bound typesAs
   f ["TypesParameterAs"]               = bound typesParameterAs
   f ["TypesReturnAs"]                  = bound typesReturnAs
-  f ["Returns", value]                 = plain (returnsMatching (with value))
   f ["Uses"]                           = bound uses
   f ["UsesAnonymousVariable"]          = plain usesAnonymousVariable
+  f ["UsesBooleanLogic"]               = plain usesBooleanLogic
   f ["UsesComposition"]                = plain usesComposition
   f ["UsesComprehension"]              = f ["UsesForComprehension"]
   f ["UsesConditional"]                = plain usesConditional
@@ -117,6 +125,7 @@ compileInspectionPrimitive = f
   f ["UsesNot"]                        = plain usesNot
   f ["UsesObjectComposition"]          = plain usesObjectComposition
   f ["UsesPatternMatching"]            = plain usesPatternMatching
+  f ["UsesPrint"]                      = plain usesPrint
   f ["UsesRepeat"]                     = plain usesRepeat
   f ["UsesStaticMethodOverload"]       = plain usesStaticMethodOverload
   f ["UsesStaticPolymorphism"]         = contextualized usesStaticPolymorphism'
@@ -125,7 +134,13 @@ compileInspectionPrimitive = f
   f ["UsesType"]                       = bound usesType
   f ["UsesWhile"]                      = plain usesWhile
   f ["UsesYield"]                      = plain usesYield
-  f _                                = Nothing
+  f [primitiveUsage -> Just p]         = plain (usesPrimitive p)
+  f [primitiveDeclaration -> Just p]   = plain (declaresPrimitive p)
+  f _                                  = Nothing
+
+  primitiveUsage = decodeUsageInspection
+  primitiveDeclaration = decodeDeclarationInspection
+
 
   contextualized :: ContextualizedInspection -> Maybe ContextualizedBoundInspection
   contextualized = Just . contextualizedBind
diff --git a/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs b/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs
index 4f0769aad..3c444eb3d 100644
--- a/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs
+++ b/src/Language/Mulang/Analyzer/SmellsAnalyzer.hs
@@ -4,7 +4,7 @@ module Language.Mulang.Analyzer.SmellsAnalyzer (
 import Language.Mulang
 import Language.Mulang.Inspector.Generic.Smell
 import Language.Mulang.DomainLanguage
-import Language.Mulang.Analyzer.Analysis hiding (DomainLanguage)
+import Language.Mulang.Analyzer.Analysis hiding (DomainLanguage, Inspection, allSmells)
 import Data.List ((\\))
 import Data.Maybe (fromMaybe)
 
@@ -31,6 +31,7 @@ allSmells = [
   "HasMisspelledIdentifiers",
   "HasRedundantBooleanComparison",
   "HasRedundantGuards",
+  "ShouldUseOtherwise",
   "HasRedundantIf",
   "HasRedundantLambda",
   "HasRedundantLocalVariableReturn",
@@ -61,6 +62,7 @@ detectionFor "HasMisspelledBindings"           = withLanguage hasMisspelledIdent
 detectionFor "HasMisspelledIdentifiers"        = withLanguage hasMisspelledIdentifiers
 detectionFor "HasRedundantBooleanComparison"   = simple hasRedundantBooleanComparison
 detectionFor "HasRedundantGuards"              = simple hasRedundantGuards
+detectionFor "ShouldUseOtherwise"              = simple shouldUseOtherwise
 detectionFor "HasRedundantIf"                  = simple hasRedundantIf
 detectionFor "HasRedundantLambda"              = simple hasRedundantLambda
 detectionFor "HasRedundantLocalVariableReturn" = simple hasRedundantLocalVariableReturn
diff --git a/src/Language/Mulang/Analyzer/Synthesizer.hs b/src/Language/Mulang/Analyzer/Synthesizer.hs
new file mode 100644
index 000000000..784a36a5e
--- /dev/null
+++ b/src/Language/Mulang/Analyzer/Synthesizer.hs
@@ -0,0 +1,60 @@
+-- Module por synthesizing inspections
+-- from tokens, keywords and operators
+module Language.Mulang.Analyzer.Synthesizer (
+  encodeUsageInspection,
+  encodeDeclarationInspection,
+  decodeUsageInspection,
+  decodeDeclarationInspection,
+  generateInspectionEncodingRules,
+  generateOperatorEncodingRules
+) where
+
+import           Language.Mulang.Analyzer.Analysis (Inspection)
+
+import           Language.Mulang.Operators (Token)
+import           Language.Mulang.Ast (Operator)
+
+import           Control.Monad ((>=>))
+
+import           Text.Read (readMaybe)
+import           Data.List (stripPrefix)
+
+type Encoder a = a -> Inspection
+type Decoder a = Inspection -> Maybe a
+
+type EncodingRuleGenerator a b = (a, b) -> [(Inspection, Inspection)]
+
+-- converts an operator into an inspection
+encodeUsageInspection :: Encoder Operator
+encodeUsageInspection = encodeInspection "Uses"
+
+encodeDeclarationInspection :: Encoder Operator
+encodeDeclarationInspection = encodeInspection "Declares"
+
+encodeInspection :: String -> Encoder Operator
+encodeInspection prefix = (prefix ++) . show
+
+-- extract an operator from an inspection
+
+decodeUsageInspection :: Decoder Operator
+decodeUsageInspection = decodeInspection "Uses"
+
+decodeDeclarationInspection :: Decoder Operator
+decodeDeclarationInspection = decodeInspection "Declares"
+
+decodeInspection :: String -> Decoder Operator
+decodeInspection prefix = stripPrefix prefix >=> readMaybe
+
+generateInspectionEncodingRules :: EncodingRuleGenerator Token Inspection
+generateInspectionEncodingRules = generateEncodingRules id id
+
+generateOperatorEncodingRules :: EncodingRuleGenerator Token Operator
+generateOperatorEncodingRules = generateEncodingRules encodeUsageInspection encodeDeclarationInspection
+
+generateEncodingRules :: Encoder a -> Encoder a -> EncodingRuleGenerator Token a
+generateEncodingRules usageEncoder declarationEncoder (k, v) = concatMap generateEncodingNegationRules baseEncodings
+  where
+    baseEncodings = [("Uses:" ++ k, usageEncoder v), ("Declares:" ++ k, declarationEncoder v)]
+
+    generateEncodingNegationRules :: EncodingRuleGenerator Inspection Inspection
+    generateEncodingNegationRules (k, v) = [(k, v), ("Not:" ++ k, "Not:" ++ v)]
diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs
index aa554177b..3e2f3ae23 100644
--- a/src/Language/Mulang/Ast.hs
+++ b/src/Language/Mulang/Ast.hs
@@ -24,6 +24,7 @@ module Language.Mulang.Ast (
     Pattern(..),
     Identifier,
     SubroutineBody,
+    Operator(..),
     debug,
     debugType,
     debugPattern,
@@ -32,6 +33,7 @@ module Language.Mulang.Ast (
     pattern SimpleProcedure,
     pattern SimpleMethod,
     pattern SimpleSend,
+    pattern PrimitiveSend,
     pattern SubroutineSignature,
     pattern VariableSignature,
     pattern ModuleSignature,
@@ -104,8 +106,7 @@ data Expression
     | Procedure Identifier SubroutineBody
     -- ^ Imperative programming procedure declaration. It is composed by a name and one or more equations
     | Method Identifier SubroutineBody
-    | EqualMethod SubroutineBody
-    | HashMethod SubroutineBody
+    | PrimitiveMethod Operator SubroutineBody
     | Variable Identifier Expression
     | Assignment Identifier Expression
     | Attribute Identifier Expression
@@ -135,6 +136,9 @@ data Expression
     -- ^ Logic programming universal cuantification
     | Reference Identifier
     -- ^ Generic variable
+    | Primitive Operator
+    -- ^ Reference to special, low level, universal operations like logical operaions and math, that may or may not be primitives
+    -- in the original language
     | 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]
@@ -168,8 +172,6 @@ data Expression
     -- ^ Generic sequence of statements
     | Other (Maybe Code) (Maybe Expression)
     -- ^ Unrecognized expression, with optional description and body
-    | Equal
-    | NotEqual
     | Self
     | None
     -- ^ Generic value indicating an absent expression, such as when there is no finally in a try or default in a switch or js' undefined
@@ -197,6 +199,31 @@ data Expression
     -- ^ Generic assertion expression such as assert, expect, etc. The first parameter indicates whether the assertion is negated or not
   deriving (Eq, Show, Read, Generic, Ord)
 
+data Operator
+    = Equal
+    -- equal operator
+    | NotEqual
+    -- ^ distinct operator
+    | Negation
+    -- ^ not operator
+    | And
+    -- ^ and operator
+    | Or
+    -- ^ or operator
+    | Hash
+    -- ^ hashcode operator
+    | GreatherOrEqualThan
+    | GreatherThan
+    | LessOrEqualThan
+    | LessThan
+    | Otherwise
+    -- ^ guard's otherwise operator
+    | ForwardComposition
+    -- (f >> g)(x) = (g . f)(x) = g(f(x)) operator
+    | BackwardComposition
+    -- (f << g)(x) = (f . g)(x) = f(g(x)) operator
+  deriving (Eq, Show, Read, Generic, Ord)
+
 data Assertion
     = Equality Expression Expression
     -- ^ assert equality between two expressions. e.g.: assert.equals(succ(3), 4)
@@ -254,6 +281,7 @@ pattern ModuleSignature name cs            = TypeSignature name (ConstrainedType
 pattern SimpleEquation params body = Equation params (UnguardedBody body)
 
 pattern SimpleSend receptor selector args = Send receptor (Reference selector) args
+pattern PrimitiveSend receptor selector args = Send receptor (Primitive selector) args
 
 pattern SimpleFunction name params body  = Function  name [SimpleEquation params body]
 pattern SimpleProcedure name params body = Procedure name [SimpleEquation params body]
diff --git a/src/Language/Mulang/Generator.hs b/src/Language/Mulang/Generator.hs
index c7bd60f14..769e112bc 100644
--- a/src/Language/Mulang/Generator.hs
+++ b/src/Language/Mulang/Generator.hs
@@ -80,6 +80,7 @@ expressions expr = expr : concatMap expressions (subExpressions expr)
     subExpressions (Not e)                 = [e]
     subExpressions (Object _ v)            = [v]
     subExpressions (Other _ (Just e))      = [e]
+    subExpressions (Print v)               = [v]
     subExpressions (Repeat e1 e2)          = [e1, e2]
     subExpressions (Return v)              = [v]
     subExpressions (Sequence es)           = es
diff --git a/src/Language/Mulang/Inspector/Functional.hs b/src/Language/Mulang/Inspector/Functional.hs
index 6878568e8..8090e8846 100644
--- a/src/Language/Mulang/Inspector/Functional.hs
+++ b/src/Language/Mulang/Inspector/Functional.hs
@@ -20,7 +20,8 @@ usesConditional = alternative usesIf usesGuards
 -- in its definition
 usesComposition :: Inspection
 usesComposition = containsExpression f
-  where f (Reference ".") = True
+  where f (Primitive BackwardComposition) = True
+        f (Primitive ForwardComposition)  = True
         f _ = False
 
 -- | Inspection that tells whether an expression uses pattern matching
diff --git a/src/Language/Mulang/Inspector/Generic.hs b/src/Language/Mulang/Inspector/Generic.hs
index 121e26b89..787255e36 100644
--- a/src/Language/Mulang/Inspector/Generic.hs
+++ b/src/Language/Mulang/Inspector/Generic.hs
@@ -19,10 +19,13 @@ module Language.Mulang.Inspector.Generic (
   returnsMatching,
   uses,
   usesAnonymousVariable,
+  usesBooleanLogic,
   usesExceptionHandling,
   usesExceptions,
   usesFor,
   usesIf,
+  usesPrimitive,
+  usesPrint,
   usesYield) where
 
 import Language.Mulang.Ast
@@ -55,6 +58,11 @@ uses :: BoundInspection
 uses p = containsExpression f
   where f = any p . referencedIdentifiers
 
+usesPrimitive :: Operator -> Inspection
+usesPrimitive operator = containsExpression f
+  where f (Primitive o) = operator == o
+        f _             = False
+
 calls :: BoundInspection
 calls = unmatching callsMatching
 
@@ -85,6 +93,11 @@ usesYield = containsExpression f
   where f (Yield _) = True
         f _         = False
 
+usesPrint :: Inspection
+usesPrint = containsExpression f
+  where f (Print _) = True
+        f _         = False
+
 usesFor :: Inspection
 usesFor = containsExpression f
   where f (For _ _) = True
@@ -143,6 +156,13 @@ declaresComputationWithArity' arityPredicate = containsBoundDeclaration f
 
         argsHaveArity = arityPredicate.length
 
+usesBooleanLogic :: Inspection
+usesBooleanLogic = containsExpression f
+  where f (Primitive Negation) = True
+        f (Primitive And)      = True
+        f (Primitive Or)       = True
+        f _                    = False
+
 raises :: BoundInspection
 raises predicate = containsExpression f
   where f (Raise (New (Reference n) _))         = predicate n
diff --git a/src/Language/Mulang/Inspector/Generic/Duplication.hs b/src/Language/Mulang/Inspector/Generic/Duplication.hs
index 5a106523e..65d5ee297 100644
--- a/src/Language/Mulang/Inspector/Generic/Duplication.hs
+++ b/src/Language/Mulang/Inspector/Generic/Duplication.hs
@@ -18,7 +18,7 @@ isLightweight (Reference _)             = True
 isLightweight Self                      = True
 isLightweight None                      = True
 isLightweight MuNil                     = True
-isLightweight Equal                     = True
+isLightweight (Primitive _)             = True
 isLightweight (Application _ es)        = not $ any isApplication es
 isLightweight (Return e)                = isLightweight e
 isLightweight (Assignment _ e)  = isLightweight e
diff --git a/src/Language/Mulang/Inspector/Generic/Smell.hs b/src/Language/Mulang/Inspector/Generic/Smell.hs
index 62a20a770..0ad6c5495 100644
--- a/src/Language/Mulang/Inspector/Generic/Smell.hs
+++ b/src/Language/Mulang/Inspector/Generic/Smell.hs
@@ -1,7 +1,10 @@
+{-# LANGUAGE ViewPatterns #-}
+
 module Language.Mulang.Inspector.Generic.Smell (
   hasRedundantBooleanComparison,
   hasRedundantIf,
   hasRedundantGuards,
+  shouldUseOtherwise,
   hasRedundantLambda,
   hasRedundantParameter,
   hasRedundantLocalVariableReturn,
@@ -22,7 +25,7 @@ import Language.Mulang.Ast
 import Language.Mulang.Generator (identifierReferences)
 import Language.Mulang.Inspector.Primitive
 
--- | Inspection that tells whether an identifier has expressions like 'x == True'
+-- | Inspection that tells whether an expression has expressions like 'x == True'
 hasRedundantBooleanComparison :: Inspection
 hasRedundantBooleanComparison = compares isBooleanLiteral
 
@@ -44,16 +47,16 @@ isLongCode = containsExpression f
 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 _                          = []
+comparisonOperands (Call (Primitive Equal)    [a1, a2])   = [a1, a2]
+comparisonOperands (Call (Primitive NotEqual) [a1, a2])   = [a1, a2]
+comparisonOperands _                                      = []
 
 returnsNil :: Inspection
 returnsNil = containsExpression f
   where f (Return MuNil) = True
         f _              = False
 
--- | Inspection that tells whether an identifier has an if expression where both branches return
+-- | Inspection that tells whether an expression has an if expression where both branches return
 -- boolean literals
 hasRedundantIf :: Inspection
 hasRedundantIf = containsExpression f
@@ -64,24 +67,28 @@ hasRedundantIf = containsExpression f
         f (If _ x y)                                 = all isBooleanLiteral [x, y]
         f _                                          = False
 
--- | Inspection that tells whether an identifier has guards where both branches return
+-- | Inspection that tells whether an expression 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]
+            (Primitive Otherwise, Return y)]) = all isBooleanLiteral [x, y]
         f _ = False
 
+-- | Inspection that tells whether an expression has guards with a hardcoded false instead of an otherwise
+shouldUseOtherwise :: Inspection
+shouldUseOtherwise = containsBody f
+  where f (GuardedBody (last -> (MuTrue, _))) = True
+        f _                                   = False
 
--- | Inspection that tells whether an identifier has lambda expressions like '\x -> g x'
+-- | Inspection that tells whether an expression 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
+-- | Inspection that tells whether an expression has parameters that
 -- can be avoided using point-free
 hasRedundantParameter :: Inspection
 hasRedundantParameter = containsExpression f
@@ -114,7 +121,6 @@ discardsExceptions = containsExpression f
         f (Try _ [(_, Print _)] _) = True
         f _                        = False
 
-
 doesConsolePrint :: Inspection
 doesConsolePrint = containsExpression f
   where f (Print _) = True
@@ -136,14 +142,14 @@ hasTooManyMethods = containsExpression f
 overridesEqualOrHashButNotBoth :: Inspection
 overridesEqualOrHashButNotBoth = containsExpression f
   where f (Sequence expressions) = (any isEqual expressions) /= (any isHash expressions)
-        f (Class _ _ (EqualMethod _)) = True
-        f (Class _ _ (HashMethod _)) = True
+        f (Class _ _ (PrimitiveMethod Equal _)) = True
+        f (Class _ _ (PrimitiveMethod Hash _)) = True
         f _ = False
 
-        isEqual (EqualMethod _) = True
+        isEqual (PrimitiveMethod Equal _) = True
         isEqual _ = False
 
-        isHash (HashMethod _) = True
+        isHash (PrimitiveMethod Hash _) = True
         isHash _ = False
 
 hasEmptyIfBranches :: Inspection
@@ -153,10 +159,10 @@ hasEmptyIfBranches = containsExpression f
 
 hasUnreachableCode :: Inspection
 hasUnreachableCode = containsExpression f
-  where f subroutine@(Subroutine _ equations) = any equationMatchesAnyValue . init $ equations 
-        f _                                   = False
-        
-        equationMatchesAnyValue (Equation patterns body) = all patternMatchesAnyValue patterns && bodyMatchesAnyValue body       
+  where f (Subroutine _ equations) = any equationMatchesAnyValue . init $ equations
+        f _                        = False
+
+        equationMatchesAnyValue (Equation patterns body) = all patternMatchesAnyValue patterns && bodyMatchesAnyValue body
 
         patternMatchesAnyValue WildcardPattern     = True
         patternMatchesAnyValue (VariablePattern _) = True
@@ -166,5 +172,5 @@ hasUnreachableCode = containsExpression f
         bodyMatchesAnyValue (GuardedBody guards) = any (isTruthy . fst) guards
 
         isTruthy (MuBool True)           = True
-        isTruthy (Reference "otherwise") = True
+        isTruthy (Primitive Otherwise)   = True
         isTruthy _                       = False
diff --git a/src/Language/Mulang/Inspector/Literal.hs b/src/Language/Mulang/Inspector/Literal.hs
index 8c787f0fa..fdf152a8e 100644
--- a/src/Language/Mulang/Inspector/Literal.hs
+++ b/src/Language/Mulang/Inspector/Literal.hs
@@ -1,7 +1,7 @@
 module Language.Mulang.Inspector.Literal (isLiteral) where
 
 import Language.Mulang.Ast
-import Language.Mulang.Inspector.Primitive (containsExpression, Inspection)
+import Language.Mulang.Inspector.Primitive (Inspection)
 
 import Text.Read (readMaybe)
 
diff --git a/src/Language/Mulang/Inspector/ObjectOriented.hs b/src/Language/Mulang/Inspector/ObjectOriented.hs
index 0cc348521..3263ff6d7 100644
--- a/src/Language/Mulang/Inspector/ObjectOriented.hs
+++ b/src/Language/Mulang/Inspector/ObjectOriented.hs
@@ -11,7 +11,8 @@ module Language.Mulang.Inspector.ObjectOriented (
   declaresInterface,
   declaresEnumeration,
   declaresAttribute,
-  declaresMethod)  where
+  declaresMethod,
+  declaresPrimitive)  where
 
 import Language.Mulang.Ast
 import Language.Mulang.Identifier
@@ -77,3 +78,8 @@ declaresMethod =  containsBoundDeclaration f
   where f (Method _ _) = True
         f _            = False
 
+-- primitive can only be declared as methods
+declaresPrimitive :: Operator -> Inspection
+declaresPrimitive operator = containsExpression f
+  where f (PrimitiveMethod o _) = operator == o
+        f _                     = False
diff --git a/src/Language/Mulang/Interpreter.hs b/src/Language/Mulang/Interpreter.hs
index b854e2523..0c71c9eea 100644
--- a/src/Language/Mulang/Interpreter.hs
+++ b/src/Language/Mulang/Interpreter.hs
@@ -116,7 +116,7 @@ evalExpr (Mu.Assert negated (Mu.Equality expected actual)) =
           | muEquals v1 v2 /= negated = return nullRef
           | otherwise                 = raiseString $ "Expected " ++ show v1 ++ " but got: " ++ show v2
 
-evalExpr (Mu.Application (Mu.Reference ">=") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.GreatherOrEqualThan) expressions) =
   evalExpressionsWith expressions f
   where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 >= n2
 
@@ -125,24 +125,24 @@ evalExpr (Mu.Application (Mu.Reference "%") expressions) =
   where f [MuNumber n1, MuNumber n2] = createReference $ MuNumber $ n1 `mod'` n2
         f params                     = error $ "Bad parameters, expected two numbers but got " ++ show params
 
-evalExpr (Mu.Application (Mu.Reference ">") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.GreatherThan) expressions) =
   evalExpressionsWith expressions f
   where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 > n2
         f params                     = error $ "Bad parameters, expected two bools but got " ++ show params
 
 -- TODO make this evaluation non strict on both parameters
-evalExpr (Mu.Application (Mu.Reference "||") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.Or) expressions) =
   evalExpressionsWith expressions f
   where f [MuBool b1, MuBool b2] = createReference $ MuBool $ b1 || b2
         f params                 = error $ "Bad parameters, expected two bools but got " ++ show params
 
 -- TODO make this evaluation non strict on both parameters
-evalExpr (Mu.Application (Mu.Reference "&&") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.And) expressions) =
   evalExpressionsWith expressions f
   where f [MuBool b1, MuBool b2] = createReference $ MuBool $ b1 && b2
         f params                 = error $ "Bad parameters, expected two bools but got " ++ show params
 
-evalExpr (Mu.Application (Mu.Reference "!") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.Negation) expressions) =
   evalExpressionsWith expressions f
   where f [MuBool b] = createReference $ MuBool $ not b
         f params     = error $ "Bad parameters, expected one bool but got " ++ show params
@@ -151,20 +151,20 @@ evalExpr (Mu.Application (Mu.Reference "*") expressions) =
   evalExpressionsWith expressions f
   where f [MuNumber n1, MuNumber n2] = createReference $ MuNumber $ n1 * n2
 
-evalExpr (Mu.Application Mu.Equal expressions) = do
+evalExpr (Mu.Application (Mu.Primitive Mu.Equal) expressions) = do
   params <- mapM evalExpr expressions
   let [r1, r2] = params
   muValuesEqual r1 r2
 
-evalExpr (Mu.Application Mu.NotEqual expressions) = do
-  evalExpr $ Mu.Application (Mu.Reference "!") [Mu.Application Mu.Equal expressions]
+evalExpr (Mu.Application (Mu.Primitive Mu.NotEqual) expressions) = do
+  evalExpr $ Mu.Application (Mu.Primitive Mu.Negation) [Mu.Application (Mu.Primitive Mu.Equal) expressions]
 
-evalExpr (Mu.Application (Mu.Reference "<=") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.LessOrEqualThan) expressions) =
   evalExpressionsWith expressions f
   where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 <= n2
         f params                     = raiseString $ "Bad parameters, expected two numbers but got " ++ show params
 
-evalExpr (Mu.Application (Mu.Reference "<") expressions) =
+evalExpr (Mu.Application (Mu.Primitive Mu.LessThan) expressions) =
   evalExpressionsWith expressions f
   where f [MuNumber n1, MuNumber n2] = createReference $ MuBool $ n1 < n2
         f params                     = raiseString $ "Bad parameters, expected two numbers but got " ++ show params
@@ -350,9 +350,6 @@ dereference ref = do
 updateGlobalObjects f context =
   context { globalObjects = f $ globalObjects context }
 
-updateLocalVariables f context =
-  context { scopes = f $ scopes context }
-
 incrementRef (Reference n) = Reference $ n + 1
 
 createReference :: Value -> Executable Reference
diff --git a/src/Language/Mulang/Operators.hs b/src/Language/Mulang/Operators.hs
new file mode 100644
index 000000000..23a483eb4
--- /dev/null
+++ b/src/Language/Mulang/Operators.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE TupleSections #-}
+
+module Language.Mulang.Operators (
+  buildTokensTable,
+  buildOperatorsTable,
+  parseOperator,
+  unparseOperator,
+  Token,
+  TokensTable,
+  OperatorsTable) where
+
+import           Language.Mulang.Ast (Operator (..))
+
+import           Data.Map.Strict (Map)
+import qualified Data.Map.Strict as Map
+import           Data.Tuple (swap)
+
+
+type Token = String
+
+type TokensTable = Map Operator [Token]
+type OperatorsTable = Map Token Operator
+
+-- C-style tokens
+defaultTokensTable :: TokensTable
+defaultTokensTable =
+  Map.fromList [
+    (Equal, ["=="]),
+    (NotEqual, ["!="]),
+    (Negation, ["!"]),
+    (And, ["&&"]),
+    (Or, ["||"]),
+    (GreatherOrEqualThan, [">="]),
+    (GreatherThan, [">"]),
+    (LessOrEqualThan, ["<="]),
+    (LessThan, ["<"])
+  ]
+
+buildTokensTable :: [(Operator, [Token])] -> TokensTable
+buildTokensTable = flip Map.union defaultTokensTable  . Map.fromList
+
+buildOperatorsTable :: TokensTable -> OperatorsTable
+buildOperatorsTable =  Map.fromList . concatMap (fill . swap) . Map.toList
+  where
+    fill (xs, t) = map (,t) xs
+
+unparseOperator :: Operator -> TokensTable -> Maybe Token
+unparseOperator target = fmap head . (Map.lookup target)
+
+parseOperator :: Token -> TokensTable -> Maybe Operator
+parseOperator target =  (Map.lookup target) . buildOperatorsTable
+
+
+
diff --git a/src/Language/Mulang/Operators/Haskell.hs b/src/Language/Mulang/Operators/Haskell.hs
new file mode 100644
index 000000000..7b61bf667
--- /dev/null
+++ b/src/Language/Mulang/Operators/Haskell.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Operators.Haskell (haskellTokensTable) where
+import Language.Mulang.Operators (TokensTable, buildTokensTable)
+import Language.Mulang.Ast (Operator (..))
+
+haskellTokensTable :: TokensTable
+haskellTokensTable =
+  buildTokensTable [
+    (NotEqual, ["/="]),
+    (Negation, ["not"]),
+    (Otherwise, ["otherwise"]),
+    (BackwardComposition, ["."])
+  ]
diff --git a/src/Language/Mulang/Operators/Java.hs b/src/Language/Mulang/Operators/Java.hs
new file mode 100644
index 000000000..d83f40064
--- /dev/null
+++ b/src/Language/Mulang/Operators/Java.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Operators.Java (javaTokensTable) where
+import Language.Mulang.Operators (TokensTable, buildTokensTable)
+import Language.Mulang.Ast (Operator (..))
+
+javaTokensTable :: TokensTable
+javaTokensTable = buildTokensTable [(Hash, ["hashCode"])]
diff --git a/src/Language/Mulang/Operators/Python.hs b/src/Language/Mulang/Operators/Python.hs
new file mode 100644
index 000000000..7dab20307
--- /dev/null
+++ b/src/Language/Mulang/Operators/Python.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Operators.Python (pythonTokensTable) where
+import Language.Mulang.Operators (TokensTable, buildTokensTable)
+import Language.Mulang.Ast (Operator (..))
+
+pythonTokensTable :: TokensTable
+pythonTokensTable =
+  buildTokensTable [
+    (NotEqual, ["!=", "<>"]),
+    (Negation, ["not"]),
+    (And, ["and"]),
+    (Or, ["or"]),
+    (Hash, ["hash"])
+  ]
diff --git a/src/Language/Mulang/Operators/Ruby.hs b/src/Language/Mulang/Operators/Ruby.hs
new file mode 100644
index 000000000..7ba98bbe1
--- /dev/null
+++ b/src/Language/Mulang/Operators/Ruby.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Operators.Ruby (rubyTokensTable) where
+import Language.Mulang.Operators (TokensTable, buildTokensTable)
+import Language.Mulang.Ast (Operator (..))
+
+rubyTokensTable :: TokensTable
+rubyTokensTable =
+  buildTokensTable [
+    (And, ["&&", "and"]),
+    (Or, ["||", "or"]),
+    (Hash, ["hash"]),
+    (ForwardComposition, [">>"]),
+    (BackwardComposition, ["<<"])
+  ]
diff --git a/src/Language/Mulang/Parsers/Haskell.hs b/src/Language/Mulang/Parsers/Haskell.hs
index 839169420..bd429a656 100644
--- a/src/Language/Mulang/Parsers/Haskell.hs
+++ b/src/Language/Mulang/Parsers/Haskell.hs
@@ -1,6 +1,8 @@
 module Language.Mulang.Parsers.Haskell (hs, parseHaskell) where
 
 import Language.Mulang.Ast
+import Language.Mulang.Operators.Haskell (haskellTokensTable)
+import Language.Mulang.Operators (parseOperator)
 import Language.Mulang.Builder (compact, normalizeWith, defaultNormalizationOptions, NormalizationOptions(..), SequenceSortMode(..))
 import Language.Mulang.Parsers
 
@@ -106,8 +108,7 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls)
     muLit (HsDoublePrim  v) = MuNumber . fromRational $ v
 
     muVar :: String -> Expression
-    muVar "==" = Equal
-    muVar "/=" = NotEqual
+    muVar v | (Just op) <- parseOperator v haskellTokensTable = Primitive op
     muVar v = Reference v
 
     muName :: HsName -> String
diff --git a/src/Language/Mulang/Parsers/Java.hs b/src/Language/Mulang/Parsers/Java.hs
index ec6725a3f..5be3d6277 100644
--- a/src/Language/Mulang/Parsers/Java.hs
+++ b/src/Language/Mulang/Parsers/Java.hs
@@ -3,8 +3,8 @@
 
 module Language.Mulang.Parsers.Java (java, parseJava) where
 
-import Language.Mulang.Ast hiding (While, Return, Equal, Lambda, Try, Switch, Assert)
-import qualified Language.Mulang.Ast as M (Expression(While, Return, Equal, Lambda, Try, Switch, Assert))
+import Language.Mulang.Ast hiding (Primitive, While, Return, Equal, Lambda, Try, Switch, Assert, Operator(..))
+import qualified Language.Mulang.Ast as M
 import Language.Mulang.Parsers
 import Language.Mulang.Builder (compact, compactMap, compactConcatMap, normalize)
 
@@ -55,19 +55,21 @@ muDecl (MemberDecl memberDecl) = muMemberDecl memberDecl
 muDecl (InitDecl _ block)      = [muBlock block]
 
 muMemberDecl :: MemberDecl -> [Expression]
-muMemberDecl (FieldDecl _ typ varDecls)                              = concatMap (variableToAttribute.muVarDecl typ) varDecls
-muMemberDecl (MethodDecl _ _ typ name params _ (MethodBody Nothing)) = return $ muMethodSignature name params typ
+muMemberDecl (FieldDecl _ typ varDecls)                                       = concatMap (variableToAttribute.muVarDecl typ) varDecls
+muMemberDecl (MethodDecl _ typeParams typ name params _ (MethodBody Nothing)) = return $ muMethodSignature name params typ typeParams
 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 _ _ returnType name params _ body)          = [ muMethodSignature name params returnType,
-                                                                         SimpleMethod (i name) (map muFormalParam params) (muMethodBody body)]
-muMemberDecl e@(ConstructorDecl _ _ _ _params _ _constructorBody)    = return . debug $ e
-muMemberDecl (MemberClassDecl decl)                                  = return $ muClassTypeDecl decl
-muMemberDecl (MemberInterfaceDecl decl)                              = return $ muInterfaceTypeDecl decl
-
-muMethodSignature name params returnType = SubroutineSignature (i name) (map muFormalParamType params) (muReturnType returnType) []
+                                                                              = return $ EntryPoint "main" (muMethodBody body)
+muMemberDecl (MethodDecl _ _ _ (Ident "equals") params _ body)                = return $ PrimitiveMethod M.Equal [SimpleEquation (map muFormalParam params) (muMethodBody body)]
+muMemberDecl (MethodDecl _ _ _ (Ident "hashCode") params _ body)              = return $ PrimitiveMethod M.Hash [SimpleEquation (map muFormalParam params) (muMethodBody body)]
+muMemberDecl (MethodDecl _ typeParams returnType name params _ body)          = [ muMethodSignature name params returnType typeParams,
+                                                                                  SimpleMethod (i name) (map muFormalParam params) (muMethodBody body)]
+muMemberDecl e@(ConstructorDecl _ _ _ _params _ _constructorBody)             = return . debug $ e
+muMemberDecl (MemberClassDecl decl)                                           = return $ muClassTypeDecl decl
+muMemberDecl (MemberInterfaceDecl decl)                                       = return $ muInterfaceTypeDecl decl
+
+muMethodSignature name params returnType typeParams = SubroutineSignature (i name) (map muFormalParamType params) (muReturnType returnType) (map muTypeParam typeParams)
+muTypeParam (TypeParam (Ident i) _) = i
+
 muEnumConstant (EnumConstant name _ _) = i name
 
 muFormalParam (FormalParam _ _ _ id)      = VariablePattern (v id)
@@ -109,7 +111,7 @@ muExp (Cond cond ifTrue ifFalse)        = If (muExp cond) (muExp ifTrue) (muExp
 muExp (ExpName name)                    = muName name
 muExp (Assign lhs EqualA exp)           = Assignment (muLhs lhs) (muExp exp)
 muExp (InstanceCreation _ clazz args _) = New (Reference $ r clazz) (map muExp args)
-muExp (PreNot exp)                      = SimpleSend (muExp exp) "!" []
+muExp (PreNot exp)                      = PrimitiveSend (muExp exp) M.Negation []
 muExp (Lambda params exp)               = M.Lambda (muLambdaParams params) (muLambdaExp exp)
 muExp (MethodRef _ message)             = M.Lambda [VariablePattern "it"] (SimpleSend (Reference "it") (i message) [])
 muExp e                                 = debug e
@@ -145,14 +147,16 @@ 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 LThan  = M.Primitive M.LessThan
+muOp LThanE = M.Primitive M.LessOrEqualThan
+muOp GThan  = M.Primitive M.GreatherThan
+muOp GThanE = M.Primitive M.GreatherOrEqualThan
+muOp And    = M.Primitive M.And
+muOp Or     = M.Primitive M.Or
+muOp CAnd   = M.Primitive M.And
+muOp COr    = M.Primitive M.Or
+muOp Equal  = M.Primitive M.Equal
+muOp NotEq  = M.Primitive M.NotEqual
 muOp e      = debug e
 
 muVarDecl typ (VarDecl id init) = [
@@ -169,13 +173,15 @@ muMethodInvocation (MethodCall (Name [Ident "System", Ident "out", Ident "print"
 muMethodInvocation (MethodCall (Name [Ident "System", Ident "out", Ident "printf"]) (expr:_)) = Print (muExp expr)
 
 muMethodInvocation (MethodCall (Name [message]) args)           = muNormalizeReference $ SimpleSend Self (i message) (map muExp args)
-muMethodInvocation (MethodCall (Name receptorAndMessage) args)  =  SimpleSend (Reference  (ns . init $ receptorAndMessage)) (i . last $ receptorAndMessage) (map muExp args)
-muMethodInvocation (PrimaryMethodCall receptor _ selector args) =  SimpleSend (muExp receptor) (i selector) (map muExp args)
+muMethodInvocation (MethodCall (Name receptorAndMessage) args)  = muNormalizeReference $ SimpleSend (Reference  (ns . init $ receptorAndMessage)) (i . last $ receptorAndMessage) (map muExp args)
+muMethodInvocation (PrimaryMethodCall receptor _ selector args) = muNormalizeReference $ SimpleSend (muExp receptor) (i selector) (map muExp args)
 muMethodInvocation e = debug e
 
 muNormalizeReference (SimpleSend Self "assertTrue" [expression])         = M.Assert False $ Truth expression
 muNormalizeReference (SimpleSend Self "assertFalse" [expression])        = M.Assert True $ Truth expression
 muNormalizeReference (SimpleSend Self "assertEquals" [expected, actual]) = M.Assert False $ Equality expected actual
+muNormalizeReference (SimpleSend one  "equals" [other])                  = M.PrimitiveSend one M.Equal [other]
+muNormalizeReference (SimpleSend one  "hashCode" [other])                = M.PrimitiveSend one M.Hash [other]
 muNormalizeReference e = e
 
 muRefType (ClassRefType clazz) = r clazz
diff --git a/src/Language/Mulang/Parsers/JavaScript.hs b/src/Language/Mulang/Parsers/JavaScript.hs
index eb539328b..ca2e8a7f6 100644
--- a/src/Language/Mulang/Parsers/JavaScript.hs
+++ b/src/Language/Mulang/Parsers/JavaScript.hs
@@ -137,7 +137,7 @@ muJSExpression (JSMemberNew _ (JSIdentifier _ name) _ args _)       = New (Refer
 muJSExpression (JSMemberSquare receptor _ index _)                  = Send (muJSExpression receptor) (Reference "[]") [muJSExpression index]
 muJSExpression (JSNewExpression _ (JSIdentifier _ name))            = New (Reference name) []
 muJSExpression (JSObjectLiteral _ propertyList _)                   = MuObject (compactMap muJSObjectProperty . muJSCommaTrailingList $ propertyList)
-muJSExpression (JSUnaryExpression (JSUnaryOpNot _) e)               = Application (Reference "!") [muJSExpression e]
+muJSExpression (JSUnaryExpression (JSUnaryOpNot _) e)               = Application (Primitive Negation) [muJSExpression e]
 muJSExpression (JSUnaryExpression op (JSIdentifier _ name))         = Assignment name (muJSUnaryOp op name)
 muJSExpression (JSVarInitExpression (JSIdentifier _ name) initial)  = Variable name (muJSVarInitializer initial)
 muJSExpression e                                                    = debug e
@@ -146,26 +146,26 @@ removeQuotes = filter (flip notElem quoteMarks)
   where quoteMarks = "\"'"
 
 muJSBinOp:: JSBinOp -> Expression
-muJSBinOp (JSBinOpAnd _)        = Reference "&&"
-muJSBinOp (JSBinOpBitAnd _)     = Reference "&"
-muJSBinOp (JSBinOpBitOr _)      = Reference "|"
+muJSBinOp (JSBinOpAnd _)        = Primitive And
+muJSBinOp (JSBinOpBitAnd _)     = Primitive And
+muJSBinOp (JSBinOpBitOr _)      = Primitive Or
 muJSBinOp (JSBinOpBitXor _)     = Reference "^"
 muJSBinOp (JSBinOpDivide _)     = Reference "/"
-muJSBinOp (JSBinOpEq _)         = Equal
-muJSBinOp (JSBinOpGe _)         = Reference ">="
-muJSBinOp (JSBinOpGt _)         = Reference ">"
+muJSBinOp (JSBinOpEq _)         = Primitive Equal
+muJSBinOp (JSBinOpGe _)         = Primitive GreatherOrEqualThan
+muJSBinOp (JSBinOpGt _)         = Primitive GreatherThan
 muJSBinOp (JSBinOpInstanceOf _) = Reference "instanceof"
-muJSBinOp (JSBinOpLe _)         = Reference "<="
+muJSBinOp (JSBinOpLe _)         = Primitive LessOrEqualThan
 muJSBinOp (JSBinOpLsh _)        = Reference "<<"
-muJSBinOp (JSBinOpLt _)         = Reference "<"
+muJSBinOp (JSBinOpLt _)         = Primitive LessThan
 muJSBinOp (JSBinOpMinus _)      = Reference "-"
 muJSBinOp (JSBinOpMod _)        = Reference "%"
-muJSBinOp (JSBinOpNeq _)        = NotEqual
-muJSBinOp (JSBinOpOr _)         = Reference "||"
+muJSBinOp (JSBinOpNeq _)        = Primitive NotEqual
+muJSBinOp (JSBinOpOr _)         = Primitive Or
 muJSBinOp (JSBinOpPlus _)       = Reference "+"
 muJSBinOp (JSBinOpRsh _)        = Reference ">>"
-muJSBinOp (JSBinOpStrictEq _)   = Equal
-muJSBinOp (JSBinOpStrictNeq _)  = NotEqual
+muJSBinOp (JSBinOpStrictEq _)   = Primitive Equal
+muJSBinOp (JSBinOpStrictNeq _)  = Primitive NotEqual
 muJSBinOp (JSBinOpTimes _)      = Reference "*"
 
 
diff --git a/src/Language/Mulang/Parsers/Python.hs b/src/Language/Mulang/Parsers/Python.hs
index 077fdc970..4fb13476b 100644
--- a/src/Language/Mulang/Parsers/Python.hs
+++ b/src/Language/Mulang/Parsers/Python.hs
@@ -205,35 +205,35 @@ muArgument e                            = M.debug e
 --muYieldArg (YieldFrom expr _)(Expr annot) annot -- ^ Yield from a generator (Version 3 only)
 muYieldArg (YieldExpr expr) = muExpr expr
 
-muOp (Equality _)           = M.Equal
-muOp (NotEquals _)          = M.NotEqual
-muOp op                     = M.Reference $ muOpReference op
-
-muOpReference (And _)                = "and"
-muOpReference (Or _)                 = "or"
-muOpReference (Not _)                = "not"
-muOpReference (Exponent _)           = "**"
-muOpReference (LessThan _)           = "<"
-muOpReference (GreaterThan _)        = ">"
-muOpReference (GreaterThanEquals _)  = ">="
-muOpReference (LessThanEquals _)     = "<="
-muOpReference (NotEqualsV2 _)        = "<>" -- Version 2 only.
-muOpReference (In _)                 = "in"
-muOpReference (Is _)                 = "is"
-muOpReference (IsNot _)              = "is not"
-muOpReference (NotIn _)              = "not in"
-muOpReference (BinaryOr _)           = "|"
-muOpReference (Xor _)                = "^"
-muOpReference (BinaryAnd _)          = "&"
-muOpReference (ShiftLeft _)          = "<<"
-muOpReference (ShiftRight _)         = ">>"
-muOpReference (Multiply _)           = "*"
-muOpReference (Plus _)               = "+"
-muOpReference (Minus _)              = "-"
-muOpReference (Divide _)             = "/"
-muOpReference (FloorDivide _)        = "//"
-muOpReference (Invert _)             = "~"
-muOpReference (Modulo _)             = "%"
+muOp (Equality _)           = M.Primitive M.Equal
+muOp (NotEquals _)          = M.Primitive M.NotEqual
+muOp op                     = muOpReference op
+
+muOpReference (And _)                = M.Primitive M.And
+muOpReference (Or _)                 = M.Primitive M.Or
+muOpReference (Not _)                = M.Primitive M.Negation
+muOpReference (Exponent _)           = M.Reference "**"
+muOpReference (LessThan _)           = M.Primitive M.LessThan
+muOpReference (GreaterThan _)        = M.Primitive M.GreatherThan
+muOpReference (GreaterThanEquals _)  = M.Primitive M.GreatherOrEqualThan
+muOpReference (LessThanEquals _)     = M.Primitive M.LessOrEqualThan
+muOpReference (NotEqualsV2 _)        = M.Primitive M.NotEqual -- Version 2 only.
+muOpReference (In _)                 = M.Reference "in"
+muOpReference (Is _)                 = M.Reference "is"
+muOpReference (IsNot _)              = M.Reference "is not"
+muOpReference (NotIn _)              = M.Reference "not in"
+muOpReference (BinaryOr _)           = M.Primitive M.Or
+muOpReference (Xor _)                = M.Reference "^"
+muOpReference (BinaryAnd _)          = M.Primitive M.And
+muOpReference (ShiftLeft _)          = M.Reference "<<"
+muOpReference (ShiftRight _)         = M.Reference ">>"
+muOpReference (Multiply _)           = M.Reference "*"
+muOpReference (Plus _)               = M.Reference "+"
+muOpReference (Minus _)              = M.Reference "-"
+muOpReference (Divide _)             = M.Reference "/"
+muOpReference (FloorDivide _)        = M.Reference "//"
+muOpReference (Invert _)             = M.Reference "~"
+muOpReference (Modulo _)             = M.Reference "%"
 
 muAssignOp (PlusAssign _)       = "+"
 muAssignOp (MinusAssign _)      = "-"
diff --git a/src/Language/Mulang/Unbuilder.hs b/src/Language/Mulang/Unbuilder.hs
new file mode 100644
index 000000000..aed35b8ec
--- /dev/null
+++ b/src/Language/Mulang/Unbuilder.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Unbuilder (
+    tab,
+    binary,
+    parenthesize,
+    binaryOperator,
+    number) where
+
+import Language.Mulang.Operators (unparseOperator, Token, TokensTable)
+import Language.Mulang.Ast (Operator)
+import Data.Maybe (fromJust)
+
+tab :: String -> String
+tab = unlines . map ("\t"++) . lines
+
+binary :: String -> String -> String -> String
+binary op arg1 arg2 = parenthesize . unwords $ [arg1, op, arg2]
+
+parenthesize :: String -> String
+parenthesize = ("("++) . (++")")
+
+number :: Double -> String
+number (properFraction -> (i, 0)) = show i
+number n                          = show n
+
+binaryOperator :: Operator -> String -> String -> TokensTable -> String
+binaryOperator op arg1 arg2 tokensTable = binary (fromJust $ unparseOperator op tokensTable) arg1 arg2
diff --git a/src/Language/Mulang/Unparsers.hs b/src/Language/Mulang/Unparsers.hs
new file mode 100644
index 000000000..e1259b11e
--- /dev/null
+++ b/src/Language/Mulang/Unparsers.hs
@@ -0,0 +1,5 @@
+module Language.Mulang.Unparsers(Unparser) where
+
+import Language.Mulang.Ast (Expression)
+
+type Unparser = Expression -> String
diff --git a/src/Language/Mulang/Unparsers/Java.hs b/src/Language/Mulang/Unparsers/Java.hs
new file mode 100644
index 000000000..3115c179a
--- /dev/null
+++ b/src/Language/Mulang/Unparsers/Java.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Unparsers.Java (unparseJava) where
+import Language.Mulang.Unparsers (Unparser)
+import Language.Mulang.Ast
+import Language.Mulang.Unbuilder (tab, parenthesize, number, binary)
+
+import Data.List (intercalate)
+import Data.String (unwords)
+
+unparseJava :: Unparser
+unparseJava = unparse
+
+unparseClassBody :: Unparser
+unparseClassBody (Sequence xs) = unparseClassBodyMembers xs
+unparseClassBody other = unparse other
+
+unparseClassBodyMembers :: [Expression] -> String
+unparseClassBodyMembers []     = ""
+unparseClassBodyMembers (s@SubroutineSignature {}:m@SimpleMethod {}:xs) = unparseMethod s m ++ unparseClassBodyMembers xs
+unparseClassBodyMembers (x:xs) = unparse x ++ unparseClassBodyMembers xs
+
+unparseMethod :: Expression -> Expression -> String
+unparseMethod (SubroutineSignature name args typ gens) (SimpleMethod name2 args2 body)
+                                                    = unwords ["public", "void", name, "(", unparseParams args args2, ")", "{", unparse body, "}"]
+
+unparseParams :: [Identifier] -> [Pattern] -> String
+unparseParams types names = intercalate "," $ zipWith unparseParam types names
+
+unparseParam :: Identifier -> Pattern -> [Char]
+unparseParam typ (VariablePattern name) = unwords [typ, name]
+
+unparseStatements :: Expression -> String
+unparseStatements (Sequence xs) = unlines (map unparseStatements xs)
+unparseStatements c@(Call {})   = unparse c ++ ";"
+unparseStatements other         = unparse other
+
+unparse :: Unparser
+unparse (Class name Nothing body)                   = unwords ["public class", name, "{", (tab . unparseClassBody) body, "}"]
+unparse (Class name (Just superclass) body)         = unwords ["public class", name, "extends", superclass, "{", (tab . unparseClassBody) body, "}"]
+unparse (Interface name extends body)               = unwords ["public interface", name, unparseExtends extends, "{", (tab . unparse) body, "}"]
+unparse MuNil                                       = "null"
+unparse None                                        = ""
+unparse Self                                        = "this"
+unparse s@(Sequence members)                        = unparseStatements s
+unparse (SubroutineSignature name args typ gens)    = unwords ["public abstract", unTypeParams gens, typ, name, "(", unparam args, ");"]
+unparse (Print exp)                                 = "System.out.println(" ++ unparse exp ++ ");"
+unparse (Return exp)                                = unwords ["return", unparse exp, ";"]
+unparse (MuNumber n)                                = number n
+unparse MuTrue                                      = "true"
+unparse MuFalse                                     = "false"
+unparse (MuString s)                                = show s
+unparse (Reference id)                              = id
+unparse (Assignment id value)                       = unwords [id, "=", unparse value, ";"]
+unparse (Call (Reference "+") [arg1, arg2])         = binary "+" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "*") [arg1, arg2])         = binary "*" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "/") [arg1, arg2])         = binary "/" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "-") [arg1, arg2])         = binary "-" (unparse arg1) (unparse arg2)
+unparse (Call (Primitive And) [arg1, arg2])         = binary "&&" (unparse arg1) (unparse arg2)
+unparse (Call (Primitive Or) [arg1, arg2])          = binary "||" (unparse arg1) (unparse arg2)
+unparse (Call (Primitive Negation) [arg1])          = parenthesize $ "!" ++ unparse arg1
+unparse (Send receptor (Reference id) args)         = unparse receptor ++ "."++ id ++"("++ unparseMany args ++")"
+unparse (While cond body)                           = unwords ["while", "(", unparse cond, ")", "{", (tab . unparseStatements) body, "}"]
+unparse (Raise arg)                                 = unwords ["throw", unparse arg, ";"]
+-- unparse (Lambda params body)                                          = "lambda { |"++unparseParams params++"| "++ unparse body ++" }"
+-- unparse (If cond trueBody falseBody)                                  = "if "++ unparse cond ++"\n"++ (tab . unparse) trueBody ++ "else\n" ++ (tab . unparse) falseBody ++ "end\n"
+unparse other                                       = error . show $ other
+
+unparseMany :: [Expression] -> String
+unparseMany = intercalate "," . map unparse
+
+unparseExtends :: [Identifier] -> String
+unparseExtends [] = ""
+unparseExtends parents = unwords ["extends", intercalate "," parents]
+
+unTypeParams :: [String] -> String
+unTypeParams = unwords . map (("<"++).(++">"))
+
+unparam :: [Identifier] -> String
+unparam = intercalate "," . zipWith buildParam [0..]
+  where
+    buildParam :: Int -> Identifier -> String
+    buildParam index typeParam = typeParam ++ " arg" ++ show index
diff --git a/src/Language/Mulang/Unparsers/Python.hs b/src/Language/Mulang/Unparsers/Python.hs
new file mode 100644
index 000000000..2f41abc1a
--- /dev/null
+++ b/src/Language/Mulang/Unparsers/Python.hs
@@ -0,0 +1,59 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Unparsers.Python (unparsePython) where
+
+import Language.Mulang.Operators.Python (pythonTokensTable)
+import Language.Mulang.Unparsers (Unparser)
+import Language.Mulang.Ast
+import Language.Mulang.Unbuilder (tab, binary, parenthesize, number, binaryOperator)
+
+import Data.List (intercalate)
+
+unparsePython :: Unparser
+unparsePython = unparse
+
+unparse MuNil                                                         = "None"
+unparse (Return body)                                                 = "return " ++ unparse body
+unparse (Print exp)                                                   = "print(" ++ unparse exp ++ ")"
+unparse (MuNumber n)                                                  = number n
+unparse (MuBool b)                                                    = show b
+unparse (MuString s)                                                  = show s
+unparse (MuList xs)                                                   = "[" ++ unparseMany xs ++ "]"
+unparse (Assignment id value)                                         = id ++ " = " ++ unparse value
+unparse (Reference id)                                                = id
+unparse (Call (Primitive Negation) [arg1])                            = parenthesize $ "not " ++ unparse arg1
+unparse (Call (Reference "+") [arg1, arg2])                           = binary "+" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "*") [arg1, arg2])                           = binary "*" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "/") [arg1, arg2])                           = binary "/" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "-") [arg1, arg2])                           = binary "-" (unparse arg1) (unparse arg2)
+unparse (Call (Primitive op) [arg1, arg2])                            = binaryOperator op (unparse arg1) (unparse arg2)  pythonTokensTable
+unparse (Application (Reference id) args)                             = id ++ "(" ++ unparseMany args ++ ")"
+unparse (Sequence xs)                                                 = unlines . map unparse $ xs
+unparse (While cond body)                                             = "while "++ unparse cond ++ ":\n" ++ (tab . unparse) body
+unparse  (For [Generator (TuplePattern [VariablePattern "x"]) generator] None) = "for x in "++ unparse generator ++": pass"
+unparse (Raise None)                                                   = "raise"
+unparse (Raise arg)                                                    = "raise " ++ unparse arg
+unparse (Lambda params body)                                           = "lambda "++ unparseParams params++ ": " ++ unparse body
+unparse (MuTuple args)                                                 = "("++ unparseMany args++")"
+unparse (Yield value)                                                  = "yield " ++ unparse value
+unparse (Class id Nothing body)                                        = "class "++ id ++":\n" ++ (tab . unparse) body
+unparse (Class id (Just parent) body)                                  = "class "++ id ++"("++parent++"):\n" ++ (tab . unparse) body
+unparse None                                                           = "pass"
+unparse (Send receptor (Reference id) args)                            =  unparse receptor ++ "."++ id ++"("++ unparseMany args ++")"
+unparse (If cond trueBody falseBody)                                   = "if "++ unparse cond ++":\n"++ (tab . unparse) trueBody ++ "\nelse:\n" ++ (tab . unparse) falseBody
+unparse (SimpleFunction id args body)                                 = unparseDef id args body
+unparse (SimpleProcedure id args body)                                = unparseDef id args body
+unparse other = error . show $ other
+
+unparseDef :: String -> [Pattern] -> Expression -> String
+unparseDef id args body = "def "++ id ++"("++ unparseParams args++"):\n" ++ (tab . unparse) body
+
+unparseParams :: [Pattern] -> String
+unparseParams = intercalate "," . map unparseParam
+
+unparseParam :: Pattern -> String
+unparseParam (VariablePattern id) = id
+unparseParam other = error . show $ other
+
+unparseMany :: [Expression] -> String
+unparseMany = intercalate "," . map unparse
diff --git a/src/Language/Mulang/Unparsers/Ruby.hs b/src/Language/Mulang/Unparsers/Ruby.hs
new file mode 100644
index 000000000..431d72f5a
--- /dev/null
+++ b/src/Language/Mulang/Unparsers/Ruby.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE ViewPatterns #-}
+
+module Language.Mulang.Unparsers.Ruby (unparseRuby) where
+
+import Language.Mulang.Operators.Ruby (rubyTokensTable)
+import Language.Mulang.Unparsers (Unparser)
+import Language.Mulang.Unbuilder (tab, binary, parenthesize, number, binaryOperator)
+import Language.Mulang.Ast
+
+import Data.List (intercalate)
+
+unparseRuby :: Unparser
+unparseRuby = unparse
+
+unparse :: Unparser
+unparse MuNil                                                         = "nil"
+unparse (Print exp)                                                   = "puts(" ++ unparse exp ++ ")"
+unparse (Return exp)                                                  = "return " ++ unparse exp
+unparse (MuNumber n)                                                  = number n
+unparse MuTrue                                                        = "true"
+unparse MuFalse                                                       = "false"
+unparse (MuString s)                                                  = show s
+unparse (MuList xs)                                                   = "[" ++ unparseMany xs ++ "]"
+unparse (Assignment id value)                                         = id ++ " = " ++ unparse value
+unparse (Reference id)                                                = id
+unparse (Call (Primitive Negation) [arg1])                            = parenthesize $ "!" ++ unparse arg1
+unparse (Call (Reference "+") [arg1, arg2])                           = binary "+" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "*") [arg1, arg2])                           = binary "*" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "/") [arg1, arg2])                           = binary "/" (unparse arg1) (unparse arg2)
+unparse (Call (Reference "-") [arg1, arg2])                           = binary "-" (unparse arg1) (unparse arg2)
+unparse (Call (Primitive op) [arg1, arg2])                            = binaryOperator op (unparse arg1) (unparse arg2)  rubyTokensTable
+unparse (Application (Reference id) args)                             = id ++ "(" ++ unparseMany args ++ ")"
+unparse (Sequence xs)                                                 = unlines . map unparse $ xs
+unparse (While cond body)                                             = "while "++ unparse cond ++ "\n" ++ (tab . unparse) body ++ "end\n"
+unparse (Raise None)                                                  = "raise"
+unparse (Raise arg)                                                   = "raise " ++ unparse arg
+unparse (Lambda params body)                                          = "lambda { |"++unparseParams params++"| "++ unparse body ++" }"
+unparse (MuTuple args)                                                = "("++ unparseMany args++")"
+unparse (Yield value)                                                 = "yield " ++ unparse value
+unparse (Class id Nothing body)                                       = "class "++ id ++"\n" ++ (tab . unparse) body ++ "end\n"
+unparse (Class id (Just parent) body)                                 = "class "++ id ++" < "++parent++"\n" ++ (tab . unparse) body ++ "end\n"
+unparse None                                                          = ""
+unparse (Send receptor (Reference id) args)                           = unparse receptor ++ "."++ id ++"("++ unparseMany args ++")"
+unparse (If cond trueBody falseBody)                                  = "if "++ unparse cond ++"\n"++ (tab . unparse) trueBody ++ "else\n" ++ (tab . unparse) falseBody ++ "end\n"
+unparse (SimpleFunction id args body)                                 = unparseDef id args body
+unparse (SimpleProcedure id args body)                                = unparseDef id args body
+unparse other                                                         = error . show $ other
+
+unparseDef :: String -> [Pattern] -> Expression -> String
+unparseDef id args body = "def "++ id ++"("++ unparseParams args++")\n" ++ (tab . unparse) body ++ "end\n"
+
+unparseParams :: [Pattern] -> String
+unparseParams = intercalate "," . map unparseParam
+
+unparseParam :: Pattern -> String
+unparseParam (VariablePattern id) = id
+unparseParam other = error . show $ other
+
+unparseMany :: [Expression] -> String
+unparseMany = intercalate "," . map unparse