From 0d41fa569947556336e09150ec71443fc6fe08ab Mon Sep 17 00:00:00 2001
From: Ivan Kuraj <ivan.kuraj@epfl.ch>
Date: Thu, 21 Mar 2013 16:09:24 +0100
Subject: [PATCH] Added added necessary sources and tests for insynth and
 condition abduction, and two synthesis rules (immediate and deferred
 instantiation)

---
 src/main/scala/insynth/InSynth.scala          |  71 ++
 src/main/scala/insynth/leon/CommonTypes.scala |  14 +
 .../scala/insynth/leon/LeonDeclaration.scala  |  51 ++
 src/main/scala/insynth/leon/LeonQuery.scala   |  20 +
 .../scala/insynth/leon/LeonQueryBuilder.scala |  24 +
 .../leon/ReconstructionExpression.scala       |  73 ++
 .../scala/insynth/leon/TypeTransformer.scala  |  52 ++
 .../leon/loader/DeclarationFactory.scala      |  75 ++
 .../insynth/leon/loader/HoleExtractor.scala   | 106 +++
 .../scala/insynth/leon/loader/LoadSpec.scala  |   6 +
 .../scala/insynth/leon/loader/Loader.scala    | 239 ++++++
 .../scala/insynth/leon/loader/PreLoader.scala | 262 ++++++
 .../scala/insynth/reconstruction/Output.scala |  12 +
 .../reconstruction/Reconstructor.scala        |  53 ++
 .../codegen/CodeGenerator.scala               | 119 +++
 src/main/scala/lesynth/ExampleRunner.scala    | 130 +++
 src/main/scala/lesynth/Globals.scala          |  22 +
 src/main/scala/lesynth/InputExamples.scala    | 148 ++++
 src/main/scala/lesynth/Refiner.scala          |  98 +++
 src/main/scala/lesynth/Report.scala           |  60 ++
 .../scala/lesynth/SynthesizerExamples.scala   | 725 +++++++++++++++++
 ...ConditionAbductionSynthesisImmediate.scala |  61 ++
 .../ConditionAbductionSynthesisTwoPhase.scala |  71 ++
 .../reconstruction/CodeGeneratorTest.scala    |  63 ++
 .../reconstruction/PhaseCombinationTest.scala |  74 ++
 .../reconstruction/ReconstructorTest.scala    |  95 +++
 .../testutil/CommonLeonExpressions.scala      |  20 +
 src/test/scala/lesynth/AnalyzerTest.scala     |  49 ++
 src/test/scala/lesynth/RefinerTest.scala      | 209 +++++
 .../TryOutSynthesizerExamplesTest.scala       | 672 +++++++++++++++
 src/test/scala/lesynth/TryOutTest.scala       | 639 +++++++++++++++
 .../lesynth/TryOutTestWithFiltering.scala     | 768 ++++++++++++++++++
 testcases/lesynth/InsertionSortFull.scala     |  51 ++
 .../lesynth/InsertionSortHoleInsert.scala     |  54 ++
 testcases/lesynth/InsertionSortHoleSort.scala |  53 ++
 testcases/lesynth/ListOperations.scala        |  45 +
 testcases/lesynth/ListOperationsHole.scala    |  24 +
 testcases/lesynth/ListOperationsHole2.scala   |  24 +
 testcases/lesynth/MergeSortHole.scala         |  81 ++
 39 files changed, 5413 insertions(+)
 create mode 100644 src/main/scala/insynth/InSynth.scala
 create mode 100644 src/main/scala/insynth/leon/CommonTypes.scala
 create mode 100644 src/main/scala/insynth/leon/LeonDeclaration.scala
 create mode 100644 src/main/scala/insynth/leon/LeonQuery.scala
 create mode 100644 src/main/scala/insynth/leon/LeonQueryBuilder.scala
 create mode 100644 src/main/scala/insynth/leon/ReconstructionExpression.scala
 create mode 100644 src/main/scala/insynth/leon/TypeTransformer.scala
 create mode 100644 src/main/scala/insynth/leon/loader/DeclarationFactory.scala
 create mode 100644 src/main/scala/insynth/leon/loader/HoleExtractor.scala
 create mode 100644 src/main/scala/insynth/leon/loader/LoadSpec.scala
 create mode 100644 src/main/scala/insynth/leon/loader/Loader.scala
 create mode 100644 src/main/scala/insynth/leon/loader/PreLoader.scala
 create mode 100644 src/main/scala/insynth/reconstruction/Output.scala
 create mode 100644 src/main/scala/insynth/reconstruction/Reconstructor.scala
 create mode 100644 src/main/scala/insynth/reconstruction/codegen/CodeGenerator.scala
 create mode 100644 src/main/scala/lesynth/ExampleRunner.scala
 create mode 100644 src/main/scala/lesynth/Globals.scala
 create mode 100755 src/main/scala/lesynth/InputExamples.scala
 create mode 100755 src/main/scala/lesynth/Refiner.scala
 create mode 100755 src/main/scala/lesynth/Report.scala
 create mode 100755 src/main/scala/lesynth/SynthesizerExamples.scala
 create mode 100755 src/main/scala/lesynth/rules/ConditionAbductionSynthesisImmediate.scala
 create mode 100755 src/main/scala/lesynth/rules/ConditionAbductionSynthesisTwoPhase.scala
 create mode 100644 src/test/scala/insynth/reconstruction/CodeGeneratorTest.scala
 create mode 100644 src/test/scala/insynth/reconstruction/PhaseCombinationTest.scala
 create mode 100644 src/test/scala/insynth/reconstruction/ReconstructorTest.scala
 create mode 100644 src/test/scala/insynth/testutil/CommonLeonExpressions.scala
 create mode 100644 src/test/scala/lesynth/AnalyzerTest.scala
 create mode 100644 src/test/scala/lesynth/RefinerTest.scala
 create mode 100755 src/test/scala/lesynth/TryOutSynthesizerExamplesTest.scala
 create mode 100644 src/test/scala/lesynth/TryOutTest.scala
 create mode 100644 src/test/scala/lesynth/TryOutTestWithFiltering.scala
 create mode 100644 testcases/lesynth/InsertionSortFull.scala
 create mode 100644 testcases/lesynth/InsertionSortHoleInsert.scala
 create mode 100644 testcases/lesynth/InsertionSortHoleSort.scala
 create mode 100644 testcases/lesynth/ListOperations.scala
 create mode 100644 testcases/lesynth/ListOperationsHole.scala
 create mode 100644 testcases/lesynth/ListOperationsHole2.scala
 create mode 100644 testcases/lesynth/MergeSortHole.scala

diff --git a/src/main/scala/insynth/InSynth.scala b/src/main/scala/insynth/InSynth.scala
new file mode 100644
index 000000000..bcba1f478
--- /dev/null
+++ b/src/main/scala/insynth/InSynth.scala
@@ -0,0 +1,71 @@
+package insynth
+
+import insynth.reconstruction.stream.{ OrderedStreamFactory, UnorderedStreamFactory }
+import insynth.reconstruction.codegen.CodeGenerator
+import insynth.reconstruction.Reconstructor
+
+import insynth.interfaces.Declaration
+import insynth.engine.InitialEnvironmentBuilder
+
+import insynth.leon.loader.LeonLoader
+import insynth.leon.LeonQueryBuilder
+
+import _root_.leon.purescala.Definitions.Program
+import _root_.leon.purescala.Trees.Hole
+import _root_.leon.purescala.TypeTrees.{ TypeTree => Type }
+
+import insynth.util.logging.HasLogger
+
+/**
+ * Main class for the synthesis process invocation
+ * @param program Leon program object that contains the hole
+ * @param hole hole in the program on which the synthesis is called 
+ */
+class InSynth(declarations: List[Declaration], goalType: Type, ordered: Boolean = true) extends HasLogger {
+  
+//  def this(program: Program, hole: Hole, ordered: Boolean) =
+//    this(new LeonLoader(program, hole).load, hole.getType, ordered)
+    
+  def this(loader: LeonLoader, ordered: Boolean) =
+    this(loader.load, loader.hole.getType, ordered)
+  
+  lazy val solver = new Solver(declarations, new LeonQueryBuilder(goalType))
+  
+  def getExpressions = {
+    val proofTree = solver.getProofTree
+    	
+		assert(proofTree != null, "Proof tree is null" )  
+    assert(1 == proofTree.getNodes.size)
+          
+    val codegen = new CodeGenerator
+    
+    Reconstructor(proofTree.getNodes.head, codegen, ordered)
+  }
+  
+  def getExpressions(builder: InitialEnvironmentBuilder) = {
+    val proofTree = solver.getProofTree(builder)
+    	
+		assert(proofTree != null, "Proof tree is null" )  
+    assert(1 == proofTree.getNodes.size)
+          
+    val codegen = new CodeGenerator
+    
+    Reconstructor(proofTree.getNodes.head, codegen, ordered)
+  }
+  
+  def getCurrentBuilder = solver.currentBuilder
+
+}
+
+object InSynth {
+  
+  def apply(declarations: List[Declaration], goalType: Type, ordered: Boolean) =
+    new InSynth(declarations, goalType, ordered)
+  
+//  def apply(program: Program, hole: Hole, ordered: Boolean) =
+//    new InSynth(new LeonLoader(program, hole).load, hole.getType, ordered)
+    
+  def apply(loader: LeonLoader, ordered: Boolean) =
+    new InSynth(loader.load, loader.hole.getType, ordered)
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/CommonTypes.scala b/src/main/scala/insynth/leon/CommonTypes.scala
new file mode 100644
index 000000000..1e7f5ba62
--- /dev/null
+++ b/src/main/scala/insynth/leon/CommonTypes.scala
@@ -0,0 +1,14 @@
+package insynth.leon
+
+import insynth.structures.{ SuccinctType, Const, Arrow, TSet }
+
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Common.FreshIdentifier
+import leon.purescala.Definitions.AbstractClassDef
+
+object CommonTypes {
+  	
+  val LeonBottomType = AbstractClassType(new AbstractClassDef(FreshIdentifier("$IDontCare$")))
+  val InSynthBottomType = Const("$IDontCare$")
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/LeonDeclaration.scala b/src/main/scala/insynth/leon/LeonDeclaration.scala
new file mode 100644
index 000000000..40255fb76
--- /dev/null
+++ b/src/main/scala/insynth/leon/LeonDeclaration.scala
@@ -0,0 +1,51 @@
+package insynth.leon
+
+import insynth.structures.SuccinctType
+import insynth.interfaces.Declaration
+import insynth.structures.Weight._
+
+import leon.purescala.TypeTrees.{ TypeTree => LeonType }
+import leon.purescala.Trees.Expr
+
+case class LeonDeclaration(
+	override val inSynthType: SuccinctType, override val weight: Weight,
+	val leonType: LeonType, val expression: ReconstructionExpression 
+)
+extends Declaration(inSynthType, weight) {
+      
+  def this(expression: ReconstructionExpression, inSynthType: SuccinctType,
+    leonType: LeonType, commutative: Boolean, weight: Weight    
+  ) = {
+    this(inSynthType, weight, leonType, expression)
+    isCommunitative = commutative
+  } 
+  
+  def this(expression: ReconstructionExpression, inSynthType: SuccinctType, leonType: LeonType)
+  	= this(inSynthType, 1.0f, leonType, expression)
+  
+  var isCommunitative = false
+	
+  private var query = false
+      
+  def getDomainType = leonType
+    
+  def getSimpleName = expression.toString
+  
+  override def toString = getSimpleName + ":" + inSynthType + ":" + leonType + "[" + expression + "]"
+  
+}
+
+object LeonDeclaration {
+  
+  def apply(expression: ReconstructionExpression, inSynthType: SuccinctType, leonType: LeonType)
+  	= new LeonDeclaration(expression, inSynthType, leonType)
+  
+  def apply(expression: ReconstructionExpression, inSynthType: SuccinctType,
+		leonType: LeonType, weight: Weight
+	) =	new LeonDeclaration(inSynthType, weight, leonType, expression)
+    
+  def apply(expression: ReconstructionExpression, inSynthType: SuccinctType,
+    leonType: LeonType, commutative: Boolean, weight: Weight    
+  ) = new LeonDeclaration(expression, inSynthType, leonType, commutative, weight)
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/LeonQuery.scala b/src/main/scala/insynth/leon/LeonQuery.scala
new file mode 100644
index 000000000..c4e1dc70c
--- /dev/null
+++ b/src/main/scala/insynth/leon/LeonQuery.scala
@@ -0,0 +1,20 @@
+package insynth.leon
+
+import insynth.leon.loader.DeclarationFactory
+import insynth.engine.InitialSender
+import insynth.structures.SuccinctType
+import insynth.interfaces.Query
+
+import leon.purescala.TypeTrees._
+import leon.purescala.Common.FreshIdentifier
+
+case class LeonQuery(override val inSynthRetType: SuccinctType, decl: LeonDeclaration, sender: InitialSender)
+extends Query(inSynthRetType) {
+  
+  def getSolution = sender.getAnswers
+  
+  def getDeclaration = decl
+  
+  def getSender = sender
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/LeonQueryBuilder.scala b/src/main/scala/insynth/leon/LeonQueryBuilder.scala
new file mode 100644
index 000000000..e8b63a103
--- /dev/null
+++ b/src/main/scala/insynth/leon/LeonQueryBuilder.scala
@@ -0,0 +1,24 @@
+package insynth.leon
+
+import insynth.leon.loader.DeclarationFactory
+import insynth.structures.{ SuccinctType, Const, Arrow, TSet }
+import insynth.engine.InitialSender
+import insynth.interfaces.QueryBuilder
+
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Common.FreshIdentifier
+import leon.purescala.Definitions.AbstractClassDef
+
+import CommonTypes._
+
+class LeonQueryBuilder(leonGoalType: LeonType) extends QueryBuilder(TypeTransformer(leonGoalType)) {
+  	  
+  val leonRetType = LeonBottomType
+  val leonType = FunctionType(List(leonGoalType), leonRetType)
+  
+  val inSynthRetType = InSynthBottomType
+  val inSynthType = Arrow(TSet(tpe), inSynthRetType)
+  
+  def getQuery = LeonQuery(inSynthRetType, new LeonDeclaration(QueryExpression, inSynthType, leonType), new InitialSender())
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/ReconstructionExpression.scala b/src/main/scala/insynth/leon/ReconstructionExpression.scala
new file mode 100644
index 000000000..26731b2ef
--- /dev/null
+++ b/src/main/scala/insynth/leon/ReconstructionExpression.scala
@@ -0,0 +1,73 @@
+package insynth.leon
+
+import leon.purescala.TypeTrees.{ TypeTree => LeonType }
+import leon.purescala.Trees.Expr
+import leon.purescala.Common.Identifier
+
+trait ReconstructionExpression {
+  	
+	def getSimpleName: String
+	
+	override def toString = getSimpleName
+  
+}
+
+case object QueryExpression extends ReconstructionExpression {
+  
+  def getSimpleName = "query"
+  
+}
+
+case object ErrorExpression extends ReconstructionExpression {
+  
+  def getSimpleName = "error"  
+  
+}
+
+object ImmediateExpression {
+  
+  def apply(id: Identifier, expr:  Expr): ImmediateExpression = ImmediateExpression(id.toString, expr)
+  
+}
+
+case class ImmediateExpression( name: String, expr:  Expr ) extends ReconstructionExpression {
+  
+  def this(id: Identifier, expr:  Expr) = this(id.toString, expr)
+  
+  def apply( ) = expr
+  
+	def getSimpleName: String = name
+  
+}
+
+object UnaryReconstructionExpression {
+  
+  def apply(id: Identifier, funToExpr: Expr => Expr): UnaryReconstructionExpression = UnaryReconstructionExpression(id.toString, funToExpr)
+  
+}
+
+case class UnaryReconstructionExpression( name: String, funToExpr: Expr => Expr ) extends ReconstructionExpression {
+  
+  def this(id: Identifier, funToExpr: Expr => Expr) = this(id.toString, funToExpr)
+  
+  def apply( op: Expr ) = funToExpr(op)
+  
+	def getSimpleName: String = name
+  
+}
+
+object NaryReconstructionExpression {
+  
+  def apply(id: Identifier, funToExpr: List[Expr] => Expr): NaryReconstructionExpression = NaryReconstructionExpression(id.toString, funToExpr)
+  
+}
+
+case class NaryReconstructionExpression( name: String, funToExpr: List[Expr] => Expr ) extends ReconstructionExpression {
+  
+  def this(id: Identifier, funToExpr: List[Expr] => Expr) = this(id.toString, funToExpr)
+  
+  def apply( op: List[Expr] ) = funToExpr(op)
+  
+	def getSimpleName: String = name
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/TypeTransformer.scala b/src/main/scala/insynth/leon/TypeTransformer.scala
new file mode 100644
index 000000000..d8358f7d1
--- /dev/null
+++ b/src/main/scala/insynth/leon/TypeTransformer.scala
@@ -0,0 +1,52 @@
+package insynth.leon
+
+import insynth.structures._
+
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, BottomType => LeonBottomType, _ }
+import leon.purescala.Common.FreshIdentifier
+import leon.purescala.Definitions._
+
+object TypeTransformer extends ( LeonType => SuccinctType ) {
+  
+  def apply(typeDef: ClassTypeDef): SuccinctType = {    		
+		implicit def singletonList(x: SuccinctType) = List(x)
+
+    typeDef match {
+      case abs: AbstractClassDef => Const(abs.id.name)
+      case caseClassDef: CaseClassDef => Const(caseClassDef.id.name)
+    }
+  }
+	
+  def apply(leonType: LeonType): SuccinctType = {    		
+		implicit def singletonList(x: SuccinctType) = List(x)
+
+    leonType match {
+      case Untyped => throw new RuntimeException("Should not happen at this point")
+      case AnyType => Const("Any")
+      case LeonBottomType => BottomType //Const("Bottom")
+      case BooleanType => Const("Boolean")
+      case UnitType => Const("Unit")
+      case Int32Type => Const("Int")
+      case ListType(baseType) => Instance("List", this(baseType) ) 
+      case ArrayType(baseType) => Instance("Array", this(baseType) )
+      case TupleType(baseTypes) => Instance("Tuple", baseTypes map { this(_) } toList )
+      case SetType(baseType) => Instance("Set", this(baseType) )
+      case MultisetType(baseType) => Instance("MultiSet", this(baseType) )
+      case MapType(from, to) => Instance("Map", List( this(from), this(to) ))
+      case FunctionType(froms, to) => transformFunction(to, froms)
+      case c: ClassType => Const(c.id.name)
+    }
+  }
+
+  private def transformFunction(fun: LeonType, params: List[LeonType]): SuccinctType = fun match {
+    case FunctionType(froms, to) =>
+      transformFunction(to, params ++ froms)
+    case Untyped => throw new RuntimeException("Should not happen at this point")
+    // query will have this
+    case LeonBottomType =>
+      Arrow( TSet(params map this distinct), this(fun) )
+    case t =>
+      Arrow( TSet(params map this distinct), this(t) )
+  }
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/loader/DeclarationFactory.scala b/src/main/scala/insynth/leon/loader/DeclarationFactory.scala
new file mode 100644
index 000000000..16c2bd6df
--- /dev/null
+++ b/src/main/scala/insynth/leon/loader/DeclarationFactory.scala
@@ -0,0 +1,75 @@
+package insynth.leon.loader
+
+import insynth.leon.{ LeonDeclaration => Declaration, ReconstructionExpression,
+  ErrorExpression, UnaryReconstructionExpression, ImmediateExpression }
+import insynth.engine.InitialEnvironmentBuilder
+import insynth.structures.{ SuccinctType => InSynthType, Variable => InSynthVariable, _}
+import insynth.leon.TypeTransformer
+
+import leon.purescala.Definitions.{ Program, FunDef, ClassTypeDef, VarDecl }
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Common.{ Identifier, FreshIdentifier }
+import leon.purescala.Trees._
+
+object DeclarationFactory {
+  
+  val WEIGHT_FOR_LITERALS = 5f
+     
+  val listOfInstanceTypes = List(BooleanType, Int32Type)
+  
+  def makeDeclaration(expression: ReconstructionExpression, leonType: LeonType) = {
+    val inSynthType = TypeTransformer(leonType)
+    Declaration(expression, inSynthType, leonType)    
+  }
+  
+  def makeLiteral(expression: ReconstructionExpression, leonType: LeonType) = {
+    val inSynthType = TypeTransformer(leonType)
+    Declaration(expression, inSynthType, leonType, WEIGHT_FOR_LITERALS)    
+  }
+  
+  def makeDeclaration(expression: ReconstructionExpression, leonType: LeonType, commutative: Boolean) = {
+    val inSynthType = TypeTransformer(leonType)
+    Declaration(expression, inSynthType, leonType)    
+  }
+  
+  def makeArgumentDeclaration(id: Identifier) = {
+    val leonType = id.getType
+    val inSynthType = TypeTransformer(leonType)
+    Declaration(ImmediateExpression(id, Variable(id)), inSynthType, leonType)    
+  }
+  
+  def makeArgumentDeclaration(varDecl: VarDecl) = {
+    val leonType = varDecl.getType
+    val inSynthType = TypeTransformer(leonType)
+    Declaration(ImmediateExpression(varDecl.id, Variable(varDecl.id)), inSynthType, leonType)    
+  }
+  
+  def makeInheritance(from: ClassTypeDef, to: ClassTypeDef) = {
+    val expr = UnaryReconstructionExpression(from + " is " + to, identity[Expr] _)
+    val inSynthType = Arrow(TSet(TypeTransformer(from)), TypeTransformer(to))
+    Declaration(expr, inSynthType, Untyped)    
+  }
+  
+  def makeInheritance(from: ClassType, to: ClassType) = {
+    val expr = UnaryReconstructionExpression("Inheritane(" + from.classDef + "<<is>>" + to.classDef + ")", identity[Expr] _)
+    val inSynthType = Arrow(TSet(TypeTransformer(from)), TypeTransformer(to))
+    Declaration(expr, inSynthType, FunctionType(List(from), to))    
+  }  
+  
+  def makeDeclarationForTypes(types: List[LeonType])(makeFunction: LeonType => _) =   
+    for (tpe <- types)
+	    makeFunction(tpe)
+	    	    
+  def yieldDeclarationForTypes(types: List[LeonType])(makeFunction: LeonType => Declaration) =   
+    for (tpe <- types)
+	    yield makeFunction(tpe)
+	    
+  def makeAbstractDeclaration(inSynthType: InSynthType) = {
+      throw new RuntimeException
+    Declaration(getAbsExpression(inSynthType), inSynthType, null)
+  }
+    	
+  // define this for abstract declarations
+  def getAbsExpression(inSynthType: InSynthType) =
+    ErrorExpression
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/loader/HoleExtractor.scala b/src/main/scala/insynth/leon/loader/HoleExtractor.scala
new file mode 100644
index 000000000..10ee46b04
--- /dev/null
+++ b/src/main/scala/insynth/leon/loader/HoleExtractor.scala
@@ -0,0 +1,106 @@
+package insynth.leon.loader
+
+import insynth.leon.{ ImmediateExpression, LeonDeclaration }
+
+import leon.purescala.Definitions.{ Program, FunDef }
+import leon.purescala.Trees._
+import leon.purescala.Extractors._
+import leon.purescala.Common.{ Identifier }
+
+class HoleExtractor(program: Program, hole: Hole) {
+  
+  import DeclarationFactory._
+  
+  def extractHole: Option[(FunDef, List[LeonDeclaration])] = {
+    
+    // the list of declarations to be returned
+    //var list = scala.collection.mutable.MutableList[Declaration]()
+    
+    // XXX we currently go through all functions, not efficient!
+    var foundHoleCount = 0
+    for (
+      funDef <-program.definedFunctions;
+      if funDef.hasBody;
+      val (foundHole, declarations) = scanMethod(funDef.getBody);      
+      if foundHole;
+      val argDeclarations = funDef.args map { makeArgumentDeclaration(_) }
+    ) {
+      // hack
+      //Globals.holeFunDef = funDef
+      
+      foundHoleCount+=1
+          	
+    	return Some((funDef, argDeclarations.toList ++ declarations))
+    }
+    //assert(foundHoleCount <= 1)
+    
+    None
+    
+  }
+  
+  def scanMethod(functionBody: Expr): (Boolean, Set[LeonDeclaration]) = {
+    
+    case class LocalPair(foundHole: Boolean, currentSet: Set[Identifier]) {
+    	def ++?(pair: Pair[Boolean, Set[Identifier]]): (Boolean, Set[Identifier]) = {
+    	  val (foundHoleSec, currentSetSec) = pair
+    	  if (foundHole)
+    	    (true, currentSet)
+    	  else (foundHoleSec, currentSet ++ currentSetSec)
+    	}  
+    	def +(id: Identifier): (Boolean, Set[Identifier]) = {
+    	  (foundHole, currentSet + id)
+    	}  
+    	def /:\(pair: Pair[Boolean, Set[Identifier]]): (Boolean, Set[Identifier]) = {
+    	  if (foundHole)
+    	    (foundHole, currentSet)
+  	    else
+  	      pair
+    	}  
+    }
+	  implicit def localPairCast(pair: Pair[Boolean, Set[Identifier]]) = LocalPair(pair._1, pair._2)
+    
+	  def allIdentifiers(expr: Expr) : (Boolean, Set[Identifier]) = expr match {
+	    case l @ Let(binder, e, b) => allIdentifiers(e) /:\ ( allIdentifiers(b) + binder )
+//	    case l @ LetVar(binder, e, b) => allIdentifiers(e) /:\ ( allIdentifiers(b) + binder )
+//	    case l @ LetDef(fd, b) =>
+//	      allIdentifiers(fd.getBody) /:\ ( allIdentifiers(b) + fd.id )
+	    
+	    //case block @ Block(exprs, last)	    
+	    // NOTE: NAryOperator covers block
+	    case n @ NAryOperator(args, _) =>
+	      ((false, Set[Identifier]()) /: (args map (allIdentifiers(_)))) {	        
+	        case (currentPair, newPair) => currentPair /:\ newPair
+	      }
+	    case b @ BinaryOperator(a1,a2,_) => allIdentifiers(a1) ++? allIdentifiers(a2)
+	    case u @ UnaryOperator(a,_) => allIdentifiers(a)
+	    case i @ IfExpr(a1,a2,a3) => allIdentifiers(a1) /:\ allIdentifiers(a2) /:\ allIdentifiers(a3)
+	    case m @ MatchExpr(scrut, cses) =>
+	      // ??
+	      allIdentifiers(scrut) ++?
+	      ( (false, Set[Identifier]()) /: ( cses map {
+	          cse =>
+	        	val rhsResult = allIdentifiers(cse.rhs)
+	        	(rhsResult._1, rhsResult._2 ++ cse.pattern.allIdentifiers)
+        	})
+        ) {        
+	        case (currentPair, newPair) => currentPair ++? newPair
+	      }
+	    case Variable(id) => (false, Set.empty)
+	    case h: Hole => (true, Set.empty) 
+	    case t: Terminal => (false, Set.empty)
+	  }
+	  
+	  val (foundHole, collectedIdentifiers) = allIdentifiers(functionBody)
+	  
+	  (
+      foundHole,
+		  for ( id <- collectedIdentifiers )
+		    yield makeDeclaration(
+	        ImmediateExpression( id, Variable(id) ), 
+	        id.getType
+	      )
+    )
+	  
+  }
+
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/loader/LoadSpec.scala b/src/main/scala/insynth/leon/loader/LoadSpec.scala
new file mode 100644
index 000000000..835e1f8fc
--- /dev/null
+++ b/src/main/scala/insynth/leon/loader/LoadSpec.scala
@@ -0,0 +1,6 @@
+package insynth.leon.loader
+
+/** defines what to load in the PreLoader */
+class LoadSpec {
+
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/loader/Loader.scala b/src/main/scala/insynth/leon/loader/Loader.scala
new file mode 100644
index 000000000..f318a7a36
--- /dev/null
+++ b/src/main/scala/insynth/leon/loader/Loader.scala
@@ -0,0 +1,239 @@
+package insynth.leon.loader
+
+import insynth.leon.{ LeonDeclaration => Declaration, NaryReconstructionExpression, ImmediateExpression, UnaryReconstructionExpression }
+import insynth.structures.{ SuccinctType => InSynthType }
+import insynth.interfaces.Loader
+import insynth.util.logging.HasLogger
+
+import leon.purescala.Definitions.{ Program, FunDef }
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Trees.{ Hole, Expr, FunctionInvocation, _ }
+import leon.purescala.Common.{ Identifier }
+import leon.purescala.Definitions.{ AbstractClassDef, CaseClassDef, ClassTypeDef }
+
+case class LeonLoader(program: Program, hole: Hole,
+  variables: List[Identifier], loadArithmeticOps: Boolean = true) extends Loader with HasLogger {  
+  //var temporaryDesiredType: LeonType = Int32Type
+  
+  lazy val classMap: Map[Identifier, ClassType] = extractClasses
+  
+  lazy val directSubclassesMap: Map[ClassType, Set[ClassType]] = initializeSubclassesMap(program)
+  
+  // arguments + all found variables in the hole function
+  lazy val variableDeclarations: Seq[Declaration] = variables.map(DeclarationFactory.makeArgumentDeclaration(_))
+  
+  //lazy val holeDef = initResults._3
+  
+  lazy val initResults = init
+  
+  import DeclarationFactory._
+        
+  def load: List[Declaration] = initResults
+  
+  private def init = {      
+
+    // the list of declarations to be returned
+    var list = scala.collection.mutable.MutableList[Declaration]()
+            
+    /* add declarations to builder */
+          
+    // add function declarations
+    for( funDef@FunDef(id, returnType, args, _, _, _) <- program.definedFunctions ) {
+      val leonFunctionType = FunctionType(args map { _.tpe } toList, returnType)
+              
+      val newDeclaration = makeDeclaration(
+        NaryReconstructionExpression( id, { args: List[Expr] => FunctionInvocation(funDef, args) } ), 
+        leonFunctionType
+      )        
+      
+      list += newDeclaration        
+      fine("Leon loader added declaration: " + newDeclaration)        
+    }
+    
+    // add predefs and literals
+    list ++= PreLoader(loadArithmeticOps)
+    
+    list ++= extractInheritances
+    
+    list ++= extractCaseClasses
+    
+    list ++= extractFields
+    
+    list ++= extractClassDependentDeclarations
+    
+    list ++= variableDeclarations
+    
+    list.toList
+    
+    // no need for doing this (we will have everything from the synthesis problem context)
+//    new HoleExtractor(program, hole).extractHole match {
+//      case Some((holeDef, decls)) =>
+//        list ++= decls
+//                  
+//        (list.toList, decls, holeDef)
+//      case _ =>
+//        throw new RuntimeException("Hole extractor problem")
+//    }     
+  }
+    
+  def initializeSubclassesMap(program: Program) = {  
+    val seqOfPairs = for (classDef <- program.definedClasses)
+    	yield classDef match {
+    		case caseClassDef: CaseClassDef =>
+    		  val caseClassType = classMap(classDef.id)
+    		  ( caseClassType, Set[ClassType]( /*caseClassType*/ ) )
+    		case absClassDef: AbstractClassDef =>
+    		  val childrenTypes = for (child <- absClassDef.knownChildren)
+    		    yield classMap(child.id)
+    		  ( classMap(absClassDef.id), childrenTypes.toSet )
+    	}
+    
+    seqOfPairs.toMap
+  }
+    
+  def extractClasses: Map[Identifier, ClassType] = {    
+    (
+      for (classDef <- program.definedClasses)
+	    	yield classDef match {
+	    		case caseClassDef: CaseClassDef => ( classDef.id, CaseClassType(caseClassDef) )
+	    		case absClassDef: AbstractClassDef => ( absClassDef.id, AbstractClassType(absClassDef) )
+	    	}
+    ) toMap
+  }
+  
+  // TODO add anyref to all and all to bottom ???
+  def extractInheritances: Seq[Declaration] = {
+    
+    def extractInheritancesRec(classDef: ClassTypeDef): List[Declaration] = 
+      classDef match {
+        case abs: AbstractClassDef =>
+          Nil ++ 
+          (
+            for (child <- abs.knownChildren)
+            	yield makeInheritance(
+          	    classMap(child.id), classMap(abs.id)
+        	    )
+          ) ++ (
+            for (child <- abs.knownChildren)
+            	yield extractInheritancesRec(child)
+          ).flatten
+        case _ =>
+          Nil
+    	}
+    
+//    (for (classHierarchyRoot <- program.classHierarchyRoots)
+//    	yield extractInheritancesRec(classHierarchyRoot)).flatten.toList
+    
+    for (classHierarchyRoot <- program.classHierarchyRoots;
+    			inheritance <- extractInheritancesRec(classHierarchyRoot))
+    	yield inheritance
+  }
+  
+  def extractFields: Seq[Declaration] = {
+    def extractFields(classDef: ClassTypeDef) = classDef match {
+      case abs: AbstractClassDef =>
+        // this case does not seem to work
+        //abs.fields
+        Seq.empty
+      case cas: CaseClassDef => 
+        for (field <- cas.fields)
+          yield makeDeclaration(
+		        UnaryReconstructionExpression( "Field(" + cas + "." + field.id + ")", { CaseClassSelector(cas, _: Expr, field.id) } ), 
+		        FunctionType(List(classMap(cas.id)), field.id.getType)
+		      )
+    }
+    
+    for (classDef <- program.definedClasses;
+    		decl <- extractFields(classDef))
+    	yield decl
+  }
+      
+  def extractCaseClasses: Seq[Declaration] = {    
+    for (caseClassDef@CaseClassDef(id, parent, fields) <- program.definedClasses)
+    	yield fields match {
+      	case Nil => makeDeclaration(
+	        ImmediateExpression( "Cst(" + id + ")", { CaseClass(caseClassDef, Nil) } ), 
+	        classMap(id)
+	      )
+      	case _ => makeDeclaration(
+	        NaryReconstructionExpression( "Cst(" + id + ")", { CaseClass(caseClassDef, _: List[Expr]) } ), 
+	        FunctionType(fields map { _.id.getType } toList, classMap(id))
+	      )
+    	}
+  }
+  
+  def extractClassDependentDeclarations: Seq[Declaration] = {
+//    def getClassDef(id: Identifier): CaseClassDef = {
+//      program.caseClassDef(id.name)
+//      program.definedClasses.find( _.id == `id` ) match {
+//        case Some(classDef) => classDef
+//        case _ => throw new RuntimeException
+//      }
+//    }
+    
+    for ( classDef@CaseClassDef(_, _, _) <- program.definedClasses filter { _.isInstanceOf[CaseClassDef] }; 
+    			if classDef.hasParent)
+      yield makeDeclaration(
+        UnaryReconstructionExpression( "isInstance[" + classDef.id + "]", { CaseClassInstanceOf(classDef, _: Expr) 
+        	} ), 
+        FunctionType(List(classMap(classDef.parent.get.id)), BooleanType)
+      )
+  }
+  
+  // XXX does not care about hiding, does not see function arguments
+  
+//  def loadLocals(functionBody: Expr, hole: Expr): Set[Declaration] = {
+//    scanMethod(functionBody, hole)._2
+//  }
+  
+}
+
+// old load function
+//  def load(program: Program, hole: Hole): List[Declaration] = {
+//    initializeClassMap(program)
+//    
+//    var list: scala.collection.mutable.LinkedList[Declaration] = scala.collection.mutable.LinkedList()
+//    
+//    /* add declarations to builder */
+//          
+//    // add function declarations
+//    for( funDef@FunDef(id, returnType, args, _, _, _) <- program.definedFunctions ) {
+//      val leonFunctionType = FunctionType(args map { _.tpe } toList, returnType)
+//              
+//      val newDeclaration = makeDeclaration(
+//        NaryReconstructionExpression( id, { args: List[Expr] => FunctionInvocation(funDef, args) } ), 
+//        leonFunctionType
+//      )        
+//      
+//      list :+= newDeclaration              
+//    }
+//    
+//    // add predefs and literals
+//    list ++= PreLoader()
+//    
+//    list ++= extractInheritances(program)
+//    
+//    list ++= extractCaseClasses(program)
+////    
+////    builder.addDeclarations( extractClassDependentDeclarations(program) )
+//    
+//    // XXX we currently go through all functions, not efficient!
+//    var foundHoleCount = 0
+//    for (
+//      funDef <-program.definedFunctions;
+//      if funDef.hasBody;
+//      val (foundHole, declarations) = scanMethod(funDef.getBody, hole);      
+//      if foundHole;
+//      val argDeclarations = funDef.args map { makeArgumentDeclaration(_) }
+//    ) {
+//      // hack
+//      Globals.holeFunDef = funDef      
+//      foundHoleCount+=1
+//      
+//    	list ++= declarations.toList
+//    	list ++= argDeclarations
+//    }
+//    assert(foundHoleCount <= 1)
+//    
+//    list toList
+//  }
\ No newline at end of file
diff --git a/src/main/scala/insynth/leon/loader/PreLoader.scala b/src/main/scala/insynth/leon/loader/PreLoader.scala
new file mode 100644
index 000000000..1f72ac43b
--- /dev/null
+++ b/src/main/scala/insynth/leon/loader/PreLoader.scala
@@ -0,0 +1,262 @@
+package insynth.leon.loader
+
+import insynth.structures.{ SuccinctType => InSynthType }
+import insynth.leon.{ LeonDeclaration => Declaration, NaryReconstructionExpression => NAE, ImmediateExpression => IE }
+import insynth.engine.InitialEnvironmentBuilder
+
+import leon.purescala.Definitions.{ Program, FunDef }
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Common.{ Identifier }
+import leon.purescala.Trees._
+
+object PreLoader extends ( (Boolean) => List[Declaration] ) {
+  
+  import DeclarationFactory._
+  
+  def apply(loadArithmeticOps: Boolean = true): List[Declaration] = {
+
+    val supportedBaseTypes = List(BooleanType, Int32Type)
+    var list = scala.collection.mutable.MutableList[Declaration]()
+        
+    list += getAnd
+    list += getNot
+    
+    list += getLessEquals
+    list ++= getEquals(supportedBaseTypes)
+    
+    if (loadArithmeticOps)
+      list ++= getArithmeticOps
+    
+    list toList
+  }
+  
+  def getAnd =
+    // case And(args) if args.isEmpty => BooleanLiteral(true)    
+    makeDeclaration(
+      makeNAE("And", { case List(arg1, arg2) => And( List(arg1, arg2) ) }),
+      FunctionType( List(BooleanType, BooleanType), BooleanType )
+    )    
+    
+  def getNot =
+    // case Not(arg) => rec(ctx, arg) match {
+    makeDeclaration(
+      makeNAE( "Not", { case List(arg) => Not( arg ) } ),
+      FunctionType( List(BooleanType), BooleanType )
+    )
+    
+  def getOr =
+    // case Or(args) if args.isEmpty => BooleanLiteral(false)    
+    makeDeclaration(
+      makeNAE( "Or", { case List(arg1, arg2) => Or( List(arg1, arg2) ) } ),
+      FunctionType( List(BooleanType, BooleanType), BooleanType )
+    )  
+    
+  def getImplies =
+    // case Implies(l, r) => (rec(ctx, l), rec(ctx, r)) match {
+    makeDeclaration(
+      makeNAE( "=>", { case List(left, right) => Implies( left, right ) } ),
+      FunctionType( List(BooleanType, BooleanType), BooleanType )
+    ) 
+    
+  def getIff =
+    //case Iff(le, re) => (rec(ctx, le), rec(ctx, re)) match {
+    makeDeclaration(
+      makeNAE( "<=>", { case List(left, right) => Iff( left, right ) } ),
+      FunctionType( List(BooleanType, BooleanType), BooleanType )
+    ) 
+    
+  def getEquals(listOfInstanceTypes: List[LeonType]) =
+    // case Equals(le, re) => {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "=", { case List(left, right) => Equals( left, right ) } ),
+	      FunctionType( List(x, x), BooleanType ),
+	      true
+	    ) 
+    }
+    
+  def getArithmeticOps = {
+	    // case Plus(l, r) => (rec(ctx, l), rec(ctx, r)) match {
+	    makeDeclaration(
+	      makeNAE( "+", { case List(left, right) => Plus( left, right ) } ),
+	      FunctionType( List(Int32Type, Int32Type), Int32Type )
+	    ) ::
+	    // case Minus(l, r) => (rec(ctx, l), rec(ctx, r)) match {
+	    makeDeclaration(
+	      makeNAE( "-", { case List(left, right) => Minus( left, right ) } ),
+	      FunctionType( List(Int32Type, Int32Type), Int32Type )
+	    ) ::
+	    // case UMinus(e) => rec(ctx, e) match {
+	    makeDeclaration(
+	      makeNAE( "UMinus", { case List(e) => UMinus( e ) } ),
+	      FunctionType( List(Int32Type), Int32Type )
+	    ) ::
+	  	//case Times(l, r) => (rec(ctx, l), rec(ctx, r)) match {
+	    makeDeclaration(
+	      makeNAE( "*", { case List(left, right) => Times( left, right ) } ),
+	      FunctionType( List(Int32Type, Int32Type), Int32Type )
+	    ) ::
+	    // case Division(l, r) => (rec(ctx, l), rec(ctx, r)) match {
+	    makeDeclaration(
+	      makeNAE( "/", { case List(left, right) => Division( left, right ) } ),
+	      FunctionType( List(Int32Type, Int32Type), Int32Type )
+	    ) ::
+	    // case Modulo(l,r) => (rec(ctx,l), rec(ctx,r)) match {
+	    makeDeclaration(
+	      makeNAE( "%", { case List(left, right) => Modulo( left, right ) } ),
+	      FunctionType( List(Int32Type, Int32Type), Int32Type )
+	    ) :: Nil
+    }
+    
+  def getLessThan =
+    // case LessThan(l,r) => (rec(ctx,l), rec(ctx,r)) match {
+    makeDeclaration(
+      makeNAE( "<", { case List(left, right) => LessThan( left, right ) } ),
+      FunctionType( List(Int32Type, Int32Type), BooleanType )
+    ) 
+    
+  def getGreaterThan =
+    // case GreaterThan(l,r) => (rec(ctx,l), rec(ctx,r)) match {
+    makeDeclaration(
+      makeNAE( ">", { case List(left, right) => LessThan( left, right ) } ),
+      FunctionType( List(Int32Type, Int32Type), BooleanType )
+    ) 
+    
+  def getLessEquals =
+    // case LessEquals(l,r) => (rec(ctx,l), rec(ctx,r)) match {
+    makeDeclaration(
+      makeNAE( "<=", { case List(left, right) => LessEquals( left, right ) } ),
+      FunctionType( List(Int32Type, Int32Type), BooleanType )
+    ) 
+    
+  def getGreaterEquals =
+    // case GreaterEquals(l,r) => (rec(ctx,l), rec(ctx,r)) match {
+    makeDeclaration(
+      makeNAE( ">=", { case List(left, right) => GreaterEquals( left, right ) } ),
+      FunctionType( List(Int32Type, Int32Type), BooleanType )
+    ) 
+
+  // currently Leon has some troubles with sets    
+  def getSetOperations(listOfInstanceTypes: List[LeonType]) = {
+        
+    // case SetUnion(s1,s2) => (rec(ctx,s1), rec(ctx,s2)) match {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "SetUnion", { case List(left, right) => SetUnion( left, right ) } ),
+	      FunctionType( List(SetType(x), SetType(x)), SetType(x) )
+	    )       
+    } ++
+    //case SetIntersection(s1,s2) => (rec(ctx,s1), rec(ctx,s2)) match {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "SetIntersection", { case List(left, right) => SetIntersection( left, right ) } ),
+	      FunctionType( List(SetType(x), SetType(x)), SetType(x) )
+	    )       
+    } ++
+    //case SetDifference(s1,s2) => (rec(ctx,s1), rec(ctx,s2)) match {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "SetDifference", { case List(left, right) => SetDifference( left, right ) } ),
+	      FunctionType( List(SetType(x), SetType(x)), SetType(x) )
+	    )       
+    } ++
+    //case ElementOfSet(el,s) => (rec(ctx,el), rec(ctx,s)) match {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "ElementOfSet", { case List(left, right) => ElementOfSet( left, right ) } ),
+	      FunctionType( List(x, SetType(x)), BooleanType )
+	    )       
+    } ++
+    // case SetCardinality(s) => {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "SetCardinality", { case List(set) => SetCardinality( set ) } ),
+	      FunctionType( List(SetType(x)), Int32Type )
+	    )       
+    }
+    
+  }
+    
+    // not covered atm
+//    case CaseClass(cd, args) => CaseClass(cd, args.map(rec(ctx, _)))
+//    case CaseClassInstanceOf(cd, expr) => {
+//    case CaseClassSelector(cd, expr, sel) => {
+  
+    // we do not synthesize ifs explicitly
+  	//case IfExpr(cond, then, elze) => {
+  def getIfExpr(listOfInstanceTypes: List[LeonType]) = {
+    yieldDeclarationForTypes(listOfInstanceTypes) {
+      x: LeonType =>
+	    makeDeclaration(
+	      makeNAE( "If", { case List(cond: Expr, then: Expr, elze: Expr) => IfExpr(cond, then, elze) } ),
+	      FunctionType( List(BooleanType, x, x), x )
+	    )       
+    }
+  }
+    
+//    no arrays atm
+//    case f @ ArrayFill(length, default) => {
+//    case ArrayLength(a) => 
+//    case ArrayUpdated(a, i, v) => 
+//    case ArraySelect(a, i) => 
+//    case FiniteArray(exprs) => 
+
+    // no maps atm
+//    case g @ MapGet(m,k) => (rec(ctx,m), rec(ctx,k)) match {
+//    case u @ MapUnion(m1,m2) => (rec(ctx,m1), rec(ctx,m2)) match {
+//    case i @ MapIsDefinedAt(m,k) => (rec(ctx,m), rec(ctx,k)) match {
+      
+    // needed?
+//    case Distinct(args) => {
+    
+    // not covered atm      
+    // case Tuple(ts) => {
+    // case TupleSelect(t, i) => {
+		// should produce all declarations with tupleselect
+    
+    // needed?
+    //case Waypoint(_, arg) => rec(ctx, arg)
+    //case FunctionInvocation(fd, args) => {
+  
+  def getLiteralDeclarations = {
+    
+    var list = scala.collection.mutable.MutableList[Declaration]()
+    
+//    case i @ IntLiteral(_) => i
+    list += makeLiteral(
+      IE( "IntLit", IntLiteral(0) ),
+      Int32Type
+    ) 
+//    case b @ BooleanLiteral(_) => b
+    list += makeLiteral(
+      IE( "BoolLit", BooleanLiteral(false) ),
+      BooleanType
+    ) 
+//    case u @ UnitLiteral => u
+    list += makeLiteral(
+      IE( "UnitLit", UnitLiteral ),
+      UnitType
+    ) 
+    
+//    case e @ EmptySet(_) => e
+    // NOTE sets are removed in Leon
+//    yieldDeclarationForTypes(listOfInstanceTypes) {
+//      x: LeonType =>
+//	    list += makeDeclaration(
+//	      IE( "SetLit", EmptySet(x) ),
+//	      SetType(x)
+//	    )       
+//    }
+    
+    list toList
+  }
+    
+  def makeNAE( name: String, fun: List[Expr]=>Expr ): NAE = NAE( name, fun )  
+
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/reconstruction/Output.scala b/src/main/scala/insynth/reconstruction/Output.scala
new file mode 100644
index 000000000..fbe07c096
--- /dev/null
+++ b/src/main/scala/insynth/reconstruction/Output.scala
@@ -0,0 +1,12 @@
+package insynth.reconstruction
+
+import insynth.structures.Weight._
+import leon.purescala.Trees.Expr
+
+/**
+ * Encapsulation of the result output from the reconstruction phase, non UI dependent
+ */
+case class Output(snippet: Expr, weight: Weight){
+  def getSnippet = snippet
+  def getWeight = weight
+}
\ No newline at end of file
diff --git a/src/main/scala/insynth/reconstruction/Reconstructor.scala b/src/main/scala/insynth/reconstruction/Reconstructor.scala
new file mode 100644
index 000000000..159f399af
--- /dev/null
+++ b/src/main/scala/insynth/reconstruction/Reconstructor.scala
@@ -0,0 +1,53 @@
+package insynth.reconstruction
+
+import insynth.structures.{ SimpleNode, Weight }
+import insynth.reconstruction.intermediate.IntermediateTransformer
+import insynth.reconstruction.stream.{ Node => LambdaNode, _ }
+import insynth.reconstruction.codegen.CodeGenerator
+
+import insynth.Config
+import insynth.util.format.{ FormatSuccinctNode, FormatIntermediate, FormatStreamUtils }
+import insynth.util.logging.HasLogger
+
+/**
+ * Object for reconstruction of proof trees into output(s)
+ */
+object Reconstructor extends ( (SimpleNode, CodeGenerator, Boolean) => Stream[Output]) with HasLogger {
+
+  def apply(tree: SimpleNode, codeGenerator: CodeGenerator, streamOrdered: Boolean = false) = {		    
+    // logging
+    entering("apply", FormatSuccinctNode(tree, 8).toString)
+    
+    // transform the trees (first two steps of the code generation phase)
+    val transformedTree = IntermediateTransformer(tree)
+         
+    // logging
+    info("intermediate transform phase done")    
+    fine("after intermediate " + FormatIntermediate(transformedTree))
+    
+    // create an ordered/unordered extractor
+    val extractor = 
+      if (streamOrdered)
+        new Extractor(new OrderedStreamFactory[LambdaNode])
+      else
+        new Extractor(new UnorderedStreamFactory[LambdaNode])
+                
+    // generate streams of lambda trees
+    val extractedTrees = extractor(transformedTree)
+    
+    // logging
+    info("extractor phase done")
+    fine("got streamable " + FormatStreamUtils(extractor.transformedStreamable))
+    
+    // for each tree, generate the code for it
+    val generatedCode = extractedTrees map {
+      resPair => Output(codeGenerator(resPair._1), resPair._2)
+    }
+        
+    // logging
+    info("solutions are generated")
+    
+    generatedCode
+  }
+  
+}
diff --git a/src/main/scala/insynth/reconstruction/codegen/CodeGenerator.scala b/src/main/scala/insynth/reconstruction/codegen/CodeGenerator.scala
new file mode 100644
index 000000000..76663ae7a
--- /dev/null
+++ b/src/main/scala/insynth/reconstruction/codegen/CodeGenerator.scala
@@ -0,0 +1,119 @@
+package insynth.reconstruction.codegen
+
+import scala.text.Document
+import scala.text.Document.empty
+
+//import ch.epfl.insynth.reconstruction.intermediate._
+//import ch.epfl.insynth.trees
+//import ch.epfl.insynth.print._
+//import ch.epfl.insynth.reconstruction.combinator.{ NormalDeclaration, AbsDeclaration }
+import insynth.leon.{ LeonDeclaration => DomainDeclaration, _ }
+import insynth.reconstruction.stream._
+
+import insynth.util.format.{ FormatLeonType => FormatDomainType, FormatIntermediate }
+import insynth.util.logging.HasLogger
+
+import leon.purescala.Trees.{ Expr }
+import leon.purescala.TypeTrees.{ TypeTree => DomainType, FunctionType => Function }
+import leon.purescala.{ TypeTrees => domain }
+import leon.purescala.Trees.{ Expr => CodeGenOutput }
+
+/**
+ * class that converts an intermediate tree into a list of output elements (elements
+ * capable of Scala code generation)
+ * should be extended to provide syntax-style variants
+ */
+class CodeGenerator extends (Node => CodeGenOutput) with HasLogger {
+
+  /**
+   * takes the tree and calls the recursive function and maps documents to Output elements
+   * @param tree root of intermediate (sub)tree to transform
+   * @return list of output (code snippet) elements
+   */
+  def apply(tree: Node) = {
+    // match the starting tree to an application that produces query type
+    tree match {
+      case Application(domain.FunctionType(_, _ /* BottomType */), queryDec :: List(innerApp)) =>
+      	transform(innerApp)
+      case _ => throw new RuntimeException
+    }
+  }
+  
+  /** transform context determines the place of the element to transform */
+  object TransformContext extends Enumeration {
+    type TransformContext = Value
+    // expression, application, parameter, argument (in a function), single parameter
+    val Expr, App, Par, Arg, SinglePar = Value
+  }
+  // import all transform context values
+  import TransformContext._
+  
+  /**
+   * main method (recursive) for transforming a intermediate (sub)tree
+   * @param tree root node of the (sub)tree to transform 
+   * @return list of documents containing all combinations of available expression for
+   * the given (sub)tree
+   */
+  def transform(tree: Node): CodeGenOutput = {    
+    tree match {
+      // variable (declared previously as arguments)
+      case Variable(tpe, name) =>
+        // what to do here
+        throw new RuntimeException
+      // identifier from the scope
+      case Identifier(tpe, DomainDeclaration(_, _, _, im: ImmediateExpression)) => 
+        im()
+      // apply parameters in the tail of params according to the head of params 
+      case app@Application(tpe, params) => {        
+        // match the application definition term
+        params.head match {
+          case Identifier(_, decl)  => {            
+	          info("Generating application: " + decl + " with params: " + params + " params.size = " + params.size)   
+
+	          // for an expression of each parameters yield the appropriate transformed expression	            
+            val paramsExpr: List[CodeGenOutput] = params.tail.map(transform _)
+	               
+            decl.expression match {
+              // identifier is a function
+              case NaryReconstructionExpression(_, fun) =>  
+		            info("NaryReconstructionExpression with params: " + paramsExpr + " paramsExpr.size = " + paramsExpr.size)  
+                assert(paramsExpr.size >= 1)             
+                
+                // return application of transformed parameters to fun
+                fun(paramsExpr)
+                
+              // identifier is an immediate expression
+              case ImmediateExpression(_, expr) =>
+                assert(paramsExpr.isEmpty)
+                expr
+                
+              // identifier is an unary operator
+              case UnaryReconstructionExpression(_, fun) =>
+                assert(paramsExpr.size == 1)
+                fun(paramsExpr.head)
+                
+              // this should not happen
+              case _ => throw new RuntimeException
+            }
+          } // case Identifier
+          
+          case innerApp@Application(appType: domain.FunctionType, params) =>
+            warning("cannot have app head: " + innerApp + " in application " + app)
+          	throw new RuntimeException
+                      
+          // function that is created as an argument or anything else
+          case /*Identifier(_, _:AbsDeclaration) | */_:Variable | _ =>
+          	throw new RuntimeException
+          	
+        } // params.head match 
+      }
+      
+      // abstraction first creates all of its arguments
+      case Abstraction(tpe, vars, subtrees) =>
+        assert(vars.size > 0)        
+        throw new RuntimeException
+        
+    } // tree match
+  }
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/lesynth/ExampleRunner.scala b/src/main/scala/lesynth/ExampleRunner.scala
new file mode 100644
index 000000000..f32f5c6a3
--- /dev/null
+++ b/src/main/scala/lesynth/ExampleRunner.scala
@@ -0,0 +1,130 @@
+package lesynth
+
+import scala.collection.mutable.{ Map => MutableMap }
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.{ LinkedList => MutableList }
+
+import leon.{ Main => LeonMain, DefaultReporter, Settings, LeonContext }
+import leon.evaluators._
+import leon.solvers.Solver
+import leon.solvers.z3.{ FairZ3Solver }
+import leon.verification.AnalysisPhase
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Trees._
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+import leon.purescala.Common.{ Identifier, FreshIdentifier }
+import leon.purescala.TreeOps
+
+import insynth.util.logging.HasLogger
+
+class ExampleRunner(program: Program, maxSteps: Int = 2000) extends HasLogger {
+
+  import TreeOps._
+
+  var counterExamples = MutableList[Map[Identifier, Expr]]()
+
+  val leonEmptyContext = LeonContext()
+
+  // its okay to construct just one, prog is not use in the default evaluator
+  lazy val defaultEvaluator = {
+    val ev = new DefaultEvaluator(leonEmptyContext, program)
+    ev.maxSteps = maxSteps
+    ev
+  }
+
+  def evaluate(expr: Expr, mapping: Map[Identifier, Expr]) = {
+    fine("to evaluate: " + expr + " for mapping: " + mapping)
+    defaultEvaluator.eval(expr, mapping) match {
+      case EvaluationSuccessful(BooleanLiteral(true)) =>
+        fine("Eval succeded: EvaluationSuccessful(true)")
+        true
+      case m =>
+        fine("Eval failed: " + m)
+        false
+    }
+  }
+
+  def evaluateToResult(expr: Expr, mapping: Map[Identifier, Expr]) = {
+    fine("to evaluate: " + expr + " for mapping: " + mapping)
+    defaultEvaluator.eval(expr, mapping)
+  }
+
+  /** filter counterexamples according to an expression (precondition) */
+  def filter(prec: Expr) = {
+    entering("filter(" + prec + ")")
+    fine("Old counterExamples.size: " + counterExamples.size)
+    counterExamples = counterExamples filter {
+      evaluate(prec, _)
+    }
+    fine("New counterExamples.size: " + counterExamples.size)
+  }
+
+  /** count how many examples pass */
+  def countPassed(expressionToCheck: Expr) = {
+    // TODO body dont have set type in synthesizer
+//    val expressionToCheck =
+//      //Globals.bodyAndPostPlug(exp)
+//      {
+//        val resFresh = FreshIdentifier("result", true).setType(body.getType)
+//        Let(
+//          resFresh, body,
+//          replace(Map(ResultVariable() -> Variable(resFresh)), matchToIfThenElse(holeFunDef.getPostcondition)))
+//      }
+    fine("expressionToCheck: " + expressionToCheck)
+
+    (0 /: counterExamples) {
+      (res, ce) =>
+        {
+          if (evaluate(expressionToCheck, ce)) res + 1
+          else res
+        }
+    }
+  }
+
+//  def countPassedAndTerminating(body: Expr): Int = {
+//    // TODO body dont have set type in synthesizer
+//    val expressionToCheck =
+//      //Globals.bodyAndPostPlug(exp)
+//      {
+//        val resFresh = FreshIdentifier("result", true).setType(body.getType)
+//        Let(
+//          resFresh, body,
+//          replace(Map(ResultVariable() -> Variable(resFresh)), matchToIfThenElse(holeFunDef.getPostcondition)))
+//      }
+//    fine("expressionToCheck: " + expressionToCheck)
+//
+//    (0 /: counterExamples) {
+//      (res, ce) =>
+//        {
+//          evaluateToResult(expressionToCheck, ce) match {
+//            case EvaluationSuccessful(BooleanLiteral(true)) =>
+//              res + 1
+//            case EvaluationError("Stack overflow") =>
+//              return -counterExamples.size
+//            case m =>
+//              res
+//          }
+//        }
+//    }
+//  }
+
+  // check if this body passes all examples
+//  def check(body: Expr): Boolean = {
+//    val examplesToCheck = counterExamples
+//    val expressionToCheck = Globals.bodyAndPostPlug(body)
+//    fine("Expression to check: " + expressionToCheck)
+//
+//    var res = true
+//    val iterator = counterExamples.iterator
+//
+//    while (res && iterator.hasNext) {
+//      val currentExample = iterator.next
+//      res = evaluate(expressionToCheck, currentExample)
+//
+//      if (!res) fine("Failed example: " + currentExample)
+//    }
+//
+//    return res
+//  }
+
+}
\ No newline at end of file
diff --git a/src/main/scala/lesynth/Globals.scala b/src/main/scala/lesynth/Globals.scala
new file mode 100644
index 000000000..a42136a79
--- /dev/null
+++ b/src/main/scala/lesynth/Globals.scala
@@ -0,0 +1,22 @@
+package lesynth
+
+import leon.purescala.Common.Identifier
+import leon.purescala.Definitions.{ Program, FunDef }
+import leon.purescala.Trees.{ Expr, Error, Hole }
+
+object Globals {
+  
+  //var bodyAndPostPlug: (Expr => Expr) = _
+  
+  //var timeout = 2
+
+  var allSolved: Option[Boolean] = None
+  
+//  var program: Option[Program] = None 
+//
+  var hole: Hole = _
+//  
+  var asMap: Map[Identifier, Expr] = _
+//  
+//  var holeFunDef: FunDef = _
+}
diff --git a/src/main/scala/lesynth/InputExamples.scala b/src/main/scala/lesynth/InputExamples.scala
new file mode 100755
index 000000000..00fa92c27
--- /dev/null
+++ b/src/main/scala/lesynth/InputExamples.scala
@@ -0,0 +1,148 @@
+package lesynth
+
+import leon.{ Main => LeonMain, Reporter, DefaultReporter, SilentReporter, Settings, LeonContext }
+import leon.solvers.{ Solver, TimeoutSolver }
+import leon.solvers.z3.{ FairZ3Solver }
+import leon.verification.AnalysisPhase
+import leon.plugin.ExtractionPhase
+import leon.purescala.TypeTrees.{ ClassType, CaseClassType, Int32Type }
+import leon.purescala.Trees.{ IntLiteral, CaseClass }
+import leon.purescala.Definitions.{ FunDef, VarDecls }
+import leon.purescala.Common.Identifier
+
+import insynth.leon.loader.{ HoleExtractor, LeonLoader }
+
+object InputExamples {
+  
+  def getInputExamples(argumentIds: Seq[Identifier], loader: LeonLoader) = {
+    argumentIds match {
+      case singleArgument :: Nil if isList(singleArgument) =>
+        introduceOneListArgumentExamples(argumentIds, loader)
+      case first :: second :: Nil if isList(first) && isList(second) =>
+        introduceTwoListArgumentsExamples(argumentIds, loader)
+      case first :: second :: Nil if isInt(first) && isList(second) =>
+        introduceExamplesIntList(argumentIds, loader)
+      case _ => null
+    }
+  }   
+  
+  def introduceExamplesIntList(argumentIds: Seq[leon.purescala.Common.Identifier], loader: LeonLoader) = {
+    
+    // list type
+    val ct = argumentIds(1).getType.asInstanceOf[ClassType]
+    
+		val setSubclasses = loader.directSubclassesMap(ct).map(_.asInstanceOf[CaseClassType].classDef)
+		
+		val (nilClassSet, consClassSet) = setSubclasses.partition(_.fieldsIds.size == 0)
+		
+		val nilClass = nilClassSet.head
+		val consClass = consClassSet.head
+		
+		var counter = 10
+		def getIntLiteral = { counter+=1; IntLiteral(counter) }
+		val intLiteral = IntLiteral(5)
+		
+		val list0 = CaseClass(nilClass, Nil)
+		val list1 = CaseClass(consClass, IntLiteral(10) :: list0 :: Nil)
+		val list32 = CaseClass(consClass, IntLiteral(5) :: CaseClass(consClass, IntLiteral(7) :: list1 :: Nil) :: Nil)
+		
+		Map(argumentIds(0) -> IntLiteral(3), argumentIds(1) -> list32) ::
+		Map(argumentIds(0) -> IntLiteral(2), argumentIds(1) -> list32) ::
+		Map(argumentIds(0) -> IntLiteral(3), argumentIds(1) -> list0) ::
+		Map(argumentIds(0) -> IntLiteral(2), argumentIds(1) -> list0) ::
+		Map(argumentIds(0) -> IntLiteral(6), argumentIds(1) -> list32) ::
+		Map(argumentIds(0) -> IntLiteral(9), argumentIds(1) -> list32) ::
+		Nil    
+  }
+  
+  def introduceOneListArgumentExamples(argumentIds: Seq[leon.purescala.Common.Identifier], loader: LeonLoader) = {
+    
+    // list type
+    val ct = argumentIds(0).getType.asInstanceOf[ClassType]
+    
+		val setSubclasses = loader.directSubclassesMap(ct).map(_.asInstanceOf[CaseClassType].classDef)
+		
+		val (nilClassSet, consClassSet) = setSubclasses.partition(_.fieldsIds.size == 0)
+		
+		val nilClass = nilClassSet.head
+		val consClass = consClassSet.head
+		
+		var counter = 10
+		def getIntLiteral = { counter+=1; IntLiteral(counter) }
+		val intLiteral = IntLiteral(5)
+		
+		val list0 = CaseClass(nilClass, Nil)
+		val list1 = CaseClass(consClass, IntLiteral(10) :: list0 :: Nil)
+		val list2s = CaseClass(consClass, IntLiteral(5) :: list1 :: Nil)
+		val list2u = CaseClass(consClass, IntLiteral(5) :: list1 :: Nil)
+		val list3s = CaseClass(consClass, IntLiteral(5) :: list2s :: Nil)
+		val list3u1 = CaseClass(consClass, IntLiteral(5) :: list2u :: Nil)
+		val list3u2 = CaseClass(consClass, IntLiteral(15) :: list2s :: Nil)
+		val list3u3 = CaseClass(consClass, IntLiteral(15) :: list2u :: Nil)
+				
+		for (list <- List(list0, list1, list2s, list2u, list3s, list3u1, list3u2, list3u3))
+      yield Map(argumentIds(0) -> list)    
+  }
+  
+  def introduceTwoListArgumentsExamples(argumentIds: Seq[leon.purescala.Common.Identifier], loader: LeonLoader) = {
+        
+		    loader.hole.getType match {
+	      case ct: ClassType =>
+	    		val setSubclasses = loader.directSubclassesMap(ct).map(_.asInstanceOf[CaseClassType].classDef)
+	    		
+	    		val (nilClassSet, consClassSet) = setSubclasses.partition(_.fieldsIds.size == 0)
+	    		
+	    		val nilClass = nilClassSet.head
+	    		val consClass = consClassSet.head
+	    		
+	    		var counter = 0
+	    		def getIntLiteral = { counter+=1; IntLiteral(counter) }
+	    		
+	    		val list0 = () => CaseClass(nilClass, Nil)
+	    		val list1 = () => CaseClass(consClass, getIntLiteral :: list0() :: Nil)
+	    		val list2 = () => CaseClass(consClass, getIntLiteral :: list1() :: Nil)
+	    		val list3 = () => CaseClass(consClass, getIntLiteral :: list2() :: Nil)
+	    		val list4 = () => CaseClass(consClass, getIntLiteral :: list3() :: Nil)
+	    		
+	    		val lists = List(list0, list1, list2, list3/*, list4*/)
+	    		
+	    		for(l1 <- lists; l2 <- lists)
+		        yield Map(argumentIds(0) -> l1(), argumentIds(1) -> l2())
+	    		
+	      case _ =>
+	        null
+		    }
+  }
+   
+  def isList(id: Identifier) = id.getType.toString == "List"
+  def isInt(id: Identifier) = id.getType == Int32Type
+        
+//  def introduceOneListArgumentExamples(argumentIds: Seq[leon.purescala.Common.Identifier], loader: LeonLoader) = {
+//    
+//    // list type
+//    val ct = argumentIds(0).getType.asInstanceOf[ClassType]
+//    
+//		val setSubclasses = loader.directSubclassesMap(ct).map(_.asInstanceOf[CaseClassType].classDef)
+//		
+//		val (nilClassSet, consClassSet) = setSubclasses.partition(_.fieldsIds.size == 0)
+//		
+//		val nilClass = nilClassSet.head
+//		val consClass = consClassSet.head
+//		
+//		var counter = 10
+//		def getIntLiteral = { counter+=1; IntLiteral(counter) }
+//		val intLiteral = IntLiteral(5)
+//		
+//		val list0 = CaseClass(nilClass, Nil)
+//		val list1 = CaseClass(consClass, IntLiteral(5) :: list0 :: Nil)
+//		val list2 = CaseClass(consClass, IntLiteral(3) :: list1 :: Nil)
+//		val list3 = CaseClass(consClass, IntLiteral(1) :: list2 :: Nil)
+//		val list32 = CaseClass(consClass, IntLiteral(10) :: CaseClass(consClass, IntLiteral(7) :: list1 :: Nil) :: Nil)
+//		
+//		val lists = List(list0, list1, list2, list3, list32)
+//		
+//		for(l1 <- lists)
+//      yield Map(argumentIds(0) -> l1)
+//    
+//  }  
+}
\ No newline at end of file
diff --git a/src/main/scala/lesynth/Refiner.scala b/src/main/scala/lesynth/Refiner.scala
new file mode 100755
index 000000000..c5dda1dbd
--- /dev/null
+++ b/src/main/scala/lesynth/Refiner.scala
@@ -0,0 +1,98 @@
+package lesynth
+
+import leon.purescala.Trees._
+import leon.purescala.Definitions.{ Program, VarDecl, FunDef, VarDecls }
+import leon.purescala.Common.{ Identifier, FreshIdentifier }
+import leon.purescala.TreeOps
+import leon.plugin.ExtractionPhase
+
+import insynth.leon.loader.LeonLoader
+
+import insynth.util.logging.HasLogger
+
+class Refiner(program: Program, hole: Hole, holeFunDef: FunDef) extends HasLogger {      
+  import Globals._
+  
+  def isAvoidable(expr: Expr, funDefArgs: List[Identifier]) = {
+    fine(
+      "Results for refining " + expr + ", are: " +
+      " ,recurentExpression == expr " + (recurentExpression == expr) +
+      " ,isCallAvoidableBySize(expr) " + isCallAvoidableBySize(expr, funDefArgs) +
+      " ,hasDoubleRecursion(expr) " + hasDoubleRecursion(expr)
+    )
+    recurentExpression == expr || isCallAvoidableBySize(expr, funDefArgs) || hasDoubleRecursion(expr)
+  }
+  
+  //val holeFunDef = Globals.holeFunDef
+    
+  val recurentExpression: Expr = 
+	  if (holeFunDef.hasBody) {
+	    FunctionInvocation(holeFunDef, holeFunDef.args map { varDecl => Variable(varDecl.id) })
+	  } else
+	    Error("Hole FunDef should have a body")
+    
+  // check according to size
+  // true - YES, false - NO or don't know
+  // basically a lexicographic (well-founded) ordering
+  def isCallAvoidableBySize(expr: Expr, funDefArgs: List[Identifier]) = {
+	    	
+    def isBadInvocation(expr2: Expr) = expr2 match {
+	    case FunctionInvocation(`holeFunDef`, args) =>
+	      (0 /: (args zip holeFunDef.args.map(_.id))) {
+	        case (res, (arg, par)) if res == 0 => isLess(arg, par)
+	        case (res, _) => res
+	      } >= 0
+	    case _ => false
+	  }
+	    
+  	import TreeOps.treeCatamorphism
+  	
+  	treeCatamorphism(
+	    isBadInvocation,
+	    (b1: Boolean, b2: Boolean) => b1 || b2,
+	    (t: Expr, b: Boolean) => b || isBadInvocation(t),
+	    expr
+    )  
+  }
+  
+  def isLess(arg: Expr, variable: Identifier): Int = {
+	  def getSize(arg: Expr, size: Int): Int = arg match {
+    	//case FunctionInvocation(_, args) => -1 // if some random calls are involved
+	    case CaseClassSelector(cas, expr, fieldId) if fieldId.name == "tail" => getSize(expr, size - 1)
+	    case CaseClassSelector(cas, expr, fieldId) if fieldId.name == "head" => size + 1
+	    case CaseClass(caseClassDef, head :: tail :: Nil) => getSize(tail, size + 1)
+	    case CaseClass(caseClassDef, Nil) => 1
+	    case v: Variable => if (v.id == variable) size else {
+	      fine("variable IDs do not match: " + v.id.uniqueName + " and " + variable.uniqueName )
+	      1
+	    }
+	    case _ => //throw new RuntimeException("Could not match " + arg + " in getSize")
+	      -1
+	  }
+	  
+	  getSize(arg, 0)
+  }
+  
+  def hasDoubleRecursion(expr: Expr) = {      
+    var found = false
+    
+  	def findRecursion(expr: Expr) = expr match {
+	    case FunctionInvocation(`holeFunDef`, args) => true
+	    case _ => false
+	  }
+    
+  	def findRecursionInCall(expr: Expr, b: Boolean) = expr match {
+	    case FunctionInvocation(`holeFunDef`, args) =>
+	      if (b) found = true
+	      true
+	    case _ => b
+	  }
+  	
+  	import TreeOps.treeCatamorphism
+  	
+  	treeCatamorphism(findRecursion, (b1: Boolean, b2: Boolean) => b1 || b2, findRecursionInCall, expr)
+  	
+  	found
+  }
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/lesynth/Report.scala b/src/main/scala/lesynth/Report.scala
new file mode 100755
index 000000000..993a9f862
--- /dev/null
+++ b/src/main/scala/lesynth/Report.scala
@@ -0,0 +1,60 @@
+package lesynth
+
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+
+trait Report {
+  def summaryString: String
+  
+  def isSuccess: Boolean
+}
+
+case object EmptyReport extends Report {
+  import Report._
+  
+  implicit val width = 70
+  
+  override def summaryString =
+    infoHeader +
+    ("║ %-" + width + "s ║\n").format("No solution found for this synthesis problem.") +
+    infoFooter
+    
+  override def isSuccess = false
+}
+
+case class FullReport(val function: FunDef, val totalTime: Long/*, innerVerificationReport */) extends Report {
+
+  import Report._
+  
+  implicit val width = 70
+  
+  override def summaryString : String = {
+    infoHeader +
+    function.toString.split("\n").map {
+    	("║ %-" + (width - 2) + "s ║\n").format(_)
+    }.mkString +
+    infoSep +
+    ("║ Total time: %" + (width - 15) + ".2fs ║\n").format(totalTime.toDouble/1000) +
+    infoFooter
+  }
+
+  override def isSuccess = true
+}
+
+object Report {
+  //def emptyReport : Report = new Report(Nil)
+
+  def fit(str : String, maxLength : Int) : String = {
+    if(str.length <= maxLength) {
+      str
+    } else {
+      str.substring(0, maxLength - 1) + "…"
+    }
+  }
+
+  def infoSep(implicit width: Int)    : String = "╟" + ("┄" * width) + "╢\n"
+  def infoFooter(implicit width: Int) : String = "╚" + ("═" * width) + "╝"
+  def infoHeader(implicit width: Int) : String = ". ┌─────────┐\n" +
+                                    "╔═╡ Summary ╞" + ("═" * (width - 12)) + "╗\n" +
+                                    "║ └─────────┘" + (" " * (width - 12)) + "║\n"
+
+}
diff --git a/src/main/scala/lesynth/SynthesizerExamples.scala b/src/main/scala/lesynth/SynthesizerExamples.scala
new file mode 100755
index 000000000..39cdcde6c
--- /dev/null
+++ b/src/main/scala/lesynth/SynthesizerExamples.scala
@@ -0,0 +1,725 @@
+package lesynth
+
+import scala.collection.mutable.{ Map => MutableMap }
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.PriorityQueue
+
+import leon.{Reporter, DefaultReporter, SilentReporter, LeonContext}
+import leon.solvers.{ Solver, TimeoutSolver }
+import leon.solvers.z3.{ FairZ3Solver }
+import leon.verification.AnalysisPhase
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Trees.{ Variable => LeonVariable, _ }
+import leon.purescala.Definitions.{FunDef, Program}
+import leon.purescala.Common.{ Identifier, FreshIdentifier }
+import leon.purescala.TreeOps
+
+import insynth.util.logging.HasLogger
+import insynth.interfaces.Declaration
+import insynth.InSynth
+import insynth.leon.loader.LeonLoader
+import insynth.leon.LeonDeclaration
+import insynth.leon.ImmediateExpression
+import insynth.engine.InitialEnvironmentBuilder
+import insynth.interfaces.Declaration
+import insynth.engine.InitialEnvironmentBuilder
+import insynth.leon.TypeTransformer
+import insynth.reconstruction.Output
+import leon.synthesis.Problem
+import leon.Main.processOptions
+import leon.purescala.TypeTrees._
+
+import scala.collection.mutable.{Map => MutableMap}
+import scala.collection.mutable.{Set => MutableSet}
+import scala.util.control.Breaks.break
+import scala.util.control.Breaks.breakable
+
+class SynthesizerForRuleExamples(    
+  // some synthesis instance information
+  val solver: Solver,
+  val program: Program,
+  val desiredType: LeonType,
+  val holeFunDef: FunDef,
+  val problem: Problem,
+  val freshResVar: LeonVariable,
+  // number of condition expressions to try before giving up on that branch expression
+  numberOfBooleanSnippets: Int = 5,
+  numberOfCounterExamplesToGenerate: Int = 5,
+  leonTimeout: Int = 2, // seconds
+  analyzeSynthesizedFunctionOnly: Boolean = false,
+  showLeonOutput: Boolean = false,
+  reporter: Reporter = new DefaultReporter,
+  //examples: List[Map[Identifier, Expr]] = Nil,
+  // we need the holeDef to know the right ids
+  introduceExamples: ((Seq[Identifier], LeonLoader) => List[Map[Identifier, Expr]]) = { (_, _) => Nil },
+  collectCounterExamplesFromLeon: Boolean = false,
+  filterOutAlreadySeenBranchExpressions: Boolean = true,
+  useStringSetForFilterOutAlreadySeenBranchExpressions: Boolean = true,  
+  numberOfTestsInIteration: Int = 50,
+  numberOfCheckInIteration: Int = 5
+) extends HasLogger {
+  
+  val fileName: String = "noFileName"
+
+  info("Synthesizer:")
+  info("fileName: %s".format(fileName))
+  info("numberOfBooleanSnippets: %d".format(numberOfBooleanSnippets))
+  info("numberOfCounterExamplesToGenerate: %d".format(numberOfCounterExamplesToGenerate))
+  info("leonTimeout: %d".format(leonTimeout))
+  //info("examples: " + examples.mkString(", "))
+  
+  info("holeFunDef: %s".format(holeFunDef))
+  info("problem: %s".format(problem.toString))
+
+  private var hole: Hole = _
+  // initial declarations
+  private var allDeclarations: List[Declaration] = _
+  // objects used in the synthesis
+  private var loader: LeonLoader = _
+  private var inSynth: InSynth = _
+  private var inSynthBoolean: InSynth = _
+  private var refiner: Refiner = _
+  //private var solver: Solver = _
+  private var ctx: LeonContext = _
+  private var initialPrecondition: Expr = _
+  private var variableRefinements: MutableMap[Identifier, MutableSet[ClassType]] = _
+  // can be used to unnecessary syntheses
+  private var variableRefinedBranch = false
+  private var variableRefinedCondition = true // assure initial synthesis
+  private var booleanExpressionsSaved: Stream[Output] = _
+  
+  private var seenBranchExpressions: Set[String] = Set.empty
+
+  // flag denoting if a correct body has been synthesized
+  private var found = false
+
+  // accumulate precondition for the remaining branch to synthesize 
+  private var accumulatingPrecondition: Expr = _
+  // accumulate the final expression of the hole
+  private var accumulatingExpression: Expr => Expr = _
+  //private var accumulatingExpressionMatch: Expr => Expr = _
+
+  // time
+  var startTime: Long = _
+  var verTime: Long = 0
+  var synTime: Long = 0
+
+  // filtering/ranking with examples support
+  var exampleRunner: ExampleRunner = _
+
+  def analyzeProgram = {
+
+    val temp = System.currentTimeMillis
+    Globals.allSolved = Some(true)
+
+    import TreeOps._
+    
+    val body = holeFunDef.getBody
+    val theExpr = {
+	    val resFresh = FreshIdentifier("result", true).setType(body.getType)
+      val bodyAndPost = 		    
+		    Let(
+	    		resFresh, body,
+	    		replace(Map(ResultVariable() -> LeonVariable(resFresh)), matchToIfThenElse(holeFunDef.getPostcondition))
+    		)	
+
+      val withPrec = if( holeFunDef.precondition.isEmpty) {
+        bodyAndPost
+      } else {
+        Implies(matchToIfThenElse(holeFunDef.precondition.get), bodyAndPost)
+      }
+
+      withPrec
+    }
+    
+    Globals.allSolved = solver.solve(theExpr)
+    fine("solver said " + Globals.allSolved + " for " + theExpr)
+    //interactivePause
+
+    val time = System.currentTimeMillis - temp
+    //fine("Analysis took: " + time + ", from report: " + report.totalTime)
+
+    // accumulate
+    verTime += time
+  }
+
+  // TODO return boolean (do not do unecessary analyze)
+  def generateCounterexamples(program: Program, funDef: FunDef, number: Int): (Seq[Map[Identifier, Expr]], Expr) = {
+
+    fine("generate counter examples with funDef.prec= " + funDef.precondition.getOrElse(BooleanLiteral(true)))
+    val temp = System.currentTimeMillis
+
+    // get current precondition
+    var precondition = funDef.precondition.getOrElse(BooleanLiteral(true))
+    // where we will accumulate counterexamples as sequence of maps
+    var maps: Seq[Map[Identifier, Expr]] = Seq.empty
+
+    // iterate specific number of times or until no further counterexample can be generated
+    var changed = true
+    var ind = 0
+    while (ind < number && changed) {
+
+      // analyze the program
+      analyzeProgram
+
+      // check if solver could solved this instance
+      if (Globals.allSolved == Some(false) && !Globals.asMap.isEmpty) {
+
+        fine("found coounterexample: " + Globals.asMap)
+        // add current counterexample
+        maps :+= Globals.asMap
+
+        // prevent this counterexample to re-occur
+        val precAddition = Not(And(Globals.asMap map { case (id, value) => Equals(LeonVariable(id), value) } toSeq))
+        precondition = And(Seq(precondition, precAddition))
+        // update precondition        
+        funDef.precondition = Some(precondition)
+      } else
+        changed = false
+
+      ind += 1
+    }
+
+    val temptime = System.currentTimeMillis - temp
+    fine("Generation of counter-examples took: " + temptime)
+    verTime += temptime
+
+    // return found counterexamples and the formed precondition
+    (maps, precondition)
+  }
+
+  def getCurrentBuilder = new InitialEnvironmentBuilder(allDeclarations)
+
+  def synthesizeBranchExpressions =
+    inSynth.getExpressions(getCurrentBuilder)
+
+  def synthesizeBooleanExpressions = {
+    if ( variableRefinedCondition ) {
+      // store for later fetch (will memoize values)
+    	booleanExpressionsSaved = 
+  			inSynthBoolean.getExpressions(getCurrentBuilder) take numberOfBooleanSnippets
+			// reset flag
+  		variableRefinedCondition = false
+    }
+  
+	  booleanExpressionsSaved
+  }
+
+  def interactivePause = {
+    System.out.println("Press Any Key To Continue...");
+    new java.util.Scanner(System.in).nextLine();
+  }
+  
+  def getNewExampleQueue = PriorityQueue[(Expr, Int)]()(
+    new Ordering[(Expr, Int)] {
+      def compare(pair1: (Expr, Int), pair2: (Expr, Int)) =
+        pair1._2.compare(pair2._2)
+    })
+
+  def initialize = {
+
+    hole = Hole(desiredType)
+    
+    // TODO lose this - globals are bad
+    Globals.allSolved = None
+
+    // context needed for verification
+    import leon.Main._
+//    val reporter =
+//      if (showLeonOutput) new DefaultReporter
+//      else new SilentReporter
+//
+//    val args =
+//      if (analyzeSynthesizedFunctionOnly)
+//        Array(fileName, "--timeout=" + leonTimeout, "--functions=" + holeFunDef.id.name)
+//      else
+//        Array(fileName, "--timeout=" + leonTimeout)
+//    info("Leon context array: " + args.mkString(","))
+//    ctx = processOptions(reporter, args.toList)
+
+    //solver = //new FairZ3Solver(ctx)
+    //  new TimeoutSolver(new FairZ3Solver(ctx), leonTimeout)
+
+    // create new insynth object
+    loader = new LeonLoader(program, hole, problem.as, false)
+    inSynth = new InSynth(loader, true)
+    // save all declarations seen
+    allDeclarations = inSynth.getCurrentBuilder.getAllDeclarations
+    // make conditions synthesizer
+    inSynthBoolean = new InSynth(allDeclarations, BooleanType, true)
+
+    // funDef of the hole
+    fine("postcondition is: " + holeFunDef.getPostcondition)
+
+    // accumulate precondition for the remaining branch to synthesize 
+    accumulatingPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+    // save initial precondition
+    initialPrecondition = accumulatingPrecondition
+    // accumulate the final expression of the hole
+    accumulatingExpression = (finalExp: Expr) => finalExp
+    //accumulatingExpressionMatch = accumulatingExpression
+
+    // each variable of super type can actually have a subtype
+    // get sine declaration maps to be able to refine them
+    val directSubclassMap = loader.directSubclassesMap
+    val variableDeclarations = loader.variableDeclarations
+    // map from identifier into a set of possible subclasses
+    variableRefinements = MutableMap.empty
+    for (varDec <- variableDeclarations) {
+      varDec match {
+        case LeonDeclaration(_, _, typeOfVar: ClassType, ImmediateExpression(_, LeonVariable(id))) =>
+          variableRefinements += (id -> MutableSet(directSubclassMap(typeOfVar).toList: _*))
+        case _ =>
+      }
+    }
+
+    // calculate cases that should not happen
+    refiner = new Refiner(program, hole, holeFunDef)
+    fine("Refiner initialized. Recursive call: " + refiner.recurentExpression)
+
+    exampleRunner = new ExampleRunner(program)
+    exampleRunner.counterExamples ++= //examples
+      introduceExamples(holeFunDef.args.map(_.id), loader)
+      
+    fine("Introduced examples: " + exampleRunner.counterExamples.mkString(", "))
+  }
+
+  def countPassedExamples(snippet: Expr) = {
+    val oldPreconditionSaved = holeFunDef.precondition
+    val oldBodySaved = holeFunDef.body
+
+    // restore initial precondition
+    holeFunDef.precondition = Some(initialPrecondition)
+
+    // get the whole body (if else...)
+    val accumulatedExpression = accumulatingExpression(snippet)
+    // set appropriate body to the function for the correct evaluation
+    holeFunDef.body = Some(accumulatedExpression)
+    
+    
+    import TreeOps._
+    val expressionToCheck =
+      //Globals.bodyAndPostPlug(exp)
+      {
+		    val resFresh = FreshIdentifier("result", true).setType(accumulatedExpression.getType)		 
+        Let(
+          resFresh, accumulatedExpression,
+          replace(Map(ResultVariable() -> LeonVariable(resFresh)), matchToIfThenElse(holeFunDef.getPostcondition)))
+      }
+    
+    fine("going to count passed for: " + holeFunDef)
+    fine("going to count passed for: " + expressionToCheck)
+
+    val count = exampleRunner.countPassed(expressionToCheck)
+//    if (snippet.toString == "Cons(l1.head, concat(l1.tail, l2))")
+//      interactivePause
+
+    holeFunDef.precondition = oldPreconditionSaved
+    holeFunDef.body = oldBodySaved
+
+    count
+  }
+
+  def synthesize: Report = {
+    reporter.info("Synthesis called on file: " + fileName)
+
+    // get start time
+    startTime = System.currentTimeMillis
+
+    reporter.info("Initializing synthesizer: ")
+    reporter.info("numberOfBooleanSnippets: %d".format(numberOfBooleanSnippets))
+    reporter.info("numberOfCounterExamplesToGenerate: %d".format(numberOfCounterExamplesToGenerate))
+    reporter.info("leonTimeout: %d".format(leonTimeout))
+    initialize
+    reporter.info("Synthesizer initialized")
+
+    // keeps status of validity
+    var keepGoing = Globals.allSolved match {
+      case Some(true) => false
+      case _ => true
+    }
+
+    // initial snippets (will update in the loop)
+    var snippets = synthesizeBranchExpressions
+    var snippetsIterator = snippets.iterator
+    
+    // ordering of expressions according to passed examples
+    var pq = getNewExampleQueue
+    
+    // iterate while the program is not valid
+    import scala.util.control.Breaks._
+    var iteration = 0
+    breakable {
+      while (keepGoing) {
+        // next iteration
+        iteration += 1
+        reporter.info("####################################")
+        reporter.info("######Iteration #" + iteration + " ###############")
+        reporter.info("####################################")
+        reporter.info("# precondition is: " + holeFunDef.precondition.getOrElse(BooleanLiteral(true)))
+        reporter.info("# accumulatingPrecondition is: " + accumulatingPrecondition)
+        reporter.info("# accumulatingExpression(Unit) is: " + accumulatingExpression(UnitLiteral))
+        reporter.info("####################################")
+
+        var numberOfTested = 0
+
+        // just printing of expressions and pass counts        
+        fine( {
+          val (it1, it2) = snippetsIterator.duplicate // we are dealing with iterators, need to duplicate
+          val logString = ((it1 zip Iterator.range(0, numberOfTestsInIteration)) map {
+            case ((snippet: Output, ind: Int)) => ind + ": snippet is " + snippet.getSnippet +
+              " pass count is " + countPassedExamples(snippet.getSnippet)
+          }).mkString("\n")
+          snippetsIterator = it2
+          logString
+        })
+        //interactivePause
+
+        reporter.info("Going into a enumeration/testing phase.")
+        fine("evaluating examples: " + exampleRunner.counterExamples.mkString("\n"))
+        
+        // found precondition?
+        found = false
+        // try to find it
+        breakable {
+          // go through all snippets
+          for (
+            snippet <- snippetsIterator; val snippetTree = snippet.getSnippet;
+            // filter if seen
+            if ! (seenBranchExpressions contains snippetTree.toString)
+          ) {
+            finest("snippetTree is: " + snippetTree)
+            // note that we do not add snippets to the set of seen if enqueued 
+
+            // skip avoidable calls
+            if (!refiner.isAvoidable(snippetTree, problem.as)) {
+
+              // passed example pairs
+              val passCount = countPassedExamples(snippetTree)
+
+              if (passCount == exampleRunner.counterExamples.size) {
+                info("All examples passed. Testing snippet " + snippetTree + " right away")
+                
+                if (tryToSynthesizeBranch(snippetTree)) {
+                  // will set found if correct body is found
+                  break
+                }
+              } else {
+                if (passCount > 0) {
+                	finest("Snippet with pass count goes into queue: " + (snippetTree, passCount))
+                	pq.enqueue((snippetTree, 100 + (passCount * iteration) - snippet.getWeight.toInt))
+                }
+              	else {
+              		fine("Snippet with pass count was dropped: " + (snippetTree, passCount) +
+            		    " while number of examples was: " + exampleRunner.counterExamples.size)
+	                // add to seen if branch was not found for it
+	                seenBranchExpressions += snippetTree.toString
+              	}
+              }
+
+            } else {
+              fine("Refiner filtered this snippet: " + snippetTree)
+              seenBranchExpressions += snippetTree.toString
+            } // if (!refiner.isAvoidable(snippetTree)) {
+
+            // check if we this makes one test iteration            
+            if (numberOfTested >= numberOfTestsInIteration) {
+            	reporter.info("Finalizing enumeration/testing phase.")
+              fine("Queue contents: " + pq.toList.take(10).mkString("\n"))
+              fine({ if (pq.isEmpty) "queue is empty" else "head of queue is: " + pq.head })
+
+              //interactivePause
+              // go and check the topmost numberOfCheckInIteration
+              for (i <- 1 to math.min(numberOfCheckInIteration, pq.size)) {
+                val nextSnippet = pq.dequeue._1
+                fine("dequeued nextSnippet: " + nextSnippet)
+                //interactivePause
+
+                if (tryToSynthesizeBranch(nextSnippet)) {
+                  break
+                }
+                
+                // dont drop snippets that were on top of queue (they may be good for else ... part)
+                //seenBranchExpressions += nextSnippet.toString
+              }
+
+              numberOfTested = 0
+            } else
+              numberOfTested += 1
+
+          } // for (snippet <- snippets
+        } // breakable { for (snippet <- snippets
+
+        // if did not found for any of the branch expressions
+        if (found) {
+          val endTime = System.currentTimeMillis
+          reporter.info("We are done, in time: " + (endTime - startTime))
+          return new FullReport(holeFunDef, (endTime - startTime))
+        }
+
+        if ( variableRefinedBranch ) {
+          fine("Variable refined, doing branch synthesis again")
+        	// get new snippets
+        	snippets = synthesizeBranchExpressions
+        	snippetsIterator = snippets.iterator
+        	pq = getNewExampleQueue
+        	
+          // reset flag
+          variableRefinedBranch = false
+        } else
+          // reseting iterator needed because we may have some expressions that previously did not work
+        	snippetsIterator = snippets.iterator
+
+        fine("filtering based on: " + holeFunDef.precondition.get)
+        fine("counterexamples before filter: " + exampleRunner.counterExamples.size)
+        exampleRunner.filter(holeFunDef.precondition.get)
+        fine("counterexamples after filter: " + exampleRunner.counterExamples.size)
+        fine("counterexamples after filter: " + exampleRunner.counterExamples.mkString("\n"))
+      }
+    } //breakable { while (!keepGoing) {
+
+    EmptyReport
+  }
+
+  def tryToSynthesizeBranch(snippetTree: Expr): Boolean = {
+    // replace hole in the body with the whole if-then-else structure, with current snippet tree
+    val oldBody = holeFunDef.getBody
+    val newBody = accumulatingExpression(snippetTree)
+    holeFunDef.body = Some(newBody)
+
+    // precondition
+    val oldPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+    holeFunDef.precondition = Some(initialPrecondition)
+
+    snippetTree.setType(hole.desiredType)
+    //holeFunDef.getBody.setType(hole.desiredType)
+
+    // TODO spare one analyzing step
+    // analyze the program
+    fine("analyzing program for funDef:" + holeFunDef)
+    analyzeProgram
+
+    // check if solver could solved this instance
+    if (Globals.allSolved == Some(true)) {
+      // mark the branch found
+      found = true
+
+      reporter.info("Wooooooow we have a winner!")
+      reporter.info("************************************")
+      reporter.info("*********And the winner is**********")
+      reporter.info(accumulatingExpression(snippetTree).toString)
+      reporter.info("************************************")
+
+      return true
+    }
+
+    // store appropriate values here, will be update in a finally branch
+    var bodyToRestore = oldBody
+    var preconditionToRestore = Some(oldPrecondition)
+
+    // because first initial test
+    holeFunDef.precondition = preconditionToRestore
+
+    // get counterexamples
+    fine("Going to generating counterexamples: " + holeFunDef)
+    val (maps, precondition) = generateCounterexamples(program, holeFunDef, numberOfCounterExamplesToGenerate)
+
+    // collect (add) counterexamples from leon
+    if (collectCounterExamplesFromLeon)
+      exampleRunner.counterExamples ++= maps
+
+    // this should not be possible
+    //    val keepGoing = Globals.allSolved match {
+    //      case Some(true) => false
+    //      case _ => true
+    //    }
+    //
+    //    // if no counterexamples and all are solved, we are done
+    //    if (maps.isEmpty && !keepGoing) {
+    //      // mark the branch found
+    //      found = true
+    //
+    //      println("Wooooooow we have a winner!")
+    //      println("************************************")
+    //      println("*********And the winner is**********")
+    //      println(accumulatingExpression(snippetTree))
+    //      println("************************************")
+    //
+    //      return true
+    //    }
+
+      //if(maps.isEmpty) throw new RuntimeException("asdasdasd")
+      
+    // will modify funDef body and precondition, restore it later
+    try {
+      if (!maps.isEmpty) {
+        // proceed with synthesizing boolean expressions
+        //solver.setProgram(program)
+
+        // reconstruct (only defined number of boolean expressions)
+        val innerSnippets = synthesizeBooleanExpressions
+        // just printing of expressions
+        fine(
+          ((innerSnippets zip Iterator.range(0, numberOfBooleanSnippets).toStream) map {
+            case ((snippet: Output, ind: Int)) => ind + ": snippet is " + snippet.getSnippet
+          }).mkString("\n"))
+
+        for (
+            innerSnippetTree <- innerSnippets map { _.getSnippet };
+            if (
+              {	val flag = !refiner.isAvoidable(innerSnippetTree, problem.as)
+                if (!flag) fine("Refiner filtered this snippet: " + innerSnippetTree)
+                flag }
+            )
+          ) {
+          fine("boolean snippet is: " + innerSnippetTree)
+
+          val (innerFound, innerPrec) = tryToSynthesizeBooleanCondition(snippetTree, innerSnippetTree, precondition)
+
+          // if precondition found
+          if (innerFound) {
+            reporter.info("Precondition " + innerPrec + " found for " + snippetTree)
+
+            innerPrec match {
+              case s @ Some(_) =>
+                // new precondition (restore in finally)
+                preconditionToRestore = s
+              case _ =>
+            }
+            return true
+          }
+
+        } // iterating over all boolean solutions
+
+        reporter.info("No precondition found for branch expression: " + snippetTree)
+        return false
+
+      } // if ( !maps.isEmpty ) {
+      // no counter examples, we just say that we cannot do anything
+      false
+    } // try
+    finally {
+      // set these to the FunDef
+      holeFunDef.precondition = preconditionToRestore
+      // restore old body (we accumulate expression)                                
+      holeFunDef.body = Some(oldBody)
+    }
+  }
+
+  def tryToSynthesizeBooleanCondition(snippetTree: Expr, innerSnippetTree: Expr, precondition: Expr): (Boolean, Option[Expr]) = {
+
+    // new condition together with existing precondition
+    val newCondition = And(Seq(accumulatingPrecondition, innerSnippetTree))
+
+    // new expression should not be false
+    val notFalseEquivalence = Not(newCondition)
+    val notFalseSolveReturn = solver.solve(notFalseEquivalence)
+    fine("solve for not false returned: " + notFalseSolveReturn)
+
+    notFalseSolveReturn match {
+      case Some(true) =>
+        (false, None)
+      case None =>
+        (false, None)
+      // nothing here
+      // here, our expression is not contradictory, continue
+      case Some(false) =>
+        // check if synthesized boolean expression implies precondition (counterexamples)
+        val implyExpression = Implies(newCondition, precondition)
+        fine("implyExpression is: " + implyExpression)
+
+        // check if synthesized condition implies counter-examples
+        val solveReturn = solver.solve(implyExpression)
+        fine("solve returned: " + solveReturn)
+
+        solveReturn match {
+          case Some(true) =>
+            // if expression implies counterexamples add it to the precondition and try to validate program
+            holeFunDef.precondition = Some(newCondition)
+            // do analysis
+            analyzeProgram
+            // program is valid, we have a branch
+            if (Globals.allSolved == Some(true)) {
+              // we found a branch
+              reporter.info("We found a branch, for expression %s, with condition %s.".format(snippetTree, innerSnippetTree))
+
+              // update accumulating expression
+              val oldAccumulatingExpression = accumulatingExpression
+              val newAccumulatingExpression =
+                (finalExpr: Expr) =>
+                  oldAccumulatingExpression({
+                    val innerIf = IfExpr(innerSnippetTree, snippetTree, finalExpr)
+                    innerIf.setType(snippetTree.getType)
+                    innerIf
+                  })
+
+              accumulatingExpression = newAccumulatingExpression
+
+              // update accumulating precondition
+              fine("updating accumulatingPrecondition")
+              accumulatingPrecondition = And(Seq(accumulatingPrecondition, Not(innerSnippetTree)))
+              fine("updating hole fun precondition and body (to be hole)")
+
+              // set to set new precondition
+              val preconditionToRestore = Some(accumulatingPrecondition)
+
+              // check for refinements
+              checkRefinements(innerSnippetTree) match {
+                case Some(refinementPair @ (id, classType)) =>
+                  fine("And now we have refinement type: " + refinementPair)
+                  fine("variableRefinements(id) before" + variableRefinements(id))
+                  variableRefinements(id) -= loader.classMap(classType.id)
+                  fine("variableRefinements(id) after" + variableRefinements(id))
+
+                  // if we have a single subclass possible to refine
+                  if (variableRefinements(id).size == 1) {
+                    reporter.info("We do variable refinement for " + id)
+
+                    val newType = variableRefinements(id).head
+                    fine("new type is: " + newType)
+
+                    // update declarations
+                    allDeclarations =
+                      for (dec <- allDeclarations)
+                        yield dec match {
+                        case LeonDeclaration(inSynthType, _, decClassType, imex @ ImmediateExpression(_, LeonVariable(`id`))) =>
+                          LeonDeclaration(
+                            imex, TypeTransformer(newType), newType)
+                        case _ =>
+                          dec
+                      }
+                    
+                    // the reason for two flags is for easier management of re-syntheses only if needed 
+                    variableRefinedBranch = true
+                    variableRefinedCondition = true
+
+                  } else
+                    fine("we cannot do variable refinement :(")
+                case _ =>
+              }
+
+              // found a boolean snippet, break
+              (true, preconditionToRestore)
+            } else {
+              // reset funDef and continue with next boolean snippet
+              val preconditionToRestore = Some(accumulatingPrecondition)
+              (false, preconditionToRestore)
+            }
+
+          case _ =>
+
+            fine("solver filtered out the precondition (does not imply counterexamples)")
+            (false, None)
+        } //solveReturn match { (for implying counterexamples)
+    } // notFalseSolveReturn match {
+  }
+
+  // inspect the expression if some refinements can be done
+  def checkRefinements(expr: Expr) = expr match {
+    case CaseClassInstanceOf(classDef, LeonVariable(id)) =>
+      Some((id, classDef))
+    case _ =>
+      None
+  }
+
+}
\ No newline at end of file
diff --git a/src/main/scala/lesynth/rules/ConditionAbductionSynthesisImmediate.scala b/src/main/scala/lesynth/rules/ConditionAbductionSynthesisImmediate.scala
new file mode 100755
index 000000000..bf54519c2
--- /dev/null
+++ b/src/main/scala/lesynth/rules/ConditionAbductionSynthesisImmediate.scala
@@ -0,0 +1,61 @@
+package lesynth
+package rules
+
+import leon.purescala.Trees._
+import leon.purescala.Common._
+import leon.purescala.TypeTrees._
+import leon.purescala.TreeOps._
+import leon.purescala.Extractors._
+import leon.purescala.Definitions._
+import leon.synthesis.{ Rule, RuleInstantiation, SynthesisContext, Problem, Solution }
+import InputExamples._
+import lesynth.SynthesizerForRuleExamples
+
+case object ConditionAbductionSynthesisImmediate extends Rule("Condition abduction synthesis (immediate).") {
+  def instantiateOn(sctx: SynthesisContext, p: Problem): Traversable[RuleInstantiation]= {
+    val solver = sctx.solver
+		val program = sctx.program
+		val reporter = sctx.reporter
+						
+		p.xs match {
+      case givenVariable :: Nil =>
+        val desiredType = givenVariable.getType
+        val holeFunDef = sctx.functionContext.get
+        
+        // temporary hack, should not mutate FunDef
+        val oldPostcondition = holeFunDef.postcondition
+        val oldPrecondition = holeFunDef.precondition
+        try {
+          val freshResID = FreshIdentifier("result").setType(holeFunDef.returnType)
+          val freshResVar = Variable(freshResID)
+	        holeFunDef.postcondition = Some(replace(
+            Map(givenVariable.toVariable -> ResultVariable().setType(holeFunDef.returnType)), p.phi)
+          )
+	        holeFunDef.precondition = Some(p.pc)
+	        
+	        val synthesizer = new SynthesizerForRuleExamples(
+	          solver, program, desiredType, holeFunDef, p, freshResVar,
+	          reporter = reporter,
+	          introduceExamples = introduceTwoListArgumentsExamples
+	        )
+	        
+	        synthesizer.synthesize match {
+	          case EmptyReport => None
+	          case FullReport(resFunDef, _) =>        
+			        List(
+			          RuleInstantiation.immediateSuccess(p, this,
+			            Solution(resFunDef.getPrecondition, Set.empty, resFunDef.body.get)
+			          )
+			        )
+	        }
+        } finally {          
+	        holeFunDef.postcondition = oldPostcondition
+	        holeFunDef.precondition = oldPrecondition
+        }
+      case _ =>
+        throw new RuntimeException("should not")
+        Nil
+    }
+    
+  }
+}
diff --git a/src/main/scala/lesynth/rules/ConditionAbductionSynthesisTwoPhase.scala b/src/main/scala/lesynth/rules/ConditionAbductionSynthesisTwoPhase.scala
new file mode 100755
index 000000000..a48556285
--- /dev/null
+++ b/src/main/scala/lesynth/rules/ConditionAbductionSynthesisTwoPhase.scala
@@ -0,0 +1,71 @@
+package lesynth
+package rules
+
+import leon.purescala.Trees._
+import leon.purescala.Common._
+import leon.purescala.TypeTrees._
+import leon.purescala.TreeOps._
+import leon.purescala.Extractors._
+import leon.purescala.Definitions._
+import leon.synthesis._
+import leon.solvers.{ Solver, TimeoutSolver }
+
+import InputExamples._
+import lesynth.SynthesizerForRuleExamples
+
+case object ConditionAbductionSynthesisTwoPhase extends Rule("Condition abduction synthesis (two phase).") {
+  def instantiateOn(sctx: SynthesisContext, p: Problem): Traversable[RuleInstantiation] = {
+
+    p.xs match {
+      case givenVariable :: Nil =>
+        List(new RuleInstantiation(p, this, SolutionBuilder.none, "Condition abduction") {
+          def apply(sctx: SynthesisContext): RuleApplicationResult = {
+            try {
+              val solver = new TimeoutSolver(sctx.solver, 2000L)
+              val program = sctx.program
+              val reporter = sctx.reporter
+
+              val desiredType = givenVariable.getType
+              val holeFunDef = sctx.functionContext.get
+
+              // temporary hack, should not mutate FunDef
+              val oldPostcondition = holeFunDef.postcondition
+              val oldPrecondition = holeFunDef.precondition
+              
+              try {
+                val freshResID = FreshIdentifier("result").setType(holeFunDef.returnType)
+                val freshResVar = Variable(freshResID)
+                
+                holeFunDef.postcondition = Some(replace(
+                  Map(givenVariable.toVariable -> ResultVariable().setType(holeFunDef.returnType)), p.phi))
+                holeFunDef.precondition = Some(p.pc)
+
+                val synthesizer = new SynthesizerForRuleExamples(
+                  solver, program, desiredType, holeFunDef, p, freshResVar,
+                  20, 2, 1,
+                  reporter = reporter,
+                  introduceExamples = getInputExamples)
+
+                synthesizer.synthesize match {
+                  case EmptyReport => RuleApplicationImpossible
+                  case FullReport(resFunDef, _) =>
+                    RuleSuccess(Solution(resFunDef.getPrecondition, Set.empty, resFunDef.body.get))
+                }
+              } catch {
+                case e: Throwable =>
+                  sctx.reporter.warning("Condition abduction crashed: " + e.getMessage)
+                  e.printStackTrace
+                  RuleApplicationImpossible
+              } finally {
+                holeFunDef.postcondition = oldPostcondition
+                holeFunDef.precondition = oldPrecondition
+              }
+            }
+          }
+        })
+      case _ =>
+        throw new RuntimeException("should not")
+        Nil
+    }
+  }
+}
diff --git a/src/test/scala/insynth/reconstruction/CodeGeneratorTest.scala b/src/test/scala/insynth/reconstruction/CodeGeneratorTest.scala
new file mode 100644
index 000000000..c9b7c528b
--- /dev/null
+++ b/src/test/scala/insynth/reconstruction/CodeGeneratorTest.scala
@@ -0,0 +1,63 @@
+package insynth.reconstruction
+
+import org.junit.Assert._
+import org.junit.{ Test, Ignore }
+
+import insynth.reconstruction.codegen.CodeGenerator
+
+import leon.purescala.Trees._
+
+import insynth.testutil.{ CommonLambda, CommonDeclarations }
+
+// NOTE function cannot return function in Leon, no need to test that
+
+class CodeGeneratorTest {
+    
+  import CommonLambda._
+  import CommonDeclarations._
+  
+  val codeGenerator = new CodeGenerator
+  
+  @Test
+  def testBooleanToIntIntermediateLambda {    
+    val codeGenResult = codeGenerator(constructBooleanToIntIntermediateLambda.head)
+      
+    assertEquals(
+      FunctionInvocation(functionBoolToIntFunDef, List(BooleanLiteral(false))),
+      codeGenResult
+    )
+  }     
+  
+  @Test
+  def testThreeParFunction {
+    
+    val generated =
+	    for (intermediateTree <- constructThreeParFunctionIntermediateLambda(4))
+	    	yield codeGenerator(intermediateTree)
+    
+    val baseCase = FunctionInvocation(threeParFunctionDef, List(IntLiteral(0), IntLiteral(0), BooleanLiteral(false)))
+    
+    val message = "Generated:\n" + generated.mkString("\n")
+    
+    assertTrue(baseCase + " not found. " + message, generated contains baseCase)
+    
+    val oneLevCase1 = FunctionInvocation(threeParFunctionDef, List(baseCase, IntLiteral(0), BooleanLiteral(false)))
+    val oneLevCase2 = FunctionInvocation(threeParFunctionDef, List(baseCase, baseCase, BooleanLiteral(false)))
+    
+    assertTrue(oneLevCase1 + " not found. " + message, generated contains oneLevCase1)
+    assertTrue(oneLevCase2 + " not found. " + message, generated contains oneLevCase2)
+        
+    val twoLevCase1 = FunctionInvocation(threeParFunctionDef, List(oneLevCase1, IntLiteral(0), BooleanLiteral(false)))
+    val twoLevCase2 = FunctionInvocation(threeParFunctionDef, List(baseCase, oneLevCase2, BooleanLiteral(false)))
+    
+    assertTrue(twoLevCase1 + " not found. " + message, generated contains twoLevCase1)
+    assertTrue(twoLevCase2 + " not found. " + message, generated contains twoLevCase2)
+        
+//    val threeLevCase1 = FunctionInvocation(threeParFunctionDef, List(oneLevCase1, twoLevCase2, BooleanLiteral(false)))
+//    val threeLevCase2 = FunctionInvocation(threeParFunctionDef, List(twoLevCase2, threeLevCase1, BooleanLiteral(false)))
+//    
+//    assertTrue(threeLevCase1 + " not found. " + message, generated contains threeLevCase1)
+//    assertTrue(threeLevCase2 + " not found. " + message, generated contains threeLevCase2)
+  }
+  
+}
\ No newline at end of file
diff --git a/src/test/scala/insynth/reconstruction/PhaseCombinationTest.scala b/src/test/scala/insynth/reconstruction/PhaseCombinationTest.scala
new file mode 100644
index 000000000..46a41a1a1
--- /dev/null
+++ b/src/test/scala/insynth/reconstruction/PhaseCombinationTest.scala
@@ -0,0 +1,74 @@
+package insynth.reconstruction
+
+import org.junit.{ Test, Ignore }
+import org.junit.Assert._
+
+import insynth.reconstruction.intermediate.IntermediateTransformer
+import insynth.reconstruction.stream.{ Extractor, UnorderedStreamFactory }
+import insynth.reconstruction.codegen.CodeGenerator
+
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+import leon.purescala.Common.{ FreshIdentifier }
+import leon.purescala.TypeTrees._
+import leon.purescala.Trees.{ Variable => LeonVariable, _ }
+
+import insynth.testutil.{ CommonProofTrees, CommonDeclarations, CommonIntermediate, CommonLambda, CommonLeonExpressions }
+
+class PhaseCombinationTest {
+
+  import CommonDeclarations._
+  import CommonProofTrees._
+  import CommonIntermediate._
+  import CommonLambda._
+  import CommonLeonExpressions._
+      
+  @Test
+  def treeBoolToInt {
+    val (queryNode, query) = exampleBoolToInt
+    
+    val intermediateTree = IntermediateTransformer(queryNode)
+        
+    val codeGenerator = new CodeGenerator
+    
+    val extractor = new Extractor(new UnorderedStreamFactory)
+    
+    val extractorResults = extractor(intermediateTree) take 1
+    
+    assertEquals(1, extractorResults.size)
+    
+    val codeGenResult = codeGenerator(extractorResults.head._1)
+    
+    assertEquals(FunctionInvocation(functionBoolToIntFunDef, List(BooleanLiteral(false))), codeGenResult)    
+  }
+  
+  @Test
+  def treeIntToIntBoth {
+    val queryNode = exampleIntToIntBoth
+    
+    val intermediateTree = IntermediateTransformer(queryNode)
+    
+    assertEquals(constructIntToIntIntermediateBoth, intermediateTree)
+            
+    val extractor = new Extractor(new UnorderedStreamFactory)
+    
+    val extractorResults = (extractor(intermediateTree) take (5 * 2 * 2)) map { _._1 }	    
+    
+    assertEquals(5 * 4, extractorResults.size)	    	  
+    
+    for (node <- constructIntAndBoolToIntIntermediateLambda(5))
+    	assertTrue(node + " is not extracted.", extractorResults contains node)
+    
+    val codeGenerator = new CodeGenerator
+    
+    val expressions = extractorResults.map(codeGenerator(_)).toSet
+    
+    assertTrue(expressions contains boolInv)
+    assertTrue(expressions contains inv1WithBoolInv)
+    assertTrue(expressions contains inv1WithInt)
+    assertTrue(expressions contains inv2WithInt)
+    assertTrue(expressions contains inv3WithInt)  
+    assertTrue(expressions contains inv2WithBoolInv)    
+    assertTrue(expressions contains inv3WithBoolInv)      
+  }
+
+}
\ No newline at end of file
diff --git a/src/test/scala/insynth/reconstruction/ReconstructorTest.scala b/src/test/scala/insynth/reconstruction/ReconstructorTest.scala
new file mode 100644
index 000000000..1c1f6b5df
--- /dev/null
+++ b/src/test/scala/insynth/reconstruction/ReconstructorTest.scala
@@ -0,0 +1,95 @@
+package insynth.reconstruction
+
+import org.junit.{ Test, Ignore, BeforeClass, AfterClass }
+import org.junit.Assert._
+
+import insynth.reconstruction.codegen.CodeGenerator
+import insynth.Config
+
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+import leon.purescala.Common.{ FreshIdentifier }
+import leon.purescala.TypeTrees._
+import leon.purescala.Trees.{ Variable => LeonVariable, _ }
+
+import insynth.testutil.{ CommonProofTrees, CommonDeclarations, CommonLeonExpressions, CommonUtils }
+
+class ReconstructorTest {
+
+  import CommonDeclarations._
+  import CommonProofTrees._
+  import CommonLeonExpressions._
+  import CommonUtils._
+  
+  val codegen = new CodeGenerator
+  
+  @Test
+  def treeBoolToInt {
+    val (queryNode, query) = exampleBoolToInt
+    
+    val expStream = Reconstructor(queryNode, codegen)
+    
+    assertEquals(1, expStream.size)
+    
+    val codeGenResult = expStream.head
+    
+    assertEquals(FunctionInvocation(functionBoolToIntFunDef, List(BooleanLiteral(false))), codeGenResult.snippet)
+    assertEquals(0f, codeGenResult.weight, 0f)    
+  }
+  
+  @Test
+  def treeIntToIntBoth {
+    val queryNode = exampleIntToIntBoth
+    
+    val expStream = Reconstructor(queryNode, codegen)
+    
+    val expressions = expStream.map(_.snippet).take(20).toSet
+    
+    assertTrue(expressions contains boolInv)
+    assertTrue(expressions contains inv1WithBoolInv)
+    assertTrue(expressions contains inv1WithInt)
+    assertTrue(expressions contains inv2WithInt)
+    assertTrue(expressions contains inv3WithInt)  
+    assertTrue(expressions contains inv2WithBoolInv)    
+    assertTrue(expressions contains inv3WithBoolInv)      
+  }
+  
+  @Test
+  def treeIntToIntBothOrdered {
+    val queryNode = exampleIntToIntBoth
+    
+    val expStream = Reconstructor(queryNode, codegen, true)
+    
+    val expressions = assertTake(expStream, 20).map(_.snippet)
+    
+    val listOfExpressions = List(boolInv, inv1WithInt, inv1WithBoolInv, inv2WithInt,
+      inv3WithInt, inv2WithBoolInv, inv3WithBoolInv)
+    
+    for (exp <- listOfExpressions)
+    	assertTrue(expressions.toSet contains exp)
+    	
+    val listOfExpressionsOrder = List(boolInv, inv1WithBoolInv, inv2WithInt,
+      inv2WithBoolInv, inv3WithBoolInv)
+    
+    for (ind <- 0 until listOfExpressionsOrder.size - 1)
+      assertTrue("Expression " + listOfExpressionsOrder(ind) + " (position " + expressions.indexOf(listOfExpressionsOrder(ind)) +
+        ") should occur before expression " + listOfExpressionsOrder(ind+1) + " (position " + expressions.indexOf(listOfExpressionsOrder(ind + 1)) + ")",
+        expressions.indexOf(listOfExpressionsOrder(ind)) < expressions.indexOf(listOfExpressionsOrder(ind+1)))
+      
+  }
+
+}
+
+//object ReconstructorTest {
+//  
+//  var useEnumerationOrdering: Boolean = _
+//  
+//  @BeforeClass
+//  def saveFlag = {
+//    useEnumerationOrdering = Config.useEnumerationOrdering
+//    Config.useEnumerationOrdering = false
+//  }
+//  
+//  @AfterClass
+//  def restoreFlag = Config.useEnumerationOrdering = useEnumerationOrdering
+//  
+//}
diff --git a/src/test/scala/insynth/testutil/CommonLeonExpressions.scala b/src/test/scala/insynth/testutil/CommonLeonExpressions.scala
new file mode 100644
index 000000000..2ce2d4246
--- /dev/null
+++ b/src/test/scala/insynth/testutil/CommonLeonExpressions.scala
@@ -0,0 +1,20 @@
+package insynth.testutil
+
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+import leon.purescala.Common.{ FreshIdentifier }
+import leon.purescala.TypeTrees._
+import leon.purescala.Trees.{ Variable => _, _ }
+
+object CommonLeonExpressions {
+
+  import CommonDeclarations._
+        
+  val boolInv = FunctionInvocation(functionBoolToIntFunDef, List(booleanLiteral))
+  val inv1WithBoolInv = FunctionInvocation(functionIntToIntFunDef, List(boolInv))
+  val inv1WithInt = FunctionInvocation(functionIntToIntFunDef, List(intLiteral))
+  val inv2WithInt = FunctionInvocation(functionIntToIntFunDef, List(inv1WithInt))
+  val inv3WithInt = FunctionInvocation(functionIntToIntFunDef, List(inv2WithInt))
+  val inv2WithBoolInv = FunctionInvocation(functionIntToIntFunDef, List(inv1WithBoolInv))
+  val inv3WithBoolInv = FunctionInvocation(functionIntToIntFunDef, List(inv2WithBoolInv))
+
+}
\ No newline at end of file
diff --git a/src/test/scala/lesynth/AnalyzerTest.scala b/src/test/scala/lesynth/AnalyzerTest.scala
new file mode 100644
index 000000000..166da8159
--- /dev/null
+++ b/src/test/scala/lesynth/AnalyzerTest.scala
@@ -0,0 +1,49 @@
+package lesynth
+
+import scala.util.Random
+
+import org.junit.Assert._
+import org.junit.{ Test, Ignore }
+
+import insynth.leon.HoleFinder
+import insynth.leon.loader.LeonLoader
+
+import _root_.leon.purescala.Trees.{ Hole, IntLiteral }
+import _root_.leon.purescala.TreeOps
+import _root_.leon.evaluators._
+import _root_.leon.{ LeonContext, DefaultReporter, Main }
+import _root_.leon.verification.AnalysisPhase
+
+import insynth.testutil.CommonUtils
+import testutil.TestConfig
+
+class AnalyzerTest {
+
+  import TestConfig._
+  import CommonUtils._
+  import TreeOps._
+  
+  val rnd = new Random(System.currentTimeMillis())
+	
+	@Test
+	def testModel = {
+    val holeFinder = new HoleFinder(lesynthTestDir + "ListOperations.scala")
+				
+    holeFinder.extract match {
+      case Some((prog, hole)) =>
+		
+	    val reporter = new DefaultReporter()
+		  val args = Array("testcases/insynth/ListOperations.scala", "--timeout=2")
+		  
+			val ctx = Main.processOptions(reporter, args.toList)
+			
+	    val verReport = AnalysisPhase.run(ctx)(prog)
+	     
+	    assertTrue(Globals.asMap.size > 0)
+        
+      case _ =>
+        fail("HoleFinder could not extract hole from the program")
+    }    
+	}
+  
+}
diff --git a/src/test/scala/lesynth/RefinerTest.scala b/src/test/scala/lesynth/RefinerTest.scala
new file mode 100644
index 000000000..861971ed1
--- /dev/null
+++ b/src/test/scala/lesynth/RefinerTest.scala
@@ -0,0 +1,209 @@
+package lesynth
+
+import scala.util.Random
+
+import org.junit.Assert._
+import org.junit.{ Test, Ignore, Before }
+
+import insynth.leon.HoleFinder
+import insynth.leon.loader.{ LeonLoader, HoleExtractor }
+import insynth.leon._
+
+import _root_.leon.purescala.Trees.{ Expr, Hole, IntLiteral, UnitLiteral, Variable, FunctionInvocation, And }
+import _root_.leon.purescala.{ TreeOps }
+import _root_.leon.purescala.Definitions.{ Program, FunDef }
+import _root_.leon.evaluators._
+import _root_.leon.{ LeonContext, DefaultReporter, Main }
+import _root_.leon.verification.AnalysisPhase
+
+import insynth.testutil.CommonUtils
+import testutil.TestConfig
+
+class RefinerTest {
+
+  import TestConfig._
+  import CommonUtils._
+  import TreeOps._
+  
+  val rnd = new Random(System.currentTimeMillis())
+  
+  var prog: Program = _
+  var hole: Hole = _
+  var holeFunDef: FunDef = _
+  
+  var tail: UnaryReconstructionExpression = _
+  var head: UnaryReconstructionExpression = _
+  var nil: Expr = _
+  var cons: NaryReconstructionExpression = _
+  
+  @Before
+  def extract = {
+    
+    val holeFinder = new HoleFinder(lesynthTestDir + "ListOperationsHole.scala")
+				
+    holeFinder.extract match {
+      case Some((progE, holeE)) =>
+                
+      prog = progE
+      hole = holeE
+        
+      holeFunDef = new HoleExtractor(prog, hole).extractHole match {
+        case Some((hfd, _)) => hfd
+        case None => fail("could not extract hole"); null
+      } 
+		
+	    val loader = new LeonLoader(prog, hole)
+	    
+	    tail = 
+	      loader.extractFields.find { 
+		      _.expression match {
+		        case ure: UnaryReconstructionExpression => ure(UnitLiteral).toString.contains(".tail")
+		        case _ => false
+		      }
+		    } match {
+		      case Some(found) => found.expression.asInstanceOf[UnaryReconstructionExpression]
+		      case _ => fail("could not extract tail"); null
+		    }
+		    
+	    head = 
+	      loader.extractFields.find { 
+		      _.expression match {
+		        case ure: UnaryReconstructionExpression => ure(UnitLiteral).toString.contains(".head")
+		        case _ => false
+		      }
+		    } match {
+		      case Some(found) => found.expression.asInstanceOf[UnaryReconstructionExpression]
+		      case _ => fail("could not extract head"); null
+		    }
+		    
+	    cons = 
+	      loader.extractCaseClasses.find { 
+		      _.expression match {
+		        case nre: NaryReconstructionExpression => nre(List(UnitLiteral, UnitLiteral)).toString.contains("Cons")
+		        case _ => false
+		      }
+		    } match {
+		      case Some(found) => found.expression.asInstanceOf[NaryReconstructionExpression]
+		      case _ => fail("could not extract cons"); null
+		    }
+		    
+	    nil = 
+	      loader.extractCaseClasses.find { 
+		      _.expression match {
+		        case im: ImmediateExpression => im().toString.contains("Nil")
+		        case _ => false
+		      }
+		    } match {
+		      case Some(found) => found.expression.asInstanceOf[ImmediateExpression]()
+		      case _ => fail("could not extract cons"); null
+		    }
+		    
+      case _ =>
+        fail("HoleFinder could not extract hole from the program")
+    }    
+  }
+	  
+	@Test
+	def testIsLess = {
+		    
+	    val refiner = new Refiner(prog, hole, holeFunDef)
+	    import refiner.isLess
+	    
+	    assertEquals(2, holeFunDef.args.size)
+	    
+	    val variable1 = holeFunDef.args.head
+	    val variable2 = holeFunDef.args(1)
+	    
+	    assertEquals(+1, isLess(cons(List(UnitLiteral, variable1.toVariable)), variable1))
+	    assertEquals(+1, isLess(cons(List(UnitLiteral, variable1.toVariable)), variable2))
+	    assertEquals(-1, isLess(tail(variable1.toVariable), variable1))
+	    assertEquals(+1, isLess(head(variable1.toVariable), variable1))
+	    assertEquals(0, isLess(variable1.toVariable, variable1))
+	    assertEquals(1, isLess(variable1.toVariable, variable2))
+	    assertEquals(1, isLess(tail(variable1.toVariable), variable2))
+	    assertEquals(1, isLess(head(variable1.toVariable), variable2))
+	    assertEquals(1, isLess(nil, variable2))
+        
+	}
+  
+	@Test
+	def testIsCallLessBySize = {
+	    
+    val refiner = new Refiner(prog, hole, holeFunDef)
+    import refiner.isCallAvoidableBySize
+    
+    assertEquals(2, holeFunDef.args.size)
+    
+    val arg1 = holeFunDef.args.head.toVariable
+    val arg2 = holeFunDef.args(1).toVariable
+    
+    def makeFunctionCall(arg1: Expr, arg2: Expr) = FunctionInvocation(holeFunDef, Seq(arg1, arg2)) 
+    
+    assertEquals(true, isCallAvoidableBySize(makeFunctionCall(nil, nil)))
+    assertEquals(true, isCallAvoidableBySize(makeFunctionCall(arg1, arg2)))
+    assertEquals(true, isCallAvoidableBySize(makeFunctionCall(arg2, arg1)))
+    assertEquals(false, isCallAvoidableBySize(makeFunctionCall(arg1, tail(arg2))))
+    assertEquals(true, isCallAvoidableBySize(makeFunctionCall(arg1, tail(arg1))))
+    assertEquals(false, isCallAvoidableBySize(makeFunctionCall(tail(arg1), tail(arg2))))
+    assertEquals(true, isCallAvoidableBySize(makeFunctionCall(cons(List(nil, tail(arg1))), arg2)))
+    assertEquals(false, isCallAvoidableBySize(makeFunctionCall(cons(List(nil, tail(arg1))), tail(arg2))))
+    assertEquals(false, isCallAvoidableBySize(nil))
+      
+	}
+	
+	@Test
+	def testHasDoubleRecursion = {
+	    
+    val refiner = new Refiner(prog, hole, holeFunDef)
+    import refiner.hasDoubleRecursion
+    
+    assertEquals(2, holeFunDef.args.size)
+    
+    val arg1 = holeFunDef.args.head.toVariable
+    val arg2 = holeFunDef.args(1).toVariable
+    
+    def makeFunctionCall(arg1: Expr, arg2: Expr) = FunctionInvocation(holeFunDef, Seq(arg1, arg2)) 
+    
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(nil, nil)))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(arg1, arg2)))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(arg2, arg1)))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(arg1, tail(arg2))))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(arg1, tail(arg1))))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(tail(arg1), tail(arg2))))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(cons(List(nil, tail(arg1))), arg2)))
+    assertEquals(false, hasDoubleRecursion(makeFunctionCall(cons(List(nil, tail(arg1))), tail(arg2))))
+    assertEquals(false, hasDoubleRecursion(nil))
+    
+    assertEquals(false, hasDoubleRecursion(And(makeFunctionCall(arg1, arg2), makeFunctionCall(arg1, arg2))))
+    assertEquals(true, hasDoubleRecursion(makeFunctionCall(makeFunctionCall(arg1, arg2), tail(arg2))))
+      
+	}
+ 
+	@Test
+	def testIsAvoidable = {
+	    
+    val refiner = new Refiner(prog, hole, holeFunDef)
+    import refiner.isAvoidable
+    
+    assertEquals(2, holeFunDef.args.size)
+    
+    val arg1 = holeFunDef.args.head.toVariable
+    val arg2 = holeFunDef.args(1).toVariable
+    
+    def makeFunctionCall(arg1: Expr, arg2: Expr) = FunctionInvocation(holeFunDef, Seq(arg1, arg2)) 
+    
+    assertEquals(true, isAvoidable(makeFunctionCall(nil, nil)))
+    assertEquals(true, isAvoidable(makeFunctionCall(arg1, arg2)))
+    assertEquals(true, isAvoidable(makeFunctionCall(arg2, arg1)))
+    assertEquals(false, isAvoidable(makeFunctionCall(arg1, tail(arg2))))
+    assertEquals(true, isAvoidable(makeFunctionCall(arg1, tail(arg1))))
+    assertEquals(false, isAvoidable(makeFunctionCall(tail(arg1), tail(arg2))))
+    assertEquals(true, isAvoidable(makeFunctionCall(cons(List(nil, tail(arg1))), arg2)))
+    assertEquals(false, isAvoidable(makeFunctionCall(cons(List(nil, tail(arg1))), tail(arg2))))
+    assertEquals(false, isAvoidable(nil))
+    
+    assertEquals(true, isAvoidable(makeFunctionCall(makeFunctionCall(arg1, arg2), tail(arg2))))
+      
+	}
+	
+}
\ No newline at end of file
diff --git a/src/test/scala/lesynth/TryOutSynthesizerExamplesTest.scala b/src/test/scala/lesynth/TryOutSynthesizerExamplesTest.scala
new file mode 100755
index 000000000..2655b3ef7
--- /dev/null
+++ b/src/test/scala/lesynth/TryOutSynthesizerExamplesTest.scala
@@ -0,0 +1,672 @@
+package lesynth
+
+import org.junit.Assert._
+import org.junit.{ Test, Ignore }
+
+import testutil.TestConfig
+
+import scala.collection.mutable.{ Map => MutableMap }
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.{ LinkedList => MutableList }
+import scala.util.matching.Regex
+import scala.collection.mutable.PriorityQueue
+
+import scala.tools.nsc.{ Settings => NSCSettings, MainGenericRunner }
+
+import leon.{ Main => LeonMain, Reporter, DefaultReporter, SilentReporter, Settings, LeonContext }
+import leon.solvers.{ Solver, TimeoutSolver }
+import leon.solvers.z3.{ FairZ3Solver }
+import leon.verification.AnalysisPhase
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Trees.{ Variable => LeonVariable, _ }
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+import leon.purescala.Common.{ Identifier, FreshIdentifier }
+import leon.purescala.TreeOps
+import leon.plugin.ExtractionPhase
+
+import insynth.util.logging.HasLogger
+import insynth.interfaces.Declaration
+import insynth.InSynth
+import insynth.reconstruction.codegen.CodeGenerator
+import insynth.leon.loader.LeonLoader
+import insynth.leon.LeonDeclaration
+import insynth.leon.ImmediateExpression
+import insynth.engine.InitialEnvironmentBuilder
+import insynth.leon.LeonQueryBuilder
+import insynth.interfaces.{ Loader, Declaration, QueryBuilder }
+import insynth.engine.{ Engine, InitialEnvironmentBuilder }
+import insynth.engine.scheduler.WeightScheduler
+import insynth.structures.ContainerNode
+import insynth.util.TimeOut
+import insynth.Config
+import insynth.reconstruction.Reconstructor
+import insynth.leon.TypeTransformer
+import insynth.leon.HoleFinder
+import insynth.leon.loader.HoleExtractor
+import insynth.reconstruction.Output
+
+class TryOutSynthesizerExamplesTest {
+  
+  @Test
+  def tryOut {
+    import TestConfig._
+    
+    val synthesizer = new TryOutSynthesizerExamples(lesynthTestDir + "ListOperationsHole.scala")
+    
+    val report = synthesizer.synthesize
+    assertTrue(report.isSuccess)
+    println(report.summaryString)
+  }
+  
+}
+
+class TryOutSynthesizerExamples(
+  fileName: String,
+  // number of condition expressions to try before giving up on that branch expression
+  numberOfBooleanSnippets: Int = 5,
+  numberOfCounterExamplesToGenerate: Int = 5,
+  leonTimeout: Int = 2, // seconds
+  analyzeSynthesizedFunctionOnly: Boolean = false,
+  showLeonOutput: Boolean = false,
+  reporter: Reporter = new DefaultReporter,
+  collectCounterExamplesFromLeon: Boolean = false) extends HasLogger {
+  
+  info("Synthesizer:")
+  info("fileName: %s".format(fileName))
+  info("numberOfBooleanSnippets: %d".format(numberOfBooleanSnippets))
+  info("numberOfCounterExamplesToGenerate: %d".format(numberOfCounterExamplesToGenerate))
+  info("leonTimeout: %d".format(leonTimeout))
+
+  // some synthesis instance information
+  private var program: Program = _
+  private var hole: Hole = _
+  private var holeFunDef: FunDef = _
+  // initial declarations
+  private var allDeclarations: List[Declaration] = _
+  // objects used in the synthesis
+  private var loader: LeonLoader = _
+  private var inSynth: InSynth = _
+  private var inSynthBoolean: InSynth = _
+  private var refiner: Refiner = _
+  private var solver: Solver = _
+  private var ctx: LeonContext = _
+  private var variableRefinements: MutableMap[Identifier, MutableSet[ClassType]] = _
+  private var initialPrecondition: Expr = _
+
+  // flag denoting if a correct body has been synthesized
+  private var found = false
+
+  // accumulate precondition for the remaining branch to synthesize 
+  private var accumulatingPrecondition: Expr = _
+  // accumulate the final expression of the hole
+  private var accumulatingExpression: Expr => Expr = _
+  //private var accumulatingExpressionMatch: Expr => Expr = _
+
+  // time
+  var startTime: Long = _
+  var verTime: Long = 0
+  var synTime: Long = 0
+
+  // filtering/ranking with examples support
+  var exampleRunner: ExampleRunner = _
+  val numberOfTestsInIteration = 50
+  val numberOfCheckInIteration = 5
+
+  // TODO function to check specifically
+  def analyzeProgram = {
+
+    val temp = System.currentTimeMillis
+    Globals.allSolved = Some(true)
+
+    val report = AnalysisPhase.run(ctx)(program)
+
+    val time = System.currentTimeMillis - temp
+    fine("Analysis took: " + time + ", from report: " + report.totalTime)
+
+    // accumulate
+    verTime += time
+
+    report
+  }
+
+  // TODO return boolean (do not do unecessary analyze)
+  def generateCounterexamples(program: Program, funDef: FunDef, number: Int): (Seq[Map[Identifier, Expr]], Expr) = {
+
+    fine("generate counter examples with funDef.prec= " + funDef.precondition.getOrElse(BooleanLiteral(true)))
+    val temp = System.currentTimeMillis
+
+    // get current precondition
+    var precondition = funDef.precondition.getOrElse(BooleanLiteral(true))
+    // where we will accumulate counterexamples as sequence of maps
+    var maps: Seq[Map[Identifier, Expr]] = Seq.empty
+
+    // iterate specific number of times or until no further counterexample can be generated
+    var changed = true
+    var ind = 0
+    while (ind < number && changed) {
+
+      // analyze the program
+      analyzeProgram
+
+      // check if solver could solved this instance
+      if (Globals.allSolved == Some(false) && !Globals.asMap.isEmpty) {
+
+        fine("found coounterexample: " + Globals.asMap)
+        // add current counterexample
+        maps :+= Globals.asMap
+
+        // prevent this counterexample to re-occur
+        val precAddition = Not(And(Globals.asMap map { case (id, value) => Equals(LeonVariable(id), value) } toSeq))
+        precondition = And(Seq(precondition, precAddition))
+        // update precondition        
+        funDef.precondition = Some(precondition)
+      } else
+        changed = false
+
+      ind += 1
+    }
+
+    val temptime = System.currentTimeMillis - temp
+    fine("Generation of counter-examples took: " + temptime)
+    verTime += temptime
+
+    // return found counterexamples and the formed precondition
+    (maps, precondition)
+  }
+
+  def getCurrentBuilder = new InitialEnvironmentBuilder(allDeclarations)
+
+  def synthesizeBranchExpressions =
+    inSynth.getExpressions(getCurrentBuilder)
+
+  def synthesizeBooleanExpressions =
+    inSynthBoolean.getExpressions(getCurrentBuilder)
+
+  def interactivePause = {
+    System.out.println("Press Any Key To Continue...");
+    new java.util.Scanner(System.in).nextLine();
+  }
+
+  def initialize = {
+
+    // TODO lose this - globals are bad
+    Globals.allSolved = None
+
+    // extract hole
+    new HoleFinder(fileName).extract match {
+      case Some((matchProgram, matchHole: Hole)) =>
+        program = matchProgram
+        hole = matchHole
+      case None => throw new RuntimeException("Cannot find hole")
+    }
+
+    // context needed for verification
+    import leon.Main._
+    val reporter =
+      if (showLeonOutput) new DefaultReporter
+      else new SilentReporter
+
+    val args =
+      if (analyzeSynthesizedFunctionOnly)
+        Array(fileName, "--timeout=" + leonTimeout, "--functions=" + holeFunDef.id.name)
+      else
+        Array(fileName, "--timeout=" + leonTimeout)
+    info("Leon context array: " + args.mkString(","))
+    ctx = processOptions(reporter, args.toList)
+
+    solver = //new FairZ3Solver(ctx)
+      new TimeoutSolver(new FairZ3Solver(ctx), leonTimeout)
+
+    // create new insynth object
+    loader = new LeonLoader(program, hole, false)
+    inSynth = new InSynth(loader, true)
+    // save all declarations seen
+    allDeclarations = inSynth.getCurrentBuilder.getAllDeclarations
+    // make conditions synthesizer
+    inSynthBoolean = new InSynth(allDeclarations, BooleanType, true)
+
+    // funDef of the hole
+    holeFunDef = loader.holeDef
+    fine("postcondition is: " + holeFunDef.getPostcondition)
+
+    // accumulate precondition for the remaining branch to synthesize 
+    accumulatingPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+    // save initial precondition
+    initialPrecondition = accumulatingPrecondition
+    // accumulate the final expression of the hole
+    accumulatingExpression = (finalExp: Expr) => finalExp
+    //accumulatingExpressionMatch = accumulatingExpression
+
+    // each variable of super type can actually have a subtype
+    // get sine declaration maps to be able to refine them
+    val directSubclassMap = loader.directSubclassesMap
+    val variableDeclarations = loader.variableDeclarations
+    // map from identifier into a set of possible subclasses
+    variableRefinements = MutableMap.empty
+    for (varDec <- variableDeclarations) {
+      varDec match {
+        case LeonDeclaration(_, _, typeOfVar: ClassType, ImmediateExpression(_, LeonVariable(id))) =>
+          variableRefinements += (id -> MutableSet(directSubclassMap(typeOfVar).toList: _*))
+        case _ =>
+      }
+    }
+
+    // calculate cases that should not happen
+    refiner = new Refiner(program, hole, holeFunDef)
+    fine("Refiner initialized. Recursive call: " + refiner.recurentExpression)
+
+    exampleRunner = new ExampleRunner(holeFunDef)
+    exampleRunner.counterExamples ++= introduceCounterExamples
+  }
+
+  def countPassedExamples(snippet: Expr) = {
+    val oldPreconditionSaved = holeFunDef.precondition
+    val oldBodySaved = holeFunDef.body
+
+    // restore initial precondition
+    holeFunDef.precondition = Some(initialPrecondition)
+
+    // get the whole body (if else...)
+    val accumulatedExpression = accumulatingExpression(snippet)
+    // set appropriate body to the function for the correct evaluation
+    holeFunDef.body = Some(accumulatedExpression)
+
+    val count = exampleRunner.countPassed(accumulatedExpression)
+
+    holeFunDef.precondition = oldPreconditionSaved
+    holeFunDef.body = oldBodySaved
+
+    count
+  }
+
+  def introduceCounterExamples = {
+    val argumentIds = holeFunDef.args.map(_.id)
+    hole.getType match {
+      case ct: ClassType =>
+        val setSubclasses = loader.directSubclassesMap(ct).map(_.asInstanceOf[CaseClassType].classDef)
+
+        val (nilClassSet, consClassSet) = setSubclasses.partition(_.fieldsIds.size == 0)
+
+        val nilClass = nilClassSet.head
+        val consClass = consClassSet.head
+
+        var counter = 0
+        def getIntLiteral = { counter += 1; IntLiteral(counter) }
+
+        val list0 = () => CaseClass(nilClass, Nil)
+        val list1 = () => CaseClass(consClass, getIntLiteral :: list0() :: Nil)
+        val list2 = () => CaseClass(consClass, getIntLiteral :: list1() :: Nil)
+        val list3 = () => CaseClass(consClass, getIntLiteral :: list2() :: Nil)
+        val list4 = () => CaseClass(consClass, getIntLiteral :: list3() :: Nil)
+
+        val lists = List(list0, list1, list2, list3 /*, list4*/ )
+
+        for (l1 <- lists; l2 <- lists)
+          yield Map(argumentIds(0) -> l1(), argumentIds(1) -> l2())
+
+      case _ =>
+        throw new RuntimeException("Could not produce initial examples: Could not match hole type")
+    }
+  }
+
+  def synthesize: Report = {
+    reporter.info("Synthesis called on file: " + fileName)
+
+    // get start time
+    startTime = System.currentTimeMillis
+
+    reporter.info("Initializing synthesizer: ")
+    reporter.info("numberOfBooleanSnippets: %d".format(numberOfBooleanSnippets))
+    reporter.info("numberOfCounterExamplesToGenerate: %d".format(numberOfCounterExamplesToGenerate))
+    reporter.info("leonTimeout: %d".format(leonTimeout))
+    initialize
+    reporter.info("Synthesizer initialized")
+
+    // keeps status of validity
+    var keepGoing = Globals.allSolved match {
+      case Some(true) => false
+      case _ => true
+    }
+
+    // initial snippets (will update in the loop)
+    var snippets = synthesizeBranchExpressions
+    // iterate while the program is not valid
+    import scala.util.control.Breaks._
+    var iteration = 0
+    breakable {
+      while (keepGoing) {
+        // next iteration
+        iteration += 1
+        reporter.info("####################################")
+        reporter.info("######Iteration #" + iteration + " ###############")
+        reporter.info("####################################")
+
+        // just printing of expressions
+        finest(
+          ((snippets zip Iterator.range(0, 200).toStream) map {
+            case ((snippet: Output, ind: Int)) => ind + ": snippet is " + snippet.getSnippet
+          }).mkString("\n"))
+        reporter.info("# precondition is: " + holeFunDef.precondition.getOrElse(BooleanLiteral(true)))
+        reporter.info("# accumulatingPrecondition is: " + accumulatingPrecondition)
+        reporter.info("# accumulatingExpression(Unit) is: " + accumulatingExpression(UnitLiteral))
+        reporter.info("####################################")
+
+        // ordering of expressions according to passed examples
+        var pq = new PriorityQueue[(Expr, Int)]()(
+          new Ordering[(Expr, Int)] {
+            def compare(pair1: (Expr, Int), pair2: (Expr, Int)) =
+              pair1._2.compare(pair2._2)
+          })
+        var numberOfTested = 0
+
+        // just printing of expressions and pass counts        
+        finest(
+          ((snippets zip Iterator.range(0, 200).toStream) map {
+            case ((snippet: Output, ind: Int)) => ind + ": snippet is " + snippet.getSnippet +
+              " pass count is " + countPassedExamples(snippet.getSnippet)
+          }).mkString("\n"))
+        //interactivePause
+
+        // found precondition?
+        found = false
+        // try to find it
+        breakable {
+          // go through all snippets
+          for (snippet <- snippets; val snippetTree = snippet.getSnippet) {
+            finest("snippetTree is: " + snippetTree)
+
+            // skip avoidable calls
+            if (!refiner.isAvoidable(snippetTree)) {
+
+              // passed example pairs
+              val passCount = countPassedExamples(snippetTree)
+
+              if (passCount == exampleRunner.counterExamples.size) {
+                info("All examples passed. Testing snippet " + snippetTree + " right away")
+                if (tryToSynthesizeBranch(snippetTree)) {
+                  // will set found if correct body is found
+                  break
+                }
+              } else {
+                info("snippet with pass count filtered: " + (snippetTree, passCount))
+                pq.enqueue((snippetTree, 100 + (passCount * (iteration - 1)) - snippet.getWeight.toInt))
+              }
+
+            } else {
+              fine("Refiner filtered this snippet: " + snippetTree)
+            } // if (!refiner.isAvoidable(snippetTree)) {
+
+            // check if we this makes one test iteration            
+            if (numberOfTested >= numberOfTestsInIteration) {
+              fine("Queue contents: " + pq.mkString(", "))
+              fine("head of queue is: " + pq.head)
+
+              //interactivePause
+              // go and check the topmost numberOfCheckInIteration
+              for (i <- 1 to math.min(numberOfCheckInIteration, pq.size)) {
+                val nextSnippet = pq.dequeue._1
+                info("dequeued nextSnippet: " + nextSnippet)
+                //interactivePause
+
+                if (tryToSynthesizeBranch(nextSnippet)) {
+                  break
+                }
+              }
+
+              numberOfTested = 0
+            } else
+              numberOfTested += 1
+
+          } // for (snippet <- snippets
+        } // breakable { for (snippet <- snippets
+
+        // if did not found for any of the branch expressions
+        if (found) {
+          val endTime = System.currentTimeMillis
+          reporter.info("We are done, in time: " + (endTime - startTime))
+          return new FullReport(holeFunDef, (endTime - startTime))
+        }
+
+        // get new snippets
+        snippets = synthesizeBranchExpressions
+
+        fine("filtering based on: " + holeFunDef.precondition.get)
+        fine("counterexamples before filter: " + exampleRunner.counterExamples.size)
+        exampleRunner.filter(holeFunDef.precondition.get)
+        fine("counterexamples after filter: " + exampleRunner.counterExamples.size)
+        fine("counterexamples after filter: " + exampleRunner.counterExamples.mkString("\n"))
+      }
+    } //breakable { while (!keepGoing) {
+
+    EmptyReport
+  }
+
+  def tryToSynthesizeBranch(snippetTree: Expr): Boolean = {
+    // replace hole in the body with the whole if-then-else structure, with current snippet tree
+    val oldBody = holeFunDef.getBody
+    val newBody = accumulatingExpression(snippetTree)
+    holeFunDef.body = Some(newBody)
+
+    // precondition
+    val oldPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+    holeFunDef.precondition = Some(initialPrecondition)
+
+    snippetTree.setType(hole.desiredType)
+    //holeFunDef.getBody.setType(hole.desiredType)
+
+    // TODO spare one analyzing step
+    // analyze the program
+    fine("analyzing program for funDef:" + holeFunDef)
+    analyzeProgram
+
+    // check if solver could solved this instance
+    if (Globals.allSolved == Some(true)) {
+      // mark the branch found
+      found = true
+
+      reporter.info("Wooooooow we have a winner!")
+      reporter.info("************************************")
+      reporter.info("*********And the winner is**********")
+      reporter.info(accumulatingExpression(snippetTree).toString)
+      reporter.info("************************************")
+
+      return true
+    }
+
+    // store appropriate values here, will be update in a finally branch
+    var bodyToRestore = oldBody
+    var preconditionToRestore = Some(oldPrecondition)
+
+    // because first initial test
+    holeFunDef.precondition = preconditionToRestore
+
+    // get counterexamples
+    fine("Going to generating counterexamples: " + holeFunDef)
+    val (maps, precondition) = generateCounterexamples(program, holeFunDef, 5)
+
+    // collect (add) counterexamples from leon
+    if (collectCounterExamplesFromLeon)
+      exampleRunner.counterExamples ++= maps
+
+    // this should not be possible
+    //    val keepGoing = Globals.allSolved match {
+    //      case Some(true) => false
+    //      case _ => true
+    //    }
+    //
+    //    // if no counterexamples and all are solved, we are done
+    //    if (maps.isEmpty && !keepGoing) {
+    //      // mark the branch found
+    //      found = true
+    //
+    //      println("Wooooooow we have a winner!")
+    //      println("************************************")
+    //      println("*********And the winner is**********")
+    //      println(accumulatingExpression(snippetTree))
+    //      println("************************************")
+    //
+    //      return true
+    //    }
+
+    // will modify funDef body and precondition, restore it later
+    try {
+      if (!maps.isEmpty) {
+        // proceed with synthesizing boolean expressions
+        solver.setProgram(program)
+
+        // reconstruct (only defined number of boolean expressions)
+        val innerSnippets = synthesizeBooleanExpressions take numberOfBooleanSnippets
+        // just printing of expressions
+        finest(
+          ((innerSnippets zip Iterator.range(0, 500).toStream) map {
+            case ((snippet: Output, ind: Int)) => ind + ": snippet is " + snippet.getSnippet
+          }).mkString("\n"))
+
+        for (innerSnippetTree <- innerSnippets map { _.getSnippet }) {
+          fine("boolean snippet is: " + innerSnippetTree)
+
+          val (innerFound, innerPrec) = tryToSynthesizeBooleanCondition(snippetTree, innerSnippetTree, precondition)
+
+          // if precondition found
+          if (innerFound) {
+            reporter.info("Precondition " + innerPrec + " found for " + snippetTree)
+
+            innerPrec match {
+              case s @ Some(_) =>
+                // new precondition (restore in finally)
+                preconditionToRestore = s
+              case _ =>
+            }
+            return true
+          }
+
+        } // iterating over all boolean solutions
+
+        reporter.info("No precondition found for branch expression: " + snippetTree)
+        return false
+
+      } // if ( !maps.isEmpty ) {
+      // no counter examples, we just say that we cannot do anything
+      false
+    } // try
+    finally {
+      // set these to the FunDef
+      holeFunDef.precondition = preconditionToRestore
+      // restore old body (we accumulate expression)                                
+      holeFunDef.body = Some(oldBody)
+    }
+  }
+
+  def tryToSynthesizeBooleanCondition(snippetTree: Expr, innerSnippetTree: Expr, precondition: Expr): (Boolean, Option[Expr]) = {
+
+    // new condition together with existing precondition
+    val newCondition = And(Seq(accumulatingPrecondition, innerSnippetTree))
+
+    // new expression should not be false
+    val notFalseEquivalence = Not(newCondition)
+    val notFalseSolveReturn = solver.solve(notFalseEquivalence)
+    fine("solve for not false returned: " + notFalseSolveReturn)
+
+    notFalseSolveReturn match {
+      case Some(true) =>
+        (false, None)
+      case None =>
+        (false, None)
+      // nothing here
+      // here, our expression is not contradictory, continue
+      case Some(false) =>
+        // check if synthesized boolean expression implies precondition (counterexamples)
+        val implyExpression = Implies(newCondition, precondition)
+        fine("implyExpression is: " + implyExpression)
+
+        // check if synthesized condition implies counter-examples
+        val solveReturn = solver.solve(implyExpression)
+        fine("solve returned: " + solveReturn)
+
+        solveReturn match {
+          case Some(true) =>
+            // if expression implies counterexamples add it to the precondition and try to validate program
+            holeFunDef.precondition = Some(newCondition)
+            // do analysis
+            analyzeProgram
+            // program is valid, we have a branch
+            if (Globals.allSolved == Some(true)) {
+              // we found a branch
+              reporter.info("Wow! We found a branch!")
+
+              // update accumulating expression
+              val oldAccumulatingExpression = accumulatingExpression
+              val newAccumulatingExpression =
+                (finalExpr: Expr) =>
+                  oldAccumulatingExpression({
+                    val innerIf = IfExpr(innerSnippetTree, snippetTree, finalExpr)
+                    innerIf.setType(snippetTree.getType)
+                    innerIf
+                  })
+
+              accumulatingExpression = newAccumulatingExpression
+
+              // update accumulating precondition
+              fine("updating accumulatingPrecondition")
+              accumulatingPrecondition = And(Seq(accumulatingPrecondition, Not(innerSnippetTree)))
+              fine("updating hole fun precondition and body (to be hole)")
+
+              // set to set new precondition
+              val preconditionToRestore = Some(accumulatingPrecondition)
+
+              // check for refinements
+              checkRefinements(innerSnippetTree) match {
+                case Some(refinementPair @ (id, classType)) =>
+                  fine("And now we have refinement type: " + refinementPair)
+                  fine("variableRefinements(id) before" + variableRefinements(id))
+                  variableRefinements(id) -= loader.classMap(classType.id)
+                  fine("variableRefinements(id) after" + variableRefinements(id))
+
+                  // if we have a single subclass possible to refine
+                  if (variableRefinements(id).size == 1) {
+                    reporter.info("We do variable refinement for " + id)
+
+                    val newType = variableRefinements(id).head
+                    fine("new type is: " + newType)
+
+                    // update declarations
+                    allDeclarations =
+                      for (dec <- allDeclarations)
+                        yield dec match {
+                        case LeonDeclaration(inSynthType, _, decClassType, imex @ ImmediateExpression(_, LeonVariable(`id`))) =>
+                          LeonDeclaration(
+                            imex, TypeTransformer(newType), newType)
+                        case _ =>
+                          dec
+                      }
+
+                  } else
+                    fine("we cannot do variable refinement :(")
+                case _ =>
+              }
+
+              // found a boolean snippet, break
+              (true, preconditionToRestore)
+            } else {
+              // reset funDef and continue with next boolean snippet
+              val preconditionToRestore = Some(accumulatingPrecondition)
+              (false, preconditionToRestore)
+            }
+
+          case _ =>
+
+            fine("solver filtered out the precondition (does not imply counterexamples)")
+            (false, None)
+        } //solveReturn match { (for implying counterexamples)
+    } // notFalseSolveReturn match {
+  }
+
+  // inspect the expression if some refinements can be done
+  def checkRefinements(expr: Expr) = expr match {
+    case CaseClassInstanceOf(classDef, LeonVariable(id)) =>
+      Some((id, classDef))
+    case _ =>
+      None
+  }
+
+}
\ No newline at end of file
diff --git a/src/test/scala/lesynth/TryOutTest.scala b/src/test/scala/lesynth/TryOutTest.scala
new file mode 100644
index 000000000..d3a44e941
--- /dev/null
+++ b/src/test/scala/lesynth/TryOutTest.scala
@@ -0,0 +1,639 @@
+package lesynth
+
+import org.junit.Assert._
+import org.junit.{ Test, Ignore }
+
+import scala.collection.mutable.{ Map => MutableMap }
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.{ LinkedList => MutableList }
+import scala.util.matching.Regex
+import scala.collection.mutable.PriorityQueue
+
+import scala.tools.nsc.{ Settings => NSCSettings, MainGenericRunner }
+
+import leon.{ Main => LeonMain, DefaultReporter, SilentReporter, Settings, LeonContext }
+import leon.solvers.{ Solver, TimeoutSolver }
+import leon.solvers.z3.{ FairZ3Solver }
+import leon.verification.AnalysisPhase
+import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+import leon.purescala.Trees.{ Variable => LeonVariable, _ }
+import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+import leon.purescala.Common.{ Identifier, FreshIdentifier }
+import leon.purescala.TreeOps
+import leon.plugin.ExtractionPhase
+
+import insynth.util.logging.HasLogger
+import insynth.interfaces.Declaration
+import insynth.InSynth
+import insynth.reconstruction.codegen.CodeGenerator
+import insynth.leon.loader.LeonLoader
+import insynth.leon.LeonDeclaration
+import insynth.leon.ImmediateExpression
+import insynth.engine.InitialEnvironmentBuilder
+import insynth.leon.LeonQueryBuilder
+import insynth.interfaces.{ Loader, Declaration, QueryBuilder }
+import insynth.engine.{ Engine, InitialEnvironmentBuilder }
+import insynth.engine.scheduler.WeightScheduler
+import insynth.structures.ContainerNode
+import insynth.util.TimeOut
+import insynth.Config
+import insynth.reconstruction.Reconstructor
+import insynth.leon.TypeTransformer
+import insynth.leon.HoleFinder
+import insynth.leon.loader.HoleExtractor
+
+import testutil.TestConfig
+
+class TryOutTest extends HasLogger {
+  
+  import TestConfig.lesynthTestDir
+
+  @Test
+  def test1 {
+    synthesize(lesynthTestDir + "ListOperationsHole.scala")
+  }
+
+  def analyzeProgram(program: Program) {
+    import leon.Main._
+
+    val temp = System.currentTimeMillis
+    Globals.allSolved = Some(true)
+
+    val reporter = new SilentReporter()
+    val args = Array("no file!", "--timeout=2")
+    val ctx = processOptions(reporter, args.toList)
+
+    AnalysisPhase.run(ctx)(program)
+
+    val time = System.currentTimeMillis - temp
+    println("analysis took " + time)
+    verTime += time
+  }
+
+  def generateCounterexamples(program: Program, funDef: FunDef, number: Int): (Seq[Map[Identifier, Expr]], Expr) = {
+
+    fine("generate counter examples with funDef.prec= " + funDef.precondition.getOrElse(BooleanLiteral(true)))
+
+    // get current precondition
+    var precondition = funDef.precondition.getOrElse(BooleanLiteral(true))
+    // where we will accumulate counterexamples as sequence of maps
+    var maps: Seq[Map[Identifier, Expr]] = Seq.empty
+
+    // iterate specific number of times or until no further counterexample can be generated
+    var changed = true
+    var ind = 0
+    while (ind < number && changed) {
+
+      // analyze the program
+      analyzeProgram(program)
+
+      // check if solver could solved this instance
+      if (Globals.allSolved == Some(false) && !Globals.asMap.isEmpty) {
+
+        fine("found coounterexample: " + Globals.asMap)
+
+        // add current counterexample
+        maps :+= Globals.asMap
+        // prevent this counterexample to reoccur
+        val precAddition = Not(And(Globals.asMap map { case (id, value) => Equals(LeonVariable(id), value) } toSeq))
+        precondition = And(Seq(precondition, precAddition))
+        funDef.precondition = Some(precondition)
+      } else
+        changed = false
+
+      ind += 1
+    }
+
+    // return found counterexamples and the formed precondition
+    (maps, precondition)
+  }
+
+  def assertL1L2Refinements(variableRefinements: MutableMap[Identifier, MutableSet[ClassType]]) =
+    for (
+      pair @ (varName, nameSet) <- List(
+        ("l2", Set("Nil", "Cons")),
+        ("l1", Set("Nil", "Cons")))
+    ) assertTrue(
+      "pair " + pair + " not found. Found: " + variableRefinements.mkString(", "),
+      (false /: variableRefinements) {
+        (res, extr) =>
+          extr match {
+            case (id, classTypeSet) => res ||
+              (
+                id.name == varName &&
+                (true /: nameSet) {
+                  (res, innerName) => res && classTypeSet.exists(_.classDef.id.name == innerName)
+                })
+            case _ => false
+          }
+      })
+
+  private var program: Program = _
+
+  private var hole: Hole = _
+  private var holeFunDef: FunDef = _
+
+  private var allDeclarations: List[Declaration] = _
+
+  private var loader: LeonLoader = _
+
+  private var inSynth: InSynth = _
+  private var codeGenerator: CodeGenerator = _
+
+  private var refiner: Refiner = _
+
+  var found = false
+
+  // accumulate precondition for the remaining branch to synthesize 
+  private var accumulatingPrecondition: Expr = _
+  // accumulate the final expression of the hole
+  private var accumulatingExpression: Expr => Expr = _
+  //private var accumulatingExpressionMatch: Expr => Expr = _
+
+  var solver: Solver = _
+  //  
+  var ctx: LeonContext = _
+  //  
+  var variableRefinements: MutableMap[Identifier, MutableSet[ClassType]] = _
+
+  var initialPrecondition: Expr = _
+
+  var startTime: Long = _
+
+  var verTime: Long = 0
+  var synTime: Long = 0
+
+  // number of condition expressions to try before giving up on that branch expression
+  val numberOfBooleanSnippets = 5
+
+  def synthesizeExpressions =
+    inSynth.getExpressions
+
+  def initialize(fileName: String) = {
+    
+    import leon.Main._
+
+    val reporter = new SilentReporter
+    val args = Array(fileName, "--timeout=2")
+    ctx = processOptions(reporter, args.toList)
+
+    // extract information about the program
+//    extractInformation(ctx, fileName)
+
+    codeGenerator = new CodeGenerator
+
+    new HoleFinder(fileName).extract match {
+      case Some((matchProgram, matchHole: Hole)) =>
+        program = matchProgram
+        hole = matchHole
+      case None => fail("could not find hole")
+    }
+
+    solver = //new FairZ3Solver(ctx)
+      new TimeoutSolver(new FairZ3Solver(ctx), 2)
+
+    loader = new LeonLoader(program, hole, false)
+    // create new insynth object
+    inSynth = new InSynth(loader, true)
+
+    // save all declarations seen
+    allDeclarations = inSynth.getCurrentBuilder.getAllDeclarations
+
+    // funDef of the hole
+    holeFunDef = loader.holeDef
+    println("postcondition is: " + holeFunDef.getPostcondition)
+
+    // accumulate precondition for the remaining branch to synthesize 
+    accumulatingPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+    // save initial precondition
+    initialPrecondition = accumulatingPrecondition
+    // accumulate the final expression of the hole
+    accumulatingExpression = (finalExp: Expr) => finalExp
+    //accumulatingExpressionMatch = accumulatingExpression
+
+    // each variable of super type can actually have a subtype
+    // get sine declaration maps to be able to refine them
+    val directSubclassMap = loader.directSubclassesMap
+    val variableDeclarations = loader.variableDeclarations
+
+    // map from identifier into a set of possible subclasses
+    variableRefinements = MutableMap.empty
+    for (varDec <- variableDeclarations) {
+      varDec match {
+        case LeonDeclaration(_, _, typeOfVar: ClassType, ImmediateExpression(_, LeonVariable(id))) =>
+          variableRefinements += (id -> MutableSet(directSubclassMap(typeOfVar).toList: _*))
+        case _ =>
+      }
+    }
+
+    // calculate cases that should not happen
+    refiner = new Refiner(program, hole, holeFunDef)
+    fine("Refiner recursive call: " + refiner.recurentExpression)
+
+  }
+
+  def synthesize(fileName: String): Unit = {
+    // get start time
+    startTime = System.currentTimeMillis
+
+    initialize(fileName)
+
+    // keeps status of validity
+    var keepGoing = Globals.allSolved match {
+      case Some(true) => false
+      case _ => true
+    }
+
+    var snippets = synthesizeExpressions
+
+    // iterate while the program is not valid
+    import scala.util.control.Breaks._
+    var iteration = 0
+    breakable {
+      while (keepGoing) {
+        // next iteration
+        iteration += 1
+        println("####################################")
+        println("######Iteration #" + iteration + " ###############")
+        println("####################################")
+
+        // just printing of expressions
+        for ((snippetTree, ind) <- (snippets map { _.getSnippet }) zip Iterator.range(0, 500).toStream) {
+          println(ind + " snippetTree is: " + snippetTree)
+        }
+        println("precondition is: " + holeFunDef.precondition.getOrElse(BooleanLiteral(true)))
+        println("accumulatingPrecondition is: " + accumulatingPrecondition)
+        println("accumulatingExpression(Unit) is: " + accumulatingExpression(UnitLiteral))
+        //        System.out.println("Press Any Key To Continue...");
+        //        new java.util.Scanner(System.in).nextLine();
+
+        // found precondition?
+        found = false
+        // try to find it
+        breakable {
+          // go through all snippets
+          for (
+            snippet <- snippets /*filter { _.getSnippet.toString == "concat(Nil(), Nil())" }*/ ;
+            val snippetTree = snippet.getSnippet
+          ) {
+            // debugging
+            println("snippetTree is: " + snippetTree)
+            snippetTree.toString match {
+              case "Cons(l1.head, concat(l1.tail, l2))" |
+                "Cons(l1.head, concat(l2, l1.tail))" |
+                "Cons(l2.head, concat(l2.tail, l1))" |
+                "Cons(l2.head, concat(l1, l2.tail))" =>
+                println("snippetTree is: " + snippetTree)
+//                System.out.println("Press Any Key To Continue...");
+//                new java.util.Scanner(System.in).nextLine();
+              case _ =>
+            }
+
+            //            System.out.println("Press Any Key To Continue...");
+            //            new java.util.Scanner(System.in).nextLine();
+
+            // skip pure recursive call
+            if (!refiner.isAvoidable(snippetTree)) {
+              if (tryToSynthesizeBranch(snippetTree)) {
+                break
+              }
+            } else {
+              println("We are skipping this snippetTree: " + snippetTree)
+            }
+
+          } // for (snippet <- snippets
+        } // breakable { for (snippet <- snippets
+
+        // if did not found for any of the branch expressions
+        if (found) {
+          info("we are done !")
+//          System.out.println("Press Any Key To Continue...");
+//          new java.util.Scanner(System.in).nextLine();
+          return
+        }
+
+        val inSynth = new InSynth(allDeclarations, hole.desiredType, true)
+        snippets = inSynth.getExpressions
+
+      }
+    } //breakable { while (!keepGoing) {
+
+    // get end time
+    val endTime = System.currentTimeMillis
+    println("whole process took time: " + (endTime - startTime))
+
+  }
+
+  def tryToSynthesizeBranch(snippetTree: Expr): Boolean = {
+    import leon.purescala.TreeOps.searchAndReplaceDFS
+    // replace hole in the body with current snippet tree
+
+    //    val oldBody = holeFunDef.getBody
+    //    val newBody = searchAndReplaceDFS(
+    //      _ match {
+    //        case _: Hole => Some(snippetTree)
+    //        case _ => None
+    //      })(oldBody)
+    val oldBody = holeFunDef.getBody
+    val newBody = accumulatingExpression(snippetTree)
+
+    holeFunDef.body = Some(newBody)
+    // save old precondition
+    val oldPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+
+    holeFunDef.precondition = Some(initialPrecondition)
+
+    // analyze the program
+    println("analyzing program for funDef:" + holeFunDef)
+
+    snippetTree.setType(hole.desiredType)
+    holeFunDef.getBody.setType(hole.desiredType)
+
+    analyzeProgram(program)
+
+    // check if solver could solved this instance
+    if (Globals.allSolved == Some(true)) {
+      // mark the branch found
+      found = true
+
+      println("Wooooooow we have a winner!")
+      println("************************************")
+      println("*********And the winner is**********")
+      println(accumulatingExpression(snippetTree))
+      println("************************************")
+
+      // get end time
+      val endTime = System.currentTimeMillis
+      println("whole process took time: " + (endTime - startTime))
+      //println("verTime, testTime" + verTime + ", " + ExampleRunner.testTime) 
+
+//      System.out.println("Press Any Key To Continue...");
+//      new java.util.Scanner(System.in).nextLine();
+
+      return true
+    }
+
+    // store appropriate values here, will be update in a finally branch
+    var bodyToRestore = oldBody
+    var preconditionToRestore = Some(oldPrecondition)
+
+    // because first initial test
+    holeFunDef.precondition = preconditionToRestore
+
+    // debug
+    println("Going to generating counterexamples: " + holeFunDef)
+    //                  System.out.println("Press Any Key To Continue...");
+    //                  new java.util.Scanner(System.in).nextLine();
+
+    //                  println("Counterexample cheking: ")
+    //                  println("Counterexamples: " + ExampleRunner.counterExamples.mkString("\n"))
+    //                  val counterExampleCheck = ExampleRunner.check(BooleanLiteral(true), newBody, holeFunDef.getPostcondition)
+    //                  println("Result of check: " + counterExampleCheck )
+    //                  
+    val temp = System.currentTimeMillis
+    // get counterexamples
+    val (maps, precondition) = generateCounterexamples(program, holeFunDef, 5)
+    val temptime = System.currentTimeMillis - temp
+    println("gen counterexamples took " + temptime)
+    verTime += temptime
+
+    // collect (add) counterexamples
+    //ExampleRunner.counterExamples ++= maps
+
+    val keepGoing = Globals.allSolved match {
+      case Some(true) => false
+      case _ => true
+    }
+
+    // if no counterexamples and all are solved, we are done
+    if (maps.isEmpty && !keepGoing) {
+      // mark the branch found
+      found = true
+
+      println("Wooooooow we have a winner!")
+      println("************************************")
+      println("*********And the winner is**********")
+      println(accumulatingExpression(snippetTree))
+      println("************************************")
+
+      return true
+    }
+
+    // will modify funDef body and precondition, restore it later
+    try {
+      // TODO is this okay?
+      // if there are no returned counterexamples just go to the next snippet
+      // and so far counter examples passed
+      if (!maps.isEmpty /*&& counterExampleCheck */ ) {
+        // proceed with synthesizing boolean expressions		      
+        assertEquals(5, maps.size)
+        // set program to the solver
+        solver.setProgram(program)
+
+        // initialize builder with previously seen declarations
+        val newBuilder = new InitialEnvironmentBuilder
+        newBuilder.addDeclarations(allDeclarations)
+
+        fine("all declarations now, size: " + newBuilder.getAllDeclarations.size)
+
+        // synthesize solution
+        val queryBuilder = new LeonQueryBuilder(BooleanType)
+        val query = queryBuilder.getQuery
+        val engine = new Engine(newBuilder, query, new WeightScheduler(), TimeOut(Config.getTimeOutSlot))
+        val solution = engine.run()
+        assertNotNull(solution)
+
+        assertNotNull(codeGenerator)
+        assertNotNull(allDeclarations)
+        // reconstruct (only defined number of boolean expressions)
+        val innerSnippets = Reconstructor(solution.getNodes.head, codeGenerator, true) take numberOfBooleanSnippets
+        checkDeclarations(inSynth)
+
+        // debugging
+        for ((snippetTree, ind) <- (innerSnippets map { _.getSnippet }) zip Iterator.range(0, 20).toStream) {
+          println(ind + " boolean snippetTree is: " + snippetTree)
+        }
+        //        System.out.println("Press Any Key To Continue...");
+        //        new java.util.Scanner(System.in).nextLine();
+
+        // precondition found?
+        found = false
+
+        // iterate over boolean snippets
+        val iterator = innerSnippets.iterator
+        while (!found && iterator.hasNext) {
+          val innerSnippetTree = iterator.next.getSnippet
+
+          // debug
+          println("boolean snippet is: " + innerSnippetTree)
+          //          System.out.println("Press Any Key To Continue...");
+          //          new java.util.Scanner(System.in).nextLine();
+
+          val (innerFound, innerPrec) = tryToSynthesizeBooleanCondition(snippetTree, innerSnippetTree, precondition)
+
+          //found = innerFound
+          innerPrec match {
+            case s @ Some(_) =>
+              preconditionToRestore = s
+            case _ =>
+          }
+
+          if (innerFound)
+            return true
+
+        } // iterating over all boolean solutions
+
+        // if none of boolean solutions work, restore body (in finally)
+        //holeFunDef.body = Some(oldBody)
+
+        assertTrue(!found)
+        info("not found :(, we give up on this branch expression")
+        return false
+
+      } // if ( !maps.isEmpty ) {
+
+      false
+    } // try
+    finally {
+      // set these to the FunDef
+      holeFunDef.precondition = preconditionToRestore
+      // restore old body (we accumulate expression)                                
+      holeFunDef.body = Some(oldBody)
+    }
+  }
+
+  def tryToSynthesizeBooleanCondition(snippetTree: Expr, innerSnippetTree: Expr, precondition: Expr): (Boolean, Option[Expr]) = {
+
+    // debug
+    //	                      println("boolean snippet is: " + innerSnippetTree)
+    //		                    System.out.println("Press Any Key To Continue...");
+    //		                    new java.util.Scanner(System.in).nextLine();
+
+    // new condition together with existing precondition
+    val newCondition = And(Seq(accumulatingPrecondition, innerSnippetTree))
+
+    // new expression should not be false
+    val notFalseEquivalence = Not(newCondition)
+    val notFalseSolveReturn = solver.solve(notFalseEquivalence)
+    fine("solve for not false returned: " + notFalseSolveReturn)
+    notFalseSolveReturn match {
+      case Some(true) =>
+        (false, None)
+      case None =>
+        (false, None)
+      // nothing here
+      // here, our expression is not contradictory, continue
+      case Some(false) =>
+        // check if synthesized boolean expression implies precondition (counterexamples)
+        val implyExpression = Implies(newCondition, precondition)
+        fine("implyExpression is: " + implyExpression)
+
+        // check if synthesized condition implies counter-examples
+        val solveReturn = solver.solve(implyExpression)
+        fine("solve returned: " + solveReturn)
+
+        solveReturn match {
+          case Some(true) =>
+            // old precondition is not here, it is before counterexamples are derived!
+            //val oldPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+
+            // if expression implies counterexamples add it to the precondition and try to validate program
+            holeFunDef.precondition = Some(newCondition)
+            // do analysis
+            analyzeProgram(program)
+            // program is valid, we have a branch
+            if (Globals.allSolved == Some(true)) {
+              // we found a branch
+              info("Wow! we found a branch!")
+
+              // update accumulating expression
+              val oldAccumulatingExpression = accumulatingExpression
+              val newAccumulatingExpression =
+                (finalExpr: Expr) =>
+                  oldAccumulatingExpression({
+                    val innerIf = IfExpr(innerSnippetTree, snippetTree, finalExpr)
+                    innerIf.setType(snippetTree.getType)
+                    innerIf
+                  })
+
+              accumulatingExpression = newAccumulatingExpression
+
+              // update accumulating precondition
+              fine("updating accumulatingPrecondition")
+              accumulatingPrecondition = And(Seq(accumulatingPrecondition, Not(innerSnippetTree)))
+              fine("updating hole fun precondition and body (to be hole)")
+
+              // set to set new precondition
+              val preconditionToRestore = Some(accumulatingPrecondition)
+
+              // check for refinements
+              checkRefinements(innerSnippetTree) match {
+                case Some(refinementPair @ (id, classType)) =>
+                  fine("And now we have refinement type: " + refinementPair)
+                  fine("variableRefinements(id) before" + variableRefinements(id))
+                  variableRefinements(id) -= loader.classMap(classType.id)
+                  fine("variableRefinements(id) after" + variableRefinements(id))
+
+                  // if we have a single subclass possible to refine
+                  if (variableRefinements(id).size == 1) {
+                    fine("wow we an do variable refinement for " + id)
+
+                    val newType = variableRefinements(id).head
+                    fine("new type is: " + newType)
+
+                    // update declarations
+                    allDeclarations =
+                      for (dec <- allDeclarations)
+                        yield dec match {
+                        case LeonDeclaration(inSynthType, _, decClassType, imex @ ImmediateExpression(_, LeonVariable(`id`))) =>
+                          LeonDeclaration(
+                            imex, TypeTransformer(newType), newType)
+                        case _ =>
+                          dec
+                      }
+
+                  } else
+                    fine("we cannot do variable refinement :(")
+                case _ =>
+              }
+              // found a boolean snippet, break
+              (true, preconditionToRestore)
+            } else {
+              // reset funDef and continue with next boolean snippet
+              val preconditionToRestore = Some(accumulatingPrecondition)
+              (false, preconditionToRestore)
+            }
+
+          case _ =>
+            println("precondition was not applied")
+            (false, None)
+        } //solveReturn match { (for implying counterexamples)
+    } // notFalseSolveReturn match {
+  }
+
+  // inspect the expression if some refinements can be done
+  def checkRefinements(expr: Expr) = expr match {
+    case CaseClassInstanceOf(classDef, LeonVariable(id)) =>
+      Some((id, classDef))
+    case _ =>
+      None
+  }
+
+  def extractInformation(ctx: LeonContext, file: String) =
+    new HoleFinder(file).extract
+   
+  // assert that there is not function that returns a function
+  def checkDeclarations(inSynth: InSynth) = {
+    assertFalse(
+      "We should not have a declaration which returns a function (not valid in Leon)",
+      (false /: inSynth.getCurrentBuilder.getAllDeclarations) {
+        case (res, dec: LeonDeclaration) =>
+          res ||
+            (dec.getDomainType match {
+              case FunctionType(_, _: FunctionType) => true
+              case _ => false
+            })
+      })
+  }
+  
+}
\ No newline at end of file
diff --git a/src/test/scala/lesynth/TryOutTestWithFiltering.scala b/src/test/scala/lesynth/TryOutTestWithFiltering.scala
new file mode 100644
index 000000000..3c65777d0
--- /dev/null
+++ b/src/test/scala/lesynth/TryOutTestWithFiltering.scala
@@ -0,0 +1,768 @@
+//package lesynth
+//
+//import org.junit.Assert._
+//import org.junit.{ Test, Ignore }
+//
+//import scala.collection.mutable.{ Map => MutableMap }
+//import scala.collection.mutable.{ Set => MutableSet }
+//import scala.collection.mutable.{ LinkedList => MutableList }
+//import scala.util.matching.Regex
+//import scala.collection.mutable.PriorityQueue
+//
+//import scala.tools.nsc.{ Settings => NSCSettings, MainGenericRunner }
+//
+//import leon.{ Main => LeonMain, DefaultReporter, Settings, LeonContext }
+//import leon.solvers.{ Solver, TimeoutSolver }
+//import leon.solvers.z3.{ FairZ3Solver }
+//import leon.verification.AnalysisPhase
+//import leon.purescala.TypeTrees.{ TypeTree => LeonType, _ }
+//import leon.purescala.Trees.{ Variable => LeonVariable, _ }
+//import leon.purescala.Definitions.{ FunDef, VarDecl, Program, ObjectDef }
+//import leon.purescala.Common.{ Identifier, FreshIdentifier }
+//import leon.purescala.TreeOps
+//import leon.plugin.ExtractionPhase
+//
+//import insynth.util.logging.HasLogger
+//import insynth.interfaces.Declaration
+//import insynth.InSynth
+//import insynth.reconstruction.codegen.CodeGenerator
+//import insynth.leon.loader.LeonLoader
+//import insynth.leon.LeonDeclaration
+//import insynth.leon.ImmediateExpression
+//import insynth.engine.InitialEnvironmentBuilder
+//import insynth.leon.LeonQueryBuilder
+//import insynth.interfaces.{ Loader, Declaration, QueryBuilder }
+//import insynth.engine.{ Engine, InitialEnvironmentBuilder }
+//import insynth.engine.scheduler.WeightScheduler
+//import insynth.structures.ContainerNode
+//import insynth.util.TimeOut
+//import insynth.Config
+//import insynth.reconstruction.Reconstructor
+//import insynth.leon.TypeTransformer
+//import insynth.leon.HoleFinder
+//
+//class TryOutTest extends HasLogger {
+//
+//  def analyzeProgram(program: Program) {
+//    import leon.Main._
+//
+//    val temp = System.currentTimeMillis
+//    Globals.allSolved = Some(true)
+//
+//    val reporter = new DefaultReporter()
+//    val args = Array("no file!", "--timeout=2")
+//    val ctx = processOptions(reporter, args.toList)
+//
+//    AnalysisPhase.run(ctx)(program)
+//
+//    val time = System.currentTimeMillis - temp
+//    println("analysis took " + time)
+//    verTime += time
+//  }
+//
+//  def generateCounterexamples(program: Program, funDef: FunDef, number: Int): (Seq[Map[Identifier, Expr]], Expr) = {
+//
+//    fine("generate counter examples with funDef.prec= " + funDef.precondition.getOrElse(BooleanLiteral(true)))
+//
+//    // get current precondition
+//    var precondition = funDef.precondition.getOrElse(BooleanLiteral(true))
+//    // where we will accumulate counterexamples as sequence of maps
+//    var maps: Seq[Map[Identifier, Expr]] = Seq.empty
+//
+//    // iterate specific number of times or until no further counterexample can be generated
+//    var changed = true
+//    var ind = 0
+//    while (ind < number && changed) {
+//
+//      // analyze the program
+//      analyzeProgram(program)
+//
+//      // check if solver could solved this instance
+//      if (Globals.allSolved == Some(false) && !Globals.asMap.isEmpty) {
+//
+//        fine("found coounterexample: " + Globals.asMap)
+//
+//        // add current counterexample
+//        maps :+= Globals.asMap
+//        // prevent this counterexample to reoccur
+//        val precAddition = Not(And(Globals.asMap map { case (id, value) => Equals(LeonVariable(id), value) } toSeq))
+//        precondition = And(Seq(precondition, precAddition))
+//        funDef.precondition = Some(precondition)
+//      } else
+//        changed = false
+//
+//      ind += 1
+//    }
+//
+//    // return found counterexamples and the formed precondition
+//    (maps, precondition)
+//  }
+//
+//  // assert that there is not function that returns a function
+//  def checkDeclarations(inSynth: InSynth) = {
+//    assertFalse(
+//      "We should not have a declaration which returns a function (not valid in Leon)",
+//      (false /: inSynth.getCurrentBuilder.getAllDeclarations) {
+//        case (res, dec: LeonDeclaration) =>
+//          res ||
+//            (dec.getDomainType match {
+//              case FunctionType(_, _: FunctionType) => true
+//              case _ => false
+//            })
+//      })
+//  }
+//
+//  def assertL1L2Refinements(variableRefinements: MutableMap[Identifier, MutableSet[ClassType]]) =
+//    for (
+//      pair @ (varName, nameSet) <- List(
+//        ("l2", Set("Nil", "Cons")),
+//        ("l1", Set("Nil", "Cons")))
+//    ) assertTrue(
+//      "pair " + pair + " not found. Found: " + variableRefinements.mkString(", "),
+//      (false /: variableRefinements) {
+//        (res, extr) =>
+//          extr match {
+//            case (id, classTypeSet) => res ||
+//              (
+//                id.name == varName &&
+//                (true /: nameSet) {
+//                  (res, innerName) => res && classTypeSet.exists(_.classDef.id.name == innerName)
+//                })
+//            case _ => false
+//          }
+//      })
+//
+//  private var program: Program = _
+//
+//  private var hole: Hole = _
+//  private var holeFunDef: FunDef = _
+//
+//  private var allDeclarations: List[Declaration] = _
+//
+//  private var loader: LeonLoader = _
+//
+//  private var inSynth: InSynth = _
+//  private var codeGenerator: CodeGenerator = _
+//
+//  private var refiner: Refiner = _
+//
+//  // accumulate precondition for the remaining branch to synthesize 
+//  private var accumulatingPrecondition: Expr = _
+//  // accumulate the final expression of the hole
+//  private var accumulatingExpression: Expr => Expr = _
+//  private var accumulatingExpressionMatch: Expr => Expr = _
+//
+//  var solver: Solver = _
+//  //  
+//  var ctx: LeonContext = _
+//  //  
+//  var variableRefinements: MutableMap[Identifier, MutableSet[ClassType]] = _
+//
+//  var initialPrecondition: Expr = _
+//
+//  var startTime: Long = _
+//
+//  var verTime: Long = 0
+//  var synTime: Long = 0
+//
+//  // number of condition expressions to try before giving up on that branch expression
+//  val numberOfBooleanSnippets = 20
+//
+//  def introduceCounterExamples = {
+//    var argumentIds = holeFunDef.args.map(_.id)
+//    assertEquals(2, argumentIds.size)
+//
+//    Globals.hole.getType match {
+//      case ct: ClassType =>
+//        val leonLoader = LeonLoader(program, hole, false)
+//
+//        leonLoader.load
+//
+//        val setSubclasses = leonLoader.directSubclassesMap(ct).map(_.asInstanceOf[CaseClassType].classDef)
+//        assertEquals(2, setSubclasses.size)
+//
+//        val (nilClassSet, consClassSet) = setSubclasses.partition(_.fieldsIds.size == 0)
+//        assertEquals(1, nilClassSet.size)
+//
+//        val nilClass = nilClassSet.head
+//        val consClass = consClassSet.head
+//
+//        var counter = 0
+//        def getIntLiteral = { counter += 1; IntLiteral(counter) }
+//
+//        val list0 = () => CaseClass(nilClass, Nil)
+//        val list1 = () => CaseClass(consClass, getIntLiteral :: list0() :: Nil)
+//        val list2 = () => CaseClass(consClass, getIntLiteral :: list1() :: Nil)
+//        val list3 = () => CaseClass(consClass, getIntLiteral :: list2() :: Nil)
+//        val list4 = () => CaseClass(consClass, getIntLiteral :: list3() :: Nil)
+//
+//        val lists = List(list0, list1, list2, list3 /*, list4*/ )
+//
+//        for (l1 <- lists; l2 <- lists) {
+//          ExampleRunner.counterExamples :+=
+//            Map(argumentIds(0) -> l1(),
+//              argumentIds(1) -> l2())
+//        }
+//      case _ =>
+//        fail
+//    }
+//
+//  }
+//
+//  def synthesizeExpressions =
+//    inSynth.getExpressions
+//
+//  def initialize(fileName: String) = {
+//
+//    import leon.Main._
+//
+//    val reporter = new DefaultReporter
+//    val args = Array(fileName, "--timeout=2")
+//    ctx = processOptions(reporter, args.toList)
+//
+//    // extract information about the program
+//    extractInformation(ctx, fileName)
+//
+//    codeGenerator = new CodeGenerator
+//
+//    // program and hole objects should be extracted
+//    (Globals.program, Globals.hole) match {
+//      case (Some(matchProgram), matchHole: Hole) =>
+//        program = matchProgram
+//        hole = matchHole
+//
+//        solver = //new FairZ3Solver(ctx)
+//          new TimeoutSolver(new FairZ3Solver(ctx), Globals.timeout)
+//
+//        loader = new LeonLoader(program, hole, false)
+//        // create new insynth object
+//        inSynth = new InSynth(loader, true)
+//
+//        // save all declarations seen
+//        allDeclarations = inSynth.getCurrentBuilder.getAllDeclarations
+//
+//        // funDef of the hole
+//        holeFunDef = Globals.holeFunDef
+//        println("postcondition is: " + holeFunDef.getPostcondition)
+//
+//        // accumulate precondition for the remaining branch to synthesize 
+//        accumulatingPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+//        // save initial precondition
+//        initialPrecondition = accumulatingPrecondition
+//        // accumulate the final expression of the hole
+//        accumulatingExpression = (finalExp: Expr) => finalExp
+//        accumulatingExpressionMatch = accumulatingExpression
+//
+//        // each variable of super type can actually have a subtype
+//        // get sine declaration maps to be able to refine them
+//        val directSubclassMap = loader.directSubclassesMap
+//        val variableDeclarations = loader.variableDeclarations
+//
+//        // map from identifier into a set of possible subclasses
+//        variableRefinements = MutableMap.empty
+//        for (varDec <- variableDeclarations) {
+//          varDec match {
+//            case LeonDeclaration(_, _, typeOfVar: ClassType, ImmediateExpression(_, LeonVariable(id))) =>
+//              variableRefinements += (id -> MutableSet(directSubclassMap(typeOfVar).toList: _*))
+//            case _ =>
+//          }
+//        }
+//
+//        // calculate cases that should not happen
+//        refiner = new Refiner(program, hole)
+//        fine("Refiner recursive call: " + refiner.recurentExpression)
+//      case _ => fail()
+//    }
+//  }
+//
+//  @Test
+//  def test1 {
+//    synthesize("testcases/insynth/ListOperationsHole.scala")
+//  }
+//
+//  def synthesize(fileName: String): Unit = {
+//    // get start time
+//    startTime = System.currentTimeMillis
+//
+//    initialize(fileName)
+//
+//    // keeps status of validity
+//    var keepGoing = Globals.allSolved match {
+//      case Some(true) => false
+//      case _ => true
+//    }
+//
+//    var snippets = synthesizeExpressions
+//
+//    introduceCounterExamples
+//    println("counterexamples after introduce: " + ExampleRunner.counterExamples.mkString("\n"))
+//
+//    // iterate while the program is not valid
+//    import scala.util.control.Breaks._
+//    var iteration = 0
+//    breakable {
+//      while (keepGoing) {
+//        // next iteration
+//        iteration += 1
+//        println("####################################")
+//        println("######Iteration #" + iteration + " ###############")
+//        println("####################################")
+//
+//        // just printing of expressions
+//        //            for ((snippetTree, ind) <- (snippets map { _.getSnippet }) zip Iterator.range(0, 20).toStream) {
+//        //              println(ind + " snippetTree is: " + snippetTree)
+//        //            }
+//        println("precondition is: " + holeFunDef.precondition.getOrElse(BooleanLiteral(true)))
+//        println("accumulatingPrecondition is: " + accumulatingPrecondition)
+//        println("accumulatingExpression(Unit) is: " + accumulatingExpression(UnitLiteral))
+//        //            System.out.println("Press Any Key To Continue...");
+//        //            new java.util.Scanner(System.in).nextLine();
+//
+//        var pq = new PriorityQueue[(Expr, Int)]()(
+//          new Ordering[(Expr, Int)] {
+//            def compare(pair1: (Expr, Int), pair2: (Expr, Int)) =
+//              pair1._2.compare(pair2._2)
+//          })
+//        var tested = 0
+//
+//        // found precondition?
+//        var found = false
+//        // try to find it
+//        breakable {
+//          // go through all snippets
+//          for (
+//            snippet <- snippets /*filter { _.getSnippet.toString == "concat(Nil(), Nil())" }*/ ;
+//            val snippetTree = snippet.getSnippet
+//          ) {
+//            // debugging
+//            println("snippetTree is: " + snippetTree)
+//            //                System.out.println("Press Any Key To Continue...");
+//            //                new java.util.Scanner(System.in).nextLine();
+//
+//            // TODO is never empty now with introduce
+//            val passCount =
+//              //if (ExampleRunner.counterExamples.isEmpty)
+//              if (iteration == 1)
+//                ExampleRunner.counterExamples.size
+//              else {
+//
+//                val oldPreconditionSaved = holeFunDef.precondition
+//                val oldBodySaved = holeFunDef.body
+//
+//                // restore initial precondition
+//                holeFunDef.precondition = Some(initialPrecondition)
+//
+//                assertEquals(BooleanLiteral(true), initialPrecondition)
+//
+//                // get the whole body (if else...)
+//                val accumulatedExpression = accumulatingExpression(snippetTree)
+//                // set appropriate body to the function for the correct evaluation
+//                holeFunDef.body = Some(accumulatedExpression)
+//
+//                //    if (snippetTree.toString == "Cons(l2.head, concat(l1, l2.tail))") {
+//                //      System.out.println("Press Any Key To Continue...");
+//                //      new java.util.Scanner(System.in).nextLine();
+//                //    }
+//                val count = ExampleRunner.countPassed(accumulatedExpression)
+//
+//                //    if (snippetTree.toString == "Cons(l2.head, concat(l1, l2.tail))") {
+//                //      System.out.println("Press Any Key To Continue...");
+//                //      new java.util.Scanner(System.in).nextLine();
+//                //    }
+//
+//                holeFunDef.precondition = oldPreconditionSaved
+//                holeFunDef.body = oldBodySaved
+//
+//                count
+//              }
+//
+//            val okay =
+//              passCount == ExampleRunner.counterExamples.size
+//            if (!okay) {
+//              //                println("snippet with pass count filtered: " + (snippet, passCount))
+//              pq.enqueue((snippetTree, 100 + (passCount * (iteration - 1)) - snippet.getWeight.toInt))
+//            }
+//
+//            // skip pure recursive call
+//            if (!refiner.isAvoidable(snippetTree) && okay) {
+//              if (tryToSynthesizeBranch(snippetTree)) {
+//                found = true
+//                pq.clear
+//                break
+//              }
+//            } else {
+//              //                  println("We are skipping this snippetTree since it is the recursive call: " + Refiner.recurentExpressions)
+//            }
+//
+//            if (tested >= 500) {
+//              println("queue is: " + pq.mkString("\n"))
+//              println("head of queue is: " + pq.head)
+//              //			            System.out.println("Press Any Key To Continue...");
+//              //			            new java.util.Scanner(System.in).nextLine();
+//              for (i <- 1 to 5) {
+//                val nextSnippet = pq.dequeue._1
+//                println("nextSnippet is: " + nextSnippet)
+//
+//                if (tryToSynthesizeBranch(nextSnippet)) {
+//                  found = true
+//                  pq.clear
+//                  break
+//                }
+//              }
+//              tested = 0
+//            } else
+//              tested += 1
+//          } // for (snippet <- snippets
+//        } // breakable { for (snippet <- snippets
+//
+//        // if did not found for any of the branch expressions
+//        if (!found) {
+//          info("we are done :(")
+//          return
+//        }
+//
+//        // debug
+//        assertTrue(found)
+//        info("variable declarations now:")
+//        info(allDeclarations.filter(
+//          _ match {
+//            case LeonDeclaration(_, _, _, imex @ ImmediateExpression(_, _: LeonVariable)) =>
+//              true
+//            case _ =>
+//              false
+//          }).mkString(" ,"))
+//
+//        info("okay we found one branch")
+//
+//        // synthesize snippets for next branch
+//        info("synthesizing new snippets")
+//
+//        val newBuilder = new InitialEnvironmentBuilder
+//        newBuilder.addDeclarations(allDeclarations)
+//        fine("all declarations now, size: " + newBuilder.getAllDeclarations.size)
+//        val queryBuilder = new LeonQueryBuilder(hole.desiredType)
+//        val query = queryBuilder.getQuery
+//        val engine = new Engine(newBuilder, query, new WeightScheduler(), TimeOut(Config.getTimeOutSlot))
+//        val proofTree = engine.run()
+//        assertNotNull(proofTree)
+//        assertEquals(1, proofTree.getNodes.size)
+//
+//        println("filtering based on: " + holeFunDef.precondition.get)
+//        println("counterexamples before filter: " + ExampleRunner.counterExamples.size)
+//        ExampleRunner.filter(holeFunDef.precondition.get)
+//        println("counterexamples after filter: " + ExampleRunner.counterExamples.size)
+//        println("counterexamples after filter: " + ExampleRunner.counterExamples.mkString("\n"))
+//
+//        //              System.out.println("Press Any Key To Continue...");
+//        //              new java.util.Scanner(System.in).nextLine();
+//
+//        snippets = Reconstructor(proofTree.getNodes.head, codeGenerator)
+//
+//        // ADHOC filter out counterexamples that have Nil (adhoc!)              
+//        //	            ExampleRunner.counterExamples = ExampleRunner.counterExamples filterNot {
+//        //	              map =>
+//        //	                (false /: map.values) {
+//        //	                  (res, value) =>
+//        //	                    res || value.toString.startsWith("Nil")
+//        //	                }
+//        //	            }      
+//
+//      }
+//    } //breakable { while (!keepGoing) {
+//
+//    // get end time
+//    val endTime = System.currentTimeMillis
+//    println("whole process took time: " + (endTime - startTime))
+//
+//  }
+//
+//  def tryToSynthesizeBranch(snippetTree: Expr): Boolean = {
+//    import leon.purescala.TreeOps.searchAndReplaceDFS
+//    // replace hole in the body with current snippet tree
+//
+//    //    val oldBody = holeFunDef.getBody
+//    //    val newBody = searchAndReplaceDFS(
+//    //      _ match {
+//    //        case _: Hole => Some(snippetTree)
+//    //        case _ => None
+//    //      })(oldBody)
+//    val oldBody = holeFunDef.getBody
+//    val newBody = accumulatingExpressionMatch(snippetTree)
+//
+//    holeFunDef.body = Some(newBody)
+//    // save old precondition
+//    val oldPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+//
+//    holeFunDef.precondition = Some(initialPrecondition)
+//
+//    // analyze the program
+//    analyzeProgram(program)
+//
+//    // check if solver could solved this instance
+//    if (Globals.allSolved == Some(true)) {
+//      // mark the branch found
+//      //found = true
+//
+//      println("Wooooooow we have a winner!")
+//      println("************************************")
+//      println("*********And the winner is**********")
+//      println(accumulatingExpression(snippetTree))
+//      println("************************************")
+//
+//      // get end time
+//      val endTime = System.currentTimeMillis
+//      println("whole process took time: " + (endTime - startTime))
+//      //println("verTime, testTime" + verTime + ", " + ExampleRunner.testTime) 
+//
+//      System.out.println("Press Any Key To Continue...");
+//      new java.util.Scanner(System.in).nextLine();
+//
+//      return true
+//    }
+//
+//    // store appropriate values here, will be update in a finally branch
+//    var bodyToRestore = oldBody
+//    var preconditionToRestore = Some(oldPrecondition)
+//
+//    // because first initial test
+//    holeFunDef.precondition = preconditionToRestore
+//
+//    // debug
+//    println("Going to generating counterexamples: " + holeFunDef)
+//    //                  System.out.println("Press Any Key To Continue...");
+//    //                  new java.util.Scanner(System.in).nextLine();
+//
+//    //                  println("Counterexample cheking: ")
+//    //                  println("Counterexamples: " + ExampleRunner.counterExamples.mkString("\n"))
+//    //                  val counterExampleCheck = ExampleRunner.check(BooleanLiteral(true), newBody, holeFunDef.getPostcondition)
+//    //                  println("Result of check: " + counterExampleCheck )
+//    //                  
+//    val temp = System.currentTimeMillis
+//    // get counterexamples
+//    val (maps, precondition) = generateCounterexamples(program, holeFunDef, 5)
+//    val temptime = System.currentTimeMillis - temp
+//    println("gen counterexamples took " + temptime)
+//    verTime += temptime
+//
+//    // collect (add) counterexamples
+//    //ExampleRunner.counterExamples ++= maps
+//
+//    val keepGoing = Globals.allSolved match {
+//      case Some(true) => false
+//      case _ => true
+//    }
+//
+//    // if no counterexamples and all are solved, we are done
+//    if (maps.isEmpty && !keepGoing) {
+//      // mark the branch found
+//      //found = true
+//
+//      println("Wooooooow we have a winner!")
+//      println("************************************")
+//      println("*********And the winner is**********")
+//      println(accumulatingExpression(snippetTree))
+//      println("************************************")
+//
+//      return true
+//    }
+//
+//    // will modify funDef body and precondition, restore it later
+//    try {
+//      // TODO is this okay?
+//      // if there are no returned counterexamples just go to the next snippet
+//      // and so far counter examples passed
+//      if (!maps.isEmpty /*&& counterExampleCheck */ ) {
+//        // proceed with synthesizing boolean expressions		      
+//        assertEquals(5, maps.size)
+//        // set program to the solver
+//        solver.setProgram(program)
+//
+//        // initialize builder with previously seen declarations
+//        val newBuilder = new InitialEnvironmentBuilder
+//        newBuilder.addDeclarations(allDeclarations)
+//
+//        fine("all declarations now, size: " + newBuilder.getAllDeclarations.size)
+//
+//        // synthesize solution
+//        val queryBuilder = new LeonQueryBuilder(BooleanType)
+//        val query = queryBuilder.getQuery
+//        val engine = new Engine(newBuilder, query, new WeightScheduler(), TimeOut(Config.getTimeOutSlot))
+//        val solution = engine.run()
+//        assertNotNull(solution)
+//
+//        assertNotNull(codeGenerator)
+//        assertNotNull(allDeclarations)
+//        // reconstruct (only defined number of boolean expressions)
+//        val innerSnippets = Reconstructor(solution.getNodes.head, codeGenerator) take numberOfBooleanSnippets
+//        checkDeclarations(inSynth)
+//
+//        // debugging
+//        //	                    for ((snippetTree, ind) <- (innerSnippets map { _.getSnippet }) zip Iterator.range(0, 20).toStream) {
+//        //	                      println(ind + " boolean snippetTree is: " + snippetTree)
+//        //	                    }
+//        //	                    System.out.println("Press Any Key To Continue...");
+//        //	                    new java.util.Scanner(System.in).nextLine();
+//
+//        // precondition found?
+//        var found = false
+//
+//        // iterate over boolean snippets
+//        val iterator = innerSnippets.iterator
+//        while (!found && iterator.hasNext) {
+//          val innerSnippetTree = iterator.next.getSnippet
+//
+//          // debug
+//          println("boolean snippet is: " + innerSnippetTree)
+//          //          System.out.println("Press Any Key To Continue...");
+//          //          new java.util.Scanner(System.in).nextLine();
+//
+//          val (innerFound, innerPrec) = tryToSynthesizeBooleanCondition(snippetTree, innerSnippetTree, precondition)
+//
+//          found = innerFound
+//          innerPrec match {
+//            case s @ Some(_) =>
+//              preconditionToRestore = s
+//            case _ =>
+//          }
+//
+//          if (found)
+//            return true
+//
+//        } // iterating over all boolean solutions
+//
+//        // if none of boolean solutions work, restore body (in finally)
+//        //holeFunDef.body = Some(oldBody)
+//
+//        assertTrue(!found)
+//        info("not found :(, we give up on this branch expression")
+//        return false
+//
+//      } // if ( !maps.isEmpty ) {
+//
+//      false
+//    } // try
+//    finally {
+//      // set these to the FunDef
+//      holeFunDef.precondition = preconditionToRestore
+//      // restore old body (we accumulate expression)                                
+//      holeFunDef.body = Some(oldBody)
+//    }
+//  }
+//
+//  def tryToSynthesizeBooleanCondition(snippetTree: Expr, innerSnippetTree: Expr, precondition: Expr): (Boolean, Option[Expr]) = {
+//
+//    // debug
+//    //	                      println("boolean snippet is: " + innerSnippetTree)
+//    //		                    System.out.println("Press Any Key To Continue...");
+//    //		                    new java.util.Scanner(System.in).nextLine();
+//
+//    // new condition together with existing precondition
+//    val newCondition = And(Seq(accumulatingPrecondition, innerSnippetTree))
+//
+//    // new expression should not be false
+//    val notFalseEquivalence = Not(newCondition)
+//    val notFalseSolveReturn = solver.solve(notFalseEquivalence)
+//    fine("solve for not false returned: " + notFalseSolveReturn)
+//    notFalseSolveReturn match {
+//      case Some(true) =>
+//        (false, None)
+//      case None =>
+//        (false, None)
+//      // nothing here
+//      // here, our expression is not contradictory, continue
+//      case Some(false) =>
+//        // check if synthesized boolean expression implies precondition (counterexamples)
+//        val implyExpression = Implies(newCondition, precondition)
+//        fine("implyExpression is: " + implyExpression)
+//
+//        // check if synthesized condition implies counter-examples
+//        val solveReturn = solver.solve(implyExpression)
+//        fine("solve returned: " + solveReturn)
+//
+//        solveReturn match {
+//          case Some(true) =>
+//            // old precondition is not here, it is before counterexamples are derived!
+//            //val oldPrecondition = holeFunDef.precondition.getOrElse(BooleanLiteral(true))
+//
+//            // if expression implies counterexamples add it to the precondition and try to validate program
+//            holeFunDef.precondition = Some(newCondition)
+//            // do analysis
+//            analyzeProgram(program)
+//            // program is valid, we have a branch
+//            if (Globals.allSolved == Some(true)) {
+//              // we found a branch
+//              info("Wow! we found a branch!")
+//
+//              // update accumulating expression
+//              val oldAccumulatingExpression = accumulatingExpression
+//              val newAccumulatingExpression =
+//                (finalExpr: Expr) =>
+//                  oldAccumulatingExpression(IfExpr(innerSnippetTree, snippetTree, finalExpr))
+//
+//              accumulatingExpression = newAccumulatingExpression
+//
+//              // update accumulating precondition
+//              fine("updating accumulatingPrecondition")
+//              accumulatingPrecondition = And(Seq(accumulatingPrecondition, Not(innerSnippetTree)))
+//              fine("updating hole fun precondition and body (to be hole)")
+//
+//              // set to set new precondition
+//              val preconditionToRestore = Some(accumulatingPrecondition)
+//
+//              // check for refinements
+//              checkRefinements(innerSnippetTree) match {
+//                case Some(refinementPair @ (id, classType)) =>
+//                  fine("And now we have refinement type: " + refinementPair)
+//                  fine("variableRefinements(id) before" + variableRefinements(id))
+//                  variableRefinements(id) -= loader.classMap(classType.id)
+//                  fine("variableRefinements(id) after" + variableRefinements(id))
+//
+//                  // if we have a single subclass possible to refine
+//                  if (variableRefinements(id).size == 1) {
+//                    fine("wow we an do variable refinement for " + id)
+//
+//                    val newType = variableRefinements(id).head
+//                    fine("new type is: " + newType)
+//
+//                    // update declarations
+//                    allDeclarations =
+//                      for (dec <- allDeclarations)
+//                        yield dec match {
+//                        case LeonDeclaration(inSynthType, _, decClassType, imex @ ImmediateExpression(_, LeonVariable(`id`))) =>
+//                          LeonDeclaration(
+//                            imex, TypeTransformer(newType), newType)
+//                        case _ =>
+//                          dec
+//                      }
+//
+//                  } else
+//                    fine("we cannot do variable refinement :(")
+//                case _ =>
+//              }
+//              // found a boolean snippet, break
+//              (true, preconditionToRestore)
+//            } else {
+//              // reset funDef and continue with next boolean snippet
+//              val preconditionToRestore = Some(accumulatingPrecondition)
+//              (false, preconditionToRestore)
+//            }
+//
+//          case _ =>
+//            println("precondition was not applied")
+//            (false, None)
+//        } //solveReturn match { (for implying counterexamples)
+//    } // notFalseSolveReturn match {
+//  }
+//
+//  // inspect the expression if some refinements can be done
+//  def checkRefinements(expr: Expr) = expr match {
+//    case CaseClassInstanceOf(classDef, LeonVariable(id)) =>
+//      Some((id, classDef))
+//    case _ =>
+//      None
+//  }
+//
+//  def extractInformation(ctx: LeonContext, file: String) =
+//    new HoleFinder(file).extract
+//
+//}
\ No newline at end of file
diff --git a/testcases/lesynth/InsertionSortFull.scala b/testcases/lesynth/InsertionSortFull.scala
new file mode 100644
index 000000000..6b68a439e
--- /dev/null
+++ b/testcases/lesynth/InsertionSortFull.scala
@@ -0,0 +1,51 @@
+import scala.collection.immutable.Set
+import leon.Annotations._
+import leon.Utils._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head:Int,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : Int = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  }) ensuring(_ >= 0)
+
+  def contents(l: List): Set[Int] = l match {
+    case Nil() => Set.empty
+    case Cons(x,xs) => contents(xs) ++ Set(x)
+  }
+
+  def isSorted(l: List): Boolean = l match {
+    case Nil() => true
+    case Cons(x, Nil()) => true
+    case Cons(x, Cons(y, ys)) => x <= y && isSorted(Cons(y, ys))
+  }   
+
+  /* Inserting element 'e' into a sorted list 'l' produces a sorted list with
+   * the expected content and size */
+  def sortedIns(e: Int, l: List): List = {
+    require(isSorted(l))
+    l match {
+      case Nil() => Cons(e,Nil())
+      case Cons(x,xs) =>
+				if (x <= e) Cons(x,sortedIns(e, xs))
+				else Cons(e, l)
+    } 
+  } ensuring(res => contents(res) == contents(l) ++ Set(e) 
+                    && isSorted(res)
+                    && size(res) == size(l) + 1
+            )
+
+  /* Insertion sort yields a sorted list of same size and content as the input
+   * list */
+  def sort(l: List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+  }) ensuring(res => contents(res) == contents(l) 
+                     && isSorted(res)
+                     && size(res) == size(l)
+             )
+
+}
diff --git a/testcases/lesynth/InsertionSortHoleInsert.scala b/testcases/lesynth/InsertionSortHoleInsert.scala
new file mode 100644
index 000000000..cde3aaacd
--- /dev/null
+++ b/testcases/lesynth/InsertionSortHoleInsert.scala
@@ -0,0 +1,54 @@
+import scala.collection.immutable.Set
+import leon.Annotations._
+import leon.Utils._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head:Int,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : Int = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  }) ensuring(_ >= 0)
+
+  def contents(l: List): Set[Int] = l match {
+    case Nil() => Set.empty
+    case Cons(x,xs) => contents(xs) ++ Set(x)
+  }
+
+  def isSorted(l: List): Boolean = l match {
+    case Nil() => true
+    case Cons(x, Nil()) => true
+    case Cons(x, Cons(y, ys)) => x <= y && isSorted(Cons(y, ys))
+  }   
+
+  /* Inserting element 'e' into a sorted list 'l' produces a sorted list with
+   * the expected content and size */
+  def sortedIns(e: Int, l: List): List = {
+    require(isSorted(l))
+    hole(l)
+//    val cond1: Boolean =  /*!*/
+//    l match {
+//      case Nil() =>  /*!*/ // Cons(e,Nil())
+//      case Cons(x,xs) =>
+//				val cond2: Boolean =  /*!*/
+//				if (x <= e)  /*!*/ // Cons(x,sortedIns(e, xs))
+//				else  /*!*/ // Cons(e, l)
+//    } 
+  } ensuring(res => contents(res) == contents(l) ++ Set(e) 
+                    && isSorted(res)
+                    && size(res) == size(l) + 1
+            )
+
+  /* Insertion sort yields a sorted list of same size and content as the input
+   * list */
+  def sort(l: List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+  }) ensuring(res => contents(res) == contents(l) 
+                     && isSorted(res)
+                     && size(res) == size(l)
+             )
+
+}
diff --git a/testcases/lesynth/InsertionSortHoleSort.scala b/testcases/lesynth/InsertionSortHoleSort.scala
new file mode 100644
index 000000000..7931fcc8a
--- /dev/null
+++ b/testcases/lesynth/InsertionSortHoleSort.scala
@@ -0,0 +1,53 @@
+import scala.collection.immutable.Set
+import leon.Annotations._
+import leon.Utils._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head:Int,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : Int = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  }) ensuring(_ >= 0)
+
+  def contents(l: List): Set[Int] = l match {
+    case Nil() => Set.empty
+    case Cons(x,xs) => contents(xs) ++ Set(x)
+  }
+
+  def isSorted(l: List): Boolean = l match {
+    case Nil() => true
+    case Cons(x, Nil()) => true
+    case Cons(x, Cons(y, ys)) => x <= y && isSorted(Cons(y, ys))
+  }   
+
+  /* Inserting element 'e' into a sorted list 'l' produces a sorted list with
+   * the expected content and size */
+  def sortedIns(e: Int, l: List): List = {
+    require(isSorted(l))
+    l match {
+      case Nil() => Cons(e,Nil())
+      case Cons(x,xs) =>
+				if (x <= e) Cons(x,sortedIns(e, xs))
+				else Cons(e, l)
+    } 
+  } ensuring(res => contents(res) == contents(l) ++ Set(e) 
+      && isSorted(res)
+      && size(res) == size(l) + 1
+)
+
+  /* Insertion sort yields a sorted list of same size and content as the input
+   * list */
+  def xxsort(l: List): List = ({
+    hole(l)
+//    val cond: Boolean =  /*!*/
+//    case Nil() =>  /*!*/ // Nil()
+//    case Cons(x,xs) =>  /*!*/ // sortedIns(x, sort(xs))
+  }) ensuring(res => contents(res) == contents(l) 
+                     && isSorted(res)
+                     && size(res) == size(l)
+             )
+
+}
diff --git a/testcases/lesynth/ListOperations.scala b/testcases/lesynth/ListOperations.scala
new file mode 100644
index 000000000..424a38aa0
--- /dev/null
+++ b/testcases/lesynth/ListOperations.scala
@@ -0,0 +1,45 @@
+import scala.collection.immutable.Set
+
+import leon.Utils._
+
+object ListOperations {
+    sealed abstract class List
+    case class Cons(head: Int, tail: List) extends List
+    case class Nil() extends List
+
+//	  def content(l: List) : Set[Int] = l match {
+//	    case Nil() => Set.empty
+//	    case Cons(head, tail) => Set(head) ++ content(tail)
+//	  }
+	  def content(l: List) : Set[Int] = l match {
+	    case Nil() => Set.empty
+	    case Cons(head, tail) => Set(head) ++ content(tail)
+	  }
+    
+	  def size(l: List) : Int = l match {
+	    case Nil() => 0
+	    case Cons(head, tail) => 1 + size(tail)
+	  }
+    
+    def isEmpty(l: List) = l match {
+	    case Nil() => true
+	    case Cons(_, _) => false      
+    }
+    
+    def concat(l1: List, l2: List) : List = ({
+      
+      l1 match {
+        case Nil() => l2
+        case Cons(l1Head, l1Tail) =>
+          l1 match {
+            case Nil() => l2
+            case _ => Cons(l1Head, Cons(l1Head, concat(l1Tail, l2)))
+          }
+      }
+
+    }) ensuring(res => 
+      content(res) == content(l1) ++ content(l2) &&
+      size(res) == size(l1) + size(l2)
+    )
+
+}
diff --git a/testcases/lesynth/ListOperationsHole.scala b/testcases/lesynth/ListOperationsHole.scala
new file mode 100644
index 000000000..bd3cb28e6
--- /dev/null
+++ b/testcases/lesynth/ListOperationsHole.scala
@@ -0,0 +1,24 @@
+import scala.collection.immutable.Set
+
+import leon.Utils._
+
+object ListOperations {
+    sealed abstract class List
+    case class Cons(head: Int, tail: List) extends List
+    case class Nil() extends List
+
+	  def content(l: List) : Set[Int] = l match {
+	    case Nil() => Set.empty
+	    case Cons(head, tail) => Set(head) ++ content(tail)
+	  }
+    
+//    def isEmpty(l: List) = l match {
+//	    case Nil() => true
+//	    case Cons(_, _) => false      
+//    }
+    
+    def concat(l1: List, l2: List) : List = ({
+      hole(l1)
+    }) ensuring(res => content(res) == content(l1) ++ content(l2))
+
+}
diff --git a/testcases/lesynth/ListOperationsHole2.scala b/testcases/lesynth/ListOperationsHole2.scala
new file mode 100644
index 000000000..c1dcf85ac
--- /dev/null
+++ b/testcases/lesynth/ListOperationsHole2.scala
@@ -0,0 +1,24 @@
+import scala.collection.immutable.Set
+
+import leon.Utils._
+
+object ListOperations {
+    sealed abstract class List
+    case class Cons(head: Int, tail: List) extends List
+    case class Nil() extends List
+
+	  def content(l: List) : Set[Int] = l match {
+	    case Nil() => Set.empty
+	    case Cons(head, tail) => Set(head) ++ content(tail)
+	  }
+    
+//    def isEmpty(l: List) = l match {
+//	    case Nil() => true
+//	    case Cons(_, _) => false      
+//    }
+    
+    def concat(l1: List, l2: List) : List = ({
+      hole[List](throw new RuntimeException)
+    }) ensuring(res => content(res) == content(l1) ++ content(l2))
+
+}
diff --git a/testcases/lesynth/MergeSortHole.scala b/testcases/lesynth/MergeSortHole.scala
new file mode 100644
index 000000000..339554c2c
--- /dev/null
+++ b/testcases/lesynth/MergeSortHole.scala
@@ -0,0 +1,81 @@
+import scala.collection.immutable.Set
+
+import leon.Utils._
+
+object MergeSort {
+  sealed abstract class List
+  case class Cons(head : Int, tail : List) extends List
+  case class Nil() extends List
+
+  sealed abstract class PairAbs
+  case class Pair(fst : List, snd : List) extends PairAbs
+
+  def contents(l : List) : Set[Int] = l match {
+    case Nil() => Set.empty
+    case Cons(x,xs) => contents(xs) ++ Set(x)
+  }
+
+  def isSorted(l : List) : Boolean = l match {
+    case Nil() => true
+    case Cons(x,xs) => xs match {
+      case Nil() => true
+      case Cons(y, ys) => x <= y && isSorted(Cons(y, ys))
+    }
+  }    
+
+  def size(list : List) : Int = list match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }
+
+  def splithelper(aList : List, bList : List, n : Int) : Pair = {
+    if (n <= 0) Pair(aList,bList)
+    else
+	bList match {
+    	      case Nil() => Pair(aList,bList)
+    	      case Cons(x,xs) => splithelper(Cons(x,aList),xs,n-1)
+	}
+  } ensuring(res => contents(aList) ++ contents(bList) == contents(res.fst) ++ contents(res.snd))
+
+//  def split(list : List, n : Int): Pair = {
+//    splithelper(Nil(),list,n)
+//  } ensuring(res => contents(list) == contents(res.fst) ++ contents(res.snd))
+  
+  def split(list: List): Pair = {
+    splithelper(Nil(),list,2)
+  } ensuring(res => contents(list) == contents(res.fst) ++ contents(res.snd))
+
+  def merge(aList : List, bList : List) : List = {
+    require(isSorted(aList) && isSorted(bList))
+    bList match {       
+      case Nil() => aList
+      case Cons(x,xs) =>
+        aList match {
+              case Nil() => bList
+              case Cons(y,ys) =>
+               if (y < x)
+                  Cons(y,merge(ys, bList))
+               else
+                  Cons(x,merge(aList, xs))               
+        }   
+    }
+  } ensuring(res => contents(res) == contents(aList) ++ contents(bList) && isSorted(res))
+
+  def isEmpty(list: List) : Boolean = list match {
+    case Nil() => true
+    case Cons(x,xs) => false
+  }
+  
+  def xxmergeSort(list : List) : List = ({
+      hole[List](list)
+//      list match {
+//    case Nil() => list
+//    case Cons(x,Nil()) => list
+//    case _ =>
+//    	 val p = split(list,size(list)/2)
+//   	 merge(mergeSort(p.fst), mergeSort(p.snd))
+      
+//      merge(mergeSort(split(list).fst), mergeSort(split(list).snd))
+  }) ensuring(res => contents(res) == contents(list) && isSorted(res))
+ 
+}
-- 
GitLab