/* ____ ____ ____ ____ ______ *\ ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** ** ** ** $Id$ \* */ package scalac.ast; import scalac.ApplicationError; import scalac.util.Name; import scalac.util.Names; import scalac.symtab.Type; import scalac.symtab.Symbol; import scalac.symtab.Modifiers; import java.util.LinkedList; public class TreeInfo { public static boolean isTerm(Tree tree) { return tree.isTerm(); } public static boolean isType(Tree tree) { return tree.isType(); } public static boolean isOwnerDefinition(Tree tree) { switch (tree) { case PackageDef(_, _): case ClassDef(_, _, _, _, _, _): case ModuleDef(_, _, _, _): case DefDef(_, _, _, _, _, _): case Import(_, _): return true; default: return false; } } public static boolean isDefinition(Tree tree) { switch (tree) { case PackageDef(_, _): case ClassDef(_, _, _, _, _, _): case ModuleDef(_, _, _, _): case DefDef(_, _, _, _, _, _): case ValDef(_, _, _, _): case AbsTypeDef(_, _, _, _): case AliasTypeDef(_, _, _, _): case Import(_, _): return true; default: return false; } } public static boolean isDeclaration(Tree tree) { switch (tree) { case DefDef(_, _, _, _, _, Tree rhs): return rhs == Tree.Empty; case ValDef(_, _, _, Tree rhs): return rhs == Tree.Empty; case AbsTypeDef(_, _, _, _): case AliasTypeDef(_, _, _, _): return true; default: return false; } } /** Is tree a pure definition? */ public static boolean isPureDef(Tree tree) { switch (tree) { case Tree.Empty: case ClassDef(_, _, _, _, _, _): case ModuleDef(_, _, _, _): case DefDef(_, _, _, _, _, _): case AbsTypeDef(_, _, _, _): case AliasTypeDef(_, _, _, _): case Import(_, _): return true; case ValDef(int mods, _, _, Tree rhs): return (mods & Modifiers.MUTABLE) == 0 && isPureExpr(rhs); default: return false; } } /** Is tree a stable & pure expression? */ public static boolean isPureExpr(Tree tree) { switch (tree) { case Empty: case This(_): case Super(_, _): return true; case Ident(_): assert tree.type != null : tree.toString(); return tree.symbol().isStable(); case Select(Tree qual, _): return tree.symbol().isStable() && isPureExpr(qual); case Apply(Tree fn, Tree[] args): return isPureExpr(fn) && args.length == 0; case TypeApply(Tree fn, Tree[] targs): return isPureExpr(fn); case Typed(Tree expr, _): return isPureExpr(expr); case Literal(_): return true; default: return false; } } /** Is tree a pure constructor? */ public static boolean isPureConstr(Tree tree) { switch (tree) { case Ident(_): case Select(_, _): return tree.symbol() != null && tree.symbol().isPrimaryConstructor(); case TypeApply(Tree constr, _): return isPureConstr(constr); case Apply(Tree fn, Tree[] args): return args.length == 0 && isPureConstr(fn); default: return false; } } /** Is tree a self constructor call? */ public static boolean isSelfConstrCall(Tree tree) { switch (tree) { case Ident(Name name): return name == Names.CONSTRUCTOR; case TypeApply(Tree constr, _): return isSelfConstrCall(constr); case Apply(Tree constr, _): return isSelfConstrCall(constr); default: return false; } } /** Is tree a variable pattern */ public static boolean isVarPattern(Tree pat) { switch (pat) { case Ident(Name name): return name.isVariable(); default: return false; } } /** Is tree a this node which belongs to `enclClass'? */ public static boolean isSelf(Tree tree, Symbol enclClass) { switch (tree) { case This(_): return tree.symbol() == enclClass; default: return false; } } /** The method symbol of an application node, or Symbol.NONE, if none exists. */ public static Symbol methSymbol(Tree tree) { Tree meth = methPart(tree); if (meth.hasSymbol()) return meth.symbol(); else return Symbol.NONE; } /** The method part of an application node */ public static Tree methPart(Tree tree) { switch (tree) { case Apply(Tree fn, _): return methPart(fn); case TypeApply(Tree fn, _): return methPart(fn); case AppliedType(Tree fn, _): return methPart(fn); default: return tree; } } /** returns true if the tree is a sequence-valued pattern. * precondition: tree is a pattern. * calls isSequenceValued( Tree, List ) because needs to remember bound * values. */ public static boolean isSequenceValued( Tree tree ) { return isSequenceValued( tree, new LinkedList() ); } /** returns true if the tree is a sequence-valued pattern. * precondition: tree is a pattern */ public static boolean isSequenceValued( Tree tree, LinkedList recVars ) { switch( tree ) { case Bind(_, Tree t): recVars.addFirst( tree.symbol() ); boolean res = isSequenceValued( t ); recVars.removeFirst(); return res; case Sequence(_): return true; case Alternative(Tree[] ts): for( int i = 0; i < ts.length; i++ ) { if( isSequenceValued( ts[ i ] ) ) return true; } return false; case Ident(Name n): // if Ident is a recursive var, then true return recVars.contains( tree.symbol() ); case Apply( _, _ ): case Literal( _ ): case Select(_,_): case Typed(_,_): return false; default: throw new scalac.ApplicationError("Unexpected pattern "+tree.getClass()); } } /** returns true if the argument is an empty sequence pattern */ public static boolean isEmptySequence( Tree tree ) { switch( tree ) { case Sequence( Tree ts[] ): return ( ts.length == 0 ); default: return false; } } }