summaryrefslogtreecommitdiff
path: root/src/main/java/io/devnulllabs/openjava/ptree/BinaryExpression.java
blob: 67ba1f423c2c15ecb8998e69cd168054062beb7d (plain)
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/*
 * BinaryExpression.java 1.0
 *
 *
 * Jun 20, 1997 by mich
 * Sep 29, 1997 by bv
 * Oct 10, 1997 by mich
 *
 * @see io.devnulllabs.openjava.ptree.ParseTree
 * @version 1.0 last updated:  Oct 10, 1997
 * @author  Michiaki Tatsubori
 */
package io.devnulllabs.openjava.ptree;

import io.devnulllabs.openjava.mop.Environment;
import io.devnulllabs.openjava.mop.OJClass;
import io.devnulllabs.openjava.mop.OJSystem;
import io.devnulllabs.openjava.ptree.util.ParseTreeVisitor;

/**
 * The <code>BinaryExpression</code> class represents
 * an expression which consists of an operators and two operands.
 * <br>
 * This doesn't includes the expression whose operator is
 * the <code>instanceof</code> operator
 * nor the expression whose operator is one of the
 * assignment operators.
 * <br>
 * If the operator in the expression of the left operand or
 * the right operand has week unity,
 * this automatically produces the code in which the left operand
 * is enclosed by parenthesises.
 * <br>
 * In the case the left is <code>a + b</code>,
 * the operator is <code>*</code>
 * the right is <code>c + d</code>,
 * this produces the code :
 * <br><blockquote><pre>
 *     (a + b) * (c + d)
 * </pre></blockquote><br>
 *
 * @see io.devnulllabs.openjava.ptree.Expression
 * @see io.devnulllabs.openjava.ptree.InstanceofExpression
 * @see io.devnulllabs.openjava.ptree.AssignmentExpression
 */
public class BinaryExpression extends NonLeaf implements Expression {
    public static final int TIMES = 0;
    public static final int DIVIDE = 1;
    public static final int MOD = 2;
    public static final int PLUS = 3;
    public static final int MINUS = 4;
    public static final int SHIFT_L = 5;
    public static final int SHIFT_R = 6;
    public static final int SHIFT_RR = 7;
    public static final int LESS = 8;
    public static final int GREATER = 9;
    public static final int LESSEQUAL = 10;
    public static final int GREATEREQUAL = 11;
    public static final int INSTANCEOF = 12;
    public static final int EQUAL = 13;
    public static final int NOTEQUAL = 14;
    public static final int BITAND = 15;
    public static final int XOR = 16;
    public static final int BITOR = 17;
    public static final int LOGICAL_AND = 18;
    public static final int LOGICAL_OR = 19;

    static final String[] opr_string =
        {
            "*",
            "/",
            "%",
            "+",
            "-",
            "<<",
            ">>",
            ">>>",
            "<",
            ">",
            "<=",
            ">=",
            "instanceof",
            "==",
            "!=",
            "&",
            "^",
            "|",
            "&&",
            "||" };

    /** the operator */
    private int opr = -1;

    /**
     * Allocates a new object.
     *
     * @param  lexp  the expression of the left operand.
     * @param  opr  the id number of operator.
     * @param  rexp  the expression of the right operand.
     */
    public BinaryExpression(Expression lexp, int opr, Expression rexp) {
        super();
        set((ParseTree) lexp, (ParseTree) rexp);
        this.opr = opr;
    }

    public BinaryExpression(Expression lexp, String opr, Expression rexp) {
        this(lexp, 0, rexp);
        for (int i = 0; i < 20; ++i) {
            if (opr_string[i].equals(opr))
                this.opr = i;
        }
    }

    BinaryExpression() {
        super();
    }

    public ParseTree makeRecursiveCopy() {
        BinaryExpression result = (BinaryExpression) super.makeRecursiveCopy();
        result.opr = this.opr;
        return result;
    }

    public ParseTree makeCopy() {
        BinaryExpression result = (BinaryExpression) super.makeCopy();
        result.opr = this.opr;
        return result;
    }

    private final boolean needsLeftPar(Expression leftexpr) {
        if (leftexpr instanceof AssignmentExpression
            || leftexpr instanceof ConditionalExpression) {
            return true;
        }

        int op = strength(getOperator());

        if (leftexpr instanceof InstanceofExpression) {
            if (op > strength(INSTANCEOF))
                return true;
            return false;
        }

        if (!(leftexpr instanceof BinaryExpression))
            return false;

        BinaryExpression lbexpr = (BinaryExpression) leftexpr;
        if (op > strength(lbexpr.getOperator()))
            return true;
        return false;
    }

    private final boolean needsRightPar(Expression rightexpr) {
        if (rightexpr instanceof AssignmentExpression
            || rightexpr instanceof ConditionalExpression) {
            return true;
        }

        int op = strength(getOperator());

        if (rightexpr instanceof InstanceofExpression) {
            if (op >= strength(INSTANCEOF))
                return true;
            return false;
        }

        if (!(rightexpr instanceof BinaryExpression))
            return false;

        BinaryExpression lbexpr = (BinaryExpression) rightexpr;
        if (op >= strength(lbexpr.getOperator()))
            return true;
        return false;
    }

    /**
     * Returns the strength of the union of the operator.
     *
     * @param  op  the id number of operator.
     * @return  the strength of the union.
     */
    protected static final int strength(int op) {
        switch (op) {
            case TIMES :
            case DIVIDE :
            case MOD :
                return 40;
            case PLUS :
            case MINUS :
                return 35;
            case SHIFT_L :
            case SHIFT_R :
            case SHIFT_RR :
                return 30;
            case LESS :
            case GREATER :
            case LESSEQUAL :
            case GREATEREQUAL :
            case INSTANCEOF :
                return 25;
            case EQUAL :
            case NOTEQUAL :
                return 20;
            case BITAND :
                return 16;
            case XOR :
                return 14;
            case BITOR :
                return 12;
            case LOGICAL_AND :
                return 10;
            case LOGICAL_OR :
                return 8;
        }
        return 100;
    }

    /**
     * Gets the expression of the left operand.
     *
     * @return  the left expression.
     */
    public Expression getLeft() {
        return (Expression) elementAt(0);
    }

    /**
     * Sets the expression of the left operand.
     *
     * @param lexpr  the left expression.
     */
    public void setLeft(Expression lexpr) {
        setElementAt(lexpr, 0);
    }

    /**
     * Gets the expression of the right operand.
     *
     * @return  the right expression.
     */
    public Expression getRight() {
        return (Expression) elementAt(1);
    }

    /**
     * Sets the expression of the right operand.
     *
     * @param  rexpr  the right expression.
     */
    public void setRight(Expression rexpr) {
        setElementAt(rexpr, 1);
    }

    /**
     * Gets the id number of the operator.
     *
     * @return  the id number of the operator.
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#TIMES
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#DIVIDE
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#MOD
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#PLUS
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#MINUS
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#SHIFT_L
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#SHIFT_R
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#SHIFT_RR
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LESS
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#GREATER
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LESSEQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#GREATEREQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#INSTANCEOF
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#EQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#NOTEQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#BITAND
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#XOR
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#BITOR
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LOGICAL_AND
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LOGICAL_OR
     */
    public int getOperator() {
        return this.opr;
    }

    /**
     * Sets the id number of the operator.
     *
     * @param  opr  the id number of the operator.
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#TIMES
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#DIVIDE
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#MOD
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#PLUS
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#MINUS
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#SHIFT_L
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#SHIFT_R
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#SHIFT_RR
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LESS
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#GREATER
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LESSEQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#GREATEREQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#INSTANCEOF
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#EQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#NOTEQUAL
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#BITAND
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#XOR
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#BITOR
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LOGICAL_AND
     * @see io.devnulllabs.openjava.ptree.BinaryExpression#LOGICAL_OR
     */
    public void setOperator(int opr) {
        this.opr = opr;
    }

    public String operatorString() {
        return opr_string[getOperator()];
    }

    public void accept(ParseTreeVisitor v) throws ParseTreeException {
        v.visit(this);
    }

    public OJClass getType(Environment env) throws Exception {
        switch (this.opr) {
            case LESS :
            case GREATER :
            case LESSEQUAL :
            case GREATEREQUAL :
            case EQUAL :
            case NOTEQUAL :
            case INSTANCEOF :
                return OJSystem.BOOLEAN;
            default :
                return chooseType(
                    getLeft().getType(env),
                    getRight().getType(env));
        }
    }

    static OJClass chooseType(OJClass left, OJClass right) {
        int leftst = strength(left), rightst = strength(right);
        if (leftst == OTHER && rightst == OTHER) {
            if (left.isAssignableFrom(right))
                return left;
            if (right.isAssignableFrom(left))
                return right;
            return right;
        }
        return ((leftst > rightst) ? left : right);
    }

    private static final int STRING = 30;
    private static final int OTHER = 4;
    private static int strength(OJClass type) {
        if (type == OJSystem.STRING)
            return STRING;
        if (type == OJSystem.DOUBLE)
            return 20;
        if (type == OJSystem.FLOAT)
            return 18;
        if (type == OJSystem.LONG)
            return 16;
        if (type == OJSystem.INT)
            return 14;
        if (type == OJSystem.CHAR)
            return 12;
        if (type == OJSystem.BYTE)
            return 10;
        if (type == OJSystem.NULLTYPE)
            return 0; /*****/
        return OTHER;
    }

}