summaryrefslogtreecommitdiff
path: root/sources/scalac/ast/TreeInfo.java
blob: 637928188f925d210bb6b592f15660b43995b5cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    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 TypeDef(_, _, _, _):
	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 TypeDef(_, _, _, _):
	    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 TypeDef(_, _, _, _):
	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 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 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) {
	switch (tree) {
	case Apply(Tree fn, _):
	    return methSymbol(fn);
	case TypeApply(Tree fn, _):
	    return methSymbol(fn);
	default:
	    if (tree.hasSymbol()) return tree.symbol();
	    else return Symbol.NONE;
	}
    }

      /** 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 Apply( _, _ ):
            case Literal( _ ):
                  return false;
            case Ident(Name n): // if Ident is a recursive var, then true
                  return recVars.contains( tree.symbol() );
            default:
                  throw new scalac.ApplicationError("Unexpected pattern "+tree);
            }
      }

    /** 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;
	}
    }

    /** returns true if the argument is a wildcard pattern
     */
    public static boolean isWildcardPattern( Tree tree ) {
	switch( tree ) {
	case Ident( Name n ):
	    return ( n == Names.WILDCARD ) && ( tree.symbol() == null );
	default:
	    return false;
	}
    }
}