From c65833c0cc727e2459f94b2cf7ad1d9ea8abe2c6 Mon Sep 17 00:00:00 2001 From: "Emmanouil (Manos) Koukoutos" <emmanouil.koukoutos@epfl.ch> Date: Tue, 9 Dec 2014 18:01:42 +0100 Subject: [PATCH] Benchmark additions/changes --- .../repair/DaysToYears/DaysToYears2.scala | 36 ++++ .../repair/DaysToYears/DaysToYears3.scala | 36 ++++ .../synthesis/repair/Desugar/Desugar.scala | 172 +++++++++++++++++ .../synthesis/repair/Desugar/Desugar1.scala | 177 ++++++++++++++++++ .../synthesis/repair/Desugar/Desugar2.scala | 172 +++++++++++++++++ .../synthesis/repair/Desugar/Desugar3.scala | 173 +++++++++++++++++ .../synthesis/repair/Desugar/Desugar4.scala | 172 +++++++++++++++++ .../synthesis/repair/Parser/Parser1.scala | 58 ++++++ .../synthesis/repair/Parser/Parser2.scala | 58 ++++++ .../synthesis/repair/Parser/Parser3.scala | 58 ++++++ .../synthesis/repair/Parser/Parser4.scala | 58 ++++++ .../synthesis/repair/Parser/Parser5.scala | 58 ++++++ .../{PropLogic5.scala => PropLogic2.scala} | 11 +- .../repair/PropLogic/PropLogic3.scala | 33 +--- .../repair/PropLogic/PropLogic4.scala | 30 +-- .../repair/PropLogic/PropLogic6.scala | 73 -------- 16 files changed, 1245 insertions(+), 130 deletions(-) create mode 100644 testcases/synthesis/repair/DaysToYears/DaysToYears2.scala create mode 100644 testcases/synthesis/repair/DaysToYears/DaysToYears3.scala create mode 100644 testcases/synthesis/repair/Desugar/Desugar.scala create mode 100644 testcases/synthesis/repair/Desugar/Desugar1.scala create mode 100644 testcases/synthesis/repair/Desugar/Desugar2.scala create mode 100644 testcases/synthesis/repair/Desugar/Desugar3.scala create mode 100644 testcases/synthesis/repair/Desugar/Desugar4.scala create mode 100644 testcases/synthesis/repair/Parser/Parser1.scala create mode 100644 testcases/synthesis/repair/Parser/Parser2.scala create mode 100644 testcases/synthesis/repair/Parser/Parser3.scala create mode 100644 testcases/synthesis/repair/Parser/Parser4.scala create mode 100644 testcases/synthesis/repair/Parser/Parser5.scala rename testcases/synthesis/repair/PropLogic/{PropLogic5.scala => PropLogic2.scala} (88%) delete mode 100644 testcases/synthesis/repair/PropLogic/PropLogic6.scala diff --git a/testcases/synthesis/repair/DaysToYears/DaysToYears2.scala b/testcases/synthesis/repair/DaysToYears/DaysToYears2.scala new file mode 100644 index 000000000..de0d31a70 --- /dev/null +++ b/testcases/synthesis/repair/DaysToYears/DaysToYears2.scala @@ -0,0 +1,36 @@ +import leon.lang._ + +object DaysToYears { + val base : Int = 1980 + + def isLeapYear(y : Int): Boolean = y % 4 == 0 + + def daysToYears(days : Int): Int = { + require(days > 0) + daysToYears1(base, days)._1 + } + + def daysToYears1(year : Int, days : Int): (Int, Int) = { + require(year >= base && days > 0) + if (days > 366 && isLeapYear(year)) + daysToYears1(year + 1, days - 366) // TODO this branch cannot be solved although it is correct because it depends on the erroneous branch + else if (days > 365 && !isLeapYear(year)) + daysToYears1(year + 1, days - 365) + else (year + 1, days) // FIXME +1 + } ensuring { res => + res._2 <= 366 && + res._2 > 0 && + res._1 >= base && + (((year,days), res) passes { + case (1980, 366 ) => (1980, 366) + case (1980, 1000) => (1982, 269) + }) + } + + def main(args : Array[String]) = { + println(daysToYears1(base, 10593 )) + println(daysToYears1(base, 366 )) + println(daysToYears1(base, 1000 )) + } +} + diff --git a/testcases/synthesis/repair/DaysToYears/DaysToYears3.scala b/testcases/synthesis/repair/DaysToYears/DaysToYears3.scala new file mode 100644 index 000000000..bb6c518b3 --- /dev/null +++ b/testcases/synthesis/repair/DaysToYears/DaysToYears3.scala @@ -0,0 +1,36 @@ +import leon.lang._ + +object DaysToYears { + val base : Int = 1980 + + def isLeapYear(y : Int): Boolean = y % 4 == 0 + + def daysToYears(days : Int): Int = { + require(days > 0) + daysToYears1(base, days)._1 + } + + def daysToYears1(year : Int, days : Int): (Int, Int) = { + require(year >= base && days > 0) + if (days > 366 && isLeapYear(year)) + daysToYears1(year + 1, days - 366) + else if (days > 365 && !isLeapYear(year)) + daysToYears1(year + 1, days - 365) + else (year, days) + } ensuring { res => + res._2 <= 366 && + res._2 > 0 && + res._1 >= base && + (((year,days), res) passes { + case (1980, 366 ) => (1980, 366) + case (1980, 1000) => (1982, 269) + }) + } + + def main(args : Array[String]) = { + println(daysToYears1(base, 10593 )) + println(daysToYears1(base, 366 )) + println(daysToYears1(base, 1000 )) + } +} + diff --git a/testcases/synthesis/repair/Desugar/Desugar.scala b/testcases/synthesis/repair/Desugar/Desugar.scala new file mode 100644 index 000000000..19cd3305a --- /dev/null +++ b/testcases/synthesis/repair/Desugar/Desugar.scala @@ -0,0 +1,172 @@ +import leon.lang._ +import leon.annotation._ +import leon.collection._ +import leon._ + +object Trees { + abstract class Expr + case class Plus(lhs: Expr, rhs: Expr) extends Expr + case class Minus(lhs: Expr, rhs: Expr) extends Expr + case class LessThan(lhs: Expr, rhs: Expr) extends Expr + case class And(lhs: Expr, rhs: Expr) extends Expr + case class Or(lhs: Expr, rhs: Expr) extends Expr + case class Not(e : Expr) extends Expr + case class Eq(lhs: Expr, rhs: Expr) extends Expr + case class Ite(cond: Expr, thn: Expr, els: Expr) extends Expr + case class IntLiteral(v: Int) extends Expr + case class BoolLiteral(b : Boolean) extends Expr +} + +object Types { + abstract class Type + case object IntType extends Type + case object BoolType extends Type +} + + +object TypeChecker { + import Trees._ + import Types._ + + def typeOf(e :Expr) : Option[Type] = e match { + case Plus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case Minus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case LessThan(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(BoolType) + case _ => None() + } + case And(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Or(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Not(e) => typeOf(e) match { + case Some(BoolType) => Some(BoolType) + case _ => None() + } + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case (Some(t1), Some(t2)) if t1 == t2 => Some(BoolType) + case _ => None() + } + case Ite(c, th, el) => (typeOf(c), typeOf(th), typeOf(el)) match { + case (Some(BoolType), Some(t1), Some(t2)) if t1 == t2 => Some(t1) + case _ => None() + } + case IntLiteral(_) => Some(IntType) + case BoolLiteral(_) => Some(BoolType) + } + + def typeChecks(e : Expr) = typeOf(e).isDefined +} + + +object Semantics { + import Trees._ + import Types._ + import TypeChecker._ + + def semI(t : Expr) : Int = { + require( typeOf(t) == ( Some(IntType) : Option[Type] )) + t match { + case Plus(lhs , rhs) => semI(lhs) + semI(rhs) + case Minus(lhs , rhs) => semI(lhs) - semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semI(thn) else semI(els) + case IntLiteral(v) => v + } + } + + def semB(t : Expr) : Boolean = { + require( (Some(BoolType): Option[Type]) == typeOf(t)) + t match { + case And(lhs, rhs ) => semB(lhs) && semB(rhs) + case Or(lhs , rhs ) => semB(lhs) || semB(rhs) + case Not(e) => !semB(e) + case LessThan(lhs, rhs) => semI(lhs) < semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semB(thn) else semB(els) + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case ( Some(IntType), Some(IntType) ) => semI(lhs) == semI(rhs) + case ( Some(BoolType), Some(BoolType) ) => semB(lhs) == semB(rhs) + } + case BoolLiteral(b) => b + } + } + + def b2i(b : Boolean) = if (b) 1 else 0 + + @induct + def semUntyped( t : Expr) : Int = { t match { + case Plus (lhs, rhs) => semUntyped(lhs) + semUntyped(rhs) + case Minus(lhs, rhs) => semUntyped(lhs) - semUntyped(rhs) + case And (lhs, rhs) => if (semUntyped(lhs)!=0) semUntyped(rhs) else 0 + case Or(lhs, rhs ) => + if (semUntyped(lhs) == 0) semUntyped(rhs) else 1 + case Not(e) => + b2i(semUntyped(e) == 0) + case LessThan(lhs, rhs) => + b2i(semUntyped(lhs) < semUntyped(rhs)) + case Eq(lhs, rhs) => + b2i(semUntyped(lhs) == semUntyped(rhs)) + case Ite(cond, thn, els) => + if (semUntyped(cond) == 0) semUntyped(els) else semUntyped(thn) + case IntLiteral(v) => v + case BoolLiteral(b) => b2i(b) + }} ensuring { res => typeOf(t) match { + case Some(IntType) => res == semI(t) + case Some(BoolType) => res == b2i(semB(t)) + case None() => true + }} + +} + + +object Desugar { + import Types._ + import TypeChecker._ + import Semantics.b2i + + abstract class SimpleE + case class Plus(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Neg(arg : SimpleE) extends SimpleE + case class Ite(cond : SimpleE, thn : SimpleE, els : SimpleE) extends SimpleE + case class Eq(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class LessThan(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Literal(i : Int) extends SimpleE + + @induct + def desugar(e : Trees.Expr) : SimpleE = { e match { + case Trees.Plus (lhs, rhs) => Plus(desugar(lhs), desugar(rhs)) + case Trees.Minus(lhs, rhs) => Plus(desugar(lhs), Neg(desugar(rhs))) + case Trees.LessThan(lhs, rhs) => LessThan(desugar(lhs), desugar(rhs)) + case Trees.And (lhs, rhs) => Ite(desugar(lhs), desugar(rhs), Literal(0)) + case Trees.Or (lhs, rhs) => Ite(desugar(lhs), Literal(1), desugar(rhs)) + case Trees.Not(e) => Ite(desugar(e), Literal(0), Literal(1)) + case Trees.Eq(lhs, rhs) => + Eq(desugar(lhs), desugar(rhs)) + case Trees.Ite(cond, thn, els) => Ite(desugar(cond), desugar(thn), desugar(els)) + case Trees.IntLiteral(v) => Literal(v) + case Trees.BoolLiteral(b) => Literal(b2i(b)) + }} ensuring { res => + sem(res) == Semantics.semUntyped(e) + } + + def sem(e : SimpleE) : Int = e match { + case Plus (lhs, rhs) => sem(lhs) + sem(rhs) + case Ite(cond, thn, els) => if (sem(cond) != 0) sem(thn) else sem(els) + case Neg(arg) => -sem(arg) + case Eq(lhs,rhs) => b2i(sem(lhs) == sem(rhs)) + case LessThan(lhs, rhs) => b2i(sem(lhs) < sem(rhs)) + case Literal(i) => i + } + +} diff --git a/testcases/synthesis/repair/Desugar/Desugar1.scala b/testcases/synthesis/repair/Desugar/Desugar1.scala new file mode 100644 index 000000000..2995bb576 --- /dev/null +++ b/testcases/synthesis/repair/Desugar/Desugar1.scala @@ -0,0 +1,177 @@ +import leon.lang._ +import leon.annotation._ +import leon.collection._ +import leon._ + +object Trees { + abstract class Expr + case class Plus(lhs: Expr, rhs: Expr) extends Expr + case class Minus(lhs: Expr, rhs: Expr) extends Expr + case class LessThan(lhs: Expr, rhs: Expr) extends Expr + case class And(lhs: Expr, rhs: Expr) extends Expr + case class Or(lhs: Expr, rhs: Expr) extends Expr + case class Not(e : Expr) extends Expr + case class Eq(lhs: Expr, rhs: Expr) extends Expr + case class Ite(cond: Expr, thn: Expr, els: Expr) extends Expr + case class IntLiteral(v: Int) extends Expr + case class BoolLiteral(b : Boolean) extends Expr +} + +object Types { + abstract class Type + case object IntType extends Type + case object BoolType extends Type +} + + +object TypeChecker { + import Trees._ + import Types._ + + def typeOf(e :Expr) : Option[Type] = e match { + case Plus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case Minus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case LessThan(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(BoolType) + case _ => None() + } + case And(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Or(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Not(e) => typeOf(e) match { + case Some(BoolType) => Some(BoolType) + case _ => None() + } + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case (Some(t1), Some(t2)) if t1 == t2 => Some(BoolType) + case _ => None() + } + case Ite(c, th, el) => (typeOf(c), typeOf(th), typeOf(el)) match { + case (Some(BoolType), Some(t1), Some(t2)) if t1 == t2 => Some(t1) + case _ => None() + } + case IntLiteral(_) => Some(IntType) + case BoolLiteral(_) => Some(BoolType) + } + + def typeChecks(e : Expr) = typeOf(e).isDefined +} + + +object Semantics { + import Trees._ + import Types._ + import TypeChecker._ + + def semI(t : Expr) : Int = { + require( typeOf(t) == ( Some(IntType) : Option[Type] )) + t match { + case Plus(lhs , rhs) => semI(lhs) + semI(rhs) + case Minus(lhs , rhs) => semI(lhs) - semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semI(thn) else semI(els) + case IntLiteral(v) => v + } + } + + def semB(t : Expr) : Boolean = { + require( (Some(BoolType): Option[Type]) == typeOf(t)) + t match { + case And(lhs, rhs ) => semB(lhs) && semB(rhs) + case Or(lhs , rhs ) => semB(lhs) || semB(rhs) + case Not(e) => !semB(e) + case LessThan(lhs, rhs) => semI(lhs) < semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semB(thn) else semB(els) + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case ( Some(IntType), Some(IntType) ) => semI(lhs) == semI(rhs) + case ( Some(BoolType), Some(BoolType) ) => semB(lhs) == semB(rhs) + } + case BoolLiteral(b) => b + } + } + + def b2i(b : Boolean) = if (b) 1 else 0 + + @induct + def semUntyped( t : Expr) : Int = { t match { + case Plus (lhs, rhs) => semUntyped(lhs) + semUntyped(rhs) + case Minus(lhs, rhs) => semUntyped(lhs) - semUntyped(rhs) + case And (lhs, rhs) => if (semUntyped(lhs)!=0) semUntyped(rhs) else 0 + case Or(lhs, rhs ) => + if (semUntyped(lhs) == 0) semUntyped(rhs) else 1 + case Not(e) => + b2i(semUntyped(e) == 0) + case LessThan(lhs, rhs) => + b2i(semUntyped(lhs) < semUntyped(rhs)) + case Eq(lhs, rhs) => + b2i(semUntyped(lhs) == semUntyped(rhs)) + case Ite(cond, thn, els) => + if (semUntyped(cond) == 0) semUntyped(els) else semUntyped(thn) + case IntLiteral(v) => v + case BoolLiteral(b) => b2i(b) + }} ensuring { res => typeOf(t) match { + case Some(IntType) => res == semI(t) + case Some(BoolType) => res == b2i(semB(t)) + case None() => true + }} + +} + + +object Desugar { + import Types._ + import TypeChecker._ + import Semantics.b2i + + abstract class SimpleE + case class Plus(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Neg(arg : SimpleE) extends SimpleE + case class Ite(cond : SimpleE, thn : SimpleE, els : SimpleE) extends SimpleE + case class Eq(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class LessThan(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Literal(i : Int) extends SimpleE + + @induct + def desugar(e : Trees.Expr) : SimpleE = { e match { + case Trees.Plus (lhs, rhs) => Neg(desugar(lhs)) // FIXME: Complete nonsense. Leon can't disprove it so it's happy... + case Trees.Minus(lhs, rhs) => Plus(desugar(lhs), Neg(desugar(rhs))) + case Trees.LessThan(lhs, rhs) => LessThan(desugar(lhs), desugar(rhs)) + case Trees.And (lhs, rhs) => Ite(desugar(lhs), desugar(rhs), Literal(0)) + case Trees.Or (lhs, rhs) => Ite(desugar(lhs), Literal(1), desugar(rhs)) + case Trees.Not(e) => Ite(desugar(e), Literal(0), Literal(1)) + case Trees.Eq(lhs, rhs) => + Eq(desugar(lhs), desugar(rhs)) + case Trees.Ite(cond, thn, els) => Ite(desugar(cond), desugar(thn), desugar(els)) + case Trees.IntLiteral(v) => Literal(v) + case Trees.BoolLiteral(b) => Literal(b2i(b)) + }} ensuring { res => + // TODO: Z3 fails to disprove this! + ((e, res) passes { + case Trees.Plus(Trees.IntLiteral(i), Trees.Minus(Trees.IntLiteral(j), Trees.IntLiteral(42))) => + Plus(Literal(i), Plus(Literal(j), Neg(Literal(42)))) + }) && + sem(res) == Semantics.semUntyped(e) + } + + def sem(e : SimpleE) : Int = e match { + case Plus (lhs, rhs) => sem(lhs) + sem(rhs) + case Ite(cond, thn, els) => if (sem(cond) != 0) sem(thn) else sem(els) + case Neg(arg) => -sem(arg) + case Eq(lhs,rhs) => b2i(sem(lhs) == sem(rhs)) + case LessThan(lhs, rhs) => b2i(sem(lhs) < sem(rhs)) + case Literal(i) => i + } + +} diff --git a/testcases/synthesis/repair/Desugar/Desugar2.scala b/testcases/synthesis/repair/Desugar/Desugar2.scala new file mode 100644 index 000000000..fc3b81d88 --- /dev/null +++ b/testcases/synthesis/repair/Desugar/Desugar2.scala @@ -0,0 +1,172 @@ +import leon.lang._ +import leon.annotation._ +import leon.collection._ +import leon._ + +object Trees { + abstract class Expr + case class Plus(lhs: Expr, rhs: Expr) extends Expr + case class Minus(lhs: Expr, rhs: Expr) extends Expr + case class LessThan(lhs: Expr, rhs: Expr) extends Expr + case class And(lhs: Expr, rhs: Expr) extends Expr + case class Or(lhs: Expr, rhs: Expr) extends Expr + case class Not(e : Expr) extends Expr + case class Eq(lhs: Expr, rhs: Expr) extends Expr + case class Ite(cond: Expr, thn: Expr, els: Expr) extends Expr + case class IntLiteral(v: Int) extends Expr + case class BoolLiteral(b : Boolean) extends Expr +} + +object Types { + abstract class Type + case object IntType extends Type + case object BoolType extends Type +} + + +object TypeChecker { + import Trees._ + import Types._ + + def typeOf(e :Expr) : Option[Type] = e match { + case Plus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case Minus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case LessThan(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(BoolType) + case _ => None() + } + case And(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Or(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Not(e) => typeOf(e) match { + case Some(BoolType) => Some(BoolType) + case _ => None() + } + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case (Some(t1), Some(t2)) if t1 == t2 => Some(BoolType) + case _ => None() + } + case Ite(c, th, el) => (typeOf(c), typeOf(th), typeOf(el)) match { + case (Some(BoolType), Some(t1), Some(t2)) if t1 == t2 => Some(t1) + case _ => None() + } + case IntLiteral(_) => Some(IntType) + case BoolLiteral(_) => Some(BoolType) + } + + def typeChecks(e : Expr) = typeOf(e).isDefined +} + + +object Semantics { + import Trees._ + import Types._ + import TypeChecker._ + + def semI(t : Expr) : Int = { + require( typeOf(t) == ( Some(IntType) : Option[Type] )) + t match { + case Plus(lhs , rhs) => semI(lhs) + semI(rhs) + case Minus(lhs , rhs) => semI(lhs) - semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semI(thn) else semI(els) + case IntLiteral(v) => v + } + } + + def semB(t : Expr) : Boolean = { + require( (Some(BoolType): Option[Type]) == typeOf(t)) + t match { + case And(lhs, rhs ) => semB(lhs) && semB(rhs) + case Or(lhs , rhs ) => semB(lhs) || semB(rhs) + case Not(e) => !semB(e) + case LessThan(lhs, rhs) => semI(lhs) < semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semB(thn) else semB(els) + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case ( Some(IntType), Some(IntType) ) => semI(lhs) == semI(rhs) + case ( Some(BoolType), Some(BoolType) ) => semB(lhs) == semB(rhs) + } + case BoolLiteral(b) => b + } + } + + def b2i(b : Boolean) = if (b) 1 else 0 + + @induct + def semUntyped( t : Expr) : Int = { t match { + case Plus (lhs, rhs) => semUntyped(lhs) + semUntyped(rhs) + case Minus(lhs, rhs) => semUntyped(lhs) - semUntyped(rhs) + case And (lhs, rhs) => if (semUntyped(lhs)!=0) semUntyped(rhs) else 0 + case Or(lhs, rhs ) => + if (semUntyped(lhs) == 0) semUntyped(rhs) else 1 + case Not(e) => + b2i(semUntyped(e) == 0) + case LessThan(lhs, rhs) => + b2i(semUntyped(lhs) < semUntyped(rhs)) + case Eq(lhs, rhs) => + b2i(semUntyped(lhs) == semUntyped(rhs)) + case Ite(cond, thn, els) => + if (semUntyped(cond) == 0) semUntyped(els) else semUntyped(thn) + case IntLiteral(v) => v + case BoolLiteral(b) => b2i(b) + }} ensuring { res => typeOf(t) match { + case Some(IntType) => res == semI(t) + case Some(BoolType) => res == b2i(semB(t)) + case None() => true + }} + +} + + +object Desugar { + import Types._ + import TypeChecker._ + import Semantics.b2i + + abstract class SimpleE + case class Plus(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Neg(arg : SimpleE) extends SimpleE + case class Ite(cond : SimpleE, thn : SimpleE, els : SimpleE) extends SimpleE + case class Eq(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class LessThan(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Literal(i : Int) extends SimpleE + + @induct + def desugar(e : Trees.Expr) : SimpleE = { e match { + case Trees.Plus (lhs, rhs) => Plus(desugar(lhs), desugar(rhs)) + case Trees.Minus(lhs, rhs) => Plus(desugar(lhs), desugar(rhs)) // FIXME forgot Neg + case Trees.LessThan(lhs, rhs) => LessThan(desugar(lhs), desugar(rhs)) + case Trees.And (lhs, rhs) => Ite(desugar(lhs), desugar(rhs), Literal(0)) + case Trees.Or (lhs, rhs) => Ite(desugar(lhs), Literal(1), desugar(rhs)) + case Trees.Not(e) => Ite(desugar(e), Literal(0), Literal(1)) + case Trees.Eq(lhs, rhs) => + Eq(desugar(lhs), desugar(rhs)) + case Trees.Ite(cond, thn, els) => Ite(desugar(cond), desugar(thn), desugar(els)) + case Trees.IntLiteral(v) => Literal(v) + case Trees.BoolLiteral(b) => Literal(b2i(b)) + }} ensuring { res => + sem(res) == Semantics.semUntyped(e) + } + + def sem(e : SimpleE) : Int = e match { + case Plus (lhs, rhs) => sem(lhs) + sem(rhs) + case Ite(cond, thn, els) => if (sem(cond) != 0) sem(thn) else sem(els) + case Neg(arg) => -sem(arg) + case Eq(lhs,rhs) => b2i(sem(lhs) == sem(rhs)) + case LessThan(lhs, rhs) => b2i(sem(lhs) < sem(rhs)) + case Literal(i) => i + } + +} diff --git a/testcases/synthesis/repair/Desugar/Desugar3.scala b/testcases/synthesis/repair/Desugar/Desugar3.scala new file mode 100644 index 000000000..ec61a78a5 --- /dev/null +++ b/testcases/synthesis/repair/Desugar/Desugar3.scala @@ -0,0 +1,173 @@ +import leon.lang._ +import leon.annotation._ +import leon.collection._ +import leon._ + +object Trees { + abstract class Expr + case class Plus(lhs: Expr, rhs: Expr) extends Expr + case class Minus(lhs: Expr, rhs: Expr) extends Expr + case class LessThan(lhs: Expr, rhs: Expr) extends Expr + case class And(lhs: Expr, rhs: Expr) extends Expr + case class Or(lhs: Expr, rhs: Expr) extends Expr + case class Not(e : Expr) extends Expr + case class Eq(lhs: Expr, rhs: Expr) extends Expr + case class Ite(cond: Expr, thn: Expr, els: Expr) extends Expr + case class IntLiteral(v: Int) extends Expr + case class BoolLiteral(b : Boolean) extends Expr +} + +object Types { + abstract class Type + case object IntType extends Type + case object BoolType extends Type +} + + +object TypeChecker { + import Trees._ + import Types._ + + def typeOf(e :Expr) : Option[Type] = e match { + case Plus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case Minus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case LessThan(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(BoolType) + case _ => None() + } + case And(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Or(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Not(e) => typeOf(e) match { + case Some(BoolType) => Some(BoolType) + case _ => None() + } + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case (Some(t1), Some(t2)) if t1 == t2 => Some(BoolType) + case _ => None() + } + case Ite(c, th, el) => (typeOf(c), typeOf(th), typeOf(el)) match { + case (Some(BoolType), Some(t1), Some(t2)) if t1 == t2 => Some(t1) + case _ => None() + } + case IntLiteral(_) => Some(IntType) + case BoolLiteral(_) => Some(BoolType) + } + + def typeChecks(e : Expr) = typeOf(e).isDefined +} + + +object Semantics { + import Trees._ + import Types._ + import TypeChecker._ + + def semI(t : Expr) : Int = { + require( typeOf(t) == ( Some(IntType) : Option[Type] )) + t match { + case Plus(lhs , rhs) => semI(lhs) + semI(rhs) + case Minus(lhs , rhs) => semI(lhs) - semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semI(thn) else semI(els) + case IntLiteral(v) => v + } + } + + def semB(t : Expr) : Boolean = { + require( (Some(BoolType): Option[Type]) == typeOf(t)) + t match { + case And(lhs, rhs ) => semB(lhs) && semB(rhs) + case Or(lhs , rhs ) => semB(lhs) || semB(rhs) + case Not(e) => !semB(e) + case LessThan(lhs, rhs) => semI(lhs) < semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semB(thn) else semB(els) + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case ( Some(IntType), Some(IntType) ) => semI(lhs) == semI(rhs) + case ( Some(BoolType), Some(BoolType) ) => semB(lhs) == semB(rhs) + } + case BoolLiteral(b) => b + } + } + + def b2i(b : Boolean) = if (b) 1 else 0 + + @induct + def semUntyped( t : Expr) : Int = { t match { + case Plus (lhs, rhs) => semUntyped(lhs) + semUntyped(rhs) + case Minus(lhs, rhs) => semUntyped(lhs) - semUntyped(rhs) + case And (lhs, rhs) => if (semUntyped(lhs)!=0) semUntyped(rhs) else 0 + case Or(lhs, rhs ) => + if (semUntyped(lhs) == 0) semUntyped(rhs) else 1 + case Not(e) => + b2i(semUntyped(e) == 0) + case LessThan(lhs, rhs) => + b2i(semUntyped(lhs) < semUntyped(rhs)) + case Eq(lhs, rhs) => + b2i(semUntyped(lhs) == semUntyped(rhs)) + case Ite(cond, thn, els) => + if (semUntyped(cond) == 0) semUntyped(els) else semUntyped(thn) + case IntLiteral(v) => v + case BoolLiteral(b) => b2i(b) + }} ensuring { res => typeOf(t) match { + case Some(IntType) => res == semI(t) + case Some(BoolType) => res == b2i(semB(t)) + case None() => true + }} + +} + + +object Desugar { + import Types._ + import TypeChecker._ + import Semantics.b2i + + abstract class SimpleE + case class Plus(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Neg(arg : SimpleE) extends SimpleE + case class Ite(cond : SimpleE, thn : SimpleE, els : SimpleE) extends SimpleE + case class Eq(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class LessThan(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Literal(i : Int) extends SimpleE + + @induct + def desugar(e : Trees.Expr) : SimpleE = { e match { + case Trees.Plus (lhs, rhs) => Plus(desugar(lhs), desugar(rhs)) + case Trees.Minus(lhs, rhs) => Plus(desugar(lhs), Neg(desugar(rhs))) + case Trees.LessThan(lhs, rhs) => LessThan(desugar(lhs), desugar(rhs)) + case Trees.And (lhs, rhs) => Ite(desugar(lhs), desugar(rhs), Literal(0)) + case Trees.Or (lhs, rhs) => Ite(desugar(lhs), Literal(1), desugar(rhs)) + case Trees.Not(e) => Ite(desugar(e), Literal(0), Literal(1)) + case Trees.Eq(lhs, rhs) => + Eq(desugar(lhs), desugar(rhs)) + // FIXME switched the branches + case Trees.Ite(cond, thn, els) => Ite(desugar(cond), desugar(els), desugar(thn)) + case Trees.IntLiteral(v) => Literal(v) + case Trees.BoolLiteral(b) => Literal(b2i(b)) + }} ensuring { res => + sem(res) == Semantics.semUntyped(e) + } + + def sem(e : SimpleE) : Int = e match { + case Plus (lhs, rhs) => sem(lhs) + sem(rhs) + case Ite(cond, thn, els) => if (sem(cond) != 0) sem(thn) else sem(els) + case Neg(arg) => -sem(arg) + case Eq(lhs,rhs) => b2i(sem(lhs) == sem(rhs)) + case LessThan(lhs, rhs) => b2i(sem(lhs) < sem(rhs)) + case Literal(i) => i + } + +} diff --git a/testcases/synthesis/repair/Desugar/Desugar4.scala b/testcases/synthesis/repair/Desugar/Desugar4.scala new file mode 100644 index 000000000..9f6ac963a --- /dev/null +++ b/testcases/synthesis/repair/Desugar/Desugar4.scala @@ -0,0 +1,172 @@ +import leon.lang._ +import leon.annotation._ +import leon.collection._ +import leon._ + +object Trees { + abstract class Expr + case class Plus(lhs: Expr, rhs: Expr) extends Expr + case class Minus(lhs: Expr, rhs: Expr) extends Expr + case class LessThan(lhs: Expr, rhs: Expr) extends Expr + case class And(lhs: Expr, rhs: Expr) extends Expr + case class Or(lhs: Expr, rhs: Expr) extends Expr + case class Not(e : Expr) extends Expr + case class Eq(lhs: Expr, rhs: Expr) extends Expr + case class Ite(cond: Expr, thn: Expr, els: Expr) extends Expr + case class IntLiteral(v: Int) extends Expr + case class BoolLiteral(b : Boolean) extends Expr +} + +object Types { + abstract class Type + case object IntType extends Type + case object BoolType extends Type +} + + +object TypeChecker { + import Trees._ + import Types._ + + def typeOf(e :Expr) : Option[Type] = e match { + case Plus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case Minus(l,r) => (typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(IntType) + case _ => None() + } + case LessThan(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(IntType), Some(IntType)) => Some(BoolType) + case _ => None() + } + case And(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Or(l,r) => ( typeOf(l), typeOf(r)) match { + case (Some(BoolType), Some(BoolType)) => Some(BoolType) + case _ => None() + } + case Not(e) => typeOf(e) match { + case Some(BoolType) => Some(BoolType) + case _ => None() + } + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case (Some(t1), Some(t2)) if t1 == t2 => Some(BoolType) + case _ => None() + } + case Ite(c, th, el) => (typeOf(c), typeOf(th), typeOf(el)) match { + case (Some(BoolType), Some(t1), Some(t2)) if t1 == t2 => Some(t1) + case _ => None() + } + case IntLiteral(_) => Some(IntType) + case BoolLiteral(_) => Some(BoolType) + } + + def typeChecks(e : Expr) = typeOf(e).isDefined +} + + +object Semantics { + import Trees._ + import Types._ + import TypeChecker._ + + def semI(t : Expr) : Int = { + require( typeOf(t) == ( Some(IntType) : Option[Type] )) + t match { + case Plus(lhs , rhs) => semI(lhs) + semI(rhs) + case Minus(lhs , rhs) => semI(lhs) - semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semI(thn) else semI(els) + case IntLiteral(v) => v + } + } + + def semB(t : Expr) : Boolean = { + require( (Some(BoolType): Option[Type]) == typeOf(t)) + t match { + case And(lhs, rhs ) => semB(lhs) && semB(rhs) + case Or(lhs , rhs ) => semB(lhs) || semB(rhs) + case Not(e) => !semB(e) + case LessThan(lhs, rhs) => semI(lhs) < semI(rhs) + case Ite(cond, thn, els) => + if (semB(cond)) semB(thn) else semB(els) + case Eq(lhs, rhs) => (typeOf(lhs), typeOf(rhs)) match { + case ( Some(IntType), Some(IntType) ) => semI(lhs) == semI(rhs) + case ( Some(BoolType), Some(BoolType) ) => semB(lhs) == semB(rhs) + } + case BoolLiteral(b) => b + } + } + + def b2i(b : Boolean) = if (b) 1 else 0 + + @induct + def semUntyped( t : Expr) : Int = { t match { + case Plus (lhs, rhs) => semUntyped(lhs) + semUntyped(rhs) + case Minus(lhs, rhs) => semUntyped(lhs) - semUntyped(rhs) + case And (lhs, rhs) => if (semUntyped(lhs)!=0) semUntyped(rhs) else 0 + case Or(lhs, rhs ) => + if (semUntyped(lhs) == 0) semUntyped(rhs) else 1 + case Not(e) => + b2i(semUntyped(e) == 0) + case LessThan(lhs, rhs) => + b2i(semUntyped(lhs) < semUntyped(rhs)) + case Eq(lhs, rhs) => + b2i(semUntyped(lhs) == semUntyped(rhs)) + case Ite(cond, thn, els) => + if (semUntyped(cond) == 0) semUntyped(els) else semUntyped(thn) + case IntLiteral(v) => v + case BoolLiteral(b) => b2i(b) + }} ensuring { res => typeOf(t) match { + case Some(IntType) => res == semI(t) + case Some(BoolType) => res == b2i(semB(t)) + case None() => true + }} + +} + + +object Desugar { + import Types._ + import TypeChecker._ + import Semantics.b2i + + abstract class SimpleE + case class Plus(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Neg(arg : SimpleE) extends SimpleE + case class Ite(cond : SimpleE, thn : SimpleE, els : SimpleE) extends SimpleE + case class Eq(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class LessThan(lhs : SimpleE, rhs : SimpleE) extends SimpleE + case class Literal(i : Int) extends SimpleE + + @induct + def desugar(e : Trees.Expr) : SimpleE = { e match { + case Trees.Plus (lhs, rhs) => Plus(desugar(lhs), desugar(rhs)) + case Trees.Minus(lhs, rhs) => Plus(desugar(lhs), Neg(desugar(rhs))) + case Trees.LessThan(lhs, rhs) => LessThan(desugar(lhs), desugar(rhs)) + case Trees.And (lhs, rhs) => Ite(desugar(lhs), desugar(rhs), Literal(0)) + case Trees.Or (lhs, rhs) => Ite(desugar(lhs), Literal(1), desugar(rhs)) + case Trees.Not(e) => Ite(desugar(e), Literal(1), Literal(1)) // FIXME else should be 0 + case Trees.Eq(lhs, rhs) => + Eq(desugar(lhs), desugar(rhs)) + case Trees.Ite(cond, thn, els) => Ite(desugar(cond), desugar(thn), desugar(els)) + case Trees.IntLiteral(v) => Literal(v) + case Trees.BoolLiteral(b) => Literal(b2i(b)) + }} ensuring { res => + sem(res) == Semantics.semUntyped(e) + } + + def sem(e : SimpleE) : Int = e match { + case Plus (lhs, rhs) => sem(lhs) + sem(rhs) + case Ite(cond, thn, els) => if (sem(cond) != 0) sem(thn) else sem(els) + case Neg(arg) => -sem(arg) + case Eq(lhs,rhs) => b2i(sem(lhs) == sem(rhs)) + case LessThan(lhs, rhs) => b2i(sem(lhs) < sem(rhs)) + case Literal(i) => i + } + +} diff --git a/testcases/synthesis/repair/Parser/Parser1.scala b/testcases/synthesis/repair/Parser/Parser1.scala new file mode 100644 index 000000000..1a12b820c --- /dev/null +++ b/testcases/synthesis/repair/Parser/Parser1.scala @@ -0,0 +1,58 @@ +import leon._ +import leon.collection._ + +object Parser { + abstract class Token + case object LParen extends Token + case object RParen extends Token + case class Id(id : Int) extends Token + + abstract class Tree + case class App(args : List[Tree]) extends Tree + case class Leaf(id : Int) extends Tree + + def parse(in : List[Token]) : (Option[Tree], List[Token]) = { in match { + case Cons(Id(s), tl) => + (Some[Tree](Leaf(s)),tl) + case Cons(LParen, tl) => parseMany(tl) match { + case (Some(trees:Cons[Tree]), Cons(RParen,rest)) => + (Some[Tree](App(trees)), rest) + case (_, rest) => (None[Tree](), rest) + } + case _ => (None[Tree](), in) + }} ensuring { _ match { + case ( Some(tree), rest@Cons(h,_)) => + print(tree, rest) == in + case ( None(), Cons(h,_) ) => + h == RParen + case _ => true + }} + + def parseMany(in : List[Token]) : (Option[List[Tree]], List[Token]) = { parse(in) match { + case (None(), rest) /*if rest == in*/ => (Some[List[Tree]](Nil()), in) // FIXME: forgot condition + //case (None(), rest) => (None[List[Tree]](), rest) + case (Some(tree), rest) => parseMany(rest) match { + case ( None(), rest2) => (None[List[Tree]](), rest2) + case ( Some(trees), rest2) => + ( Some[List[Tree]](tree::trees), rest2 ) + } + }} ensuring { _ match { + case ( Some(t), rest@Cons(h, _) ) => + h == RParen && printL(t, rest) == in + case ( None(), Cons(h, _)) => + h == RParen + case _ => true + }} + + + def printL(args : List[Tree], rest : List[Token]) : List[Token] = args match { + case Nil() => rest + case Cons(h,t) => print(h, printL(t, rest)) + } + + def print(t : Tree, rest : List[Token]) : List[Token] = t match { + case Leaf(s) => Id(s) :: rest + case App(args) => LParen :: printL(args, RParen :: rest) + } + +} diff --git a/testcases/synthesis/repair/Parser/Parser2.scala b/testcases/synthesis/repair/Parser/Parser2.scala new file mode 100644 index 000000000..24fef5686 --- /dev/null +++ b/testcases/synthesis/repair/Parser/Parser2.scala @@ -0,0 +1,58 @@ +import leon._ +import leon.collection._ + +object Parser { + abstract class Token + case object LParen extends Token + case object RParen extends Token + case class Id(id : Int) extends Token + + abstract class Tree + case class App(args : List[Tree]) extends Tree + case class Leaf(id : Int) extends Tree + + def parse(in : List[Token]) : (Option[Tree], List[Token]) = { in match { + case Cons(Id(s), tl) => + (Some[Tree](Leaf(s)),tl) + case Cons(LParen, tl) => parseMany(tl) match { + case (Some(trees:Cons[Tree]), Cons(RParen,rest)) => + (Some[Tree](App(trees)), rest) + case (_, rest) => (None[Tree](), rest) + } + case _ => (None[Tree](), in) + }} ensuring { _ match { + case ( Some(tree), rest@Cons(h,_)) => + print(tree, rest) == in + case ( None(), Cons(h,_) ) => + h == RParen + case _ => true + }} + + def parseMany(in : List[Token]) : (Option[List[Tree]], List[Token]) = { parse(in) match { + case (None(), rest) if rest == in => (Some[List[Tree]](Nil()), in) + case (None(), rest) => (None[List[Tree]](), rest) + case (Some(tree), rest) => parseMany(rest) match { + case ( None(), rest2) => (None[List[Tree]](), rest2) + case ( Some(trees), rest2) => + ( Some[List[Tree]](trees), rest2 ) // FIXME: should be tree::trees + } + }} ensuring { _ match { + case ( Some(t), rest@Cons(h, _) ) => + h == RParen && printL(t, rest) == in + case ( None(), Cons(h, _)) => + h == RParen + case _ => true + }} + + + def printL(args : List[Tree], rest : List[Token]) : List[Token] = args match { + case Nil() => rest + case Cons(h,t) => print(h, printL(t, rest)) + } + + def print(t : Tree, rest : List[Token]) : List[Token] = t match { + case Leaf(s) => Id(s) :: rest + case App(args) => LParen :: printL(args, RParen :: rest) + } + +} diff --git a/testcases/synthesis/repair/Parser/Parser3.scala b/testcases/synthesis/repair/Parser/Parser3.scala new file mode 100644 index 000000000..dcc8107f3 --- /dev/null +++ b/testcases/synthesis/repair/Parser/Parser3.scala @@ -0,0 +1,58 @@ +import leon._ +import leon.collection._ + +object Parser { + abstract class Token + case object LParen extends Token + case object RParen extends Token + case class Id(id : Int) extends Token + + abstract class Tree + case class App(args : List[Tree]) extends Tree + case class Leaf(id : Int) extends Tree + + def parse(in : List[Token]) : (Option[Tree], List[Token]) = { in match { + case Cons(Id(s), tl) => + (Some[Tree](Leaf(s)),tl) + case Cons(LParen, tl) => parseMany(tl) match { + case (Some(trees:Cons[Tree]), Cons(RParen,rest)) => + (Some[Tree](App(trees)), rest) + case (_, rest) => (None[Tree](), rest) + } + case _ => (None[Tree](), in) + }} ensuring { _ match { + case ( Some(tree), rest@Cons(h,_)) => + print(tree, rest) == in + case ( None(), Cons(h,_) ) => + h == RParen + case _ => true + }} + + def parseMany(in : List[Token]) : (Option[List[Tree]], List[Token]) = { parse(in) match { + case (None(), rest) if rest == in => (Some[List[Tree]](Nil()), in) + case (None(), rest) => (None[List[Tree]](), rest) + case (Some(tree), rest) => parseMany(rest) match { + case ( None(), rest2) => (None[List[Tree]](), rest2) + case ( Some(trees), rest2) => + ( Some[List[Tree]](tree::trees), rest2 ) + } + }} ensuring { _ match { + case ( Some(t), rest@Cons(h, _) ) => + h == RParen && printL(t, rest) == in + case ( None(), Cons(h, _)) => + h == RParen + case _ => true + }} + + + def printL(args : List[Tree], rest : List[Token]) : List[Token] = args match { + case Nil() => rest + case Cons(h,t) => print(h, printL(t, rest)) + } + + def print(t : Tree, rest : List[Token]) : List[Token] = t match { + case Leaf(s) => Id(s) :: rest + case App(args) => LParen :: printL(args, RParen :: rest) + } + +} diff --git a/testcases/synthesis/repair/Parser/Parser4.scala b/testcases/synthesis/repair/Parser/Parser4.scala new file mode 100644 index 000000000..dcc8107f3 --- /dev/null +++ b/testcases/synthesis/repair/Parser/Parser4.scala @@ -0,0 +1,58 @@ +import leon._ +import leon.collection._ + +object Parser { + abstract class Token + case object LParen extends Token + case object RParen extends Token + case class Id(id : Int) extends Token + + abstract class Tree + case class App(args : List[Tree]) extends Tree + case class Leaf(id : Int) extends Tree + + def parse(in : List[Token]) : (Option[Tree], List[Token]) = { in match { + case Cons(Id(s), tl) => + (Some[Tree](Leaf(s)),tl) + case Cons(LParen, tl) => parseMany(tl) match { + case (Some(trees:Cons[Tree]), Cons(RParen,rest)) => + (Some[Tree](App(trees)), rest) + case (_, rest) => (None[Tree](), rest) + } + case _ => (None[Tree](), in) + }} ensuring { _ match { + case ( Some(tree), rest@Cons(h,_)) => + print(tree, rest) == in + case ( None(), Cons(h,_) ) => + h == RParen + case _ => true + }} + + def parseMany(in : List[Token]) : (Option[List[Tree]], List[Token]) = { parse(in) match { + case (None(), rest) if rest == in => (Some[List[Tree]](Nil()), in) + case (None(), rest) => (None[List[Tree]](), rest) + case (Some(tree), rest) => parseMany(rest) match { + case ( None(), rest2) => (None[List[Tree]](), rest2) + case ( Some(trees), rest2) => + ( Some[List[Tree]](tree::trees), rest2 ) + } + }} ensuring { _ match { + case ( Some(t), rest@Cons(h, _) ) => + h == RParen && printL(t, rest) == in + case ( None(), Cons(h, _)) => + h == RParen + case _ => true + }} + + + def printL(args : List[Tree], rest : List[Token]) : List[Token] = args match { + case Nil() => rest + case Cons(h,t) => print(h, printL(t, rest)) + } + + def print(t : Tree, rest : List[Token]) : List[Token] = t match { + case Leaf(s) => Id(s) :: rest + case App(args) => LParen :: printL(args, RParen :: rest) + } + +} diff --git a/testcases/synthesis/repair/Parser/Parser5.scala b/testcases/synthesis/repair/Parser/Parser5.scala new file mode 100644 index 000000000..dcc8107f3 --- /dev/null +++ b/testcases/synthesis/repair/Parser/Parser5.scala @@ -0,0 +1,58 @@ +import leon._ +import leon.collection._ + +object Parser { + abstract class Token + case object LParen extends Token + case object RParen extends Token + case class Id(id : Int) extends Token + + abstract class Tree + case class App(args : List[Tree]) extends Tree + case class Leaf(id : Int) extends Tree + + def parse(in : List[Token]) : (Option[Tree], List[Token]) = { in match { + case Cons(Id(s), tl) => + (Some[Tree](Leaf(s)),tl) + case Cons(LParen, tl) => parseMany(tl) match { + case (Some(trees:Cons[Tree]), Cons(RParen,rest)) => + (Some[Tree](App(trees)), rest) + case (_, rest) => (None[Tree](), rest) + } + case _ => (None[Tree](), in) + }} ensuring { _ match { + case ( Some(tree), rest@Cons(h,_)) => + print(tree, rest) == in + case ( None(), Cons(h,_) ) => + h == RParen + case _ => true + }} + + def parseMany(in : List[Token]) : (Option[List[Tree]], List[Token]) = { parse(in) match { + case (None(), rest) if rest == in => (Some[List[Tree]](Nil()), in) + case (None(), rest) => (None[List[Tree]](), rest) + case (Some(tree), rest) => parseMany(rest) match { + case ( None(), rest2) => (None[List[Tree]](), rest2) + case ( Some(trees), rest2) => + ( Some[List[Tree]](tree::trees), rest2 ) + } + }} ensuring { _ match { + case ( Some(t), rest@Cons(h, _) ) => + h == RParen && printL(t, rest) == in + case ( None(), Cons(h, _)) => + h == RParen + case _ => true + }} + + + def printL(args : List[Tree], rest : List[Token]) : List[Token] = args match { + case Nil() => rest + case Cons(h,t) => print(h, printL(t, rest)) + } + + def print(t : Tree, rest : List[Token]) : List[Token] = t match { + case Leaf(s) => Id(s) :: rest + case App(args) => LParen :: printL(args, RParen :: rest) + } + +} diff --git a/testcases/synthesis/repair/PropLogic/PropLogic5.scala b/testcases/synthesis/repair/PropLogic/PropLogic2.scala similarity index 88% rename from testcases/synthesis/repair/PropLogic/PropLogic5.scala rename to testcases/synthesis/repair/PropLogic/PropLogic2.scala index d86d184ed..192f7e3e7 100644 --- a/testcases/synthesis/repair/PropLogic/PropLogic5.scala +++ b/testcases/synthesis/repair/PropLogic/PropLogic2.scala @@ -30,15 +30,14 @@ object SemanticsPreservation { case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs))) case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs))) case Not(Const(v)) => Const(!v) - case Not(Not(e)) => nnf(e) case And(lhs, rhs) => And(nnf(lhs), nnf(rhs)) case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs)) + // FIXME: forgot to handle the Not(Not(_)) case case other => other }} ensuring { res => - isNNF(res) && ((formula, res) passes { - case Not(And(Const(a), Const(b))) => Or(Const(!a), Const(!b)) - case x@And(Literal(_), Literal(_)) => x - }) + isNNF(res) && ((formula, res) passes { + case Not(Not(Not(Const(a)))) => Const(!a) + }) } def isNNF(f : Formula) : Boolean = f match { @@ -58,7 +57,7 @@ object SemanticsPreservation { case Or(_, Const(true)) => Const(true) case Or(Const(false), e) => partEval(e) case Or(e, Const(false)) => partEval(e) - case Not(Const(c)) => Const(c) // FIXME should be !c + case Not(Const(c)) => Const(!c) case other => other }} ensuring { size(_) <= size(formula) } diff --git a/testcases/synthesis/repair/PropLogic/PropLogic3.scala b/testcases/synthesis/repair/PropLogic/PropLogic3.scala index 600c59ed2..b65f6e2a2 100644 --- a/testcases/synthesis/repair/PropLogic/PropLogic3.scala +++ b/testcases/synthesis/repair/PropLogic/PropLogic3.scala @@ -29,16 +29,16 @@ object SemanticsPreservation { def nnf(formula : Formula) : Formula = { formula match { case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs))) case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs))) - case Not(Const(v)) => Const(!v) + case Not(Const(v)) => Const(v) // FIXME should be !v. + case Not(Not(e)) => nnf(e) case And(lhs, rhs) => And(nnf(lhs), nnf(rhs)) case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs)) - // FIXME: forgot to handle the Not(Not(_)) case case other => other - }} ensuring { res => - isNNF(res) && ((formula, res) passes { - case Not(And(Const(a), Const(b))) => Or(Const(!a), Const(!b)) - case x@And(Literal(_), Literal(_)) => x - }) + }} ensuring { res => + isNNF(res) && ((formula, res) passes { + case Not(Const(true)) => Const(false) + case Not(Const(false)) => Const(true) + }) } def isNNF(f : Formula) : Boolean = f match { @@ -49,23 +49,4 @@ object SemanticsPreservation { case _ => true } - def partEval(formula : Formula) : Formula = { formula match { - case And(Const(false), _ ) => Const(false) - case And(_, Const(false)) => Const(false) - case And(Const(true), e) => partEval(e) - case And(e, Const(true)) => partEval(e) - case Or(Const(true), _ ) => Const(true) - case Or(_, Const(true)) => Const(true) - case Or(Const(false), e) => partEval(e) - case Or(e, Const(false)) => partEval(e) - case Not(Const(c)) => Const(!c) - case other => other - }} ensuring { size(_) <= size(formula) } - - - @induct - def partEvalSound (f : Formula, env : Set[Int]) = { - eval(partEval(f))(env) == eval(f)(env) - }.holds - } diff --git a/testcases/synthesis/repair/PropLogic/PropLogic4.scala b/testcases/synthesis/repair/PropLogic/PropLogic4.scala index facbe08aa..20e44fe92 100644 --- a/testcases/synthesis/repair/PropLogic/PropLogic4.scala +++ b/testcases/synthesis/repair/PropLogic/PropLogic4.scala @@ -1,3 +1,4 @@ +// Fails import leon.lang._ import leon.annotation._ import leon.collection._ @@ -32,13 +33,12 @@ object SemanticsPreservation { case Not(Const(v)) => Const(!v) case Not(Not(e)) => nnf(e) case And(lhs, rhs) => And(nnf(lhs), nnf(rhs)) - case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs)) + case Or(lhs, rhs) => And(nnf(lhs), nnf(rhs)) // FIXME should be Or case other => other }} ensuring { res => - isNNF(res) && ((formula, res) passes { - case Not(And(Const(a), Const(b))) => Or(Const(!a), Const(!b)) - case x@And(Literal(_), Literal(_)) => x - }) + isNNF(res) && ((formula, res) passes { + case Or(Not(Const(c)), Not(Literal(l))) => Or(Const(c), Not(Literal(l))) + }) } def isNNF(f : Formula) : Boolean = f match { @@ -49,24 +49,4 @@ object SemanticsPreservation { case _ => true } - def partEval(formula : Formula) : Formula = { formula match { - case And(Const(false), _ ) => Const(false) - case And(_, Const(false)) => Const(false) - case And(Const(true), e) => partEval(e) - case And(e, Const(true)) => partEval(e) - // FIXME (hard!) : treats Or as And - case Or(Const(false), _ ) => Const(false) - case Or(_, Const(false)) => Const(false) - case Or(Const(true), e) => partEval(e) - case Or(e, Const(true)) => partEval(e) - case Not(Const(c)) => Const(!c) - case other => other - }} ensuring { size(_) <= size(formula) } - - - @induct - def partEvalSound (f : Formula, env : Set[Int]) = { - eval(partEval(f))(env) == eval(f)(env) - }.holds - } diff --git a/testcases/synthesis/repair/PropLogic/PropLogic6.scala b/testcases/synthesis/repair/PropLogic/PropLogic6.scala deleted file mode 100644 index 4fee819e2..000000000 --- a/testcases/synthesis/repair/PropLogic/PropLogic6.scala +++ /dev/null @@ -1,73 +0,0 @@ -import leon.lang._ -import leon.annotation._ -import leon.collection._ - -object SemanticsPreservation { - - sealed abstract class Formula - case class And(lhs : Formula, rhs : Formula) extends Formula - case class Or(lhs : Formula, rhs : Formula) extends Formula - case class Not(f: Formula) extends Formula - case class Const(v: Boolean) extends Formula - case class Literal(id: Int) extends Formula - - def size(f : Formula) : Int = { f match { - case And(l,r) => 1 + size(l) + size(r) - case Or(l,r) => 1 + size(l) + size(r) - case Not(e) => 1 + size(e) - case _ => 1 - }} ensuring { _ >= 0 } - - def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match { - case And(lhs, rhs) => eval(lhs) && eval(rhs) - case Or(lhs, rhs) => eval(lhs) || eval(rhs) - case Not(f) => !eval(f) - case Const(v) => v - case Literal(id) => trueVars contains id - } - - def nnf(formula : Formula) : Formula = { formula match { - case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs))) - case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs))) - case Not(Const(v)) => Const(!v) - case Not(Not(e)) => nnf(e) - case And(lhs, rhs) => And(nnf(lhs), nnf(rhs)) - case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs)) - case other => other - }} ensuring { res => - isNNF(res) && ((formula, res) passes { - case Not(And(Const(a), Const(b))) => Or(Const(!a), Const(!b)) - case x@And(Literal(_), Literal(_)) => x - }) - } - - def isNNF(f : Formula) : Boolean = f match { - case Not(Literal(_)) => true - case Not(_) => false - case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs) - case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs) - case _ => true - } - - def partEval(formula : Formula) : Formula = { formula match { - case And(Const(false), _ ) => Const(false) - case And(_, Const(false)) => Const(false) - case And(Const(true), e) => partEval(e) - case And(e, Const(true)) => partEval(e) - case Or(Const(true), _ ) => Const(true) - case Or(_, Const(true)) => Const(true) - case Or(Const(false), e) => partEval(e) - case Or(e, Const(false)) => partEval(e) - case Not(Const(c)) => Const(!c) - case other => other - }} ensuring { size(_) < size(formula) } - // FIXME: should be <= - // Can you realize you cannot fix this without breaking partEvalSound? - - - @induct - def partEvalSound (f : Formula, env : Set[Int]) = { - eval(partEval(f))(env) == eval(f)(env) - }.holds - -} -- GitLab