summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/internal/TreeInfo.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/reflect/internal/TreeInfo.scala')
-rw-r--r--src/compiler/scala/reflect/internal/TreeInfo.scala209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala
index ce3de94335..039c8e557a 100644
--- a/src/compiler/scala/reflect/internal/TreeInfo.scala
+++ b/src/compiler/scala/reflect/internal/TreeInfo.scala
@@ -531,4 +531,213 @@ abstract class TreeInfo {
case _ => None
}
}
+
+ def isApplyDynamicName(name: Name) = (name == nme.updateDynamic) || (name == nme.selectDynamic) || (name == nme.applyDynamic) || (name == nme.applyDynamicNamed)
+
+ class DynamicApplicationExtractor(nameTest: Name => Boolean) {
+ def unapply(tree: Tree) = tree match {
+ case Apply(TypeApply(Select(qual, oper), _), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name))
+ case Apply(Select(qual, oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name))
+ case Apply(Ident(oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((EmptyTree, name))
+ case _ => None
+ }
+ }
+ object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic)
+ object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName)
+ object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed)
+
+
+ // domain-specific extractors for reification
+
+ import definitions._
+
+ object TypedOrAnnotated {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case ty @ Typed(_, _) =>
+ Some(ty)
+ case at @ Annotated(_, _) =>
+ Some(at)
+ case _ =>
+ None
+ }
+ }
+
+ object TreeSplice {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(splicee, _) if tree.symbol == ExprEval || tree.symbol == ExprValue =>
+ Some(splicee)
+ case _ =>
+ None
+ }
+ }
+
+ object EvalSplice {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(splicee, _) if tree.symbol == ExprEval =>
+ Some(splicee)
+ case _ =>
+ None
+ }
+ }
+
+ object ValueSplice {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(splicee, _) if tree.symbol == ExprValue =>
+ Some(splicee)
+ case _ =>
+ None
+ }
+ }
+
+ object Reified {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
+ case ReifiedTree(reifee, symbolTable, reified, _) =>
+ Some(reifee, symbolTable, reified)
+ case ReifiedType(reifee, symbolTable, reified) =>
+ Some(reifee, symbolTable, reified)
+ case _ =>
+ None
+ }
+ }
+
+ object ReifiedTree {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match {
+ case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(Apply(_, List(tree)), List(Apply(_, List(tpe))))) if mrDef.name == nme.MIRROR_SHORT =>
+ Some(reifee, symbolTable, tree, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object InlineableTreeSplice {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree, Symbol)] = tree match {
+ case select @ Select(ReifiedTree(splicee, symbolTable, tree, tpe), _) if select.symbol == ExprEval || select.symbol == ExprValue =>
+ Some(splicee, symbolTable, tree, tpe, select.symbol)
+ case _ =>
+ None
+ }
+ }
+
+ object InlinedTreeSplice {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match {
+ case Select(ReifiedTree(splicee, symbolTable, tree, tpe), name) if name == ExprTree.name =>
+ Some(splicee, symbolTable, tree, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object ReifiedType {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
+ case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, List(tpe))) if mrDef.name == nme.MIRROR_SHORT =>
+ Some(reifee, symbolTable, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object InlinedTypeSplice {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
+ case Select(ReifiedType(splicee, symbolTable, tpe), name) if name == TypeTagTpe.name =>
+ Some(splicee, symbolTable, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object FreeDef {
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match {
+ case FreeTermDef(mrRef, name, binding, origin) =>
+ Some(mrRef, name, binding, origin)
+ case FreeTypeDef(mrRef, name, binding, origin) =>
+ Some(mrRef, name, binding, origin)
+ case _ =>
+ None
+ }
+ }
+
+ object FreeTermDef {
+ lazy val newFreeTermMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeTerm)
+
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match {
+ case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(origin: String)))))
+ if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == newFreeTermMethod.name =>
+ Some(mrRef, name, binding, origin)
+ case _ =>
+ None
+ }
+ }
+
+ object FreeTypeDef {
+ lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType)
+
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match {
+ case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(origin: String)))))
+ if mrRef1.name == nme.MIRROR_SHORT && newFreeType == newFreeTypeMethod.name =>
+ value match {
+ case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null))))
+ if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply =>
+ Some(mrRef1, name, binding, origin)
+ case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null))))
+ if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag =>
+ Some(mrRef1, name, binding, origin)
+ case _ =>
+ throw new Error("unsupported free type def: " + showRaw(tree))
+ }
+ case _ =>
+ None
+ }
+ }
+
+ object FreeRef {
+ def unapply(tree: Tree): Option[(Tree, TermName)] = tree match {
+ case Apply(Select(mrRef @ Ident(_), ident), List(Ident(name: TermName))) if ident == nme.Ident && name.startsWith(nme.MIRROR_FREE_PREFIX) =>
+ Some(mrRef, name)
+ case _ =>
+ None
+ }
+ }
+
+ object TypeRefToFreeType {
+ def unapply(tree: Tree): Option[TermName] = tree match {
+ case Apply(Select(Select(mrRef @ Ident(_), typeRef), apply), List(Select(_, noSymbol), Ident(freeType: TermName), nil))
+ if (mrRef.name == nme.MIRROR_SHORT && typeRef == nme.TypeRef && noSymbol == nme.NoSymbol && freeType.startsWith(nme.MIRROR_FREE_PREFIX)) =>
+ Some(freeType)
+ case _ =>
+ None
+ }
+ }
+
+ object NestedExpr {
+ def unapply(tree: Tree): Option[(Tree, Tree, Tree)] = tree match {
+ case Apply(Apply(factory @ Select(expr, apply), List(tree)), List(typetag)) if expr.symbol == ExprModule && apply == nme.apply =>
+ Some(factory, tree, typetag)
+ case _ =>
+ None
+ }
+ }
+
+ object BoundTerm {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Ident(name) if name.isTermName =>
+ Some(tree)
+ case This(_) =>
+ Some(tree)
+ case _ =>
+ None
+ }
+ }
+
+ object BoundType {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(_, name) if name.isTypeName =>
+ Some(tree)
+ case SelectFromTypeTree(_, name) if name.isTypeName =>
+ Some(tree)
+ case Ident(name) if name.isTypeName =>
+ Some(tree)
+ case _ =>
+ None
+ }
+ }
}