summaryrefslogblamecommitdiff
path: root/sources/scalac/ast/TreeInfo.java
blob: 81c97a7e731703d63fa35f4069fcbf7691fb0c91 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                          
                         



                               

                            





























                                                        

                                      












                                                    

                                      









                                                
                        


                                        

                                      














                                                                      
                         

                        
                                                       
                                            
                                  
                                                                



                                                      









                                    



                                                   
                          
                                                                                 

                                        

                                                        




                         














                                                       

                                  








                                                  



                                                               

                                              




                         


                                                                                 







                                                   

                               
                                
                                   
                                
                                     
                                
                
                        

         
 
 


























                                                                               

                                                                         

                               
                             
                            
                             
                    
                                                                                           

             
 









                                                                 
 
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    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;
	}
    }
}