diff --git a/src/main/scala/leon/purescala/CheckADTFieldsTypes.scala b/src/main/scala/leon/purescala/CheckADTFieldsTypes.scala index 9de511180a260f6bf1fd04d1b04188d085b0b71a..ee78b4b5f3daadaea5ef7222105c13eaefc35401 100644 --- a/src/main/scala/leon/purescala/CheckADTFieldsTypes.scala +++ b/src/main/scala/leon/purescala/CheckADTFieldsTypes.scala @@ -3,11 +3,8 @@ package leon package purescala -import Common._ import Definitions._ -import Types._ import TypeOps._ -import Expressions._ object CheckADTFieldsTypes extends UnitPhase[Program] { @@ -20,7 +17,9 @@ object CheckADTFieldsTypes extends UnitPhase[Program] { for(vd <- ccd.fields) { val tpe = vd.getType if (bestRealType(tpe) != tpe) { - ctx.reporter.warning("Definition of "+ccd.id+" has a field of a sub-type ("+vd+"): this type is not supported as-is by solvers and will be up-casted. This may cause issues such as crashes.") + ctx.reporter.warning("Definition of "+ccd.id+" has a field of a sub-type ("+vd+"): " + + "this type is not supported as-is by solvers and will be up-cast. " + + "This may cause issues such as crashes.") } } case _ => diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala index 1809ba00e66815cf0aec252d91340693ec1964ff..90f9d82b671f25fdee27e292768a56c17eeac2ad 100644 --- a/src/main/scala/leon/purescala/ExprOps.scala +++ b/src/main/scala/leon/purescala/ExprOps.scala @@ -157,9 +157,8 @@ object ExprOps { val rec = postMap(f, applyRec) _ val Operator(es, builder) = e + val newEs = es.map(rec) val newV = { - val newEs = es.map(rec) - if ((newEs zip es).exists { case (bef, aft) => aft ne bef }) { builder(newEs).copiedFrom(e) } else { diff --git a/src/main/scala/leon/xlang/ArrayTransformation.scala b/src/main/scala/leon/xlang/ArrayTransformation.scala index dfa87a993fde5eb4df3a418c4f018b4f97a7f19b..c283a1be7665a7bed4f084a9a4f47421e44ef681 100644 --- a/src/main/scala/leon/xlang/ArrayTransformation.scala +++ b/src/main/scala/leon/xlang/ArrayTransformation.scala @@ -4,49 +4,32 @@ package leon.xlang import leon.UnitPhase import leon.LeonContext -import leon.purescala.Common._ import leon.purescala.Definitions._ import leon.purescala.Expressions._ +import leon.purescala.ExprOps.simplePostTransform +import leon.purescala.Extractors.IsTyped +import leon.purescala.Types.ArrayType import leon.xlang.Expressions._ -import leon.purescala.Extractors._ -import leon.purescala.Types._ object ArrayTransformation extends UnitPhase[Program] { val name = "Array Transformation" - val description = "Add bound checking for array access and remove array update with side effect" + val description = "Remove side-effectful array updates" def apply(ctx: LeonContext, pgm: Program) = { - pgm.definedFunctions.foreach(fd => { - fd.fullBody = transform(fd.fullBody)(Map()) - }) + pgm.definedFunctions.foreach(fd => + fd.fullBody = simplePostTransform { + case up@ArrayUpdate(a, i, v) => + val ra@Variable(id) = a + Assignment(id, ArrayUpdated(ra, i, v).setPos(up)).setPos(up) + + case l@Let(i, IsTyped(v, ArrayType(_)), b) => + LetVar(i, v, b).setPos(l) + + case e => + e + }(fd.fullBody) + ) } - def transform(expr: Expr)(implicit env: Map[Identifier, Identifier]): Expr = (expr match { - case up@ArrayUpdate(a, i, v) => { - val ra = transform(a) - val ri = transform(i) - val rv = transform(v) - val Variable(id) = ra - Assignment(id, ArrayUpdated(ra, ri, rv).setPos(up)) - } - case Let(i, v, b) => { - v.getType match { - case ArrayType(_) => { - val freshIdentifier = FreshIdentifier("t", i.getType) - val newEnv = env + (i -> freshIdentifier) - LetVar(freshIdentifier, transform(v)(newEnv), transform(b)(newEnv)) - } - case _ => Let(i, transform(v), transform(b)) - } - } - case v@Variable(i) => { - Variable(env.getOrElse(i, i)) - } - - case Operator(args, recons) => recons(args.map(transform)) - - case unhandled => scala.sys.error("Non-terminal case should be handled in ArrayTransformation: " + unhandled) - }).setPos(expr) - } diff --git a/src/main/scala/leon/xlang/EpsilonElimination.scala b/src/main/scala/leon/xlang/EpsilonElimination.scala index 91b39ad5bf104583025e9791ea97196a517fc7d3..37775688971c77cb604285bb5f29e750c6a91ba9 100644 --- a/src/main/scala/leon/xlang/EpsilonElimination.scala +++ b/src/main/scala/leon/xlang/EpsilonElimination.scala @@ -2,7 +2,7 @@ package leon.xlang -import leon.{UnitPhase, TransformationPhase, LeonContext} +import leon.{UnitPhase, LeonContext} import leon.purescala.Common._ import leon.purescala.Definitions._ import leon.purescala.Expressions._ diff --git a/src/main/scala/leon/xlang/FixReportLabels.scala b/src/main/scala/leon/xlang/FixReportLabels.scala index 6346402c2985855bfcc9e2973fdd6a6babc8a427..9f18a2646915c9e1d6c624f55a0ef924f4685a28 100644 --- a/src/main/scala/leon/xlang/FixReportLabels.scala +++ b/src/main/scala/leon/xlang/FixReportLabels.scala @@ -4,14 +4,18 @@ package leon package xlang import leon.purescala.Definitions.IsLoop -import leon.verification.{VC, VCKinds, VerificationReport} -import leon.xlang.XLangAnalysisPhase.VCXLangKinds._ +import leon.verification._ object FixReportLabels extends LeonPhase[VerificationReport, VerificationReport]{ override val name: String = "fixReportLabels" override val description: String = "Fix verification report labels to reflect the original imperative VCs" + // TODO: something of this sort should be included + // case object InvariantEntry extends VCKind("invariant init", "inv. init.") + case object InvariantPost extends VCKind("invariant postcondition", "inv. post.") + case object InvariantInd extends VCKind("invariant inductive", "inv. ind.") + def run(ctx: LeonContext)(vr: VerificationReport): VerificationReport = { //this is enough to convert invariant postcondition and inductive conditions. However the initial validity //of the invariant (before entering the loop) will still appear as a regular function precondition diff --git a/src/main/scala/leon/xlang/XLangAnalysisPhase.scala b/src/main/scala/leon/xlang/XLangAnalysisPhase.scala index 5d154854f56038d8317b08abb0ce3e3d1f05fce1..470c0d38990ceaad3a0a9fffb1fe9625b227ac0c 100644 --- a/src/main/scala/leon/xlang/XLangAnalysisPhase.scala +++ b/src/main/scala/leon/xlang/XLangAnalysisPhase.scala @@ -5,26 +5,19 @@ package xlang import purescala.Definitions.Program import purescala.FunctionClosure -import verification._ object XLangAnalysisPhase extends TransformationPhase { - val name = "xlang analysis" - val description = "apply analysis on xlang" - - object VCXLangKinds { - // TODO: something of this sort should be included - // case object InvariantEntry extends VCKind("invariant init", "inv. init.") - case object InvariantPost extends VCKind("invariant postcondition", "inv. post.") - case object InvariantInd extends VCKind("invariant inductive", "inv. ind.") - } + val name = "xlang desugaring" + val description = "Desugar xlang features into PureScala" def apply(ctx: LeonContext, pgm: Program): Program = { - ArrayTransformation(ctx, pgm) // In-place - EpsilonElimination(ctx, pgm) // In-place - (ImperativeCodeElimination andThen FunctionClosure).run(ctx)(pgm) + val phases = + ArrayTransformation andThen + EpsilonElimination andThen + ImperativeCodeElimination andThen + FunctionClosure + phases.run(ctx)(pgm) } - - }