KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > expr > Expression


1 /* Expression Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: Expression.java.in,v 4.3.2.4 2002/05/28 17:34:06 hoenicke Exp $
18  */

19
20 package jode.expr;
21 import jode.type.Type;
22 import jode.GlobalOptions;
23 import jode.decompiler.TabbedPrintWriter;
24
25 import java.util.Collection JavaDoc;
26 import java.util.Set JavaDoc;
27
28 public abstract class Expression {
29     protected Type type;
30
31     Operator parent = null;
32
33     public Expression(Type type) {
34         this.type = type;
35     }
36
37     public void setType(Type otherType) {
38     Type newType = otherType.intersection(type);
39     if (type.equals(newType))
40         return;
41     if (newType == Type.tError && otherType != Type.tError) {
42         GlobalOptions.err.println("setType: Type error in "+this
43                       +": merging "+type+" and "+otherType);
44         if (parent != null)
45         GlobalOptions.err.println("\tparent is "+parent);
46         if ((GlobalOptions.debuggingFlags
47          & GlobalOptions.DEBUG_TYPES) != 0)
48         Thread.dumpStack();
49     }
50     type = newType;
51     if (type != Type.tError)
52         updateSubTypes();
53     }
54
55     public void updateParentType(Type otherType) {
56     setType(otherType);
57     if (parent != null)
58         parent.updateType();
59     }
60
61     /**
62      * Tells an expression that an inner expression may have changed and
63      * that the type should be recalculated.
64      *
65      * This may call setType of the caller again.
66      */

67     public abstract void updateType();
68
69     /**
70      * Tells an expression that an outer expression has changed our type
71      * and that the inner types should be recalculated.
72      */

73     public abstract void updateSubTypes();
74
75     public Type getType() {
76         return type;
77     }
78
79     public Operator getParent() {
80         return parent;
81     }
82
83     /**
84      * Get priority of the operator.
85      * Currently this priorities are known:
86      * <ul><li> 1000 constant
87      * </li><li> 950 new, .(field access), []
88      * </li><li> 900 new[]
89      * </li><li> 800 ++,-- (post)
90      * </li><li> 700 ++,--(pre), +,-(unary), ~, !, cast
91      * </li><li> 650 *,/, %
92      * </li><li> 610 +,-
93      * </li><li> 600 <<, >>, >>>
94      * </li><li> 550 >, <, >=, <=, instanceof
95      * </li><li> 500 ==, !=
96      * </li><li> 450 &
97      * </li><li> 420 ^
98      * </li><li> 410 |
99      * </li><li> 350 &&
100      * </li><li> 310 ||
101      * </li><li> 200 ?:
102      * </li><li> 100 =, +=, -=, etc.
103      * </li></ul>
104      */

105     public abstract int getPriority();
106
107     /**
108      * Get the penalty for splitting up this operator.
109      */

110     public int getBreakPenalty() {
111     return 0;
112     }
113
114     /**
115      * Get the number of operands.
116      * @return The number of stack entries this expression needs.
117      */

118     public abstract int getFreeOperandCount();
119
120     public abstract Expression addOperand(Expression op);
121
122     public Expression negate() {
123         Operator negop =
124             new UnaryOperator(Type.tBoolean, Operator.LOG_NOT_OP);
125     negop.addOperand(this);
126     return negop;
127     }
128
129     /**
130      * Checks if the value of the given expression can change, due to
131      * side effects in this expression. If this returns false, the
132      * expression can safely be moved behind the current expresion.
133      * @param expr the expression that should not change.
134      */

135     public boolean hasSideEffects(Expression expr) {
136     return false;
137     }
138
139     /**
140      * Checks if the given Expression (which should be a CombineableOperator)
141      * can be combined into this expression.
142      * @param e The store expression, must be of type void.
143      * @return 1, if it can, 0, if no match was found and -1, if a
144      * conflict was found. You may wish to check for >0.
145      */

146     public int canCombine(CombineableOperator combOp) {
147     return 0;
148     }
149
150     /**
151      * Checks if this expression contains a load, that matches the
152      * given CombineableOperator (which must be an Operator)
153      * @param e The store expression.
154      * @return if this expression contains a matching load.
155      * @exception ClassCastException, if e.getOperator
156      * is not a CombineableOperator.
157      */

158     public boolean containsMatchingLoad(CombineableOperator e) {
159     return false;
160     }
161
162     /**
163      * Checks if this expression contains a conflicting load, that
164      * matches the given CombineableOperator. The sub expressions are
165      * not checked.
166      * @param op The combineable operator.
167      * @return if this expression contains a matching load. */

168     public boolean containsConflictingLoad(MatchableOperator op) {
169         return false;
170     }
171
172     /**
173      * Combines the given Expression (which should be a StoreInstruction)
174      * into this expression. You must only call this if
175      * canCombine returns the value 1.
176      * @param e The store expression,
177      * the operator must be a CombineableOperator.
178      * @return The combined expression.
179      * @exception ClassCastException, if e.getOperator
180      * is not a CombineableOperator.
181      */

182     public Expression combine(CombineableOperator comb) {
183         return null;
184     }
185
186     /**
187      * This method should remove local variables that are only written
188      * and read one time directly after another. <br>
189      *
190      * In this case this is a non void LocalStoreOperator, whose local
191      * isn't used in other places.
192      * @return an expression where the locals are removed.
193      */

194     public Expression removeOnetimeLocals() {
195     return this;
196     }
197
198     public Expression simplify() {
199         return this;
200     }
201     public Expression simplifyString() {
202         return this;
203     }
204
205     public static Expression EMPTYSTRING = new ConstOperator("");
206
207     public Expression simplifyStringBuffer() {
208         return null;
209     }
210
211     public void makeInitializer(Type type) {
212     }
213
214     public boolean isConstant() {
215         return true;
216     }
217
218     public void fillInGenSet(Collection JavaDoc in, Collection JavaDoc gen) {
219     }
220
221     public void fillDeclarables(Collection JavaDoc used) {
222     }
223
224     public void makeDeclaration(Set JavaDoc done) {
225     }
226
227     public abstract void dumpExpression(TabbedPrintWriter writer)
228     throws java.io.IOException JavaDoc;
229
230     public void dumpExpression(int options, TabbedPrintWriter writer)
231     throws java.io.IOException JavaDoc
232     {
233     writer.startOp(options, getBreakPenalty());
234     dumpExpression(writer);
235     writer.endOp();
236     }
237
238     public void dumpExpression(TabbedPrintWriter writer, int minPriority)
239     throws java.io.IOException JavaDoc {
240     int options;
241     boolean needParen1 = false, needParen2 = false;
242     boolean needEndOp1 = false, needEndOp2 = false;
243
244     String JavaDoc typecast = "";
245
246     if (type == Type.tError)
247         typecast = "/*TYPE_ERROR*/";
248     else if ((GlobalOptions.debuggingFlags
249           & GlobalOptions.DEBUG_TYPES) != 0)
250         typecast = "(TYPE "+type+")";
251
252     if (typecast != "") {
253         if (minPriority > 700) {
254         needParen1 = true;
255         needEndOp1 = true;
256         writer.print("(");
257         writer.startOp(writer.EXPL_PAREN, 0);
258         } else if (minPriority < 700) {
259         needEndOp1 = true;
260         writer.startOp(writer.IMPL_PAREN, 1);
261         }
262         writer.print(typecast);
263         writer.breakOp();
264         writer.print(" ");
265         minPriority = 700;
266     }
267
268     int priority = getPriority();
269     if (priority < minPriority) {
270         needParen2 = true;
271         needEndOp2 = true;
272         writer.print("(");
273         writer.startOp(writer.EXPL_PAREN, getBreakPenalty());
274     } else if (priority != minPriority) {
275         needEndOp2 = true;
276         if (getType() == Type.tVoid)
277         writer.startOp(writer.NO_PAREN, getBreakPenalty());
278         else
279         writer.startOp(writer.IMPL_PAREN, 1 + getBreakPenalty());
280     }
281
282     try {
283         dumpExpression(writer);
284     } catch (RuntimeException JavaDoc ex) {
285         writer.print("(RUNTIME ERROR IN EXPRESSION)");
286         ex.printStackTrace(GlobalOptions.err);
287     }
288
289     if (needEndOp2) {
290         writer.endOp();
291         if (needParen2)
292         writer.print(")");
293     }
294     if (needEndOp1) {
295         writer.endOp();
296         if (needParen1)
297         writer.print(")");
298     }
299     }
300
301     public String JavaDoc toString() {
302         try {
303             java.io.StringWriter JavaDoc strw = new java.io.StringWriter JavaDoc();
304             TabbedPrintWriter writer = new TabbedPrintWriter(strw);
305             dumpExpression(writer);
306             return strw.toString();
307         } catch (java.io.IOException JavaDoc ex) {
308             return "/*IOException*/"+super.toString();
309         } catch (RuntimeException JavaDoc ex) {
310         return "/*RuntimeException*/"+super.toString();
311     }
312     }
313
314     public boolean isVoid() {
315         return getType() == Type.tVoid;
316     }
317 }
318
Popular Tags