All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gapt.expr.util.syntacticMatching.scala Maven / Gradle / Ivy

The newest version!
package gapt.expr.util

import gapt.expr.Abs
import gapt.expr.App
import gapt.expr.Const
import gapt.expr.Expr
import gapt.expr.Var
import gapt.expr.formula.fol.FOLExpression
import gapt.expr.formula.fol.FOLTerm
import gapt.expr.formula.fol.FOLVar
import gapt.expr.subst.FOLSubstitution
import gapt.expr.subst.PreSubstitution
import gapt.expr.subst.Substitution
import gapt.expr.ty.->:
import gapt.expr.ty.TBase
import gapt.expr.ty.TVar
import gapt.expr.ty.Ty
import gapt.utils.UNone
import gapt.utils.UOption
import gapt.utils.USome

object syntacticMatching {

  private def go(a: Ty, b: Ty, subst: PreSubstitution): UOption[PreSubstitution] =
    (a, b) match {
      case (TBase(an, as), TBase(bn, bs)) if an == bn =>
        go(as, bs, subst)
      case (a: TVar, _) if subst.typeMap.get(a).contains(b) =>
        USome(subst)
      case (a: TVar, _) if !subst.typeMap.contains(a) =>
        USome(subst.+(a, b))
      case (a1 ->: a2, b1 ->: b2) =>
        go(a1, b1, subst) match {
          case USome(subst1) => go(a2, b2, subst1)
          case _             => UNone()
        }
      case _ => UNone()
    }

  private def go(as: List[Ty], bs: List[Ty], subst: PreSubstitution): UOption[PreSubstitution] =
    (as, bs) match {
      case (a :: as_, b :: bs_) =>
        go(a, b, subst) match {
          case USome(subst1) => go(as_, bs_, subst1)
          case _             => UNone()
        }
      case (Nil, Nil) => USome(subst)
      case _          => UNone()
    }

  private def go(a: Expr, b: Expr, subst: PreSubstitution): UOption[PreSubstitution] =
    (a, b) match {
      case (App(a1, b1), App(a2, b2)) =>
        go(a1, a2, subst) match {
          case USome(subst1) => go(b1, b2, subst1)
          case _             => UNone()
        }

      case (Const(n1, ty1, ps1), Const(n2, ty2, ps2)) if n1 == n2 =>
        go(ty1 :: ps1, ty2 :: ps2, subst)

      case (Abs(v1, e1), Abs(v2, e2)) =>
        go(v1.ty, v2.ty, subst) match {
          case USome(subst1) =>
            val v1_ = rename(v1, subst1.domain ++ subst1.range ++ freeVariables(List(a, b)))
            val v2_ = Var(v1_.name, v2.ty)
            go(Substitution(v1 -> v1_)(e1), Substitution(v2 -> v2_)(e2), subst1.+(v1_, v2_)).map(subst2 => new PreSubstitution(subst2.map - v1_, subst2.typeMap))
          case _ => UNone()
        }

      case (v: Var, exp) if subst.map.get(v).contains(exp) =>
        USome(subst)

      case (v: Var, exp) if !subst.map.contains(v) =>
        go(v.ty, exp.ty, subst).map(_.+(v, exp))

      case _ => UNone()
    }

  def apply(from: Expr, to: Expr): Option[Substitution] =
    apply(from, to, PreSubstitution())

  def apply(from: Expr, to: Expr, alreadyFixed: PreSubstitution): Option[Substitution] =
    go(from, to, alreadyFixed).map(_.toSubstitution).toOption

  def apply(
      pairs: Iterable[(Expr, Expr)],
      alreadyFixed: PreSubstitution
  ): Option[Substitution] = {
    var subst: UOption[PreSubstitution] = USome(alreadyFixed)
    pairs.foreach { case (a, b) => subst = subst.flatMap(go(a, b, _)) }
    subst.map(_.toSubstitution).toOption
  }

  def apply(from: FOLExpression, to: FOLExpression): Option[FOLSubstitution] =
    apply(from: Expr, to).map(_.asFOLSubstitution)

  def apply(pairs: Iterable[(FOLExpression, FOLExpression)])(implicit dummyImplicit: DummyImplicit): Option[FOLSubstitution] =
    apply(pairs, Map[FOLVar, FOLTerm]())

  def apply(
      pairs: Iterable[(FOLExpression, FOLExpression)],
      alreadyFixed: Map[FOLVar, FOLTerm]
  )(implicit dummyImplicit: DummyImplicit): Option[FOLSubstitution] =
    apply(
      pairs: Iterable[(Expr, Expr)],
      PreSubstitution(alreadyFixed)
    ).map(_.asFOLSubstitution)

  def apply(pairs: List[(Expr, Expr)]): Option[Substitution] =
    apply(pairs, PreSubstitution())

  def apply(
      pairs: Iterable[(Ty, Ty)]
  )(implicit dummyImplicit: DummyImplicit, dummyImplicit2: DummyImplicit): Option[Substitution] =
    apply(pairs, PreSubstitution())(DummyImplicit.dummyImplicit)

  def apply(
      pairs: Iterable[(Ty, Ty)],
      alreadyFixed: PreSubstitution
  )(implicit dummyImplicit: DummyImplicit): Option[Substitution] = {
    var subst: UOption[PreSubstitution] = USome(alreadyFixed)
    pairs.foreach { case (a, b) => subst = subst.flatMap(go(a, b, _)) }
    subst.map(_.toSubstitution).toOption
  }

  def apply(from: Ty, to: Ty): Option[Substitution] =
    go(from, to, PreSubstitution()).map(_.toSubstitution).toOption
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy