diff --git a/project/Build.scala b/project/Build.scala
index 9fb755bee863d37219eedbe014adb577238420cc..a9a95b2bd8c4985d94fc6b602e9fb597503506cc 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -80,6 +80,6 @@ object Leon extends Build {
     def project(repo: String, version: String) = RootProject(uri(s"${repo}#${version}"))
 
     lazy val bonsai      = project("git://github.com/colder/bonsai.git",     "8f485605785bda98ac61885b0c8036133783290a")
-    lazy val scalaSmtLib = project("git://github.com/regb/scala-smtlib.git", "51742fa4652243827c34703365e26f0d34adec81")
+    lazy val scalaSmtLib = project("git://github.com/regb/scala-smtlib.git", "e676aab157382847b27eb436b43d2e0abd8e29ba")
   }
 }
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
index 155e84522b4a383da933c15d9148dafdf6702d5d..d26e4d47d39c4036c5c6e060c005143ef4323853 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
@@ -39,7 +39,7 @@ trait SMTLIBCVC4Target extends SMTLIBTarget {
     }
   }
 
-  override def fromSMT(s: Term, tpe: TypeTree)(implicit letDefs: Map[SSymbol, Term]): Expr = (s, tpe) match {
+  override def fromSMT(s: Term, tpe: TypeTree)(implicit lets: Map[SSymbol, Term], letDefs: Map[SSymbol, DefineFun]): Expr = (s, tpe) match {
     case (SimpleSymbol(s), tp: TypeParameter) =>
       val n = s.name.split("_").toList.last
       GenericValue(tp, n.toInt)
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
index 51ea6f67e6af29c97898316ece355c17073255a3..fe1149bb0e947088635b6f942c28b3b5c4513a28 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
@@ -219,13 +219,12 @@ trait SMTLIBTarget {
     e match {
       case Variable(id) =>
         declareSort(e.getType)
-        bindings.getOrElse(id, QualifiedIdentifier(SMTIdentifier(variables.toB(id))))
+        bindings.getOrElse(id, variables.toB(id))
 
       case UnitLiteral() =>
         declareSort(UnitType)
-        QualifiedIdentifier(SMTIdentifier(
-          declareVariable(FreshIdentifier("Unit").setType(UnitType))
-        ))
+
+        declareVariable(FreshIdentifier("Unit").setType(UnitType))
 
       case IntLiteral(i) => if (i > 0) Ints.NumeralLit(i) else Ints.Neg(Ints.NumeralLit(-i))
       case BooleanLiteral(v) => Core.BoolConst(v)
@@ -233,7 +232,7 @@ trait SMTLIBTarget {
       case Let(b,d,e) =>
         val id      = id2sym(b)
         val value   = toSMT(d)
-        val newBody = toSMT(e)(bindings + (b -> QualifiedIdentifier(SMTIdentifier(id))))
+        val newBody = toSMT(e)(bindings + (b -> id))
 
         SMTLet(
           VarBinding(id, value),
@@ -243,55 +242,63 @@ trait SMTLIBTarget {
 
       case er @ Error(_) =>
         val s = declareVariable(FreshIdentifier("error_value").setType(er.getType))
-        QualifiedIdentifier(SMTIdentifier(s))
+        s
 
       case s @ CaseClassSelector(cct, e, id) =>
         declareSort(cct)
         val selector = selectors.toB((cct, s.selectorIndex))
-        FunctionApplication(QualifiedIdentifier(SMTIdentifier(selector)), Seq(toSMT(e)))
+        FunctionApplication(selector, Seq(toSMT(e)))
 
       case CaseClassInstanceOf(cct, e) =>
         declareSort(cct)
         val tester = testers.toB(cct)
-        FunctionApplication(QualifiedIdentifier(SMTIdentifier(tester)), Seq(toSMT(e)))
+        FunctionApplication(tester, Seq(toSMT(e)))
 
       case CaseClass(cct, es) =>
         declareSort(cct)
         val constructor = constructors.toB(cct)
         if (es.isEmpty) {
-          QualifiedIdentifier(SMTIdentifier(constructor))
+          constructor
         } else {
-          FunctionApplication(QualifiedIdentifier(SMTIdentifier(constructor)), es.map(toSMT))
+          FunctionApplication(constructor, es.map(toSMT))
         }
 
       case t @ Tuple(es) =>
         val tpe = normalizeType(t.getType)
         declareSort(tpe)
         val constructor = constructors.toB(tpe)
-        FunctionApplication(QualifiedIdentifier(SMTIdentifier(constructor)), es.map(toSMT))
+        FunctionApplication(constructor, es.map(toSMT))
 
       case ts @ TupleSelect(t, i) =>
         val tpe = normalizeType(t.getType)
         declareSort(tpe)
         val selector = selectors.toB((tpe, i-1))
-        FunctionApplication(QualifiedIdentifier(SMTIdentifier(selector)), Seq(toSMT(t)))
+        FunctionApplication(selector, Seq(toSMT(t)))
+
+      case al @ ArrayLength(a) =>
+        val tpe = normalizeType(a.getType)
+        val selector = selectors.toB((tpe, 0))
+
+        FunctionApplication(selector, Seq(toSMT(a)))
+
+      case al @ ArraySelect(a, i) =>
+        val tpe = normalizeType(a.getType)
 
-      //TODO
-      //case al @ ArrayLength(a) =>
-      //  val tpe = normalizeType(a.getType)
-      //  SList(selectors.toB((tpe, 0)), toSMT(a))
+        val scontent = FunctionApplication(selectors.toB((tpe, 1)), Seq(toSMT(a)))
 
-      //case as @ ArraySelect(a, i) =>
-      //  val tpe = normalizeType(a.getType)
-      //  SList(SSymbol("select"), SList(selectors.toB((tpe, 1)), toSMT(a)), toSMT(i))
+        ArraysEx.Select(scontent, toSMT(i))
 
-      //case as @ ArrayUpdated(a, i, e) =>
-      //  val tpe = normalizeType(a.getType)
+      case al @ ArrayUpdated(a, i, e) =>
+        val tpe = normalizeType(a.getType)
 
-      //  val ssize    = SList(selectors.toB((tpe, 0)), toSMT(a))
-      //  val scontent = SList(selectors.toB((tpe, 1)), toSMT(a))
+        val sa = toSMT(a)
+        val ssize    = FunctionApplication(selectors.toB((tpe, 0)), Seq(sa))
+        val scontent = FunctionApplication(selectors.toB((tpe, 1)), Seq(sa))
 
-      //  SList(constructors.toB(tpe), ssize, SList(SSymbol("store"), scontent, toSMT(i), toSMT(e)))
+        val newcontent = ArraysEx.Store(scontent, toSMT(i), toSMT(e))
+
+        val constructor = constructors.toB(tpe)
+        FunctionApplication(constructor, Seq(ssize, newcontent))
 
 
       case e @ UnaryOperator(u, _) =>
@@ -325,7 +332,7 @@ trait SMTLIBTarget {
           case (_: IfExpr) => Core.ITE(toSMT(sub(0)), toSMT(sub(1)), toSMT(sub(2))) 
           case (f: FunctionInvocation) => 
             FunctionApplication(
-              QualifiedIdentifier(SMTIdentifier(declareFunction(f.tfd))),
+              declareFunction(f.tfd),
               sub.map(toSMT)
             )
           case _ => reporter.fatalError("Unhandled nary "+e)
@@ -336,11 +343,11 @@ trait SMTLIBTarget {
     }
   }
 
-  def fromSMT(pair: (Term, TypeTree))(implicit letDefs: Map[SSymbol, Term]): Expr = {
+  def fromSMT(pair: (Term, TypeTree))(implicit lets: Map[SSymbol, Term], letDefs: Map[SSymbol, DefineFun]): Expr = {
     fromSMT(pair._1, pair._2)
   }
 
-  def fromSMT(s: Term, tpe: TypeTree)(implicit letDefs: Map[SSymbol, Term]): Expr = (s, tpe) match {
+  def fromSMT(s: Term, tpe: TypeTree)(implicit lets: Map[SSymbol, Term], letDefs: Map[SSymbol, DefineFun]): Expr = (s, tpe) match {
     case (_, UnitType) =>
       UnitLiteral()
 
@@ -360,8 +367,8 @@ trait SMTLIBTarget {
           unsupported("woot? for a single constructor for non-case-object: "+t)
       }
 
-    case (SimpleSymbol(s), tpe) if letDefs contains s =>
-      fromSMT(letDefs(s), tpe)
+    case (SimpleSymbol(s), tpe) if lets contains s =>
+      fromSMT(lets(s), tpe)
 
     case (SimpleSymbol(s), _) =>
       variables.getA(s).map(_.toVariable).getOrElse {
@@ -396,10 +403,10 @@ trait SMTLIBTarget {
         case VarBinding(s, value) => (s, value)
       }.toMap
 
-      fromSMT(body, tpe)(letDefs ++ defsMap)
+      fromSMT(body, tpe)(lets ++ defsMap, letDefs)
 
     case (FunctionApplication(SimpleSymbol(SSymbol(app)), args), tpe) => {
-      name match {
+      app match {
         case "-" =>
           args match {
             case List(a) => UMinus(fromSMT(a, Int32Type))
@@ -407,9 +414,11 @@ trait SMTLIBTarget {
           }
 
         case _ =>
-          unsupported(s)
+          unsupported("Function "+app+" not handled in fromSMT: "+s)
       }
     }
+    case (QualifiedIdentifier(id, sort), tpe) =>
+      unsupported("Unhandled case in fromSMT: " + id +": "+sort +" ("+tpe+")")
     case _ =>
       unsupported("Unhandled case in fromSMT: " + (s, tpe))
   }
@@ -444,7 +453,7 @@ trait SMTLIBTarget {
   override def getModel: Map[Identifier, Expr] = {
     val syms = variables.bSet.toList
     val cmd: Command = 
-      GetValue(QualifiedIdentifier(SMTIdentifier(syms.head)), 
+      GetValue(syms.head, 
                syms.tail.map(s => QualifiedIdentifier(SMTIdentifier(s)))
               )
 
@@ -455,7 +464,7 @@ trait SMTLIBTarget {
       case (SimpleSymbol(sym), value) if variables.containsB(sym) =>
         val id = variables.toA(sym)
 
-        (id, fromSMT(value, id.getType)(Map()))
+        (id, fromSMT(value, id.getType)(Map(), Map()))
     }.toMap
   }
 
@@ -475,4 +484,9 @@ trait SMTLIBTarget {
 
   }
 
+  import scala.language.implicitConversions
+  implicit def symbolToQualifiedId(s: SSymbol): QualifiedIdentifier = {
+    QualifiedIdentifier(SMTIdentifier(s))
+  }
+
 }
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
index 779d759c165bab114700f129f61989d3704f768e..4feb6a3942ae8b61351eb255301538f97b59762e 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBZ3Target.scala
@@ -16,7 +16,7 @@ import _root_.smtlib.parser.Terms.{Identifier => SMTIdentifier, _}
 import _root_.smtlib.parser.Commands.{DefineSort, GetValue, NonStandardCommand, GetModel, DefineFun}
 import _root_.smtlib.interpreters.Z3Interpreter
 import _root_.smtlib.parser.CommandsResponses.{SExprResponse, GetModelResponse}
-import _root_.smtlib.theories.Core._
+import _root_.smtlib.theories.Core.{Equals => SMTEquals, _}
 import _root_.smtlib.theories.ArraysEx
 
 trait SMTLIBZ3Target extends SMTLIBTarget {
@@ -97,7 +97,7 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
         declareOptionSort(to)
 
         val arraySort = Sort(SMTIdentifier(SSymbol("Array")),
-                             Seq(Sort(SMTIdentifier(optionSort.get)), Sort(SMTIdentifier(b))))
+                             Seq(Sort(SMTIdentifier(a)), Sort(SMTIdentifier(optionSort.get), Seq(Sort(SMTIdentifier(b))))))
 
         val cmd = DefineSort(m, Seq(a, b), arraySort)
         sendCommand(cmd)
@@ -107,64 +107,64 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
     Sort(SMTIdentifier(mapSort.get), Seq(declareSort(from), declareSort(to)))
   }
 
-  override def fromSMT(s: Term, tpe: TypeTree)(implicit letDefs: Map[SSymbol, Term]): Expr = (s, tpe) match {
+  override def fromSMT(s: Term, tpe: TypeTree)(implicit lets: Map[SSymbol, Term], letDefs: Map[SSymbol, DefineFun]): Expr = (s, tpe) match {
     case (SimpleSymbol(s), tp: TypeParameter) =>
       val n = s.name.split("!").toList.last
       GenericValue(tp, n.toInt)
 
 
-    //case (SList(List(`extSym`, SSymbol("as-array"), k: SSymbol)), tpe) =>
-    //  if (letDefs contains k) {
-    //    // Need to recover value form function model
-    //    fromRawArray(extractRawArray(letDefs(k)), tpe)
-    //  } else {
-    //    unsupported(" as-array on non-function or unknown symbol "+k)
-    //  }
+    case (QualifiedIdentifier(ExtendedIdentifier(SSymbol("as-array"), k: SSymbol), _), tpe) =>
+      if (letDefs contains k) {
+        // Need to recover value form function model
+        fromRawArray(extractRawArray(letDefs(k)), tpe)
+      } else {
+        unsupported(" as-array on non-function or unknown symbol "+k)
+      }
 
-    // SMT representation for empty sets: Array(* -> false)
-    //case (SList(List(SList(List(SSymbol("as"), SSymbol("const"), SList(List(SSymbol("Array"), k, v)))), defV)), tpe) =>
-    //  val ktpe = sorts.fromB(Sort(SMTIdentifier(k)))
-    //  val vtpe = sorts.fromB(Sort(SMTIdentifier(v)))
+    case (FunctionApplication(QualifiedIdentifier(SimpleSymbol(SSymbol("const")), Some(ArraysEx.ArraySort(k, v))), Seq(defV)), tpe) =>
+      val ktpe = sorts.fromB(k)
+      val vtpe = sorts.fromB(v)
 
-    //  fromRawArray(RawArrayValue(ktpe, Map(), fromSMT(defV, vtpe)), tpe)
+      fromRawArray(RawArrayValue(ktpe, Map(), fromSMT(defV, vtpe)), tpe)
 
     case _ =>
       super[SMTLIBTarget].fromSMT(s, tpe)
   }
 
   override def toSMT(e: Expr)(implicit bindings: Map[Identifier, Term]): Term = e match {
-      //case a @ FiniteArray(elems) =>
-      //  val tpe @ ArrayType(base) = normalizeType(a.getType)
-      //  declareSort(tpe)
+      case a @ FiniteArray(elems) =>
+        val tpe @ ArrayType(base) = normalizeType(a.getType)
+        declareSort(tpe)
 
-      //  var ar = SList(SList(SSymbol("as"), SSymbol("const"), declareSort(RawArrayType(Int32Type, base))), toSMT(simplestValue(base)))
+        
+        var ar: Term = ArrayConst(declareSort(RawArrayType(Int32Type, base)), toSMT(simplestValue(base)))
 
-      //  for ((e, i) <- elems.zipWithIndex) {
-      //    ar = SList(SSymbol("store"), ar, toSMT(IntLiteral(i)), toSMT(e))
-      //  }
+        for ((e, i) <- elems.zipWithIndex) {
+          ar = ArraysEx.Store(ar, toSMT(IntLiteral(i)), toSMT(e))
+        }
 
-      //  SList(constructors.toB(tpe), toSMT(IntLiteral(elems.size)), ar)
+        FunctionApplication(constructors.toB(tpe), List(toSMT(IntLiteral(elems.size)), ar))
 
-      ///**
-      // * ===== Map operations =====
-      // */
-      //case MapGet(m, k) =>
-      //  declareSort(m.getType)
-      //  SList(SSymbol("Some_v"), SList(SSymbol("select"), toSMT(m), toSMT(k)))
+      /**
+       * ===== Map operations =====
+       */
+      case MapGet(m, k) =>
+        declareSort(m.getType)
+        FunctionApplication(SSymbol("Some_v"), List(ArraysEx.Select(toSMT(m), toSMT(k))))
 
-      //case MapIsDefinedAt(m, k) =>
-      //  declareSort(m.getType)
-      //  SList(SSymbol("is-Some"), SList(SSymbol("select"), toSMT(m), toSMT(k)))
+      case MapIsDefinedAt(m, k) =>
+        declareSort(m.getType)
+        FunctionApplication(SSymbol("is-Some"), List(ArraysEx.Select(toSMT(m), toSMT(k))))
 
-      //case m @ FiniteMap(elems) =>
-      //  val ms = declareSort(m.getType)
+      case m @ FiniteMap(elems) =>
+        val ms = declareSort(m.getType)
 
-      //  var res = SList(SList(SSymbol("as"), SSymbol("const"), ms), SSymbol("None"))
-      //  for ((k, v) <- elems) {
-      //    res = SList(SSymbol("store"), res, toSMT(k), SList(SSymbol("Some"), toSMT(v)))
-      //  }
+        var res: Term = FunctionApplication(QualifiedIdentifier(SMTIdentifier(SSymbol("const")), Some(ms)), List(SSymbol("None")))
+        for ((k, v) <- elems) {
+          res = ArraysEx.Store(res, toSMT(k), FunctionApplication(SSymbol("Some"), List(toSMT(v))))
+        }
 
-      //  res
+        res
 
       /**
        * ===== Set operations =====
@@ -182,49 +182,50 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
 
         res
 
-      //case SubsetOf(ss, s) =>
-      //  // a isSubset b   ==>   (a zip b).map(implies) == (* => true)
-      //  val allTrue    = SList(SList(SSymbol("as"), SSymbol("const"), declareSort(s.getType)), SSymbol("true"))
-      //  val mapImplies = SList(SList(extSym, SSymbol("map"), SSymbol("implies")), toSMT(ss), toSMT(s))
+      case SubsetOf(ss, s) =>
+        // a isSubset b   ==>   (a zip b).map(implies) == (* => true)
+        val allTrue = ArrayConst(declareSort(s.getType), True())
+
+        SMTEquals(ArrayMap(SSymbol("implies"), toSMT(ss), toSMT(s)), allTrue)
 
-      //  SList(SSymbol("="), mapImplies, allTrue)
+      case ElementOfSet(e, s) =>
+        ArraysEx.Select(toSMT(s), toSMT(e))
 
-      //case ElementOfSet(e, s) =>
-      //  SList(SSymbol("select"), toSMT(s), toSMT(e))
+      case SetDifference(a, b) =>
+        // a -- b
+        // becomes:
+        // a && not(b)
+
+        ArrayMap(SSymbol("and"), toSMT(a), ArrayMap(SSymbol("not"), toSMT(b)))
 
-      //case SetDifference(a, b) =>
-      //  // a -- b
-      //  // becomes:
-      //  // a && not(b)
-      //  SList(SList(extSym, SSymbol("map"), SSymbol("and")), toSMT(a), SList(SList(extSym, SSymbol("map"), SSymbol("not")), toSMT(b)))
       case SetUnion(l, r) =>
-        FunctionApplication(
-          QualifiedIdentifier(SMTIdentifier(SSymbol("(_ map or)"))), //hack to get around Z3 syntax
-          Seq(toSMT(l), toSMT(r)))
+        ArrayMap(SSymbol("or"), toSMT(l), toSMT(r))
 
-      //case SetIntersection(l, r) =>
-      //  SList(SList(extSym, SSymbol("map"), SSymbol("and")), toSMT(l), toSMT(r))
+      case SetIntersection(l, r) =>
+        ArrayMap(SSymbol("and"), toSMT(l), toSMT(r))
 
       case _ =>
         super.toSMT(e)
   }
 
-  def extractRawArray(s: SExpr)(implicit letDefs: Map[SSymbol, SExpr]): RawArrayValue = s match {
-    //case SList(List(SSymbol("define-fun"), a: SSymbol, SList(SList(List(arg, akind)) :: Nil), rkind, body)) =>
-    //  val argTpe = sorts.toA(Sort(SMTIdentifier(akind)))
-    //  val retTpe = sorts.toA(Sort(SMTIdentifier(rkind)))
+  def extractRawArray(s: DefineFun)(implicit lets: Map[SSymbol, Term], letDefs: Map[SSymbol, DefineFun]): RawArrayValue = s match {
+    case DefineFun(a, List(SortedVar(arg, akind)), rkind, body) =>
+
+      val argTpe = sorts.toA(akind)
+      val retTpe = sorts.toA(rkind)
 
-    //  def extractCases(e: SExpr): (Map[Expr, Expr], Expr) = e match {
-    //    case SList(SSymbol("ite") :: SList(SSymbol("=") :: `arg` :: k :: Nil) :: v :: e :: Nil) =>
-    //      val (cs, d) = extractCases(e)
-    //      (Map(fromSMT(k, argTpe) -> fromSMT(v, retTpe)) ++ cs, d)
-    //    case e =>
-    //      (Map(),fromSMT(e, retTpe))
-    //  }
+      def extractCases(e: Term): (Map[Expr, Expr], Expr) = e match {
+        case ITE(SMTEquals(SimpleSymbol(`arg`), k), v, e) =>
+          val (cs, d) = extractCases(e)
+          (Map(fromSMT(k, argTpe) -> fromSMT(v, retTpe)) ++ cs, d)
+        case e =>
+          (Map(),fromSMT(e, retTpe))
+      }
+
+      val (cases, default) = extractCases(body)
 
-    //  val (cases, default) = extractCases(body)
+      RawArrayValue(argTpe, cases, default)
 
-    //  RawArrayValue(argTpe, cases, default)
     case _ =>
       unsupported("Unable to extract "+s)
   }
@@ -249,7 +250,7 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
 
     val res = sendCommand(cmd)
 
-    val smodel: Seq[DefineFun] = res match {
+    val smodel: Seq[SExpr] = res match {
       case GetModelResponse(model) => model
       case _ => Nil
     }
@@ -258,7 +259,7 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
 
     // First pass to gather functions (arrays defs)
     for (me <- smodel) me match {
-      case DefineFun(a, args, _, _) if args.nonEmpty =>
+      case me @ DefineFun(a, args, _, _) if args.nonEmpty =>
         modelFunDefs += a -> me
       case _ =>
     }
@@ -270,11 +271,28 @@ trait SMTLIBZ3Target extends SMTLIBTarget {
         if(args.isEmpty) {
           val id = variables.toA(s)
           // EK: this is a little hack, we pass models for array functions as let-defs
-          model += id -> fromSMT(e, id.getType)(null)//modelFunDefs)
+          model += id -> fromSMT(e, id.getType)(Map(), modelFunDefs)
         }
+      case _ =>
     }
 
 
     model
   }
+
+  object ArrayMap {
+    def apply(op: SSymbol, arrs: Term*) = {
+      FunctionApplication(
+        QualifiedIdentifier(SMTIdentifier(SSymbol("(_ map "+op.name+")"))), //hack to get around Z3 syntax
+        arrs)
+    }
+  }
+
+  object ArrayConst {
+    def apply(sort: Sort, default: Term) = {
+      FunctionApplication(
+        QualifiedIdentifier(SMTIdentifier(SSymbol("const")), Some(sort)),
+        List(default))
+    }
+  }
 }