Skip to content
Snippets Groups Projects
Commit 847511c1 authored by Manos Koukoutos's avatar Manos Koukoutos
Browse files

Improvements to Path

Bindings get bubbled as early in the sequence of bindings/conditions as possible

Define Element type

'true' conditions get filtered out
parent 685d25ba
No related branches found
No related tags found
No related merge requests found
...@@ -11,6 +11,7 @@ import ExprOps._ ...@@ -11,6 +11,7 @@ import ExprOps._
import Types._ import Types._
object Path { object Path {
final type Element = Either[(Identifier, Expr), Expr]
def empty: Path = new Path(Seq.empty) def empty: Path = new Path(Seq.empty)
def apply(p: Expr): Path = p match { def apply(p: Expr): Path = p match {
case Let(i, e, b) => new Path(Seq(Left(i -> e))) merge apply(b) case Let(i, e, b) => new Path(Seq(Left(i -> e))) merge apply(b)
...@@ -26,18 +27,30 @@ object Path { ...@@ -26,18 +27,30 @@ object Path {
* in the context of the provided let-bindings. * in the context of the provided let-bindings.
* *
* This encoding enables let-bindings over types for which equality is * This encoding enables let-bindings over types for which equality is
* not defined, whereas previous encoding of let-bindings into equals * not defined, whereas an encoding of let-bindings with equalities
* could introduce non-sensical equations. * could introduce non-sensical equations.
*/ */
class Path private[purescala]( class Path private[purescala](
private[purescala] val elements: Seq[Either[(Identifier, Expr), Expr]]) extends Printable { private[purescala] val elements: Seq[Path.Element]) extends Printable {
import Path.Element
/** Add a binding to this [[Path]] */ /** Add a binding to this [[Path]] */
def withBinding(p: (Identifier, Expr)) = new Path(elements :+ Left(p)) def withBinding(p: (Identifier, Expr)) = {
def withBindings(ps: Iterable[(Identifier, Expr)]) = new Path(elements ++ ps.map(Left(_))) def exprOf(e: Element) = e match { case Right(e) => e; case Left((_, e)) => e }
val (before, after) = elements span (el => !variablesOf(exprOf(el)).contains(p._1))
new Path(before ++ Seq(Left(p)) ++ after)
}
def withBindings(ps: Iterable[(Identifier, Expr)]) = {
ps.foldLeft(this)( _ withBinding _ )
}
/** Add a condition to this [[Path]] */ /** Add a condition to this [[Path]] */
def withCond(e: Expr) = new Path(elements :+ Right(e)) def withCond(e: Expr) = {
def withConds(es: Iterable[Expr]) = new Path(elements ++ es.map(Right(_))) if (e == BooleanLiteral(true)) this
else new Path(elements :+ Right(e))
}
def withConds(es: Iterable[Expr]) = new Path(elements ++ es.filterNot( _ == BooleanLiteral(true)).map(Right(_)))
/** Remove bound variables from this [[Path]] /** Remove bound variables from this [[Path]]
* @param ids the bound variables to remove * @param ids the bound variables to remove
...@@ -131,7 +144,7 @@ class Path private[purescala]( ...@@ -131,7 +144,7 @@ class Path private[purescala](
* for proposition expressions. * for proposition expressions.
*/ */
private def fold[T](base: T, combineLet: (Identifier, Expr, T) => T, combineCond: (Expr, T) => T) private def fold[T](base: T, combineLet: (Identifier, Expr, T) => T, combineCond: (Expr, T) => T)
(elems: Seq[Either[(Identifier, Expr), Expr]]): T = elems.foldRight(base) { (elems: Seq[Element]): T = elems.foldRight(base) {
case (Left((id, e)), res) => combineLet(id, e, res) case (Left((id, e)), res) => combineLet(id, e, res)
case (Right(e), res) => combineCond(e, res) case (Right(e), res) => combineCond(e, res)
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment