package scala.tools.nsc
package matching
import transform.ExplicitOuter
import collection.immutable.TreeMap
import PartialFunction._
trait PatternBindings extends ast.TreeDSL
{
self: ExplicitOuter with ParallelMatching =>
import global.{ typer => _, _ }
import definitions.{ EqualsPatternClass }
import CODE._
import Debug._
def isEquals(tpe: Type) = cond(tpe) { case TypeRef(_, EqualsPatternClass, _) => true }
def mkEqualsRef(tpe: Type) = typeRef(NoPrefix, EqualsPatternClass, List(tpe))
def decodedEqualsType(tpe: Type) = condOpt(tpe) { case TypeRef(_, EqualsPatternClass, List(arg)) => arg } getOrElse (tpe)
def matches(arg1: Type, arg2: Type) = decodedEqualsType(arg1) matchesPattern decodedEqualsType(arg2)
def isEquivalentTree(t1: Tree, t2: Tree) = (t1.symbol == t2.symbol) && (t1 equalsStructure t2)
def moveBindings(oldTree: Tree, newTree: Tree): Tree = oldTree match {
case b @ Bind(x, body) => Bind(b.symbol, moveBindings(body, newTree))
case _ => newTree
}
case class PseudoType(o: Tree) extends SimpleTypeProxy {
override def underlying: Type = o.tpe
override def safeToString: String = "PseudoType("+o+")"
}
def extractBindings(p: Pattern): List[Pattern] =
toPats(_extractBindings(p.boundTree, identity))
private def _extractBindings(p: Tree, prevBindings: Tree => Tree): List[Tree] = {
def newPrev(b: Bind) = (x: Tree) => treeCopy.Bind(b, b.name, x) setType x.tpe
p match {
case b @ Bind(_, body) => _extractBindings(body, newPrev(b))
case Alternative(ps) => ps map prevBindings
}
}
trait PatternBindingLogic {
self: Pattern =>
def subpatternsForVars: List[Pattern] = Nil
private var _boundTree: Tree = tree
def boundTree = _boundTree
def setBound(x: Bind): Pattern = {
_boundTree = x
this
}
def boundVariables = strip(boundTree)
def rebindTo(t: Tree): Pattern = Pattern(moveBindings(boundTree, t))
def rebindToType(tpe: Type, ascription: Type = null): Pattern = {
val aType = if (ascription == null) tpe else ascription
rebindTo(Typed(WILD(tpe), TypeTree(aType)) setType tpe)
}
def rebindToEmpty(tpe: Type): Pattern =
rebindTo(Typed(EmptyTree, TypeTree(tpe)) setType tpe)
def rebindToEqualsCheck(): Pattern =
rebindToType(equalsCheck)
def rebindToObjectCheck(): Pattern =
rebindToType(mkEqualsRef(sufficientType), sufficientType)
private def wrapBindings(vs: List[Symbol], pat: Tree): Tree = vs match {
case Nil => pat
case x :: xs => Bind(x, wrapBindings(xs, pat)) setType pat.tpe
}
private def strip(t: Tree): List[Symbol] = t match {
case b @ Bind(_, pat) => b.symbol :: strip(pat)
case _ => Nil
}
private def deepstrip(t: Tree): List[Symbol] =
treeCollect(t, { case x: Bind => x.symbol })
}
case class Binding(pvar: Symbol, tvar: Symbol) {
override def toString() = pvar.name + " -> " + tvar.name
}
class Bindings(private val vlist: List[Binding]) {
def get() = vlist
def toMap = vlist map (x => (x.pvar, x.tvar)) toMap
def add(vs: Iterable[Symbol], tvar: Symbol): Bindings = {
val newBindings = vs.toList map (v => Binding(v, tvar))
new Bindings(newBindings ++ vlist)
}
override def toString() =
if (vlist.isEmpty) "<none>"
else vlist.mkString(", ")
}
val NoBinding: Bindings = new Bindings(Nil)
}