diff --git a/src/main/scala/leon/laziness/ClosurePreAsserter.scala b/src/main/scala/leon/laziness/ClosurePreAsserter.scala
index c0324fe7677c8007441bc65c4ed7ac3843f4b41a..a55cbbc00e7747835a9751e9c9140c1ebd761188 100644
--- a/src/main/scala/leon/laziness/ClosurePreAsserter.scala
+++ b/src/main/scala/leon/laziness/ClosurePreAsserter.scala
@@ -61,8 +61,12 @@ class ClosurePreAsserter(p: Program) {
         case ((CaseClass(CaseClassType(ccd, _), argsRet), st), path) =>
           anchorfd = Some(fd)
           val target = lookupOp(ccd) //find the target corresponding to the closure
+
           val pre = target.precondition.get
-          val args = argsRet.dropRight(1) // drop the return value which is the right-most field
+          val args =
+            if (!isMemoized(target))
+              argsRet.dropRight(1) // drop the return value which is the right-most field
+            else argsRet
           val nargs =
             if (target.params.size > args.size) // target takes state ?
               args :+ st
@@ -93,7 +97,7 @@ class ClosurePreAsserter(p: Program) {
   val monoLemmas = {
     var exprsProcessed = Set[ExprStructure]()
     ccToOp.values.flatMap {
-      case op if op.hasPrecondition =>
+      case op if op.hasPrecondition && !isMemoized(op) => // ignore memoized functions which are always evaluated at the time of creation
         // get the state param
         op.paramIds.find(isStateParam) match {
           case Some(stparam) =>
@@ -122,7 +126,7 @@ class ClosurePreAsserter(p: Program) {
                   val fieldSelect = (id: Identifier) => CaseClassSelector(stType, id.toVariable, fld.id)
                   SubsetOf(fieldSelect(stparam), fieldSelect(superSt))
                 })
-              // create a function for each pre-disjunct that is not processed              
+              // create a function for each pre-disjunct that is not processed
               preDisjs.map(new ExprStructure(_)).collect {
                 case preStruct if !exprsProcessed(preStruct) =>
                   exprsProcessed += preStruct
diff --git a/src/main/scala/leon/laziness/LazinessEliminationPhase.scala b/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
index c8121446f28971e9e6a8ba5f63b52346fe941b53..88ef5bda269629ae924219647f4ba8ab1d4c923b 100644
--- a/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
+++ b/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
@@ -57,6 +57,9 @@ object LazinessEliminationPhase extends TransformationPhase {
   // options that control behavior
   val optRefEquality = LeonFlagOptionDef("refEq", "Uses reference equality for comparing closures", false)
 
+  /**
+   * TODO: add inlining annotations for optimization.
+   */
   def apply(ctx: LeonContext, prog: Program): Program = {
 
     if (dumpInputProg)
@@ -113,6 +116,7 @@ object LazinessEliminationPhase extends TransformationPhase {
   }
 
   /**
+   * TODO: enforce that lazy and nested types do not overlap
    * TODO: we are forced to make an assumption that lazy ops takes as type parameters only those
    * type parameters of their return type and not more. (This is checked in the closureFactory,\
    * but may be check this upfront)
@@ -155,7 +159,16 @@ object LazinessEliminationPhase extends TransformationPhase {
             if (nestedCheckFailed) {
               failMsg = "Nested suspension creation in the body:  " + fd.id
               false
-            } else true
+            } else {
+              // arguments or return types of memoized functions cannot be lazy because we do not know how to compare them for equality
+              if (isMemoized(fd)) {
+                val argCheckFailed = (fd.params.map(_.getType) :+ fd.returnType).exists(LazinessUtil.isLazyType)
+                if (argCheckFailed) {
+                  failMsg = "Memoized function has a lazy argument or return type: " + fd.id
+                  false
+                } else true
+              } else true
+            }
           }
         }
       case _ => true
@@ -172,6 +185,11 @@ object LazinessEliminationPhase extends TransformationPhase {
     "lazyarg" + globalId
   }
 
+  /**
+   * (a) The functions lifts arguments of '$' to functions
+   * (b) lifts eager computations to lazy computations if necessary
+   * (c) converts memoization to lazy evaluation
+   */
   def liftLazyExpressions(prog: Program): Program = {
     var newfuns = Map[ExprStructure, (FunDef, ModuleDef)]()
     val fdmap = prog.definedFunctions.collect {
@@ -180,43 +198,60 @@ object LazinessEliminationPhase extends TransformationPhase {
         fd.flags.foreach(nfd.addFlag(_))
         (fd -> nfd)
     }.toMap
+
+    lazy val lazyFun = ProgramUtil.functionByFullName("leon.lazyeval.$.apply", prog).get
+    lazy val valueFun = ProgramUtil.functionByFullName("leon.lazyeval.$.value", prog).get
+
     prog.modules.foreach { md =>
-      md.definedFunctions.foreach {
-        case fd if fd.hasBody && !fd.isLibrary =>
-          val nbody = simplePostTransform {
-            // is the arugment of lazy invocation not a function ?
-            case finv @ FunctionInvocation(lazytfd, Seq(arg)) if isLazyInvocation(finv)(prog) && !arg.isInstanceOf[FunctionInvocation] =>
-              val freevars = variablesOf(arg).toList
-              val tparams = freevars.map(_.getType) flatMap getTypeParameters distinct
-              val argstruc = new ExprStructure(arg)
-              val argfun =
-                if (newfuns.contains(argstruc)) {
-                  newfuns(argstruc)._1
-                } else {
-                  //construct type parameters for the function
-                  // note: we should make the base type of arg as the return type
-                  val nfun = new FunDef(FreshIdentifier(freshFunctionNameForArg, Untyped, true), tparams map TypeParameterDef.apply,
-                    freevars.map(ValDef(_)), bestRealType(arg.getType))
-                  nfun.body = Some(arg)
-                  newfuns += (argstruc -> (nfun, md))
-                  nfun
-                }
-              FunctionInvocation(lazytfd, Seq(FunctionInvocation(TypedFunDef(argfun, tparams),
-                freevars.map(_.toVariable))))
+      def exprLifter(inspec: Boolean)(expr: Expr) = expr match {
+        // is the arugment of lazy invocation not a function ?
+        case finv @ FunctionInvocation(lazytfd, Seq(arg)) if isLazyInvocation(finv)(prog) && !arg.isInstanceOf[FunctionInvocation] =>
+          val freevars = variablesOf(arg).toList
+          val tparams = freevars.map(_.getType).flatMap(getTypeParameters).distinct
+          val argstruc = new ExprStructure(arg)
+          val argfun =
+            if (newfuns.contains(argstruc)) {
+              newfuns(argstruc)._1
+            } else {
+              //construct type parameters for the function
+              // note: we should make the base type of arg as the return type
+              val nfun = new FunDef(FreshIdentifier(freshFunctionNameForArg, Untyped, true), tparams map TypeParameterDef.apply,
+                freevars.map(ValDef(_)), bestRealType(arg.getType))
+              nfun.body = Some(arg)
+              newfuns += (argstruc -> (nfun, md))
+              nfun
+            }
+          FunctionInvocation(lazytfd, Seq(FunctionInvocation(TypedFunDef(argfun, tparams),
+            freevars.map(_.toVariable))))
 
-            // is the argument of eager invocation not a variable ?
-            case finv @ FunctionInvocation(TypedFunDef(fd, _), Seq(arg)) if isEagerInvocation(finv)(prog) && !arg.isInstanceOf[Variable] =>
-              val rootType = bestRealType(arg.getType)
-              val freshid = FreshIdentifier("t", rootType)
-              Let(freshid, arg, FunctionInvocation(TypedFunDef(fd, Seq(rootType)), Seq(freshid.toVariable)))
+        // is the argument of eager invocation not a variable ?
+        case finv @ FunctionInvocation(TypedFunDef(fd, _), Seq(arg)) if isEagerInvocation(finv)(prog) && !arg.isInstanceOf[Variable] =>
+          val rootType = bestRealType(arg.getType)
+          val freshid = FreshIdentifier("t", rootType)
+          Let(freshid, arg, FunctionInvocation(TypedFunDef(fd, Seq(rootType)), Seq(freshid.toVariable)))
 
-            case FunctionInvocation(TypedFunDef(fd, targs), args) if fdmap.contains(fd) =>
-              FunctionInvocation(TypedFunDef(fdmap(fd), targs), args)
-            case e => e
+        case FunctionInvocation(TypedFunDef(fd, targs), args) if isMemoized(fd) && !inspec =>
+          // calling a memoized function is modeled as creating a lazy closure and forcing it
+          val tfd = TypedFunDef(fdmap.getOrElse(fd, fd), targs)
+          val finv = FunctionInvocation(tfd, args)
+          // enclose the call within the $ and force it
+          val susp = FunctionInvocation(TypedFunDef(lazyFun, Seq(tfd.returnType)), Seq(finv))
+          FunctionInvocation(TypedFunDef(valueFun, Seq(tfd.returnType)), Seq(susp))
 
-          }(fd.fullBody) // TODO: specs should not create lazy closures. enforce this
+        case FunctionInvocation(TypedFunDef(fd, targs), args) if fdmap.contains(fd) =>
+          FunctionInvocation(TypedFunDef(fdmap(fd), targs), args)
+        case e => e
+      }
+      md.definedFunctions.foreach {
+        case fd if fd.hasBody && !fd.isLibrary =>
+          val nbody = simplePostTransform(exprLifter(false))(fd.body.get)
+          val npre = fd.precondition.map(simplePostTransform(exprLifter(true)))
+          val npost = fd.postcondition.map(simplePostTransform(exprLifter(true)))
           //println(s"New body of $fd: $nbody")
-          fdmap(fd).fullBody = nbody
+          val nfd = fdmap(fd)
+          nfd.body = Some(nbody)
+          nfd.precondition = npre
+          nfd.postcondition = npost
         case _ => ;
       }
     }
diff --git a/src/main/scala/leon/laziness/LazyClosureConverter.scala b/src/main/scala/leon/laziness/LazyClosureConverter.scala
index b30eca6874241456b9cad3114e647a8f3d05edcd..c86ec021f87ccfb08a2a3a41b95ddfe2fe69dbb1 100644
--- a/src/main/scala/leon/laziness/LazyClosureConverter.scala
+++ b/src/main/scala/leon/laziness/LazyClosureConverter.scala
@@ -49,7 +49,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
   val consCallers = funsManager.callersOfLazyCons  // transitive constructors of closures
   val starCallers = funsManager.funsNeedStateTps
   val fvFactory = new FreeVariableFactory()
-  val tnames = closureFactory.lazyTypeNames
+  val lazyTnames = closureFactory.lazyTypeNames
   val lazyops = closureFactory.lazyops
 
   val funMap = p.definedFunctions.collect {
@@ -178,7 +178,8 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
    * Note that by using 'assume-pre' we can also assume the preconditions of closures at
    * the call-sites.
    */
-  val evalFunctions = tnames.map { tname =>
+  val evalFunctions = lazyTnames.map { tname =>
+    val ismem = closureFactory.isMemType(tname)
     val tpe = /*freshenTypeArguments(*/ closureFactory.lazyType(tname) //)
     val absdef = closureFactory.absClosureType(tname)
     val cdefs = closureFactory.closures(tname)
@@ -204,8 +205,11 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       val binder = FreshIdentifier("t", ctype)
       val pattern = InstanceOfPattern(Some(binder), ctype)
       // create a body of the match
-      // the last field represents the result
-      val args = cdef.fields.dropRight(1) map { fld =>
+      // the last field represents the result (only if the type is a susp type)
+      val flds =
+        if (!ismem) cdef.fields.dropRight(1)
+        else cdef.fields
+      val args = flds map { fld =>
         CaseClassSelector(ctype, binder.toVariable, fld.id)
       }
       val op = closureFactory.caseClassToOp(cdef)
@@ -231,17 +235,18 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       val rhs = Let(invokeRes, invoke, Tuple(Seq(valPart, stPart)))
       MatchCase(pattern, None, rhs)
     }
-    // create a new match case for eager evaluation
-    val eagerCase = {
-      val eagerDef = closureFactory.eagerClosure(tname)
+    val cases = if (!ismem) {
+      // create a new match case for eager evaluation
+      val eagerDef = closureFactory.eagerClosure(tname).get
       val ctype = CaseClassType(eagerDef, recvTparams)
       val binder = FreshIdentifier("t", ctype)
       // create a body of the match
       val valPart = CaseClassSelector(ctype, binder.toVariable, eagerDef.fields(0).id)
       val rhs = Tuple(Seq(valPart, param2.toVariable)) // state doesn't change for eager closure
-      MatchCase(InstanceOfPattern(Some(binder), ctype), None, rhs)
-    }
-    dfun.body = Some(MatchExpr(param1.toVariable, eagerCase +: bodyMatchCases))
+      MatchCase(InstanceOfPattern(Some(binder), ctype), None, rhs) +: bodyMatchCases
+    } else
+      bodyMatchCases
+    dfun.body = Some(MatchExpr(param1.toVariable, cases))
     dfun.addFlag(Annotation("axiom", Seq()))
     (tname -> dfun)
   }.toMap
@@ -272,7 +277,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
    * They are defined for each lazy class since it avoids generics and
    * simplifies the type inference (which is not full-fledged in Leon)
    */
-  val closureCons = tnames.map { tname =>
+  val closureCons = lazyTnames.map { tname =>
     val adt = closureFactory.absClosureType(tname)
     val param1Type = AbstractClassType(adt, adt.tparams.map(_.tp))
     val param1 = FreshIdentifier("cc", param1Type)
@@ -283,7 +288,6 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
     val fun = new FunDef(FreshIdentifier(closureConsName(tname)), tparamdefs,
       Seq(ValDef(param1), ValDef(param2)), param1Type)
     fun.body = Some(param1.toVariable)
-
     // assert that the closure in unevaluated if useRefEquality is enabled
     // not supported as of now
     /*if (refEq) {
@@ -295,21 +299,25 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
     (tname -> fun)
   }.toMap
 
-  def mapBody(body: Expr)(implicit stTparams: Seq[TypeParameter]): (Option[Expr] => Expr, Boolean) = body match {
+  def mapExpr(expr: Expr)(implicit stTparams: Seq[TypeParameter], inSpec: Boolean): (Option[Expr] => Expr, Boolean) = expr match {
 
     case finv @ FunctionInvocation(_, Seq(FunctionInvocation(TypedFunDef(argfd, tparams), args))) // lazy construction ?
-    if isLazyInvocation(finv)(p) =>
+    if isLazyInvocation(finv)(p) && !inSpec =>
       val op = (nargs: Seq[Expr]) => ((st: Option[Expr]) => {
         val adt = closureFactory.closureOfLazyOp(argfd)
         // create lets to bind the nargs to variables
-        val (flatArgs, letCons) = nargs.foldRight((Seq[Variable](), (e : Expr) => e)){
+        val (flatArgs, letCons) = nargs.foldRight((Seq[Variable](), (e: Expr) => e)) {
           case (narg, (fargs, lcons)) =>
             val id = FreshIdentifier("a", narg.getType, true)
             (id.toVariable +: fargs, e => Let(id, narg, lcons(e)))
         }
-        // construct a value for the result (an uninterpreted function)
-        val resval = FunctionInvocation(TypedFunDef(uiFuncs(argfd)._1, tparams), flatArgs)
-        val cc = CaseClass(CaseClassType(adt, tparams), flatArgs :+ resval)
+        val ccArgs = if (!isMemoized(argfd)) {
+          // construct a value for the result (an uninterpreted function)
+          val resval = FunctionInvocation(TypedFunDef(uiFuncs(argfd)._1, tparams), flatArgs)
+          flatArgs :+ resval
+        } else
+          flatArgs
+        val cc = CaseClass(CaseClassType(adt, tparams), ccArgs)
         val baseLazyTypeName = closureFactory.lazyTypeNameOfClosure(adt)
         val fi = FunctionInvocation(TypedFunDef(closureCons(baseLazyTypeName), tparams ++ stTparams),
           Seq(cc, st.get))
@@ -317,13 +325,29 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       }, false)
       mapNAryOperator(args, op)
 
+    // TODO: we don't have to create a dummy return value for memoized functions, as they wouldn't be stored in other structures
+    case finv @ FunctionInvocation(_, Seq(FunctionInvocation(TypedFunDef(argfd, tparams), args))) // invocation in spec ?
+    if isLazyInvocation(finv)(p) && inSpec =>
+      // in this case argfd is a memoized function
+      val op = (nargs: Seq[Expr]) => ((st: Option[Expr]) => {
+        val adt = closureFactory.closureOfLazyOp(argfd)
+        /*// create lets to bind the nargs to variables
+        val (flatArgs, letCons) = nargs.foldRight((Seq[Variable](), (e : Expr) => e)){
+          case (narg, (fargs, lcons)) =>
+            val id = FreshIdentifier("a", narg.getType, true)
+            (id.toVariable +: fargs, e => Let(id, narg, lcons(e)))
+        }*/
+        CaseClass(CaseClassType(adt, tparams), nargs)
+      }, false)
+      mapNAryOperator(args, op)
+
     case finv @ FunctionInvocation(_, Seq(arg)) if isEagerInvocation(finv)(p) =>
       // here arg is guaranteed to be a variable
       ((st: Option[Expr]) => {
         val rootType = bestRealType(arg.getType)
         val tname = typeNameWOParams(rootType)
         val tparams = getTypeArguments(rootType)
-        val eagerClosure = closureFactory.eagerClosure(tname)
+        val eagerClosure = closureFactory.eagerClosure(tname).get
         CaseClass(CaseClassType(eagerClosure, tparams), Seq(arg))
       }, false)
 
@@ -336,9 +360,13 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
         val stType = CaseClassType(closureFactory.state, stTparams)
         val cls = closureFactory.selectFieldOfState(tname, st, stType)
         val memberTest = ElementOfSet(narg, cls)
-        val subtypeTest = IsInstanceOf(narg,
-          CaseClassType(closureFactory.eagerClosure(tname), getTypeArguments(baseType)))
-        Or(memberTest, subtypeTest)
+        if(closureFactory.isMemType(tname)) {
+          memberTest
+        } else {
+          val subtypeTest = IsInstanceOf(narg,
+          CaseClassType(closureFactory.eagerClosure(tname).get, getTypeArguments(baseType)))
+          Or(memberTest, subtypeTest)
+        }
       }, false)
       mapNAryOperator(args, op)
 
@@ -366,8 +394,8 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
         throw new IllegalStateException("The arguments to `withState` should equal the number of states: "+numStates)
 
       val CaseClass(_, Seq(exprNeedingState)) = recvr
-      val (nexprCons, exprReturnsState) = mapBody(exprNeedingState)
-      val nstConses = stArgs map mapBody
+      val (nexprCons, exprReturnsState) = mapExpr(exprNeedingState)
+      val nstConses = stArgs map mapExpr
       if(nstConses.exists(_._2)) // any 'stArg' returning state
         throw new IllegalStateException("One of the  arguments to `withState` returns a new state, which is not supported: "+finv)
       else {
@@ -398,13 +426,6 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
         val dispFun = evalFunctions(tname)
         val tparams = (getTypeParameters(baseType) ++ stTparams).distinct
         FunctionInvocation(TypedFunDef(dispFun, tparams), nargs :+ st)
-        //val dispRes = FreshIdentifier("dres", dispFun.returnType, true)
-        /*val nstates = tnames map {
-          case `tname` =>
-            TupleSelect(dispRes.toVariable, 2)
-          case other => st(other)
-        }*/
-        //Let(dispRes, dispFunInv, Tuple(TupleSelect(dispRes.toVariable, 1) +: nstates))
       }, true)
       mapNAryOperator(args, op)
 
@@ -433,14 +454,13 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
         }, funsRetStates(fd)))
 
     case Let(id, value, body) =>
-      val (valCons, valUpdatesState) = mapBody(value)
-      val (bodyCons, bodyUpdatesState) = mapBody(body)
+      val (valCons, valUpdatesState) = mapExpr(value)
+      val (bodyCons, bodyUpdatesState) = mapExpr(body)
       ((st: Option[Expr]) => {
         val nval = valCons(st)
         if (valUpdatesState) {
           val freshid = FreshIdentifier(id.name, nval.getType, true)
           val nextState = TupleSelect(freshid.toVariable, 2)
-          //val nsMap = (tnames zip nextStates).toMap
           val transBody = replace(Map(id.toVariable -> TupleSelect(freshid.toVariable, 1)),
             bodyCons(Some(nextState)))
           if (bodyUpdatesState)
@@ -452,9 +472,9 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       }, valUpdatesState || bodyUpdatesState)
 
     case IfExpr(cond, thn, elze) =>
-      val (condCons, condState) = mapBody(cond)
-      val (thnCons, thnState) = mapBody(thn)
-      val (elzeCons, elzeState) = mapBody(elze)
+      val (condCons, condState) = mapExpr(cond)
+      val (thnCons, thnState) = mapExpr(thn)
+      val (elzeCons, elzeState) = mapExpr(elze)
       ((st: Option[Expr]) => {
         val (ncondCons, nst) =
           if (condState) {
@@ -479,10 +499,10 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       }, condState || thnState || elzeState)
 
     case MatchExpr(scr, cases) =>
-      val (scrCons, scrUpdatesState) = mapBody(scr)
+      val (scrCons, scrUpdatesState) = mapExpr(scr)
       val casesRes = cases.foldLeft(Seq[(Option[Expr] => Expr, Boolean)]()) {
         case (acc, MatchCase(pat, None, rhs)) =>
-          acc :+ mapBody(rhs)
+          acc :+ mapExpr(rhs)
         case mcase =>
           throw new IllegalStateException("Match case with guards are not supported yet: " + mcase)
       }
@@ -525,12 +545,12 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
     case t: Terminal => (_ => t, false)
   }
 
-  def mapNAryOperator(args: Seq[Expr], op: Seq[Expr] => (Option[Expr] => Expr, Boolean))(implicit stTparams: Seq[TypeParameter]) = {
+  def mapNAryOperator(args: Seq[Expr], op: Seq[Expr] => (Option[Expr] => Expr, Boolean))(implicit stTparams: Seq[TypeParameter], inSpec: Boolean) = {
     // create n variables to model n lets
     val letvars = args.map(arg => FreshIdentifier("arg", arg.getType, true).toVariable)
     (args zip letvars).foldRight(op(letvars)) {
       case ((arg, letvar), (accCons, stUpdatedBefore)) =>
-        val (argCons, stUpdateFlag) = mapBody(arg)
+        val (argCons, stUpdateFlag) = mapExpr(arg)
         val cl = if (!stUpdateFlag) {
           // here arg does not affect the newstate
           (st: Option[Expr]) => replace(Map(letvar -> argCons(st)), accCons(st))
@@ -541,13 +561,6 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
               val narg = argCons(st)
               val argres = FreshIdentifier("a", narg.getType, true).toVariable
               val nstate = Some(TupleSelect(argres, 2))
-              /*val nstateSeq = tnames.zipWithIndex.map {
-                // states start from index 2
-                case (tn, i) => TupleSelect(argres, i + 2)
-              }
-              val nstate = (tnames zip nstateSeq).map {
-                case (tn, st) => (tn -> st)
-              }.toMap[String, Expr]*/
               val letbody =
                 if (stUpdatedBefore) accCons(nstate) // here, 'acc' already returns a superseeding state
                 else Tuple(Seq(accCons(nstate), nstate.get)) // here, 'acc; only returns the result
@@ -568,7 +581,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
   def assignBodiesToFunctions = funMap foreach {
     case (fd, nfd) =>
       //println("Considering function: "+fd)
-      // Here, using name to identify 'state' parameters      
+      // Here, using name to identify 'state' parameters
       val stateParam = nfd.params.collectFirst {
         case vd if isStateParam(vd.id) =>
           vd.id.toVariable
@@ -578,7 +591,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       val stTparams = nfd.tparams.collect{
         case tpd if isPlaceHolderTParam(tpd.tp) => tpd.tp
       }
-      val (nbodyFun, bodyUpdatesState) = mapBody(fd.body.get)(stTparams)
+      val (nbodyFun, bodyUpdatesState) = mapExpr(fd.body.get)(stTparams, false)
       val nbody = nbodyFun(stateParam)
       val bodyWithState =
         if (!bodyUpdatesState && funsRetStates(fd))
@@ -593,7 +606,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       // This guarantees their observational purity/transparency
       // collect class invariants that need to be added
       if (fd.hasPrecondition) {
-        val (npreFun, preUpdatesState) = mapBody(fd.precondition.get)(stTparams)
+        val (npreFun, preUpdatesState) = mapExpr(fd.precondition.get)(stTparams, true)
         nfd.precondition =
           if (preUpdatesState)
             Some(TupleSelect(npreFun(stateParam), 1)) // ignore state updated by pre
@@ -657,7 +670,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
             case e => e
           }(post)
           // thread state through postcondition
-          val (npostFun, postUpdatesState) = mapBody(tpost)(stTparams)
+          val (npostFun, postUpdatesState) = mapExpr(tpost)(stTparams, true)
           val resval =
             if (bodyUpdatesState || funsRetStates(fd))
               TupleSelect(newres.toVariable, 1)
@@ -678,6 +691,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
 
   def assignContractsForEvals = evalFunctions.foreach {
     case (tname, evalfd) =>
+      val ismem = closureFactory.isMemType(tname)
       val cdefs = closureFactory.closures(tname)
       val recvTparams = getTypeParameters(evalfd.params.head.getType)
       val postres = FreshIdentifier("res", evalfd.returnType)
@@ -689,12 +703,18 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
         val binder = FreshIdentifier("t", ctype)
         val pattern = InstanceOfPattern(Some(binder), ctype)
         // t.clres == res._1
-        val clresField = cdef.fields.last
-        val clause1 = Equals(TupleSelect(postres.toVariable, 1),
-          CaseClassSelector(ctype, binder.toVariable, clresField.id))
+        val clause1 = if(ismem) {
+          val clresField = cdef.fields.last
+          Equals(TupleSelect(postres.toVariable, 1),
+            CaseClassSelector(ctype, binder.toVariable, clresField.id))
+        } else
+          Util.tru
         //res._1 == uifun(args)
         val clause2 = if (takesStateButIndep(op)) {
-          val args = cdef.fields.dropRight(1) map {
+          val flds =
+            if (!ismem) cdef.fields.dropRight(1)
+            else cdef.fields
+          val args = flds map {
             fld => CaseClassSelector(ctype, binder.toVariable, fld.id)
           }
           Some(Equals(TupleSelect(postres.toVariable, 1),
diff --git a/src/main/scala/leon/laziness/LazyClosureFactory.scala b/src/main/scala/leon/laziness/LazyClosureFactory.scala
index 91a33252161cad2187f75ab24086d039aa9c2aaf..49151ed151946c50fc984aefc834672d9a6f410b 100644
--- a/src/main/scala/leon/laziness/LazyClosureFactory.scala
+++ b/src/main/scala/leon/laziness/LazyClosureFactory.scala
@@ -32,39 +32,49 @@ import LazinessUtil._
 class LazyClosureFactory(p: Program) {
   val debug = false
   implicit val prog = p
+
+  /**
+   * all the operations that could be lazily evaluated
+   */
+  val lazyopsList = p.definedFunctions.flatMap {
+    case fd if (fd.hasBody) =>
+      filter(isLazyInvocation)(fd.body.get) map {
+        case FunctionInvocation(_, Seq(FunctionInvocation(tfd, _))) => tfd.fd
+      }
+    case _ => Seq()
+  }.distinct
+
+  if (debug) {
+    println("Lazy operations found: \n" + lazyopsList.map(_.id).mkString("\n"))
+  }
+
   /**
-   * Create a mapping from types to the lazyops that may produce a value of that type
+   * Create a mapping from types to the lazy/mem ops that may produce a value of that type
    * TODO: relax the requirement that type parameters of return type of a function
-   * lazy evaluated should include all of its type parameters
+   * lazy evaluated/memoized should include all of its type parameters.
    */
-  private val (tpeToADT, opToCaseClass) = {
-    // collect all the operations that could be lazily evaluated.
-    val lazyops = p.definedFunctions.flatMap {
-      case fd if (fd.hasBody) =>
-        filter(isLazyInvocation)(fd.body.get) map {
-          case FunctionInvocation(_, Seq(FunctionInvocation(tfd, _))) => tfd.fd
-        }
-      case _ => Seq()
-    }.distinct
-    if (debug) {
-      println("Lazy operations found: \n" + lazyops.map(_.id).mkString("\n"))
-    }
+  private def closuresForOps(ops: List[FunDef]) = {
     // using tpe name below to avoid mismatches due to type parameters
-    val tpeToLazyops = lazyops.groupBy(lops => typeNameWOParams(lops.returnType))
-    if(debug) {
-      println("Type to lazy ops: "+tpeToLazyops.map{
-        case (k,v) => s"$k --> ${v.map(_.id).mkString(",")}" }.mkString("\n"))
+    val tpeToLazyops = ops.groupBy(lop => typeNameWOParams(lop.returnType))
+    if (debug) {
+      println("Type to Ops: " + tpeToLazyops.map {
+        case (k, v) => s"$k --> ${v.map(_.id).mkString(",")}"
+      }.mkString("\n"))
     }
     val tpeToAbsClass = tpeToLazyops.map {
       case (tpename, ops) =>
         val tpcount = getTypeParameters(ops(0).returnType).size
-        // check that tparams of all ops should match and should be equal to the tparams of return type
-        // a safety check
+        //Safety check:
+        // (a) check that tparams of all ops should match and should be equal to the tparams of return type
+        // (b) all are either memoized or all are lazy
         ops.foreach { op =>
           if (op.tparams.size != tpcount)
-            throw new IllegalStateException(s"Type parameters of the lazy operation ${op.id.name}" +
+            throw new IllegalStateException(s"Type parameters of the lazy/memoized operation ${op.id.name}" +
               "should match the type parameters of the return type of the operation")
         }
+        if(ops.size >= 2) {
+          ops.tail.forall(op => isMemoized(op) == isMemoized(ops.head))
+        }
         val absTParams = (1 to tpcount).map(i => TypeParameterDef(TypeParameter.fresh("T" + i)))
         tpename -> AbstractClassDef(FreshIdentifier(typeNameToADTName(tpename), Untyped),
           absTParams, None)
@@ -72,6 +82,7 @@ class LazyClosureFactory(p: Program) {
     var opToAdt = Map[FunDef, CaseClassDef]()
     val tpeToADT = tpeToLazyops map {
       case (tpename, ops) =>
+        val ismem = isMemoized(ops(0))
         val baseT = ops(0).returnType //TODO: replace targs here i.e, use clresType ?
         val absClass = tpeToAbsClass(tpename)
         val absTParamsDef = absClass.tparams
@@ -92,26 +103,32 @@ class LazyClosureFactory(p: Program) {
                 val btname = typeNameWOParams(btype)
                 val baseAbs = tpeToAbsClass(btname)
                 ValDef(FreshIdentifier(vd.id.name,
-                    AbstractClassType(baseAbs, getTypeParameters(btype))))
+                  AbstractClassType(baseAbs, getTypeParameters(btype))))
             }
           }
-          // add a result field as well
-          val resField = ValDef(FreshIdentifier("clres", opfd.returnType))
-          cdef.setFields(nfields :+ resField)
+          if (!ismem) {
+            // add a result field as well
+            val resField = ValDef(FreshIdentifier("clres", opfd.returnType))
+            cdef.setFields(nfields :+ resField)
+          } else
+            cdef.setFields(nfields)
           absClass.registerChild(cdef)
           opToAdt += (opfd -> cdef)
           cdef
         }
-        // create a case class to represent eager evaluation
-        val clresType = ops(0).returnType match {
-          case NAryType(tparams, tcons) => tcons(absTParams)
-        }
-        val eagerid = FreshIdentifier("Eager"+TypeUtil.typeNameWOParams(clresType))
-        val eagerClosure = CaseClassDef(eagerid, absTParamsDef,
+        if (!ismem) {
+          // create a case class to represent eager evaluation (when handling lazy ops)
+          val clresType = ops(0).returnType match {
+            case NAryType(tparams, tcons) => tcons(absTParams)
+          }
+          val eagerid = FreshIdentifier("Eager" + TypeUtil.typeNameWOParams(clresType))
+          val eagerClosure = CaseClassDef(eagerid, absTParamsDef,
             Some(AbstractClassType(absClass, absTParams)), isCaseObject = false)
-        eagerClosure.setFields(Seq(ValDef(FreshIdentifier("a", clresType))))
-        absClass.registerChild(eagerClosure)
-        (tpename -> (baseT, absClass, cdefs, eagerClosure))
+          eagerClosure.setFields(Seq(ValDef(FreshIdentifier("a", clresType))))
+          absClass.registerChild(eagerClosure)
+          (tpename -> (baseT, absClass, cdefs, Some(eagerClosure), ismem))
+        } else
+          (tpename -> (baseT, absClass, cdefs, None, ismem))
     }
     /*tpeToADT.foreach {
       case (k, v) => println(s"$k --> ${ (v._2 +: v._3).mkString("\n\t") }")
@@ -119,38 +136,31 @@ class LazyClosureFactory(p: Program) {
     (tpeToADT, opToAdt)
   }
 
+  private val (tpeToADT, opToCaseClass) = closuresForOps(lazyopsList)
+
   // this fixes an ordering on lazy types
   val lazyTypeNames = tpeToADT.keys.toSeq
-
   val lazyops = opToCaseClass.keySet
-
-  val allClosuresAndParents : Seq[ClassDef] = tpeToADT.values.flatMap(v => v._2 +: v._3 :+ v._4).toSeq
-
+  lazy val caseClassToOp = opToCaseClass map { case (k, v) => v -> k }
+  val allClosuresAndParents: Seq[ClassDef] = tpeToADT.values.flatMap(v => (v._2 +: v._3) ++ v._4.toList).toSeq
   val allClosureSet = allClosuresAndParents.toSet
 
+  // lazy operations
   def lazyType(tn: String) = tpeToADT(tn)._1
-
+  def isMemType(tn: String) = tpeToADT(tn)._5
   def absClosureType(tn: String) = tpeToADT(tn)._2
-
   def closures(tn: String) = tpeToADT(tn)._3
-
   def eagerClosure(tn: String) = tpeToADT(tn)._4
-
-  lazy val caseClassToOp = opToCaseClass map { case (k, v) => v -> k }
-
   def lazyopOfClosure(cl: CaseClassDef) = caseClassToOp(cl)
-
   def closureOfLazyOp(op: FunDef) = opToCaseClass(op)
-
   def isLazyOp(op: FunDef) = opToCaseClass.contains(op)
-
   def isClosureType(cd: ClassDef) = allClosureSet.contains(cd)
 
   /**
    * Here, the lazy type name is recovered from the closure's name.
    * This avoids the use of additional maps.
    */
-  def lazyTypeNameOfClosure(cl: CaseClassDef) =  adtNameToTypeName(cl.parent.get.classDef.id.name)
+  def lazyTypeNameOfClosure(cl: CaseClassDef) = adtNameToTypeName(cl.parent.get.classDef.id.name)
 
   /**
    * Define a state as an ADT whose fields are sets of closures.
@@ -162,7 +172,7 @@ class LazyClosureFactory(p: Program) {
     def freshTParams(n: Int): Seq[TypeParameter] = {
       val start = i + 1
       i += n // create 'n' fresh ids
-      val nparams = (start to i).map(index => TypeParameter.fresh("T"+index))
+      val nparams = (start to i).map(index => TypeParameter.fresh("T" + index))
       tparams ++= nparams
       nparams
     }
@@ -180,7 +190,7 @@ class LazyClosureFactory(p: Program) {
 
   def selectFieldOfState(tn: String, st: Expr, stType: CaseClassType) = {
     val selName = typeToFieldName(tn)
-    stType.classDef.fields.find{ fld => fld.id.name ==  selName} match {
+    stType.classDef.fields.find { fld => fld.id.name == selName } match {
       case Some(fld) =>
         CaseClassSelector(stType, st, fld.id)
       case _ =>
@@ -188,22 +198,22 @@ class LazyClosureFactory(p: Program) {
     }
   }
 
-  val stateUpdateFuns : Map[String, FunDef] =
-    lazyTypeNames.map{ tn =>
+  val stateUpdateFuns: Map[String, FunDef] =
+    lazyTypeNames.map { tn =>
       val fldname = typeToFieldName(tn)
       val tparams = state.tparams.map(_.tp)
       val stType = CaseClassType(state, tparams)
       val param1 = FreshIdentifier("st@", stType)
-      val SetType(baseT) = stType.classDef.fields.find{ fld => fld.id.name == fldname}.get.getType
+      val SetType(baseT) = stType.classDef.fields.find { fld => fld.id.name == fldname }.get.getType
       val param2 = FreshIdentifier("cl", baseT)
 
       // TODO: as an optimization we can mark all these functions as inline and inline them at their callees
-      val updateFun = new FunDef(FreshIdentifier("updState"+tn),
-          state.tparams, Seq(ValDef(param1), ValDef(param2)), stType)
+      val updateFun = new FunDef(FreshIdentifier("updState" + tn),
+        state.tparams, Seq(ValDef(param1), ValDef(param2)), stType)
       // create a body for the updateFun:
-      val nargs = state.fields.map{ fld =>
+      val nargs = state.fields.map { fld =>
         val fldSelect = CaseClassSelector(stType, param1.toVariable, fld.id)
-        if(fld.id.name == fldname) {
+        if (fld.id.name == fldname) {
           SetUnion(fldSelect, FiniteSet(Set(param2.toVariable), baseT)) // st@.tn + Set(param2)
         } else {
           fldSelect
diff --git a/testcases/lazy-datastructures/memoization/FibonacciMemoized.scala b/testcases/lazy-datastructures/memoization/FibonacciMemoized.scala
index 385c1498feb848fe4905eea2b859142c572fc009..786c392b6f1f87410025fb25d63c048ea50934a9 100644
--- a/testcases/lazy-datastructures/memoization/FibonacciMemoized.scala
+++ b/testcases/lazy-datastructures/memoization/FibonacciMemoized.scala
@@ -4,28 +4,25 @@ import leon.lazyeval._
 import leon.lang._
 import leon.annotation._
 import leon.instrumentation._
-import scala.math.BigInt.int2bigInt
 //import leon.invariant._
 
 object FibMem {
-
-  /**
-   * A simple non-lazy list of integers
-   */
   sealed abstract class IList
   case class Cons(x: BigInt, tail: IList) extends IList
   case class Nil() extends IList
 
+  @memoize
   def fibRec(n: BigInt): BigInt = {
-    require(n <= 2 || ($(fibRec(n-1)).isEvaluated && // previous two values have been evaluated
-        $(fibRec(n-2)).isEvaluated))
+    require(n >= 0)
         if(n <= 2)
           BigInt(1)
         else
-          fibRec(n-1) + fibRec(n-2)
-  } ensuring(_ => time <= 50)
+          fibRec(n-1) + fibRec(n-2) // postcondition implies that the second call would be cached
+  } ensuring(_ =>
+    (n <= 2 || ($(fibRec(n-1)).isEvaluated &&
+        $(fibRec(n-2)).isEvaluated))  && time <= 40*n + 10)
 
-  def fibRange(i: BigInt, k: BigInt): IList = {
+  /*def fibRange(i: BigInt, k: BigInt): IList = {
     require(k >= 1 && i <= k &&
         (i <= 1 ||
         (($(fibRec(i-1)).isEvaluated) &&
@@ -33,7 +30,7 @@ object FibMem {
     if(i == k)
       Cons(fibRec(i), Nil())
     else {
-      val x = $(fibRec(i)).value
+      val x = fibRec(i)
       Cons(x, fibRange(i + 1, k))
     }
   } ensuring(_ => time <= (k - i + 1) * 60)
@@ -41,5 +38,5 @@ object FibMem {
   def kfibs(k: BigInt) = {
     require(k >= 1)
     fibRange(1, k)
-  } ensuring(_ => time <= 70 * k)
+  } ensuring(_ => time <= 70 * k)*/
 }