From 6dad0efb71a93a0e001578b542187add6fe5d36a Mon Sep 17 00:00:00 2001 From: Regis Blanc <regwblanc@gmail.com> Date: Wed, 6 Jan 2016 16:33:01 +0100 Subject: [PATCH] improve mapping with context --- src/main/scala/leon/purescala/ExprOps.scala | 17 +++++++++++--- .../leon/unit/purescala/ExprOpsSuite.scala | 22 +++++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala index 6623d1248..92ce18e2c 100644 --- a/src/main/scala/leon/purescala/ExprOps.scala +++ b/src/main/scala/leon/purescala/ExprOps.scala @@ -221,13 +221,24 @@ object ExprOps { * the recursion in its children. The context is "lost" when going back up, * so changes made by one node will not be see by its siblings. */ - def preMapWithContext[C](f: (Expr, C) => (Option[Expr], C))(e: Expr, c: C): Expr = { + def preMapWithContext[C](f: (Expr, C) => (Option[Expr], C), applyRec: Boolean = false) + (e: Expr, c: C): Expr = { def rec(expr: Expr, context: C): Expr = { val (newV, newCtx) = { - val res = f(expr, context) - (res._1.getOrElse(expr), res._2) + if(applyRec) { + var ctx = context + val finalV = fixpoint{ e: Expr => { + val res = f(e, ctx) + ctx = res._2 + res._1.getOrElse(e) + }} (expr) + (finalV, ctx) + } else { + val res = f(expr, context) + (res._1.getOrElse(expr), res._2) + } } val Operator(es, builder) = newV diff --git a/src/test/scala/leon/unit/purescala/ExprOpsSuite.scala b/src/test/scala/leon/unit/purescala/ExprOpsSuite.scala index 10b64f75a..827596fc6 100644 --- a/src/test/scala/leon/unit/purescala/ExprOpsSuite.scala +++ b/src/test/scala/leon/unit/purescala/ExprOpsSuite.scala @@ -289,7 +289,8 @@ class ExprOpsSuite extends LeonTestSuite with helpers.WithLikelyEq with helpers. case _ => (None, set) } - assert(preMapWithContext(op)(expr, Set()) === Plus(bi(2), bi(2))) + assert(preMapWithContext(op, false)(expr, Set()) === Plus(bi(2), bi(2))) + assert(preMapWithContext(op, true)(expr, Set()) === Plus(bi(42), bi(42))) val expr2 = Let(x.id, bi(1), Let(y.id, bi(2), Plus(x, y))) def op2(e: Expr, bindings: Map[Identifier, BigInt]): (Option[Expr], Map[Identifier, BigInt]) = e match { @@ -298,7 +299,24 @@ class ExprOpsSuite extends LeonTestSuite with helpers.WithLikelyEq with helpers. case _ => (None, bindings) } - assert(preMapWithContext(op2)(expr2, Map()) === Let(x.id, bi(1), Let(y.id, bi(2), Plus(bi(1), bi(2))))) + assert(preMapWithContext(op2, false)(expr2, Map()) === Let(x.id, bi(1), Let(y.id, bi(2), Plus(bi(1), bi(2))))) + + def op3(e: Expr, bindings: Map[Identifier, BigInt]): (Option[Expr], Map[Identifier, BigInt]) = e match { + case Let(id, InfiniteIntegerLiteral(v), body) => (Some(body), bindings + (id -> v)) + case Variable(id) => (bindings.get(id).map(v => InfiniteIntegerLiteral(v)), bindings) + case _ => (None, bindings) + } + assert(preMapWithContext(op3, true)(expr2, Map()) === Plus(bi(1), bi(2))) + + + val expr4 = Plus(Let(y.id, bi(2), y), + Let(y.id, bi(4), y)) + def op4(e: Expr, bindings: Map[Identifier, BigInt]): (Option[Expr], Map[Identifier, BigInt]) = e match { + case Let(id, InfiniteIntegerLiteral(v), body) => (Some(body), if(bindings.contains(id)) bindings else (bindings + (id -> v))) + case Variable(id) => (bindings.get(id).map(v => InfiniteIntegerLiteral(v)), bindings) + case _ => (None, bindings) + } + assert(preMapWithContext(op4, true)(expr4, Map()) === Plus(bi(2), bi(4))) } } -- GitLab