diff --git a/src/main/scala/leon/Analysis.scala b/src/main/scala/leon/Analysis.scala
index 176cb96b1f9fe411be0553afca3a31895d7e962a..2ba7a69ad7aa69be4b49d0cdd7b395dfa2bf6c34 100644
--- a/src/main/scala/leon/Analysis.scala
+++ b/src/main/scala/leon/Analysis.scala
@@ -327,3 +327,12 @@ object Analysis {
     liftLets(Implies(And(trueThings.reverse), result))
   }
 }
+
+object AnalysisPhase extends plugin.UnitPhase {
+  val name = "Analysis"
+  val description = "Leon Analyses"
+
+  def apply(program: Program) {
+    new Analysis(program).analyse
+  }
+}
diff --git a/src/main/scala/leon/ArrayTransformation.scala b/src/main/scala/leon/ArrayTransformation.scala
index 7d0d94458291b71381d8719a25e13751ca3cdd9f..0dab758176b2b3381eaed88c67415d95d5cd8df3 100644
--- a/src/main/scala/leon/ArrayTransformation.scala
+++ b/src/main/scala/leon/ArrayTransformation.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object ArrayTransformation extends Pass {
+object ArrayTransformation extends plugin.TransformationPhase {
 
+  val name = "Array Transformation"
   val description = "Add bound checking for array access and remove array update with side effect"
 
   def apply(pgm: Program): Program = {
diff --git a/src/main/scala/leon/EpsilonElimination.scala b/src/main/scala/leon/EpsilonElimination.scala
index 585888f4c771ea6354df64f8792d0becd90dea52..5cc7645d54e99c6480f09dcfd16b46e01e4a0713 100644
--- a/src/main/scala/leon/EpsilonElimination.scala
+++ b/src/main/scala/leon/EpsilonElimination.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object EpsilonElimination extends Pass {
+object EpsilonElimination extends plugin.TransformationPhase {
 
+  val name = "Epsilon Elimination"
   val description = "Remove all epsilons from the program"
 
   def apply(pgm: Program): Program = {
diff --git a/src/main/scala/leon/FunctionClosure.scala b/src/main/scala/leon/FunctionClosure.scala
index 8a6fd5bffd1a7c6a9a6a9b6fdde5e8bd3598f940..64c0c123f7d1c289e6b59a0bbe13ddd6390f5ae4 100644
--- a/src/main/scala/leon/FunctionClosure.scala
+++ b/src/main/scala/leon/FunctionClosure.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object FunctionClosure extends Pass {
+object FunctionClosure extends plugin.TransformationPhase{
 
+  val name = "Function Closure"
   val description = "Closing function with its scoping variables"
 
   private var pathConstraints: List[Expr] = Nil
diff --git a/src/main/scala/leon/FunctionHoisting.scala b/src/main/scala/leon/FunctionHoisting.scala
index 37bc69c41fa12e41c94b3c8d876631f8e3f47220..e467f3f20eb0c414936a3584001285fdc24d9eba 100644
--- a/src/main/scala/leon/FunctionHoisting.scala
+++ b/src/main/scala/leon/FunctionHoisting.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object FunctionHoisting extends Pass {
+object FunctionHoisting extends plugin.TransformationPhase {
 
+  val name = "Function Hoisting"
   val description = "Hoist function at the top level"
 
   def apply(program: Program): Program = {
diff --git a/src/main/scala/leon/ImperativeCodeElimination.scala b/src/main/scala/leon/ImperativeCodeElimination.scala
index d3cd29907c5cd8c30fb574d06ddd1682e5bfa59a..bb770ba8e15eede296321707f58bcf4460404a98 100644
--- a/src/main/scala/leon/ImperativeCodeElimination.scala
+++ b/src/main/scala/leon/ImperativeCodeElimination.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object ImperativeCodeElimination extends Pass {
+object ImperativeCodeElimination extends plugin.TransformationPhase {
 
+  val name = "Imperative Code Elimination"
   val description = "Transform imperative constructs into purely functional code"
 
   private var varInScope = Set[Identifier]()
diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index 9af1b41e731e32ff4b25942c4ec4f6ac63f91b0a..760e5c5de0a994f450c2d6190e9ce89624d79fac 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -27,19 +27,7 @@ object Main {
   def run(args: Array[String], reporter: Reporter = new DefaultReporter, classPath : Option[Seq[String]] = None) : Unit = {
     val settings = new NSCSettings
     classPath.foreach(s => settings.classpath.tryToSet(s.toList))
-    runWithSettings(args, settings, s => reporter.info(s), Some(p => defaultAction(p, reporter)))
-  }
-
-  private def defaultAction(program: Program, reporter: Reporter) : Unit = {
-    Logger.debug("Default action on program: " + program, 3, "main")
-    val passManager = new PassManager(Seq(ArrayTransformation, EpsilonElimination, ImperativeCodeElimination, /*UnitElimination,*/ FunctionClosure, /*FunctionHoisting,*/ Simplificator))
-    val program2 = passManager.run(program)
-    assert(program2.isPure)
-    val analysis = new Analysis(program2, reporter)
-    analysis.analyse
-  }
 
-  private def runWithSettings(args : Array[String], settings : NSCSettings, printerFunction : String=>Unit, actionOnProgram : Option[Program=>Unit] = None) : Unit = {
     val (leonOptions, nonLeonOptions) = args.toList.partition(_.startsWith("--"))
     val command = new CompilerCommand(nonLeonOptions, settings) {
       override val cmdName = "leon"
@@ -49,9 +37,9 @@ object Main {
       if(settings.version.value) {
         println(command.cmdName + " beta.")
       } else {
-        val runner = new PluginRunner(settings, printerFunction, actionOnProgram)
-        runner.leonPlugin.processOptions(leonOptions.map(_.substring(2)), Console.err.println(_))
-        runner.leonPlugin.stopAfterAnalysis = false
+        val runner = new PluginRunner(settings, reporter)
+        runner.leonPlugin.processOptions(leonOptions.map(_.substring(2)), reporter.error(_))
+
         val run = new runner.Run
         run.compile(command.files)
       }
@@ -61,8 +49,8 @@ object Main {
 
 /** This class is a compiler that will be used for running the plugin in
  * standalone mode. Original version courtesy of D. Zufferey. */
-class PluginRunner(settings : NSCSettings, reportingFunction : String => Unit, actionOnProgram : Option[Program=>Unit]) extends Global(settings, new plugin.SimpleReporter(settings, reportingFunction)) {
-  val leonPlugin = new plugin.LeonPlugin(this, actionOnProgram)
+class PluginRunner(settings : NSCSettings, reporter : Reporter) extends Global(settings, new plugin.SimpleReporter(settings, reporter)) {
+  val leonPlugin = new plugin.LeonPlugin(this, reporter)
 
   protected def myAddToPhasesSet(sub : SubComponent, descr : String) : Unit = {
     phasesSet += sub
diff --git a/src/main/scala/leon/Pass.scala b/src/main/scala/leon/Pass.scala
deleted file mode 100644
index 4bbc88856c20b96bd5c9c3fd9e1815b57b85d976..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/Pass.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package leon
-
-import purescala.Definitions._
-
-abstract class Pass {
-
-  def apply(pgm: Program): Program
-
-  val description: String
-
-
-  //Maybe adding some dependency declaration and tree checking methods
-
-}
diff --git a/src/main/scala/leon/PassManager.scala b/src/main/scala/leon/PassManager.scala
deleted file mode 100644
index 307a227ffb0ce0decb39624b1dde34bc6a589a39..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/PassManager.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package leon
-
-import purescala.Definitions._
-
-class PassManager(passes: Seq[Pass]) {
-
-  def run(program: Program): Program = {
-    passes.foldLeft(program)((pgm, pass) => {
-      Logger.debug("Running Pass: " + pass.description, 1, "passman")
-      val newPgm = pass(pgm)
-      TypeChecking(newPgm)
-      Logger.debug("Resulting program: " + newPgm, 3, "passman")
-      newPgm
-    })
-  }
-
-}
diff --git a/src/main/scala/leon/Settings.scala b/src/main/scala/leon/Settings.scala
index dc88a7cb365f1942aa5bfa5ebdf6841057cb30bd..4c15d2cbea3ad72442aca4a42b12c39eebaa285d 100644
--- a/src/main/scala/leon/Settings.scala
+++ b/src/main/scala/leon/Settings.scala
@@ -27,4 +27,10 @@ object Settings {
   var debugLevel: Int = 0
   var debugTags: Set[String] = Set.empty
   var simpleOutput: Boolean = false
+  var synthesis: Boolean = false
+  var transformProgram: Boolean              = true
+  var stopAfterExtraction: Boolean           = false
+  var stopAfterTransformation: Boolean       = false
+  var stopAfterAnalysis: Boolean             = true
+  var silentlyTolerateNonPureBodies: Boolean = false
 }
diff --git a/src/main/scala/leon/Simplificator.scala b/src/main/scala/leon/Simplificator.scala
index d52d6fe0d380b90424c239f3d302fb3620d502c4..c9de13922b3a93ee8e9055046dfcf020bd64c74e 100644
--- a/src/main/scala/leon/Simplificator.scala
+++ b/src/main/scala/leon/Simplificator.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object Simplificator extends Pass {
+object Simplificator extends plugin.TransformationPhase {
 
+  val name = "Simplificator"
   val description = "Some safe and minimal simplification"
 
   def apply(pgm: Program): Program = {
diff --git a/src/main/scala/leon/TypeChecking.scala b/src/main/scala/leon/TypeChecking.scala
index f6d4b259f19ab5e19e462cd4ba137d39bba16917..67a2e1bafb7e9d2e9f7f4c169ee77918b45d73d1 100644
--- a/src/main/scala/leon/TypeChecking.scala
+++ b/src/main/scala/leon/TypeChecking.scala
@@ -5,11 +5,12 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object TypeChecking extends Pass {
+object TypeChecking extends plugin.UnitPhase {
 
+  val name = "Type Checking"
   val description = "Type check the AST"
 
-  def apply(pgm: Program): Program = {
+  def apply(pgm: Program): Unit = {
     val allFuns = pgm.definedFunctions
 
     allFuns.foreach(fd  => {
@@ -17,8 +18,6 @@ object TypeChecking extends Pass {
       fd.postcondition.foreach(typeCheck)
       fd.body.foreach(typeCheck)
     })
-
-    pgm
   }
 
   private def typeCheck(expr: Expr): Unit = { //expr match {
diff --git a/src/main/scala/leon/UnitElimination.scala b/src/main/scala/leon/UnitElimination.scala
index 2c5d4d5a532614873b9b6786481e82f0ebd4a3de..f653b8b7c8d9cd75e1dc60b400410316d1dcb6b3 100644
--- a/src/main/scala/leon/UnitElimination.scala
+++ b/src/main/scala/leon/UnitElimination.scala
@@ -5,8 +5,9 @@ import purescala.Definitions._
 import purescala.Trees._
 import purescala.TypeTrees._
 
-object UnitElimination extends Pass {
+object UnitElimination extends plugin.TransformationPhase {
 
+  val name = "Unit Elimination"
   val description = "Remove all usage of the Unit type and value"
 
   private var fun2FreshFun: Map[FunDef, FunDef] = Map()
diff --git a/src/main/scala/leon/plugin/AnalysisComponent.scala b/src/main/scala/leon/plugin/AnalysisComponent.scala
index 08b94f8304030fedd3cc8b19c6fbff5ae255c8b1..0578055c5d0486bcaa544dba6b7d090685fe2d91 100644
--- a/src/main/scala/leon/plugin/AnalysisComponent.scala
+++ b/src/main/scala/leon/plugin/AnalysisComponent.scala
@@ -4,7 +4,10 @@ package plugin
 import scala.tools.nsc._
 import scala.tools.nsc.plugins._
 
-class AnalysisComponent(val global: Global, val pluginInstance: LeonPlugin)
+import purescala.Definitions.Program
+import synthesis.SynthesisPhase
+
+class AnalysisComponent(val global: Global, val leonReporter: Reporter, val pluginInstance: LeonPlugin)
   extends PluginComponent
   with CodeExtraction
 {
@@ -22,7 +25,7 @@ class AnalysisComponent(val global: Global, val pluginInstance: LeonPlugin)
   protected def stopIfErrors: Unit = {
     if(reporter.hasErrors) {
       if(Settings.simpleOutput)
-        println("error")
+        leonReporter.fatalError("errrr")
       sys.exit(1)
       //throw new Exception("There were errors.")
     }
@@ -31,34 +34,58 @@ class AnalysisComponent(val global: Global, val pluginInstance: LeonPlugin)
   def newPhase(prev: Phase) = new AnalysisPhase(prev)
 
   class AnalysisPhase(prev: Phase) extends StdPhase(prev) {
+    def computeLeonPhases: List[LeonPhase] = {
+      List(
+        if (Settings.transformProgram) {
+          List(
+            ArrayTransformation,
+            EpsilonElimination,
+            ImperativeCodeElimination,
+            /*UnitElimination,*/
+            FunctionClosure,
+            /*FunctionHoisting,*/
+            Simplificator
+          )
+        } else {
+          Nil
+        }
+      ,
+        if (Settings.synthesis)
+          List(
+            new SynthesisPhase(leonReporter)
+          )
+        else
+          Nil
+      ,
+        if (!Settings.stopAfterTransformation) {
+          List(
+            AnalysisPhase
+          )
+        } else {
+          Nil
+        }
+      ).flatten
+    }
+
     def apply(unit: CompilationUnit): Unit = {
       //global ref to freshName creator
       fresh = unit.fresh
 
-      val prog: purescala.Definitions.Program = extractCode(unit)
-      if(pluginInstance.stopAfterExtraction) {
-        println("Extracted program for " + unit + ": ")
-        println(prog)
-        println("Extraction complete. Now terminating the compiler process.")
+      var ac = LeonContext(program = extractCode(unit))
+
+      if(Settings.stopAfterExtraction) {
+        leonReporter.info("Extracted program for " + unit + ": ")
+        leonReporter.info(ac.program)
         sys.exit(0)
-      } else {
-        if(!pluginInstance.actionAfterExtraction.isDefined) {
-          println("Extracted program for " + unit + ". Re-run with -P:leon:parse to see the output.")
-        }
-        //println(prog)
       }
 
-      if(!pluginInstance.actionAfterExtraction.isDefined) {
-        println("Starting analysis.")
-        val analysis = new Analysis(prog)
-        analysis.analyse
-        if(pluginInstance.stopAfterAnalysis) {
-          println("Analysis complete. Now terminating the compiler process.")
-          sys.exit(0)
-        }
-      } else {
-        pluginInstance.actionAfterExtraction.get(prog)
+      val phases = computeLeonPhases
+
+      for ((phase, i) <- phases.zipWithIndex) {
+        leonReporter.info("%2d".format(i)+": "+phase.name)
+        ac = phase.run(ac)
       }
+
     }
   }
 }
diff --git a/src/main/scala/leon/plugin/CodeExtraction.scala b/src/main/scala/leon/plugin/CodeExtraction.scala
index 24f49dfab090b3b7735671faaa98a4b1b252b3ed..9c2d4fbf80afe77e878ec4fb1892365a69fad44e 100644
--- a/src/main/scala/leon/plugin/CodeExtraction.scala
+++ b/src/main/scala/leon/plugin/CodeExtraction.scala
@@ -289,7 +289,7 @@ trait CodeExtraction extends Extractors {
       }
       
       val bodyAttempt = try {
-        Some(flattenBlocks(scala2PureScala(unit, pluginInstance.silentlyTolerateNonPureBodies)(realBody)))
+        Some(flattenBlocks(scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies)(realBody)))
       } catch {
         case e: ImpureCodeEncounteredException => None
       }
@@ -441,7 +441,7 @@ trait CodeExtraction extends Extractors {
       realBody match {
         case ExEnsuredExpression(body2, resSym, contract) => {
           varSubsts(resSym) = (() => ResultVariable().setType(funDef.returnType))
-          val c1 = scala2PureScala(unit, pluginInstance.silentlyTolerateNonPureBodies) (contract)
+          val c1 = scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies) (contract)
           // varSubsts.remove(resSym)
           realBody = body2
           ensCont = Some(c1)
@@ -456,13 +456,13 @@ trait CodeExtraction extends Extractors {
       realBody match {
         case ExRequiredExpression(body3, contract) => {
           realBody = body3
-          reqCont = Some(scala2PureScala(unit, pluginInstance.silentlyTolerateNonPureBodies) (contract))
+          reqCont = Some(scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies) (contract))
         }
         case _ => ;
       }
       
       val bodyAttempt = try {
-        Some(flattenBlocks(scala2PureScala(unit, pluginInstance.silentlyTolerateNonPureBodies)(realBody)))
+        Some(flattenBlocks(scala2PureScala(unit, Settings.silentlyTolerateNonPureBodies)(realBody)))
       } catch {
         case e: ImpureCodeEncounteredException => None
       }
diff --git a/src/main/scala/leon/plugin/LeonContext.scala b/src/main/scala/leon/plugin/LeonContext.scala
new file mode 100644
index 0000000000000000000000000000000000000000..29274a5fdd6d602007ce2be7956b79566f37dd2c
--- /dev/null
+++ b/src/main/scala/leon/plugin/LeonContext.scala
@@ -0,0 +1,9 @@
+package leon
+package plugin
+
+import purescala.Definitions.Program
+
+case class LeonContext(
+  val program: Program
+)
+
diff --git a/src/main/scala/leon/plugin/LeonPhase.scala b/src/main/scala/leon/plugin/LeonPhase.scala
new file mode 100644
index 0000000000000000000000000000000000000000..13f437ea4b0f1e9eb0846cb6921980320723f62d
--- /dev/null
+++ b/src/main/scala/leon/plugin/LeonPhase.scala
@@ -0,0 +1,23 @@
+package leon
+package plugin
+
+import purescala.Definitions.Program
+
+abstract class LeonPhase {
+  val name: String
+  val description: String
+
+  def run(ac: LeonContext): LeonContext
+}
+
+abstract class TransformationPhase extends LeonPhase {
+  def apply(p: Program): Program
+
+  override def run(ac: LeonContext) = ac.copy(program = apply(ac.program))
+}
+
+abstract class UnitPhase extends LeonPhase {
+  def apply(p: Program): Unit
+
+  override def run(ac: LeonContext) = { apply(ac.program); ac }
+}
diff --git a/src/main/scala/leon/plugin/LeonPlugin.scala b/src/main/scala/leon/plugin/LeonPlugin.scala
index e37b5b1a8c047cc5b7af6ab26d5cdabb03731287..b2efd9d536d779036ebd8fa8665c0369969af00b 100644
--- a/src/main/scala/leon/plugin/LeonPlugin.scala
+++ b/src/main/scala/leon/plugin/LeonPlugin.scala
@@ -7,16 +7,12 @@ import scala.tools.nsc.plugins.{Plugin,PluginComponent}
 import purescala.Definitions.Program
 
 /** This class is the entry point for the plugin. */
-class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=>Unit] = None) extends Plugin {
+class LeonPlugin(val global: Global, val reporter: Reporter) extends Plugin {
   import global._
 
   val name = "leon"
   val description = "The Leon static analyzer"
 
-  var stopAfterAnalysis: Boolean = true
-  var stopAfterExtraction: Boolean = false
-  var silentlyTolerateNonPureBodies: Boolean = false
-
   /** The help message displaying the options for that plugin. */
   override val optionsHelp: Option[String] = Some(
     "  --uniqid             When pretty-printing purescala trees, show identifiers IDs" + "\n" +
@@ -43,7 +39,8 @@ class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=
     "  --noverifymodel      Do not verify the correctness of models returned by Z3" + "\n" +
     "  --debug=[1-5]        Debug level" + "\n" +
     "  --tags=t1:...        Filter out debug information that are not of one of the given tags" + "\n" +
-    "  --oneline            Reduce the output to a single line: valid if all properties were valid, invalid if at least one is invalid, unknown else"
+    "  --oneline            Reduce the output to a single line: valid if all properties were valid, invalid if at least one is invalid, unknown else" + "\n" +
+    "  --synthesis          Magic!"
   )
 
   /** Processes the command-line options. */
@@ -51,10 +48,10 @@ class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=
   override def processOptions(options: List[String], error: String => Unit) {
     for(option <- options) {
       option match {
-        case "with-code"     =>                     stopAfterAnalysis = false
+        case "with-code"     =>                     leon.Settings.stopAfterAnalysis = false
         case "uniqid"        =>                     leon.Settings.showIDs = true
-        case "parse"         =>                     stopAfterExtraction = true
-        case "tolerant"      =>                     silentlyTolerateNonPureBodies = true
+        case "parse"         =>                     leon.Settings.stopAfterExtraction = true
+        case "tolerant"      =>                     leon.Settings.silentlyTolerateNonPureBodies = true
         case "nodefaults"    =>                     leon.Settings.runDefaultExtensions = false
         case "axioms"        =>                     leon.Settings.noForallAxioms = false
         case "bapa"          =>                     leon.Settings.useBAPA = true
@@ -68,6 +65,9 @@ class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=
         case "oneline"       =>                     leon.Settings.simpleOutput = true
         case "noLuckyTests"  =>                     leon.Settings.luckyTest = false
         case "noverifymodel" =>                     leon.Settings.verifyModel = false
+        case "synthesis"     =>                     leon.Settings.synthesis = true;
+                                                    leon.Settings.transformProgram = false;
+                                                    leon.Settings.stopAfterTransformation = true;
 
         case s if s.startsWith("debug=") =>       leon.Settings.debugLevel = try { s.substring("debug=".length, s.length).toInt } catch { case _ => 0 }
         case s if s.startsWith("tags=") =>       leon.Settings.debugTags = Set(splitList(s.substring("tags=".length, s.length)): _*)
@@ -82,6 +82,6 @@ class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=
     }
   }
 
-  val components = List[PluginComponent](new AnalysisComponent(global, this))
+  val components = List(new AnalysisComponent(global, reporter, this))
   val descriptions = List[String]("leon analyses")
 }
diff --git a/src/main/scala/leon/plugin/SimpleReporter.scala b/src/main/scala/leon/plugin/SimpleReporter.scala
index 0d8e4b0adf6d93d355c5bfaf57f49916b630851b..31cc4d7b132be2dafb1b712bc5355eadba35c46b 100644
--- a/src/main/scala/leon/plugin/SimpleReporter.scala
+++ b/src/main/scala/leon/plugin/SimpleReporter.scala
@@ -4,10 +4,11 @@ package plugin
 import scala.tools.nsc.Settings
 import scala.tools.nsc.reporters.AbstractReporter
 import scala.tools.nsc.util._
+import scala.tools.util.StringOps
 
 /** This implements a reporter that calls the callback with every line that a
 regular ConsoleReporter would display. */
-class SimpleReporter(val settings: Settings, callback: String => Unit) extends AbstractReporter {
+class SimpleReporter(val settings: Settings, reporter: leon.Reporter) extends AbstractReporter {
   final val ERROR_LIMIT = 5
 
   private def label(severity: Severity): String = severity match {
@@ -22,10 +23,10 @@ class SimpleReporter(val settings: Settings, callback: String => Unit) extends A
   }
 
   private def getCountString(severity: Severity): String =
-    countElementsAsString((severity).count, label(severity))
+    StringOps.countElementsAsString((severity).count, label(severity))
 
   /** Prints the message. */
-  def printMessage(msg: String) { callback(msg) }
+  def printMessage(msg: String) { reporter.info(msg) }
 
   /** Prints the message with the given position indication. */
   def printMessage(posIn: Position, msg: String) {
diff --git a/src/main/scala/leon/synthesis/Main.scala b/src/main/scala/leon/synthesis/Main.scala
index 10520ef26cd2f4b0d67c7bc437b941f2c2f96d53..a3704d349db726b52bcd657fbecb94d31a67f404 100644
--- a/src/main/scala/leon/synthesis/Main.scala
+++ b/src/main/scala/leon/synthesis/Main.scala
@@ -2,11 +2,4 @@ package leon
 package synthesis
 
 object Main {
-  def main(args : Array[String]) {
-    val reporter = new DefaultReporter
-    val solvers  = List(new TrivialSolver(reporter))
-
-    new Synthesizer(reporter, solvers).test()
-  }
-
 }
diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala
index 0472c87ecedc0942805991b3253adceb02da8cca..5d7af0d5f1e4659335c6f24e8471e4f5c805418c 100644
--- a/src/main/scala/leon/synthesis/Rules.scala
+++ b/src/main/scala/leon/synthesis/Rules.scala
@@ -64,6 +64,25 @@ class OnePoint(synth: Synthesizer) extends Rule("One-point", synth) {
 
 class Ground(synth: Synthesizer) extends Rule("Ground", synth) {
   def isApplicable(p: Problem, parent: Task): List[Task] = {
-    Nil
+    if (p.as.isEmpty) {
+      synth.solveSAT(p.phi) match {
+        case (Some(true), model) =>
+          val onSuccess: List[Solution] => Solution = { 
+            case Nil => Solution(BooleanLiteral(true), replaceFromIDs(model, p.phi))
+          }
+
+          List(new Task(synth, parent, this, p, Nil, onSuccess, 200))
+        case (Some(false), model) =>
+          val onSuccess: List[Solution] => Solution = { 
+            case Nil => Solution(BooleanLiteral(false), BooleanLiteral(false))
+          }
+
+          List(new Task(synth, parent, this, p, Nil, onSuccess, 200))
+        case _ =>
+          Nil
+      }
+    } else {
+      Nil
+    }
   }
 }
diff --git a/src/main/scala/leon/synthesis/SynthesisPhase.scala b/src/main/scala/leon/synthesis/SynthesisPhase.scala
new file mode 100644
index 0000000000000000000000000000000000000000..da729fe3c23143f87ad3ff0cdb0f0243e6d6eeaf
--- /dev/null
+++ b/src/main/scala/leon/synthesis/SynthesisPhase.scala
@@ -0,0 +1,18 @@
+package leon
+package synthesis
+
+import purescala.Definitions.Program
+
+class SynthesisPhase(reporter: Reporter) extends plugin.TransformationPhase {
+  val name        = "Synthesis"
+  val description = "Synthesis"
+
+  def apply(program: Program): Program = {
+    val solvers  = List(
+      new TrivialSolver(reporter),
+      new FairZ3Solver(reporter)
+    )
+
+    new Synthesizer(reporter, solvers).synthesizeAll(program)
+  }
+}
diff --git a/src/main/scala/leon/synthesis/Synthesizer.scala b/src/main/scala/leon/synthesis/Synthesizer.scala
index 3f7ba6a85355b9cb7ccf6249cb1dfce890b34b8d..c8dccc8ba481d013fd073419d6cc4a3c725869d8 100644
--- a/src/main/scala/leon/synthesis/Synthesizer.scala
+++ b/src/main/scala/leon/synthesis/Synthesizer.scala
@@ -1,7 +1,10 @@
 package leon
 package synthesis
 
+import purescala.Common._
 import purescala.Definitions.Program
+import purescala.Trees.{Expr, Not}
+
 import Extensions.Solver
 
 import collection.mutable.PriorityQueue
@@ -61,6 +64,19 @@ class Synthesizer(val r: Reporter, val solvers: List[Solver]) {
     solution
   }
 
+  def solveSAT(phi: Expr): (Option[Boolean], Map[Identifier, Expr]) = {
+    for (s <- solvers) {
+      s.solveOrGetCounterexample(Not(phi)) match {
+        case (Some(true), _) =>
+          return (Some(false), Map())
+        case (Some(false), model) =>
+          return (Some(true), model)
+        case _ =>
+      }
+    }
+    (None, Map())
+  }
+
   def onTaskSucceeded(task: Task, solution: Solution) {
     info(" => Solved "+task.problem+" ⊢  "+solution)
     task match {
@@ -83,5 +99,9 @@ class Synthesizer(val r: Reporter, val solvers: List[Solver]) {
 
     synthesize(p, Rules.all(this))
   }
-}
 
+  def synthesizeAll(program: Program) = {
+    solvers.foreach(_.setProgram(program))
+    program
+  }
+}