From 0fc04443a07af9a22c765c7ce92980c2e72954f1 Mon Sep 17 00:00:00 2001 From: Regis Blanc <regwblanc@gmail.com> Date: Thu, 22 Oct 2015 14:28:40 +0200 Subject: [PATCH] test evaluation order of function arguments --- .../xlang/ImperativeCodeElimination.scala | 18 +++++++++++---- .../valid/FunInvocEvaluationOrder1.scala | 22 +++++++++++++++++++ .../valid/FunInvocEvaluationOrder2.scala | 17 ++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder1.scala create mode 100644 src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder2.scala diff --git a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala index 7a00cb7f8..2f8b89796 100644 --- a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala +++ b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala @@ -230,6 +230,15 @@ object ImperativeCodeElimination extends UnitPhase[Program] { //a function invocation can update variables in scope. case fi@FunctionInvocation(tfd, args) => + + + val (recArgs, argScope, argFun) = args.foldRight((Seq[Expr](), (body: Expr) => body, Map[Identifier, Identifier]()))((arg, acc) => { + val (accArgs, accScope, accFun) = acc + val (argVal, argScope, argFun) = toFunction(arg) + val newScope = (body: Expr) => argScope(replaceNames(argFun, accScope(body))) + (argVal +: accArgs, newScope, argFun ++ accFun) + }) + val fd = tfd.fd state.funDefsMapping.get(fd) match { case Some((newFd, modifiedVars)) => { @@ -238,16 +247,17 @@ object ImperativeCodeElimination extends UnitPhase[Program] { val tmpTuple = FreshIdentifier("t", newFd.returnType) val scope = (body: Expr) => { - Let(tmpTuple, newInvoc, + argScope(Let(tmpTuple, newInvoc, freshNames.zipWithIndex.foldRight(body)((p, b) => Let(p._1, TupleSelect(tmpTuple.toVariable, p._2 + 2), b)) - ) + )) } - val newMap = modifiedVars.zip(freshNames).toMap + val newMap = modifiedVars.zip(freshNames).toMap ++ argFun (TupleSelect(tmpTuple.toVariable, 1), scope, newMap) } - case None => (fi, x => x, Map()) + case None => + (FunctionInvocation(tfd, recArgs).copiedFrom(fi), argScope, argFun) } diff --git a/src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder1.scala b/src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder1.scala new file mode 100644 index 000000000..8ef668a2a --- /dev/null +++ b/src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder1.scala @@ -0,0 +1,22 @@ +object FunInvocEvaluationOrder1 { + + def test(): Int = { + + var res = 10 + justAddingStuff({ + res += 1 + res + }, { + res *= 2 + res + }, { + res += 10 + res + }) + + res + } ensuring(_ == 32) + + def justAddingStuff(x: Int, y: Int, z: Int): Int = x + y + z + +} diff --git a/src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder2.scala b/src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder2.scala new file mode 100644 index 000000000..12090f0f3 --- /dev/null +++ b/src/test/resources/regression/verification/xlang/valid/FunInvocEvaluationOrder2.scala @@ -0,0 +1,17 @@ +object FunInvocEvaluationOrder2 { + + def leftToRight(n: BigInt): BigInt = { + require(n > 0) + + var a = BigInt(0) + + def nested(x: BigInt, y: BigInt): BigInt = { + require(y >= x) + x + y + } + + nested({a += 10; a}, {a *= 2; a}) + + } ensuring(_ == 30) + +} -- GitLab