diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 796c1aabed3dfd46281fb844404ba2191c1afd82..360b1306193074649e2b38a2e1b46ba2d3bcefd2 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -6,7 +6,6 @@ package purescala
 object PrettyPrinter {
   import Common._
   import Trees._
-  import xlang.Trees._
   import TypeTrees._
   import Definitions._
 
@@ -28,8 +27,8 @@ object PrettyPrinter {
   }
 
   private def ind(sb: StringBuffer, lvl: Int) : StringBuffer = {
-      sb.append("  " * lvl)
-      sb
+    sb.append("  " * lvl)
+    sb
   }
 
   // EXPRESSIONS
@@ -89,15 +88,6 @@ object PrettyPrinter {
       sb.append(")")
       sb
     }
-    case LetVar(b,d,e) => {
-      sb.append("(letvar (" + b + " := ");
-      pp(d, sb, lvl)
-      sb.append(") in\n")
-      ind(sb, lvl+1)
-      pp(e, sb, lvl+1)
-      sb.append(")")
-      sb
-    }
     case LetDef(fd,e) => {
       sb.append("\n")
       pp(fd, sb, lvl+1)
@@ -118,38 +108,6 @@ object PrettyPrinter {
     case BooleanLiteral(v) => sb.append(v)
     case StringLiteral(s) => sb.append("\"" + s + "\"")
     case UnitLiteral => sb.append("()")
-    case Block(exprs, last) => {
-      sb.append("{\n")
-      (exprs :+ last).foreach(e => {
-        ind(sb, lvl+1)
-        pp(e, sb, lvl+1)
-        sb.append("\n")
-      })
-      ind(sb, lvl)
-      sb.append("}\n")
-      sb
-    }
-    case Assignment(lhs, rhs) => ppBinary(sb, lhs.toVariable, rhs, " = ", lvl)
-    case wh@While(cond, body) => {
-      wh.invariant match {
-        case Some(inv) => {
-          sb.append("\n")
-          ind(sb, lvl)
-          sb.append("@invariant: ")
-          pp(inv, sb, lvl)
-          sb.append("\n")
-          ind(sb, lvl)
-        }
-        case None =>
-      }
-      sb.append("while(")
-      pp(cond, sb, lvl)
-      sb.append(")\n")
-      ind(sb, lvl+1)
-      pp(body, sb, lvl+1)
-      sb.append("\n")
-    }
-
     case t@Tuple(exprs) => ppNary(sb, exprs, "(", ", ", ")", lvl)
     case s@TupleSelect(t, i) => {
       pp(t, sb, lvl)
@@ -157,14 +115,6 @@ object PrettyPrinter {
       sb
     }
 
-    case e@Epsilon(pred) => {
-      var nsb = sb
-      nsb.append("epsilon(x" + e.posIntInfo._1 + "_" + e.posIntInfo._2 + ". ")
-      nsb = pp(pred, nsb, lvl)
-      nsb.append(")")
-      nsb
-    }
-
     case c@Choose(vars, pred) => {
       var nsb = sb
       nsb.append("choose("+vars.mkString(", ")+" => ")
@@ -173,12 +123,6 @@ object PrettyPrinter {
       nsb
     }
 
-    case Waypoint(i, expr) => {
-      sb.append("waypoint_" + i + "(")
-      pp(expr, sb, lvl)
-      sb.append(")")
-    }
-
     case OptionSome(a) => {
       var nsb = sb
       nsb.append("Some(")
@@ -300,13 +244,6 @@ object PrettyPrinter {
       pp(i, sb, lvl)
       sb.append(")")
     }
-    case up@ArrayUpdate(ar, i, v) => {
-      pp(ar, sb, lvl)
-      sb.append("(")
-      pp(i, sb, lvl)
-      sb.append(") = ")
-      pp(v, sb, lvl)
-    }
     case up@ArrayUpdated(ar, i, v) => {
       pp(ar, sb, lvl)
       sb.append(".updated(")
@@ -411,7 +348,6 @@ object PrettyPrinter {
     }
 
     case ResultVariable() => sb.append("#res")
-    case EpsilonVariable((row, col)) => sb.append("x" + row + "_" + col)
     case Not(expr) => ppUnary(sb, expr, "\u00AC(", ")", lvl)               // \neg
 
     case e @ Error(desc) => {
@@ -422,9 +358,15 @@ object PrettyPrinter {
       nsb
     }
 
+    case (expr: PrettyPrintable) => expr.pp(sb, lvl, pp)
+
     case _ => sb.append("Expr?")
   }
 
+  trait PrettyPrintable {
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer
+  }
+
   // TYPE TREES
   // all type trees are printed in-line
   private def ppNaryType(sb: StringBuffer, tpes: Seq[TypeTree], pre: String, op: String, post: String, lvl: Int): StringBuffer = {
diff --git a/src/main/scala/leon/xlang/Trees.scala b/src/main/scala/leon/xlang/Trees.scala
index b1b7fffe1bdd28f7f817f6ff4332e47d3646c740..e04fcbb7ecb7067df6e90c5e99b306359912f6a4 100644
--- a/src/main/scala/leon/xlang/Trees.scala
+++ b/src/main/scala/leon/xlang/Trees.scala
@@ -6,10 +6,16 @@ import leon.purescala.TypeTrees._
 import leon.purescala.Trees._
 import leon.purescala.Definitions._
 import leon.purescala.Extractors._
+import leon.purescala.PrettyPrinter._
 
 object Trees {
 
-  case class Block(exprs: Seq[Expr], last: Expr) extends Expr with NAryExtractable {
+  private def ind(sb: StringBuffer, lvl: Int) : StringBuffer = {
+    sb.append("  " * lvl)
+    sb
+  }
+
+  case class Block(exprs: Seq[Expr], last: Expr) extends Expr with NAryExtractable with PrettyPrintable {
     //val t = last.getType
     //if(t != Untyped)
      // setType(t)
@@ -18,16 +24,38 @@ object Trees {
       val Block(args, rest) = this
       Some((args :+ rest, exprs => Block(exprs.init, exprs.last)))
     }
+
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      sb.append("{\n")
+      (exprs :+ last).foreach(e => {
+        ind(sb, lvl+1)
+        rp(e, sb, lvl+1)
+        sb.append("\n")
+      })
+      ind(sb, lvl)
+      sb.append("}\n")
+      sb
+    }
+
   }
 
-  case class Assignment(varId: Identifier, expr: Expr) extends Expr with FixedType with UnaryExtractable {
+  case class Assignment(varId: Identifier, expr: Expr) extends Expr with FixedType with UnaryExtractable with PrettyPrintable {
     val fixedType = UnitType
 
     def extract: Option[(Expr, (Expr)=>Expr)] = {
       Some((expr, Assignment(varId, _)))
     }
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      var nsb: StringBuffer = sb
+      nsb.append("(")
+      nsb.append(varId.name)
+      nsb.append(" = ")
+      nsb = rp(expr, nsb, lvl)
+      nsb.append(")")
+      nsb
+    }
   }
-  case class While(cond: Expr, body: Expr) extends Expr with FixedType with ScalacPositional with BinaryExtractable {
+  case class While(cond: Expr, body: Expr) extends Expr with FixedType with ScalacPositional with BinaryExtractable with PrettyPrintable {
     val fixedType = UnitType
     var invariant: Option[Expr] = None
 
@@ -38,17 +66,52 @@ object Trees {
     def extract: Option[(Expr, Expr, (Expr, Expr)=>Expr)] = {
       Some((cond, body, (t1, t2) => While(t1, t2).setInvariant(this.invariant).setPosInfo(this)))
     }
+
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      invariant match {
+        case Some(inv) => {
+          sb.append("\n")
+          ind(sb, lvl)
+          sb.append("@invariant: ")
+          rp(inv, sb, lvl)
+          sb.append("\n")
+          ind(sb, lvl)
+        }
+        case None =>
+      }
+      sb.append("while(")
+      rp(cond, sb, lvl)
+      sb.append(")\n")
+      ind(sb, lvl+1)
+      rp(body, sb, lvl+1)
+      sb.append("\n")
+    }
+
   }
 
-  case class Epsilon(pred: Expr) extends Expr with ScalacPositional with UnaryExtractable {
+  case class Epsilon(pred: Expr) extends Expr with ScalacPositional with UnaryExtractable with PrettyPrintable {
     def extract: Option[(Expr, (Expr)=>Expr)] = {
       Some((pred, (expr: Expr) => Epsilon(expr).setType(this.getType).setPosInfo(this)))
     }
+
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      var nsb = sb
+      nsb.append("epsilon(x" + this.posIntInfo._1 + "_" + this.posIntInfo._2 + ". ")
+      nsb = rp(pred, nsb, lvl)
+      nsb.append(")")
+      nsb
+    }
+
+  }
+  case class EpsilonVariable(pos: (Int, Int)) extends Expr with Terminal with PrettyPrintable {
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      val (row, col) = pos
+      sb.append("x" + row + "_" + col)
+    }
   }
-  case class EpsilonVariable(pos: (Int, Int)) extends Expr with Terminal
 
   //same as let, buf for mutable variable declaration
-  case class LetVar(binder: Identifier, value: Expr, body: Expr) extends Expr with BinaryExtractable {
+  case class LetVar(binder: Identifier, value: Expr, body: Expr) extends Expr with BinaryExtractable with PrettyPrintable {
     binder.markAsLetBinder
     val et = body.getType
     if(et != Untyped)
@@ -58,22 +121,47 @@ object Trees {
       val LetVar(binders, expr, body) = this
       Some((expr, body, (e: Expr, b: Expr) => LetVar(binders, e, b)))
     }
+
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      val LetVar(b,d,e) = this
+      sb.append("(letvar (" + b + " := ");
+      rp(d, sb, lvl)
+      sb.append(") in\n")
+      ind(sb, lvl+1)
+      rp(e, sb, lvl+1)
+      sb.append(")")
+      sb
+    }
   }
 
-  case class Waypoint(i: Int, expr: Expr) extends Expr with UnaryExtractable {
+  case class Waypoint(i: Int, expr: Expr) extends Expr with UnaryExtractable with PrettyPrintable {
     def extract: Option[(Expr, (Expr)=>Expr)] = {
       Some((expr, (e: Expr) => Waypoint(i, e)))
     }
+
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      sb.append("waypoint_" + i + "(")
+      rp(expr, sb, lvl)
+      sb.append(")")
+    }
   }
 
   //the difference between ArrayUpdate and ArrayUpdated is that the former has a side effect while the latter is the functional version
   //ArrayUpdate should be eliminated soon in the analysis while ArrayUpdated is kept all the way to the backend
-  case class ArrayUpdate(array: Expr, index: Expr, newValue: Expr) extends Expr with ScalacPositional with FixedType with NAryExtractable {
+  case class ArrayUpdate(array: Expr, index: Expr, newValue: Expr) extends Expr with ScalacPositional with FixedType with NAryExtractable with PrettyPrintable {
     val fixedType = UnitType
 
     def extract: Option[(Seq[Expr], (Seq[Expr])=>Expr)] = {
       val ArrayUpdate(t1, t2, t3) = this
       Some((Seq(t1,t2,t3), (as: Seq[Expr]) => ArrayUpdate(as(0), as(1), as(2))))
     }
+
+    def pp(sb: StringBuffer, lvl: Int, rp: (Expr, StringBuffer, Int) => StringBuffer): StringBuffer = {
+      rp(array, sb, lvl)
+      sb.append("(")
+      rp(index, sb, lvl)
+      sb.append(") = ")
+      rp(newValue, sb, lvl)
+    }
   }
 }