diff --git a/src/main/scala/inox/ast/SymbolOps.scala b/src/main/scala/inox/ast/SymbolOps.scala index deadd9826ab8dd9aadb434d52bd23492ecccca41..515cc2c45d630b2418ae4f9fb5cec9adb4d7c0ad 100644 --- a/src/main/scala/inox/ast/SymbolOps.scala +++ b/src/main/scala/inox/ast/SymbolOps.scala @@ -116,7 +116,7 @@ trait SymbolOps { self: TypeOps => val remainingIds: MutableMap[Type, List[Identifier]] = MutableMap.empty ++ typedIds.toMap def getId(e: Expr): Identifier = { - val tpe = bestRealType(e.getType) + val tpe = e.getType val newId = remainingIds.get(tpe) match { case Some(x :: xs) => remainingIds += tpe -> xs diff --git a/src/main/scala/inox/solvers/unrolling/LambdaTemplates.scala b/src/main/scala/inox/solvers/unrolling/LambdaTemplates.scala index 16510afc7fe73c9c88d31b674bb3ccbb259a6e45..9ced30029faf11da39d2fb35019bfefce3b76426 100644 --- a/src/main/scala/inox/solvers/unrolling/LambdaTemplates.scala +++ b/src/main/scala/inox/solvers/unrolling/LambdaTemplates.scala @@ -55,7 +55,6 @@ trait LambdaTemplates { self: Templates => ids: (Variable, Encoded), pathVar: (Variable, Encoded), arguments: Seq[(Variable, Encoded)], - closures: Seq[(Variable, Encoded)], condVars: Map[Variable, Encoded], exprVars: Map[Variable, Encoded], condTree: Map[Variable, Set[Variable]], @@ -72,14 +71,14 @@ trait LambdaTemplates { self: Templates => val tpe = ids._1.getType.asInstanceOf[FunctionType] val (clauses, blockers, applications, matchers, templateString) = Template.encode(pathVar, arguments, condVars, exprVars, guardedExprs, equations, - lambdas, quantifications, substMap = baseSubstMap + ids ++ closures, optApp = Some(id -> tpe)) + lambdas, quantifications, substMap = baseSubstMap + ids, optApp = Some(id -> tpe)) val lambdaString : () => String = () => { "Template for lambda " + ids._1 + ": " + lambda + " is :\n" + templateString() } new LambdaTemplate( - ids, pathVar, arguments, closures, + ids, pathVar, arguments, condVars, exprVars, condTree, clauses, blockers, applications, matchers, lambdas, quantifications, @@ -201,7 +200,6 @@ trait LambdaTemplates { self: Templates => val ids: (Variable, Encoded), val pathVar: (Variable, Encoded), val arguments: Seq[(Variable, Encoded)], - val closures: Seq[(Variable, Encoded)], val condVars: Map[Variable, Encoded], val exprVars: Map[Variable, Encoded], val condTree: Map[Variable, Set[Variable]], @@ -222,7 +220,7 @@ trait LambdaTemplates { self: Templates => def substitute(substituter: Encoded => Encoded, msubst: Map[Encoded, Matcher]): LambdaTemplate = new LambdaTemplate( ids._1 -> substituter(ids._2), pathVar._1 -> substituter(pathVar._2), - arguments, closures, condVars, exprVars, condTree, + arguments, condVars, exprVars, condTree, clauses.map(substituter), blockers.map { case (b, fis) => substituter(b) -> fis.map(_.substitute(substituter, msubst)) }, applications.map { case (b, apps) => substituter(b) -> apps.map(_.substitute(substituter, msubst)) }, @@ -235,10 +233,10 @@ trait LambdaTemplates { self: Templates => /** This must be called right before returning the clauses in [[structure.instantiation]]! */ def concretize(idT: Encoded): LambdaTemplate = { assert(!isConcrete, "Can't concretize concrete lambda template") - val substituter = mkSubstituter(Map(ids._2 -> idT) ++ (closures.map(_._2) zip structure.locals.map(_._2))) + val substituter = mkSubstituter(Map(ids._2 -> idT)) new LambdaTemplate( ids._1 -> idT, - pathVar, arguments, closures, condVars, exprVars, condTree, + pathVar, arguments, condVars, exprVars, condTree, clauses map substituter, blockers.map { case (b, fis) => b -> fis.map(_.substitute(substituter, Map.empty)) }, applications.map { case (b, apps) => b -> apps.map(_.substitute(substituter, Map.empty)) }, diff --git a/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala b/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala index dc519c71903f51543629a96e516c8b555ead4b1a..0bd78b8a124511c692ff3af4382f33026ae3b3a0 100644 --- a/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala +++ b/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala @@ -278,21 +278,16 @@ trait TemplateGenerator { self: Templates => val (struct, deps) = normalizeStructure(l) val sortedDeps = deps.toSeq.sortBy(_._1.id.uniqueName) - val idDeps = sortedDeps.map(_._1) - val trDeps = idDeps.map(id => encodeSymbol(id)) - val lid = Variable(FreshIdentifier("lambda", true), bestRealType(l.getType)) - val clauses = liftedEquals(lid, struct, idArgs, inlineFirst = true) + val depsByScope: Seq[(Variable, Expr)] = { + def rec(v: Variable): Seq[Variable] = + (exprOps.variablesOf(deps(v)) & deps.keySet).toSeq.flatMap(rec) :+ v + deps.keys.toSeq.flatMap(rec).distinct.map(v => v -> deps(v)) + } val localSubst: Map[Variable, Encoded] = substMap ++ condVars ++ exprVars ++ lambdaVars - val clauseSubst: Map[Variable, Encoded] = localSubst ++ (idArgs zip trArgs) ++ (idDeps zip trDeps) - val (lambdaConds, lambdaExprs, lambdaTree, lambdaGuarded, lambdaEqs, lambdaTemplates, lambdaQuants) = - clauses.foldLeft(emptyClauses)((clsSet, cls) => clsSet ++ mkClauses(pathVar, cls, clauseSubst)) - - val ids: (Variable, Encoded) = lid -> storeLambda(lid) - val (depSubst, (depConds, depExprs, depTree, depGuarded, depEqs, depLambdas, depQuants)) = - sortedDeps.foldLeft[(Map[Variable, Encoded], TemplateClauses)](localSubst -> emptyClauses) { + depsByScope.foldLeft[(Map[Variable, Encoded], TemplateClauses)](localSubst -> emptyClauses) { case ((depSubst, clsSet), (v, expr)) => if (!exprOps.isSimple(expr)) { val (e, cls @ (_, _, _, _, _, lmbds, quants)) = mkExprClauses(pathVar, expr, depSubst) @@ -322,8 +317,36 @@ trait TemplateGenerator { self: Templates => struct, dependencies, pathVar -> encodedCond(pathVar), depClosures, depConds, depExprs, depTree, depClauses, depCalls, depApps, depMatchers, depLambdas, depQuants) + val isNormalForm: Boolean = { + def extractBody(e: Expr): (Seq[ValDef], Expr) = e match { + case Lambda(args, body) => + val (nextArgs, nextBody) = extractBody(body) + (args ++ nextArgs, nextBody) + case _ => (Seq.empty, e) + } + + extractBody(struct) match { + case (params, ApplicationExtractor(caller: Variable, args)) => + (params.map(_.toVariable) == args) && (deps.get(caller) match { + case Some(_: Application | _: FunctionInvocation) => true + case _ => false + }) + case _ => false + } + } + + val realLambda = if (isNormalForm) l else struct + val lid = Variable(FreshIdentifier("lambda", true), bestRealType(l.getType)) + val clauses = liftedEquals(lid, realLambda, idArgs, inlineFirst = true) + + val clauseSubst: Map[Variable, Encoded] = depSubst ++ (idArgs zip trArgs) + val (lambdaConds, lambdaExprs, lambdaTree, lambdaGuarded, lambdaEqs, lambdaTemplates, lambdaQuants) = + clauses.foldLeft(emptyClauses)((clsSet, cls) => clsSet ++ mkClauses(pathVar, cls, clauseSubst)) + + val ids: (Variable, Encoded) = lid -> storeLambda(lid) + val template = LambdaTemplate(ids, pathVar -> encodedCond(pathVar), - idArgs zip trArgs, idDeps zip trDeps, lambdaConds, lambdaExprs, lambdaTree, + idArgs zip trArgs, lambdaConds, lambdaExprs, lambdaTree, lambdaGuarded, lambdaEqs, lambdaTemplates, lambdaQuants, structure, depSubst, l) registerLambda(template) lid