From 508c8049062d518f35cfd5623dad1908dac83937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Mayer?= <mikael.mayer@epfl.ch> Date: Fri, 22 Apr 2016 15:11:48 +0200 Subject: [PATCH] Corrected 3 bugs in AbstractEvaluator.scala * FunctionInvocation now considers abstract parameters * Applications on lambdas are now handled * Pattern matching now considers abstract parameters --- .../leon/evaluators/AbstractEvaluator.scala | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/main/scala/leon/evaluators/AbstractEvaluator.scala b/src/main/scala/leon/evaluators/AbstractEvaluator.scala index b950aff5f..a5a26e02f 100644 --- a/src/main/scala/leon/evaluators/AbstractEvaluator.scala +++ b/src/main/scala/leon/evaluators/AbstractEvaluator.scala @@ -88,11 +88,9 @@ class AbstractEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvalu case MatchExpr(scrut, cases) => val (escrut, tscrut) = e(scrut) - cases.toStream.map(c => matchesCaseAbstract(escrut, c)).find(_.nonEmpty) match { - case Some(Some((c, mappings))) => - e(c.rhs)(rctx.withNewVars2(mappings), gctx) - case _ => - throw RuntimeError("MatchError(Abstract evaluation): "+escrut.asString+" did not match any of the cases :\n" + cases.mkString("\n")) + cases.toStream.map(c => matchesCaseAbstract(escrut, tscrut, c)).find(_.nonEmpty) match { + case Some(Some((c, mappings))) => e(c.rhs)(rctx.withNewVars2(mappings), gctx) + case _ => throw RuntimeError("MatchError(Abstract evaluation): "+escrut.asString+" did not match any of the cases :\n" + cases.mkString("\n")) } case FunctionInvocation(tfd, args) => @@ -105,7 +103,7 @@ class AbstractEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvalu val evArgsOrigin = evArgs.map(_._2) // build a mapping for the function... - val frame = rctx.withNewVars(tfd.paramSubst(evArgsValues)) + val frame = rctx.withNewVars2((tfd.paramIds zip evArgs).toMap) val callResult = if ((evArgsValues forall ExprOps.isValue) && tfd.fd.annotations("extern") && ctx.classDir.isDefined) { (scalaEv.call(tfd, evArgsValues), functionInvocation(tfd.fd, evArgsOrigin)) @@ -125,17 +123,32 @@ class AbstractEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvalu case Let(i, ex, b) => val (first, second) = e(ex) e(b)(rctx.withNewVar(i, (first, second)), gctx) + case Application(caller, args) => + underlying.e(caller) match { + case l @ Lambda(params, body) => + val newArgs = args.map(e) + val mapping = (params map { _.id } zip newArgs).toMap + e(body)(rctx.withNewVars2(mapping), gctx) + case FiniteLambda(mapping, dflt, _) => + mapping.find { case (pargs, res) => + (args zip pargs).forall(p => underlying.e(Equals(p._1, p._2)) == BooleanLiteral(true)) + }.map{ case (key, value) => (value, value)}.getOrElse((dflt, dflt)) + case f => + throw EvalError("Cannot apply non-lambda function " + f.asString) + } case Operator(es, builder) => val (ees, ts) = es.map(e).unzip if(ees forall ExprOps.isValue) { - (underlying.e(builder(ees)), builder(ts)) + val conc_value = underlying.e(builder(ees)) + val abs_value = builder(ts) + (conc_value, abs_value) } else { (builder(ees), builder(ts)) } } } - def matchesCaseAbstract(scrut: Expr, caze: MatchCase)(implicit rctx: RC, gctx: GC): Option[(MatchCase, Map[Identifier, (Expr, Expr)])] = { + def matchesCaseAbstract(scrut: Expr, abstractScrut: Expr, caze: MatchCase)(implicit rctx: RC, gctx: GC): Option[(MatchCase, Map[Identifier, (Expr, Expr)])] = { import purescala.TypeOps.isSubtypeOf import purescala.Extractors._ @@ -151,7 +164,9 @@ class AbstractEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvalu case (CaseClassPattern(ob, pct, subs), CaseClass(ct, args)) => if (pct == ct) { - val res = (subs zip args zip ct.classDef.fieldsIds).map{ case ((s, a), id) => matchesPattern(s, a, CaseClassSelector(ct, exprFromScrut, id)) } + val res = (subs zip args zip ct.classDef.fieldsIds).map{ + case ((s, a), id) => matchesPattern(s, a, CaseClassSelector(ct, exprFromScrut, id)) + } if (res.forall(_.isDefined)) { Some(obind(ob, expr, exprFromScrut) ++ res.flatten.flatten) } else { @@ -198,13 +213,13 @@ class AbstractEvaluator(ctx: LeonContext, prog: Program) extends ContextualEvalu caze match { case SimpleCase(p, rhs) => - matchesPattern(p, scrut, scrut).map(r => + matchesPattern(p, scrut, abstractScrut).map(r => (caze, r) ) case GuardedCase(p, g, rhs) => for { - r <- matchesPattern(p, scrut, scrut) + r <- matchesPattern(p, scrut, abstractScrut) if e(g)(rctx.withNewVars2(r), gctx)._1 == BooleanLiteral(true) } yield (caze, r) } -- GitLab