From bfc1abffb88d43197dd9463a280e9bf60666de98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Mayer?= <mikael.mayer@epfl.ch> Date: Mon, 25 Jan 2016 16:22:29 +0100 Subject: [PATCH] Abstract interpretation not failing if the function is not defined. Added the tree tests. --- .../leon/evaluators/AbstractEvaluator.scala | 9 +-- .../solvers/StringRenderSuite.scala | 62 +++++++++++++++---- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/main/scala/leon/evaluators/AbstractEvaluator.scala b/src/main/scala/leon/evaluators/AbstractEvaluator.scala index 52cdb94a1..12bfde020 100644 --- a/src/main/scala/leon/evaluators/AbstractEvaluator.scala +++ b/src/main/scala/leon/evaluators/AbstractEvaluator.scala @@ -74,11 +74,12 @@ class AbstractEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvalu val callResult = if ((evArgsValues forall ExprOps.isValue) && tfd.fd.annotations("extern") && ctx.classDir.isDefined) { (scalaEv.call(tfd, evArgsValues), FunctionInvocation(tfd, evArgsOrigin)) } else { - if(!tfd.hasBody && !rctx.mappings.isDefinedAt(tfd.id)) { - throw EvalError("Evaluation of function with unknown implementation.") + if((!tfd.hasBody && !rctx.mappings.isDefinedAt(tfd.id)) || tfd.body.exists(b => ExprOps.exists(e => e.isInstanceOf[Choose])(b))) { + (FunctionInvocation(tfd, evArgsValues), FunctionInvocation(tfd, evArgsOrigin)) + } else { + val body = tfd.body.getOrElse(rctx.mappings(tfd.id)) + e(body)(frame, gctx) } - val body = tfd.body.getOrElse(rctx.mappings(tfd.id)) - e(body)(frame, gctx) } callResult case Operator(es, builder) => diff --git a/src/test/scala/leon/integration/solvers/StringRenderSuite.scala b/src/test/scala/leon/integration/solvers/StringRenderSuite.scala index 8d294df9f..d642880c3 100644 --- a/src/test/scala/leon/integration/solvers/StringRenderSuite.scala +++ b/src/test/scala/leon/integration/solvers/StringRenderSuite.scala @@ -166,6 +166,24 @@ class StringRenderSuite extends LeonTestSuiteWithProgram with Matchers with Scal | case class Config(i: BigInt, t: (Int, String)) | | def configToString(c: Config): String = ??? ensuring { (res: String) => (c, res) passes { case Config(BigInt(1), (2, "3")) => "1: 2 -> 3" } } + | def configToString2(c: Config): String = ??? ensuring { (res: String) => (c, res) passes { case Config(BigInt(1), (2, "3")) => "3: 1 -> 2" } } + | + | sealed abstract class Tree + | case class Knot(left: Tree, right: Tree) extends Tree + | case class Bud(v: String) extends Tree + | + | def treeToString(t: Tree): String = ???[String] ensuring { + | (res : String) => (t, res) passes { + | case Knot(Knot(Bud("17"), Bud("14")), Bud("23")) => + | "<<17Y14>Y23>" + | case Bud("foo") => + | "foo" + | case Knot(Bud("foo"), Bud("foo")) => + | "<fooYfoo>" + | case Knot(Bud("foo"), Knot(Bud("bar"), Bud("foo"))) => + | "<fooY<barYfoo>>" + | } + | } | | case class Node(tag: String, l: List[Edge]) | case class Edge(start: Node, end: Node) @@ -218,29 +236,47 @@ class StringRenderSuite extends LeonTestSuiteWithProgram with Matchers with Scal Seq(StringLiteral("\t")) -> "done...\\t") }*/ - - test("Case class synthesis"){ case (ctx: LeonContext, program: Program) => - object Config { - def apply(i: Int, b: (Int, String)): CaseClass = { - CaseClass(program.lookupCaseClass("StringRenderSuite.Config").get.typed, - Seq(InfiniteIntegerLiteral(i), tupleWrap(Seq(IntLiteral(b._1), StringLiteral(b._2))))) - } + case class ConfigBuilder(program: Program) { + def apply(i: Int, b: (Int, String)): CaseClass = { + CaseClass(program.lookupCaseClass("StringRenderSuite.Config").get.typed, + Seq(InfiniteIntegerLiteral(i), tupleWrap(Seq(IntLiteral(b._1), StringLiteral(b._2))))) } + } + StringRender.enforceDefaultStringMethodsIfAvailable = false + test("Case class synthesis"){ case (ctx: LeonContext, program: Program) => + val Config = ConfigBuilder(program) synthesizeAndTest("configToString", Seq(Config(4, (5, "foo"))) -> "4: 5 -> foo") } - test("Recursive case class synthesis"){ case (ctx: LeonContext, program: Program) => - - } - test("Out of order synthesis"){ case (ctx: LeonContext, program: Program) => + val Config = ConfigBuilder(program) + synthesizeAndTest("configToString2", + Seq(Config(4, (5, "foo"))) -> "foo: 4 -> 5") + } + class TreeBuilder(program: Program) { + object Knot { + def apply(left: Expr, right: Expr): CaseClass = { + CaseClass(program.lookupCaseClass("StringRenderSuite.Knot").get.typed, + Seq(left, right)) + } + } + object Bud { + def apply(s: String): CaseClass = { + CaseClass(program.lookupCaseClass("StringRenderSuite.Bud").get.typed, + Seq(StringLiteral(s))) + } + } } - test("Tuple synthesis"){ case (ctx: LeonContext, program: Program) => - + test("Recursive case class synthesis"){ case (ctx: LeonContext, program: Program) => + val tb = new TreeBuilder(program) + import tb._ + synthesizeAndTest("treeToString", + Seq(Knot(Knot(Bud("aa"), Bud("bb")), Knot(Bud("mm"), Bud("nn")))) -> + "<<aaYbb>Y<mmYnn>>") } test("Abstract synthesis"){ case (ctx: LeonContext, program: Program) => -- GitLab