
gapt.expr.subst.ExprSubstitutable1.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gapt_3 Show documentation
Show all versions of gapt_3 Show documentation
General Architecture for Proof Theory
The newest version!
package gapt.expr.subst
import gapt.expr.Abs
import gapt.expr.App
import gapt.expr.ClosedUnderSub
import gapt.expr.Const
import gapt.expr.Expr
import gapt.expr.Var
import gapt.expr.ty.{TArr, TBase, TVar, Ty}
import gapt.expr.util.freeVariables
import gapt.expr.util.rename
trait ExprSubstitutable1 {
implicit object SubstitutableTy extends ClosedUnderSub[Ty] {
override def applySubstitution(sub: Substitution, ty: Ty): Ty =
applySubstitution(sub: PreSubstitution, ty)
def applySubstitution(sub: PreSubstitution, ty: Ty): Ty = ty match {
case _ if sub.typeMap.isEmpty => ty
case ty @ TBase(_, Nil) => ty
case TBase(n, ps) => TBase(n, ps.map(applySubstitution(sub, _)))
case TArr(in, out) => applySubstitution(sub, in) ->: applySubstitution(sub, out)
case v @ TVar(_) => sub.typeMap.getOrElse(v, v)
}
}
/**
* The general method for applying substitutions to lambda expressions.
*
* @param sub A substitution.
* @param t A lambda expression.
* @return The substituted lambda expression.
*/
protected def applySub(sub: Substitution, t: Expr): Expr =
if (sub.isIdentity) t
else {
val sub1 = if (sub.typeMap.isEmpty) sub
else {
Substitution(
freeVariables(t).map(v => v -> sub.applyToTypeOnly(v)).toMap ++ sub.map,
sub.typeMap
)
}
go(sub1, t)
}
// if sub.typeMap.nonEmpty, then every free variable must in the domain of sub
private def go(sub: Substitution, t: Expr): Expr = t match {
case _ if sub.isEmpty => t
case v: Var => sub(v)
case c @ Const(x, ty, ps) =>
if (sub.typeMap.isEmpty) c
else
Const(x, SubstitutableTy.applySubstitution(sub, ty), ps.map(SubstitutableTy.applySubstitution(sub, _)))
case App(a, b) => App(go(sub, a), go(sub, b))
case Abs(v, _) if sub.domain contains v =>
go(Substitution(sub.map - v, sub.typeMap), t)
case Abs(v, s) if sub.range contains sub.applyToTypeOnly(v) =>
// It is safe to rename the bound variable to any variable that is not in freeVariables(s).
val newV = rename(v, freeVariables(s) union sub.range)
applySub(sub, Abs(newV, applySub(Substitution(v -> newV), s)))
case Abs(v, s) =>
val newV = sub.applyToTypeOnly(v)
Abs(newV, go(Substitution(sub.map + (v -> newV), sub.typeMap), s))
}
implicit val ExprClosedUnderSub: ClosedUnderSub[Expr] =
(sub, t) => applySub(sub, t)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy