diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/TreeInfo.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala new file mode 100644 index 0000000000..dedfc6b03a --- /dev/null +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -0,0 +1,187 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc.ast; + +import symtab.Flags._; + +abstract class TreeInfo { + + val global: Global; + import global._; + + def isTerm(tree: Tree): boolean = tree.isTerm; + def isType(tree: Tree): boolean = tree.isType; + + def isOwnerDefinition(tree: Tree): boolean = tree match { + case PackageDef(_, _) + | ClassDef(_, _, _, _, _) + | ModuleDef(_, _, _) + | DefDef(_, _, _, _, _, _) + | Import(_, _) => true + case _ => false + } + + def isDefinition(tree: Tree): boolean = tree.isDef; + + def isDeclaration(tree: Tree): boolean = tree match { + case DefDef(_, _, _, _, _, EmptyTree) + | ValDef(_, _, _, EmptyTree) + | AbsTypeDef(_, _, _, _) + | AliasTypeDef(_, _, _, _) => true + case _ => false + } + + /** Is tree legal as a member definition of an interface? + */ + def isInterfaceMember(tree: Tree): boolean = tree match { + case EmptyTree => true + case Import(_, _) => true + case AbsTypeDef(_, _, _, _) => true + case AliasTypeDef(_, _, _, _) => true + case DefDef(mods, _, _, _, _, __) => mods.hasFlag(DEFERRED) + case ValDef(mods, _, _, _) => mods.hasFlag(DEFERRED) + case DocDef(_, definition) => isInterfaceMember(definition) + case Attributed(_, definition) => isInterfaceMember(definition) + case _ => false + } + + + /** Is tree a pure definition? + */ + def isPureDef(tree: Tree): boolean = tree match { + case EmptyTree + | ClassDef(_, _, _, _, _) + | ModuleDef(_, _, _) + | AbsTypeDef(_, _, _, _) + | AliasTypeDef(_, _, _, _) + | Import(_, _) + | DefDef(_, _, _, _, _, _) => + true + case ValDef(mods, _, _, rhs) => + mods.hasFlag(MUTABLE) && isPureExpr(rhs) + case DocDef(_, definition) => + isPureDef(definition) + case Attributed(_, definition) => + isPureDef(definition) + case _ => + false + } + + /** Is tree a stable & pure expression? + */ + def isPureExpr(tree: Tree): boolean = tree match { + case EmptyTree + | This(_) + | Super(_, _) + | Literal(_) => + true + case Ident(_) => + tree.symbol.isStable + case Select(qual, _) => + tree.symbol.isStable && isPureExpr(qual) + case TypeApply(fn, _) => + isPureExpr(fn) + case Apply(fn, List()) => + isPureExpr(fn) + case Typed(expr, _) => + isPureExpr(expr) + case Block(stats, expr) => + (stats forall isPureDef) && isPureExpr(expr) + case _ => + false + } + + /** Is tree a self constructor call? + */ + def isSelfConstrCall(tree: Tree): boolean = tree match { + case Ident(nme.CONSTRUCTOR) => + true + case TypeApply(constr, _) => + isSelfConstrCall(constr) + case Apply(constr, _) => + isSelfConstrCall(constr) + case _ => + false + } + + /** Is tree a variable pattern */ + def isVarPattern(pat: Tree): boolean = pat match { + case Ident(name) => isVariableName(name) + case _ => false + } + + /** The longest statement suffix that starts with a constructor */ + def firstConstructor(stats: List[Tree]): Tree = stats.head match { + case constr @ DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => constr + case _ => firstConstructor(stats.tail) + } + + /** Is name a left-associative operator? */ + def isLeftAssoc(operator: Name): boolean = + operator.length > 0 && operator(operator.length - 1) != ':'; + + /** Is name a variable name? */ + def isVariableName(name: Name): boolean = { + val first = name(0); + ((('a' <= first && first <= 'z') || first == '_') + && name != nme.false_ + && name != nme.true_ + && name != nme.null_) + } + + /** Is tree a this node which belongs to `enclClass'? */ + def isSelf(tree: Tree, enclClass: Symbol): boolean = tree match { + case This(_) => tree.symbol == enclClass + case _ => false + } + + /** Is this pattern node a catch-all (wildcard or variable) pattern? */ + def isDefaultCase(cdef: CaseDef) = cdef match { + case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true + case CaseDef(Bind(_, Ident(nme.WILDCARD)), EmptyTree, _) => true + case _ => false + } + + /** Is this pattern node a catch-all or type-test pattern? */ + def isCatchCase(cdef: CaseDef) = cdef match { + case CaseDef(Typed(Ident(nme.WILDCARD), tpt), EmptyTree, _) => isSimple(tpt.tpe) + case CaseDef(Bind(_, Typed(Ident(nme.WILDCARD), tpt)), EmptyTree, _) => isSimple(tpt.tpe) + case _ => isDefaultCase(cdef) + } + + private def isSimple(tp: Type): boolean = true; + /* If we have run-time types, and these are used for pattern matching, + we should replace this by something like: + + tp match { + case TypeRef(pre, sym, args) => + args.isEmpty && (sym.owner.isPackageClass || isSimple(pre)) + case NoPrefix => + true + case _ => + false + } +*/ + + /** Is this pattern node a sequence-valued pattern? */ + def isSequenceValued(tree: Tree): boolean = tree match { + case Bind(_, body) => isSequenceValued(body) + case Sequence(_) => true + case ArrayValue(_, _) => true + case Star(_) => true + case Alternative(ts) => ts exists isSequenceValued + case _ => false + } + + /** The method part of an application node + */ + def methPart(tree: Tree): Tree = tree match { + case Apply(fn, _) => methPart(fn) + case TypeApply(fn, _) => methPart(fn) + case AppliedTypeTree(fn, _) => methPart(fn) + case _ => tree + } +} |