Skip to content
Snippets Groups Projects
Commit f85c484b authored by Régis Blanc's avatar Régis Blanc
Browse files

merge closure and hoisting. fix wrong id when accessing let value defined with...

merge closure and hoisting. fix wrong id when accessing let value defined with more than 1 level higher
parent 41a7ba30
No related branches found
No related tags found
No related merge requests found
...@@ -6,7 +6,7 @@ failedtests="" ...@@ -6,7 +6,7 @@ failedtests=""
for f in testcases/regression/valid/*.scala; do for f in testcases/regression/valid/*.scala; do
echo -n "Running $f, expecting VALID, got: " echo -n "Running $f, expecting VALID, got: "
res=`./leon --timeout=5 --oneline "$f"` res=`./leon --timeout=10 --oneline "$f"`
echo $res | tr [a-z] [A-Z] echo $res | tr [a-z] [A-Z]
if [ $res = valid ]; then if [ $res = valid ]; then
nbsuccess=$((nbsuccess + 1)) nbsuccess=$((nbsuccess + 1))
...@@ -17,7 +17,7 @@ done ...@@ -17,7 +17,7 @@ done
for f in testcases/regression/invalid/*.scala; do for f in testcases/regression/invalid/*.scala; do
echo -n "Running $f, expecting INVALID, got: " echo -n "Running $f, expecting INVALID, got: "
res=`./leon --timeout=5 --oneline "$f"` res=`./leon --timeout=10 --oneline "$f"`
echo $res | tr [a-z] [A-Z] echo $res | tr [a-z] [A-Z]
if [ $res = invalid ]; then if [ $res = invalid ]; then
nbsuccess=$((nbsuccess + 1)) nbsuccess=$((nbsuccess + 1))
...@@ -28,7 +28,7 @@ done ...@@ -28,7 +28,7 @@ done
for f in testcases/regression/error/*.scala; do for f in testcases/regression/error/*.scala; do
echo -n "Running $f, expecting ERROR, got: " echo -n "Running $f, expecting ERROR, got: "
res=`./leon --timeout=5 --oneline "$f"` res=`./leon --timeout=10 --oneline "$f"`
echo $res | tr [a-z] [A-Z] echo $res | tr [a-z] [A-Z]
if [ $res = error ]; then if [ $res = error ]; then
nbsuccess=$((nbsuccess + 1)) nbsuccess=$((nbsuccess + 1))
......
...@@ -12,6 +12,8 @@ object FunctionClosure extends Pass { ...@@ -12,6 +12,8 @@ object FunctionClosure extends Pass {
private var pathConstraints: List[Expr] = Nil private var pathConstraints: List[Expr] = Nil
private var enclosingLets: List[(Identifier, Expr)] = Nil private var enclosingLets: List[(Identifier, Expr)] = Nil
private var newFunDefs: Map[FunDef, FunDef] = Map() private var newFunDefs: Map[FunDef, FunDef] = Map()
private var originalsIds: Map[Identifier, Identifier] = Map()
private var topLevelFuns: Set[FunDef] = Set()
def apply(program: Program): Program = { def apply(program: Program): Program = {
newFunDefs = Map() newFunDefs = Map()
...@@ -20,7 +22,8 @@ object FunctionClosure extends Pass { ...@@ -20,7 +22,8 @@ object FunctionClosure extends Pass {
pathConstraints = fd.precondition.toList pathConstraints = fd.precondition.toList
fd.body = fd.body.map(b => functionClosure(b, fd.args.map(_.id).toSet, Map(), Map())) fd.body = fd.body.map(b => functionClosure(b, fd.args.map(_.id).toSet, Map(), Map()))
}) })
program val Program(id, ObjectDef(objId, defs, invariants)) = program
Program(id, ObjectDef(objId, defs ++ topLevelFuns, invariants))
} }
private def functionClosure(expr: Expr, bindedVars: Set[Identifier], id2freshId: Map[Identifier, Identifier], fd2FreshFd: Map[FunDef, (FunDef, Seq[Variable])]): Expr = expr match { private def functionClosure(expr: Expr, bindedVars: Set[Identifier], id2freshId: Map[Identifier, Identifier], fd2FreshFd: Map[FunDef, (FunDef, Seq[Variable])]): Expr = expr match {
...@@ -29,6 +32,7 @@ object FunctionClosure extends Pass { ...@@ -29,6 +32,7 @@ object FunctionClosure extends Pass {
val capturedConstraints: Set[Expr] = pathConstraints.toSet val capturedConstraints: Set[Expr] = pathConstraints.toSet
val freshIds: Map[Identifier, Identifier] = capturedVars.map(id => (id, FreshIdentifier(id.name).setType(id.getType))).toMap val freshIds: Map[Identifier, Identifier] = capturedVars.map(id => (id, FreshIdentifier(id.name).setType(id.getType))).toMap
freshIds.foreach(p => originalsIds += (p._2 -> p._1))
val freshVars: Map[Expr, Expr] = freshIds.map(p => (p._1.toVariable, p._2.toVariable)) val freshVars: Map[Expr, Expr] = freshIds.map(p => (p._1.toVariable, p._2.toVariable))
val extraVarDeclOldIds: Seq[Identifier] = capturedVars.toSeq val extraVarDeclOldIds: Seq[Identifier] = capturedVars.toSeq
...@@ -39,6 +43,7 @@ object FunctionClosure extends Pass { ...@@ -39,6 +43,7 @@ object FunctionClosure extends Pass {
val newFunId = FreshIdentifier(fd.id.name) val newFunId = FreshIdentifier(fd.id.name)
val newFunDef = new FunDef(newFunId, fd.returnType, newVarDecls).setPosInfo(fd) val newFunDef = new FunDef(newFunId, fd.returnType, newVarDecls).setPosInfo(fd)
topLevelFuns += newFunDef
newFunDef.fromLoop = fd.fromLoop newFunDef.fromLoop = fd.fromLoop
newFunDef.parent = fd.parent newFunDef.parent = fd.parent
newFunDef.addAnnotation(fd.annotations.toSeq:_*) newFunDef.addAnnotation(fd.annotations.toSeq:_*)
...@@ -57,11 +62,11 @@ object FunctionClosure extends Pass { ...@@ -57,11 +62,11 @@ object FunctionClosure extends Pass {
val freshRest = functionClosure(rest, bindedVars, id2freshId, fd2FreshFd + (fd -> val freshRest = functionClosure(rest, bindedVars, id2freshId, fd2FreshFd + (fd ->
((newFunDef, extraVarDeclOldIds.map(id => id2freshId.get(id).getOrElse(id).toVariable))))) ((newFunDef, extraVarDeclOldIds.map(id => id2freshId.get(id).getOrElse(id).toVariable)))))
LetDef(newFunDef, freshRest).setType(l.getType) freshRest.setType(l.getType)
} }
case l @ Let(i,e,b) => { case l @ Let(i,e,b) => {
val re = functionClosure(e, bindedVars, id2freshId, fd2FreshFd) val re = functionClosure(e, bindedVars, id2freshId, fd2FreshFd)
enclosingLets ::= (i, re) enclosingLets ::= (i, replace(originalsIds.map(p => (p._1.toVariable, p._2.toVariable)), re))
//pathConstraints :: Equals(i.toVariable, re) //pathConstraints :: Equals(i.toVariable, re)
val rb = functionClosure(b, bindedVars + i, id2freshId, fd2FreshFd) val rb = functionClosure(b, bindedVars + i, id2freshId, fd2FreshFd)
enclosingLets = enclosingLets.tail enclosingLets = enclosingLets.tail
...@@ -106,8 +111,10 @@ object FunctionClosure extends Pass { ...@@ -106,8 +111,10 @@ object FunctionClosure extends Pass {
} }
case v @ Variable(id) => id2freshId.get(id) match { case v @ Variable(id) => id2freshId.get(id) match {
case None => replace( case None => replace(
id2freshId.map(p => (p._1.toVariable, p._2.toVariable)).toMap, id2freshId.map(p => (p._1.toVariable, p._2.toVariable)),
enclosingLets.foldLeft(v: Expr){ case (expr, (id, value)) => replace(Map(id.toVariable -> value), expr) }) enclosingLets.foldLeft(v: Expr){
case (expr, (id, value)) => replace(Map(id.toVariable -> value), expr)
})
case Some(nid) => Variable(nid) case Some(nid) => Variable(nid)
} }
case t if t.isInstanceOf[Terminal] => t case t if t.isInstanceOf[Terminal] => t
......
...@@ -32,7 +32,7 @@ object Main { ...@@ -32,7 +32,7 @@ object Main {
private def defaultAction(program: Program, reporter: Reporter) : Unit = { private def defaultAction(program: Program, reporter: Reporter) : Unit = {
Logger.debug("Default action on program: " + program, 3, "main") Logger.debug("Default action on program: " + program, 3, "main")
val passManager = new PassManager(Seq(ArrayTransformation, EpsilonElimination, ImperativeCodeElimination, /*UnitElimination,*/ FunctionClosure, FunctionHoisting, Simplificator)) val passManager = new PassManager(Seq(ArrayTransformation, EpsilonElimination, ImperativeCodeElimination, /*UnitElimination,*/ FunctionClosure, /*FunctionHoisting,*/ Simplificator))
val program2 = passManager.run(program) val program2 = passManager.run(program)
assert(program2.isPure) assert(program2.isPure)
val analysis = new Analysis(program2, reporter) val analysis = new Analysis(program2, reporter)
......
object Nested4 {
def foo(a: Int, a2: Int): Int = {
require(a >= 0 && a <= 50)
val b = a + 2
val c = a + b
if(a2 > a) {
def rec1(d: Int): Int = {
require(d >= 0 && d <= 50)
val e = d + b + c + a2
def rec2(f: Int): Int = {
require(f >= c)
f + e
} ensuring(_ > 0)
rec2(c+1)
} ensuring(_ > 0)
rec1(2)
} else {
5
}
} ensuring(_ > 0)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment