KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > expr > Operator


1 /* Operator 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: Operator.java.in,v 4.3.2.1 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 Operator extends Expression {
29     /* Don't reorder these constants unless you know what you are doing! */
30     public final static int ADD_OP = 1;
31     public final static int SUB_OP = 2;
32     public final static int SHIFT_OP = 6;
33     public final static int AND_OP = 9;
34     public final static int ASSIGN_OP = 12;
35     public final static int OPASSIGN_OP= 12;
36     public final static int INC_OP = 24; /* must be even! */
37     public final static int DEC_OP = 25;
38     public final static int COMPARE_OP = 26; /* must be even! */
39     public final static int EQUALS_OP = 26;
40     public final static int NOTEQUALS_OP = 27;
41     public final static int LESS_OP = 28;
42     public final static int GREATEREQ_OP = 29;
43     public final static int GREATER_OP = 30;
44     public final static int LESSEQ_OP = 31;
45     public final static int LOG_AND_OP = 32; /* must be even! */
46     public final static int LOG_OR_OP = 33;
47     public final static int LOG_NOT_OP = 34;
48     public final static int NEG_OP = 36;
49     static String JavaDoc opString[] = {
50         "", " + ", " - ", " * ", " / ", " % ",
51     " << ", " >> ", " >>> ", " & ", " | ", " ^ ",
52         " = ", " += ", " -= ", " *= ", " /= ", " %= ",
53     " <<= ", " >>= ", " >>>= ", " &= ", " |= ", " ^= ",
54         "++", "--",
55         " == "," != "," < "," >= "," > ", " <= ", " && ", " || ",
56         "!", "~", "-"
57     };
58
59     protected int operatorIndex;
60     private int operandcount;
61
62     Expression[] subExpressions;
63
64     public Operator(Type type) {
65     this(type,0);
66     }
67
68     public Operator(Type type, int op) {
69         super(type);
70         this.operatorIndex = op;
71         if (type == null)
72             throw new jode.AssertError("type == null");
73     }
74
75     public void initOperands(int opcount) {
76     operandcount = opcount;
77     subExpressions = new Expression[opcount];
78         for (int i=0; i < opcount; i++) {
79         subExpressions[i] = new NopOperator(Type.tUnknown);
80         subExpressions[i].parent = this;
81     }
82     updateSubTypes();
83     }
84
85     public int getFreeOperandCount() {
86     return operandcount;
87     }
88
89     /**
90      * Tells if this is an operator, that doesn't have any
91      * subExpression, yet.
92      */

93     public boolean isFreeOperator() {
94     return subExpressions.length == 0
95         || subExpressions[subExpressions.length-1] instanceof NopOperator;
96     }
97
98     /**
99      * Tells if this is an operator, that doesn't have any
100      * subExpression, yet, and that expects opcount operands
101      */

102     public boolean isFreeOperator(int opcount) {
103     return subExpressions.length == opcount
104         && (opcount == 0
105         || subExpressions[opcount-1] instanceof NopOperator);
106     }
107
108     public Expression addOperand(Expression op) {
109     for (int i= subExpressions.length; i-- > 0;) {
110         int opcount = subExpressions[i].getFreeOperandCount();
111         if (opcount > 0) {
112         subExpressions[i] = subExpressions[i].addOperand(op);
113         operandcount
114             += subExpressions[i].getFreeOperandCount() - opcount;
115         updateType();
116         return this;
117         }
118     }
119     throw new jode.AssertError("addOperand called, but no operand needed");
120     }
121
122     public Operator getOperator() {
123         return this;
124     }
125
126     public Expression[] getSubExpressions() {
127         return subExpressions;
128     }
129
130     public void setSubExpressions(int i, Expression expr) {
131     int diff = expr.getFreeOperandCount()
132         - subExpressions[i].getFreeOperandCount();
133         subExpressions[i] = expr;
134     expr.parent = this;
135     for (Operator ce = this; ce != null; ce = (Operator) ce.parent)
136         ce.operandcount += diff;
137         updateType();
138     }
139
140     public int getOperatorIndex() {
141         return operatorIndex;
142     }
143     public void setOperatorIndex(int op) {
144         operatorIndex = op;
145     }
146
147     public String JavaDoc getOperatorString() {
148         return opString[operatorIndex];
149     }
150
151     public boolean opEquals(Operator o) {
152     return this == o;
153     }
154
155     public Expression simplify() {
156         for (int i=0; i< subExpressions.length; i++) {
157         subExpressions[i] = subExpressions[i].simplify();
158         subExpressions[i].parent = this;
159         }
160     return this;
161     }
162
163     public void fillInGenSet(Collection JavaDoc in, Collection JavaDoc gen) {
164     if (this instanceof LocalVarOperator) {
165             LocalVarOperator varOp = (LocalVarOperator) this;
166             if (varOp.isRead() && in != null)
167                 in.add(varOp.getLocalInfo());
168             if (gen != null)
169         gen.add(varOp.getLocalInfo());
170     }
171         for (int i=0; i< subExpressions.length; i++)
172         subExpressions[i].fillInGenSet(in,gen);
173     }
174
175     public void fillDeclarables(Collection JavaDoc used) {
176         for (int i=0; i< subExpressions.length; i++)
177         subExpressions[i].fillDeclarables(used);
178     }
179
180     public void makeDeclaration(Set JavaDoc done) {
181         for (int i=0; i< subExpressions.length; i++)
182         subExpressions[i].makeDeclaration(done);
183     }
184
185
186     /**
187      * Checks if the value of the given expression can change, due to
188      * side effects in this expression. If this returns false, the
189      * expression can safely be moved behind the current expresion.
190      * @param expr the expression that should not change.
191      */

192     public boolean hasSideEffects(Expression expr) {
193     if (expr instanceof MatchableOperator
194         && expr.containsConflictingLoad((MatchableOperator)expr))
195         return true;
196     for (int i=0; i < subExpressions.length; i++) {
197         if (subExpressions[i].hasSideEffects(expr))
198         return true;
199     }
200     return false;
201     }
202
203     /**
204      * Checks if this expression contains a conflicting load, that
205      * matches the given CombineableOperator. The sub expressions are
206      * not checked.
207      * @param op The combineable operator.
208      * @return if this expression contains a matching load.
209      */

210     public boolean containsConflictingLoad(MatchableOperator op) {
211     if (op.matches(this))
212         return true;
213     for (int i=0; i < subExpressions.length; i++) {
214         if (subExpressions[i].containsConflictingLoad(op))
215         return true;
216     }
217     return false;
218     }
219
220     /**
221      * Checks if this expression contains a matching load, that matches the
222      * given Expression.
223      * @param comb The store expression.
224      * @return true, iff this expression contains a matching load.
225      * @exception ClassCastException, if e.getOperator
226      * is not a CombineableOperator.
227      */

228     public boolean containsMatchingLoad(CombineableOperator comb) {
229     Operator combOp = (Operator) comb;
230     if (comb.getLValue().matches(this)) {
231         if (subsEquals((Operator) comb.getLValue()))
232         return true;
233         }
234         for (int i=0; i < subExpressions.length; i++) {
235             if (subExpressions[i].containsMatchingLoad(comb))
236                 return true;
237         }
238     return false;
239     }
240
241     /**
242      * Checks if the given Expression (which must be a CombineableOperator)
243      * can be combined into this expression.
244      * @param e The store expression, must be of type void.
245      * @return 1, if it can, 0, if no match was found and -1, if a
246      * conflict was found. You may wish to check for >0.
247      * @exception ClassCastException, if e.getOperator
248      * is not a CombineableOperator.
249      */

250     public int canCombine(CombineableOperator combOp) {
251 // GlobalOptions.err.println("Try to combine "+e+" into "+this);
252
if (combOp.getLValue() instanceof LocalStoreOperator
253         && ((Operator)combOp).getFreeOperandCount() == 0) {
254         // Special case for locals created on inlining methods, which may
255
// combine everywhere, as long as there are no side effects.
256

257         for (int i=0; i < subExpressions.length; i++) {
258         int result = subExpressions[i].canCombine(combOp);
259         if (result != 0)
260             return result;
261         if (subExpressions[i].hasSideEffects((Expression)combOp))
262             return -1;
263         }
264     }
265
266     if (combOp.lvalueMatches(this))
267         return subsEquals((Operator)combOp) ? 1 : -1;
268     if (subExpressions.length > 0)
269         return subExpressions[0].canCombine(combOp);
270     return 0;
271     }
272
273     /**
274      * Combines the given Expression (which should be a StoreInstruction)
275      * into this expression. You must only call this if
276      * canCombine returns the value 1.
277      * @param e The store expression.
278      * @return The combined expression.
279      * @exception ClassCastException, if e.getOperator
280      * is not a CombineableOperator.
281      */

282     public Expression combine(CombineableOperator comb) {
283     Operator combOp = (Operator) comb;
284         if (comb.lvalueMatches(this)) {
285         /* We already checked in canCombine that subExpressions match */
286             comb.makeNonVoid();
287         combOp.parent = parent;
288             return combOp;
289         }
290         for (int i=0; i < subExpressions.length; i++) {
291         Expression combined = subExpressions[i].combine(comb);
292         if (combined != null) {
293         subExpressions[i] = combined;
294         updateType();
295         return this;
296         }
297         }
298         return null;
299     }
300
301     public boolean subsEquals(Operator other) {
302         if (this == other)
303             return true;
304     if (other.subExpressions == null)
305         return (subExpressions == null);
306         
307         if (subExpressions.length != other.subExpressions.length)
308             return false;
309
310         for (int i=0; i<subExpressions.length; i++) {
311         if(!subExpressions[i].equals(other.subExpressions[i]))
312                 return false;
313         }
314         return true;
315     }
316
317     public boolean equals(Object JavaDoc o) {
318         if (this == o)
319             return true;
320     if (!(o instanceof Operator))
321         return false;
322     Operator other = (Operator) o;
323     return opEquals(other) && subsEquals(other);
324     }
325
326     public boolean isConstant() {
327         for (int i=0; i< subExpressions.length; i++)
328             if (!subExpressions[i].isConstant())
329                 return false;
330         return true;
331     }
332
333     public abstract void dumpExpression(TabbedPrintWriter writer)
334     throws java.io.IOException JavaDoc;
335 }
336
337
Popular Tags