From 4cbc399d2d4c5618e5be7c6c464b4843f37c5d80 Mon Sep 17 00:00:00 2001 From: Regis Blanc <regwblanc@gmail.com> Date: Thu, 21 Jan 2016 17:37:56 +0100 Subject: [PATCH] workaround for xlang (non-)mutually rec letdefs --- .../xlang/ImperativeCodeElimination.scala | 154 +++++++++--------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala index ac9535783..45bb36770 100644 --- a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala +++ b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala @@ -218,88 +218,90 @@ object ImperativeCodeElimination extends UnitPhase[Program] { case LetDef(fds, b) => if(fds.size > 1) { - sys.error("Xlang does not support mutually recursive functions") - } + //TODO: no support for true mutually recursion + toFunction(LetDef(Seq(fds.head), LetDef(fds.tail, b))) + } else { - val fd = fds.head + val fd = fds.head - def fdWithoutSideEffects = { - fd.body.foreach { bd => - val (fdRes, fdScope, _) = toFunction(bd) - fd.body = Some(fdScope(fdRes)) + def fdWithoutSideEffects = { + fd.body.foreach { bd => + val (fdRes, fdScope, _) = toFunction(bd) + fd.body = Some(fdScope(fdRes)) + } + val (bodyRes, bodyScope, bodyFun) = toFunction(b) + (bodyRes, (b2: Expr) => LetDef(Seq(fd), bodyScope(b2)).setPos(fd).copiedFrom(expr), bodyFun) } - val (bodyRes, bodyScope, bodyFun) = toFunction(b) - (bodyRes, (b2: Expr) => LetDef(Seq(fd), bodyScope(b2)).setPos(fd).copiedFrom(expr), bodyFun) - } - fd.body match { - case Some(bd) => { - - val modifiedVars: List[Identifier] = - collect[Identifier]({ - case Assignment(v, _) => Set(v) - case FunctionInvocation(tfd, _) => state.funDefsMapping.get(tfd.fd).map(p => p._2.toSet).getOrElse(Set()) - case _ => Set() - })(bd).intersect(state.varsInScope).toList - - if(modifiedVars.isEmpty) fdWithoutSideEffects else { - - val freshNames: List[Identifier] = modifiedVars.map(id => id.freshen) - - val newParams: Seq[ValDef] = fd.params ++ freshNames.map(n => ValDef(n)) - val freshVarDecls: List[Identifier] = freshNames.map(id => id.freshen) - - val rewritingMap: Map[Identifier, Identifier] = - modifiedVars.zip(freshVarDecls).toMap - val freshBody = - preMap({ - case Assignment(v, e) => rewritingMap.get(v).map(nv => Assignment(nv, e)) - case Variable(id) => rewritingMap.get(id).map(nid => Variable(nid)) - case _ => None - })(bd) - val wrappedBody = freshNames.zip(freshVarDecls).foldLeft(freshBody)((body, p) => { - LetVar(p._2, Variable(p._1), body) - }) - - val newReturnType = TupleType(fd.returnType :: modifiedVars.map(_.getType)) - - val newFd = new FunDef(fd.id.freshen, fd.tparams, newParams, newReturnType).setPos(fd) - newFd.addFlags(fd.flags) - - val (fdRes, fdScope, fdFun) = - toFunction(wrappedBody)( - State(state.parent, - Set(), - state.funDefsMapping.map{case (fd, (nfd, mvs)) => (fd, (nfd, mvs.map(v => rewritingMap.getOrElse(v, v))))} + - (fd -> ((newFd, freshVarDecls)))) - ) - val newRes = Tuple(fdRes :: freshVarDecls.map(vd => fdFun(vd).toVariable)) - val newBody = fdScope(newRes) - - newFd.body = Some(newBody) - newFd.precondition = fd.precondition.map(prec => { - replace(modifiedVars.zip(freshNames).map(p => (p._1.toVariable, p._2.toVariable)).toMap, prec) - }) - newFd.postcondition = fd.postcondition.map(post => { - val Lambda(Seq(res), postBody) = post - val newRes = ValDef(FreshIdentifier(res.id.name, newFd.returnType)) - - val newBody = - replace( - modifiedVars.zipWithIndex.map{ case (v, i) => - (v.toVariable, TupleSelect(newRes.toVariable, i+2)): (Expr, Expr)}.toMap ++ - modifiedVars.zip(freshNames).map{ case (ov, nv) => - (Old(ov), nv.toVariable)}.toMap + - (res.toVariable -> TupleSelect(newRes.toVariable, 1)), - postBody) - Lambda(Seq(newRes), newBody).setPos(post) - }) - - val (bodyRes, bodyScope, bodyFun) = toFunction(b)(state.withFunDef(fd, newFd, modifiedVars)) - (bodyRes, (b2: Expr) => LetDef(Seq(newFd), bodyScope(b2)).copiedFrom(expr), bodyFun) + fd.body match { + case Some(bd) => { + + val modifiedVars: List[Identifier] = + collect[Identifier]({ + case Assignment(v, _) => Set(v) + case FunctionInvocation(tfd, _) => state.funDefsMapping.get(tfd.fd).map(p => p._2.toSet).getOrElse(Set()) + case _ => Set() + })(bd).intersect(state.varsInScope).toList + + if(modifiedVars.isEmpty) fdWithoutSideEffects else { + + val freshNames: List[Identifier] = modifiedVars.map(id => id.freshen) + + val newParams: Seq[ValDef] = fd.params ++ freshNames.map(n => ValDef(n)) + val freshVarDecls: List[Identifier] = freshNames.map(id => id.freshen) + + val rewritingMap: Map[Identifier, Identifier] = + modifiedVars.zip(freshVarDecls).toMap + val freshBody = + preMap({ + case Assignment(v, e) => rewritingMap.get(v).map(nv => Assignment(nv, e)) + case Variable(id) => rewritingMap.get(id).map(nid => Variable(nid)) + case _ => None + })(bd) + val wrappedBody = freshNames.zip(freshVarDecls).foldLeft(freshBody)((body, p) => { + LetVar(p._2, Variable(p._1), body) + }) + + val newReturnType = TupleType(fd.returnType :: modifiedVars.map(_.getType)) + + val newFd = new FunDef(fd.id.freshen, fd.tparams, newParams, newReturnType).setPos(fd) + newFd.addFlags(fd.flags) + + val (fdRes, fdScope, fdFun) = + toFunction(wrappedBody)( + State(state.parent, + Set(), + state.funDefsMapping.map{case (fd, (nfd, mvs)) => (fd, (nfd, mvs.map(v => rewritingMap.getOrElse(v, v))))} + + (fd -> ((newFd, freshVarDecls)))) + ) + val newRes = Tuple(fdRes :: freshVarDecls.map(vd => fdFun(vd).toVariable)) + val newBody = fdScope(newRes) + + newFd.body = Some(newBody) + newFd.precondition = fd.precondition.map(prec => { + replace(modifiedVars.zip(freshNames).map(p => (p._1.toVariable, p._2.toVariable)).toMap, prec) + }) + newFd.postcondition = fd.postcondition.map(post => { + val Lambda(Seq(res), postBody) = post + val newRes = ValDef(FreshIdentifier(res.id.name, newFd.returnType)) + + val newBody = + replace( + modifiedVars.zipWithIndex.map{ case (v, i) => + (v.toVariable, TupleSelect(newRes.toVariable, i+2)): (Expr, Expr)}.toMap ++ + modifiedVars.zip(freshNames).map{ case (ov, nv) => + (Old(ov), nv.toVariable)}.toMap + + (res.toVariable -> TupleSelect(newRes.toVariable, 1)), + postBody) + Lambda(Seq(newRes), newBody).setPos(post) + }) + + val (bodyRes, bodyScope, bodyFun) = toFunction(b)(state.withFunDef(fd, newFd, modifiedVars)) + (bodyRes, (b2: Expr) => LetDef(Seq(newFd), bodyScope(b2)).copiedFrom(expr), bodyFun) + } } + case None => fdWithoutSideEffects } - case None => fdWithoutSideEffects } case c @ Choose(b) => -- GitLab