diff --git a/library/proof/Internal.scala b/library/proof/Internal.scala new file mode 100644 index 0000000000000000000000000000000000000000..3ac2903103998e0add424c95a8e213f23d94d5a4 --- /dev/null +++ b/library/proof/Internal.scala @@ -0,0 +1,61 @@ +/* Copyright 2009-2014 EPFL, Lausanne */ +package leon.proof + +import leon.lang._ + +/** Internal helper classes and methods for the 'proof' package. */ +object Internal { + + /*** Helper classes for relational reasoning ***/ + + case class WithRel[A, B](x: A, r: (A, B) => Boolean, prop: Boolean) { + + /** Continue with the next relation. */ + def ^^(y: B): RelReasoning[B] = { + require(prop ==> r(x, y)) + RelReasoning(y, prop && r(x, y)) + } + + /** Add a proof. */ + def ^^|(proof: Boolean): WithProof[A, B] = { + require(proof) + WithProof(x, r, proof, prop) + } + + /** Short-hand for equational reasoning. */ + def ==|(proof: Boolean): WithProof[A, A] = { + require(proof) + WithProof(x, _ == _, proof, prop) + } + + def qed: Boolean = prop + } + + case class WithProof[A, B]( + x: A, r: (A, B) => Boolean, proof: Boolean, prop: Boolean) { + + /** Close a proof. */ + def |[C](that: WithProof[B, C]): WithProof[B, C] = { + require(this.prop && this.proof ==> this.r(this.x, that.x)) + WithProof( + that.x, that.r, that.proof, + this.prop && this.proof && this.r(this.x, that.x)) + } + + /** Close a proof. */ + def |[C](that: WithRel[B, C]): WithRel[B, C] = { + require(this.prop && this.proof ==> this.r(this.x, that.x)) + WithRel( + that.x, that.r, + this.prop && this.proof && this.r(this.x, that.x)) + } + + /** Close a proof. */ + def |(that: RelReasoning[B]): RelReasoning[B] = { + require(this.prop && this.proof ==> this.r(this.x, that.x)) + RelReasoning( + that.x, + this.prop && this.proof && this.r(this.x, that.x)) + } + } +} diff --git a/library/proof/package.scala b/library/proof/package.scala new file mode 100644 index 0000000000000000000000000000000000000000..fd07a8128439127a8c80b6f977a4f01d162415d9 --- /dev/null +++ b/library/proof/package.scala @@ -0,0 +1,59 @@ +/* Copyright 2009-2014 EPFL, Lausanne */ +package leon + +import leon.annotation._ +import leon.lang._ +import scala.language.implicitConversions + +import leon.proof.Internal._ + +package object proof { + + case class ProofOps(prop: Boolean) { + def because(proof: Boolean): Boolean = proof && prop + def neverHolds: Boolean = { + require(!prop) + !prop + } + } + + implicit def boolean2ProofOps(prop: Boolean): ProofOps = ProofOps(prop) + + def trivial: Boolean = true + + def by(proof: Boolean)(prop: Boolean): Boolean = + proof && prop + + def check(prop: Boolean): Boolean = { + require(prop) + prop + } + + /** + * Relational reasoning. + * + * { + * ((y :: ys) :+ x).last ^^ _ == _ ^^| trivial | + * (y :: (ys :+ x)).last ==| trivial | + * (ys :+ x).last ==| snocLast(ys, x) | + * x + * }.qed + */ + case class RelReasoning[A](x: A, prop: Boolean) { + + def ^^[B](r: (A, B) => Boolean): WithRel[A, B] = WithRel(x, r, prop) + + /** Short-hand for equational reasoning. */ + def ==|(proof: Boolean): WithProof[A, A] = { + require(proof) + WithProof(x, _ == _, proof, prop) + } + + def qed: Boolean = prop + } + + implicit def any2RelReasoning[A](x: A): RelReasoning[A] = + RelReasoning(x, true) + +} +