Fix bug #672
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / BinaryExpression.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
20
21 public class BinaryExpression extends OperatorExpression {
22
23         public Expression left, right;
24
25         public Constant optimizedBooleanConstant;
26
27         public BinaryExpression(Expression left, Expression right, int operator) {
28
29                 this.left = left;
30                 this.right = right;
31                 this.bits |= operator << OperatorSHIFT; // encode operator
32                 this.sourceStart = left.sourceStart;
33                 this.sourceEnd = right.sourceEnd;
34         }
35
36         public FlowInfo analyseCode(BlockScope currentScope,
37                         FlowContext flowContext, FlowInfo flowInfo) {
38
39                 return right.analyseCode(
40                                 currentScope,
41                                 flowContext,
42                                 left.analyseCode(currentScope, flowContext, flowInfo)
43                                                 .unconditionalInits()).unconditionalInits();
44         }
45
46         public void computeConstant(BlockScope scope, int leftId, int rightId) {
47
48                 // compute the constant when valid
49                 if ((this.left.constant != Constant.NotAConstant)
50                                 && (this.right.constant != Constant.NotAConstant)) {
51                         try {
52                                 this.constant = Constant.computeConstantOperation(
53                                                 this.left.constant, leftId,
54                                                 (this.bits & OperatorMASK) >> OperatorSHIFT,
55                                                 this.right.constant, rightId);
56                         } catch (ArithmeticException e) {
57                                 this.constant = Constant.NotAConstant;
58                                 // 1.2 no longer throws an exception at compile-time
59                                 // scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
60                         }
61                 } else {
62                         this.constant = Constant.NotAConstant;
63                         // add some work for the boolean operators & |
64                         // this.optimizedBooleanConstant(
65                         // leftId,
66                         // (this.bits & OperatorMASK) >> OperatorSHIFT,
67                         // rightId);
68                 }
69         }
70
71         public Constant optimizedBooleanConstant() {
72
73                 return this.optimizedBooleanConstant == null ? this.constant
74                                 : this.optimizedBooleanConstant;
75         }
76
77         /**
78          * Code generation for a binary operation
79          */
80         // public void generateCode(
81         // BlockScope currentScope,
82         // CodeStream codeStream,
83         // boolean valueRequired) {
84         //
85         // int pc = codeStream.position;
86         // Label falseLabel, endLabel;
87         // if (constant != Constant.NotAConstant) {
88         // if (valueRequired)
89         // codeStream.generateConstant(constant, implicitConversion);
90         // codeStream.recordPositionsFrom(pc, this.sourceStart);
91         // return;
92         // }
93         // bits |= OnlyValueRequiredMASK;
94         // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
95         // case PLUS :
96         // switch (bits & ReturnTypeIDMASK) {
97         // case T_String :
98         // codeStream.generateStringAppend(currentScope, left, right);
99         // if (!valueRequired)
100         // codeStream.pop();
101         // break;
102         // case T_int :
103         // left.generateCode(currentScope, codeStream, valueRequired);
104         // right.generateCode(currentScope, codeStream, valueRequired);
105         // if (valueRequired)
106         // codeStream.iadd();
107         // break;
108         // case T_long :
109         // left.generateCode(currentScope, codeStream, valueRequired);
110         // right.generateCode(currentScope, codeStream, valueRequired);
111         // if (valueRequired)
112         // codeStream.ladd();
113         // break;
114         // case T_double :
115         // left.generateCode(currentScope, codeStream, valueRequired);
116         // right.generateCode(currentScope, codeStream, valueRequired);
117         // if (valueRequired)
118         // codeStream.dadd();
119         // break;
120         // case T_float :
121         // left.generateCode(currentScope, codeStream, valueRequired);
122         // right.generateCode(currentScope, codeStream, valueRequired);
123         // if (valueRequired)
124         // codeStream.fadd();
125         // break;
126         // }
127         // break;
128         // case MINUS :
129         // switch (bits & ReturnTypeIDMASK) {
130         // case T_int :
131         // left.generateCode(currentScope, codeStream, valueRequired);
132         // right.generateCode(currentScope, codeStream, valueRequired);
133         // if (valueRequired)
134         // codeStream.isub();
135         // break;
136         // case T_long :
137         // left.generateCode(currentScope, codeStream, valueRequired);
138         // right.generateCode(currentScope, codeStream, valueRequired);
139         // if (valueRequired)
140         // codeStream.lsub();
141         // break;
142         // case T_double :
143         // left.generateCode(currentScope, codeStream, valueRequired);
144         // right.generateCode(currentScope, codeStream, valueRequired);
145         // if (valueRequired)
146         // codeStream.dsub();
147         // break;
148         // case T_float :
149         // left.generateCode(currentScope, codeStream, valueRequired);
150         // right.generateCode(currentScope, codeStream, valueRequired);
151         // if (valueRequired)
152         // codeStream.fsub();
153         // break;
154         // }
155         // break;
156         // case MULTIPLY :
157         // switch (bits & ReturnTypeIDMASK) {
158         // case T_int :
159         // left.generateCode(currentScope, codeStream, valueRequired);
160         // right.generateCode(currentScope, codeStream, valueRequired);
161         // if (valueRequired)
162         // codeStream.imul();
163         // break;
164         // case T_long :
165         // left.generateCode(currentScope, codeStream, valueRequired);
166         // right.generateCode(currentScope, codeStream, valueRequired);
167         // if (valueRequired)
168         // codeStream.lmul();
169         // break;
170         // case T_double :
171         // left.generateCode(currentScope, codeStream, valueRequired);
172         // right.generateCode(currentScope, codeStream, valueRequired);
173         // if (valueRequired)
174         // codeStream.dmul();
175         // break;
176         // case T_float :
177         // left.generateCode(currentScope, codeStream, valueRequired);
178         // right.generateCode(currentScope, codeStream, valueRequired);
179         // if (valueRequired)
180         // codeStream.fmul();
181         // break;
182         // }
183         // break;
184         // case DIVIDE :
185         // switch (bits & ReturnTypeIDMASK) {
186         // case T_int :
187         // left.generateCode(currentScope, codeStream, true);
188         // right.generateCode(currentScope, codeStream, true);
189         // codeStream.idiv();
190         // if (!valueRequired)
191         // codeStream.pop();
192         // break;
193         // case T_long :
194         // left.generateCode(currentScope, codeStream, true);
195         // right.generateCode(currentScope, codeStream, true);
196         // codeStream.ldiv();
197         // if (!valueRequired)
198         // codeStream.pop2();
199         // break;
200         // case T_double :
201         // left.generateCode(currentScope, codeStream, valueRequired);
202         // right.generateCode(currentScope, codeStream, valueRequired);
203         // if (valueRequired)
204         // codeStream.ddiv();
205         // break;
206         // case T_float :
207         // left.generateCode(currentScope, codeStream, valueRequired);
208         // right.generateCode(currentScope, codeStream, valueRequired);
209         // if (valueRequired)
210         // codeStream.fdiv();
211         // break;
212         // }
213         // break;
214         // case REMAINDER :
215         // switch (bits & ReturnTypeIDMASK) {
216         // case T_int :
217         // left.generateCode(currentScope, codeStream, true);
218         // right.generateCode(currentScope, codeStream, true);
219         // codeStream.irem();
220         // if (!valueRequired)
221         // codeStream.pop();
222         // break;
223         // case T_long :
224         // left.generateCode(currentScope, codeStream, true);
225         // right.generateCode(currentScope, codeStream, true);
226         // codeStream.lrem();
227         // if (!valueRequired)
228         // codeStream.pop2();
229         // break;
230         // case T_double :
231         // left.generateCode(currentScope, codeStream, valueRequired);
232         // right.generateCode(currentScope, codeStream, valueRequired);
233         // if (valueRequired)
234         // codeStream.drem();
235         // break;
236         // case T_float :
237         // left.generateCode(currentScope, codeStream, valueRequired);
238         // right.generateCode(currentScope, codeStream, valueRequired);
239         // if (valueRequired)
240         // codeStream.frem();
241         // break;
242         // }
243         // break;
244         // case AND :
245         // switch (bits & ReturnTypeIDMASK) {
246         // case T_int :
247         // // 0 & x
248         // if ((left.constant != Constant.NotAConstant)
249         // && (left.constant.typeID() == T_int)
250         // && (left.constant.intValue() == 0)) {
251         // right.generateCode(currentScope, codeStream, false);
252         // if (valueRequired)
253         // codeStream.iconst_0();
254         // } else {
255         // // x & 0
256         // if ((right.constant != Constant.NotAConstant)
257         // && (right.constant.typeID() == T_int)
258         // && (right.constant.intValue() == 0)) {
259         // left.generateCode(currentScope, codeStream, false);
260         // if (valueRequired)
261         // codeStream.iconst_0();
262         // } else {
263         // left.generateCode(currentScope, codeStream, valueRequired);
264         // right.generateCode(currentScope, codeStream, valueRequired);
265         // if (valueRequired)
266         // codeStream.iand();
267         // }
268         // }
269         // break;
270         // case T_long :
271         // // 0 & x
272         // if ((left.constant != Constant.NotAConstant)
273         // && (left.constant.typeID() == T_long)
274         // && (left.constant.longValue() == 0L)) {
275         // right.generateCode(currentScope, codeStream, false);
276         // if (valueRequired)
277         // codeStream.lconst_0();
278         // } else {
279         // // x & 0
280         // if ((right.constant != Constant.NotAConstant)
281         // && (right.constant.typeID() == T_long)
282         // && (right.constant.longValue() == 0L)) {
283         // left.generateCode(currentScope, codeStream, false);
284         // if (valueRequired)
285         // codeStream.lconst_0();
286         // } else {
287         // left.generateCode(currentScope, codeStream, valueRequired);
288         // right.generateCode(currentScope, codeStream, valueRequired);
289         // if (valueRequired)
290         // codeStream.land();
291         // }
292         // }
293         // break;
294         // case T_boolean : // logical and
295         // generateOptimizedLogicalAnd(
296         // currentScope,
297         // codeStream,
298         // null,
299         // (falseLabel = new Label(codeStream)),
300         // valueRequired);
301         // /* improving code gen for such a case: boolean b = i < 0 && false;
302         // * since the label has never been used, we have the inlined value on the
303         // stack. */
304         // if (falseLabel.hasForwardReferences()) {
305         // if (valueRequired) {
306         // codeStream.iconst_1();
307         // if ((bits & ValueForReturnMASK) != 0) {
308         // codeStream.ireturn();
309         // falseLabel.place();
310         // codeStream.iconst_0();
311         // } else {
312         // codeStream.goto_(endLabel = new Label(codeStream));
313         // codeStream.decrStackSize(1);
314         // falseLabel.place();
315         // codeStream.iconst_0();
316         // endLabel.place();
317         // }
318         // } else {
319         // falseLabel.place();
320         // }
321         // }
322         // }
323         // break;
324         // case OR :
325         // switch (bits & ReturnTypeIDMASK) {
326         // case T_int :
327         // // 0 | x
328         // if ((left.constant != Constant.NotAConstant)
329         // && (left.constant.typeID() == T_int)
330         // && (left.constant.intValue() == 0)) {
331         // right.generateCode(currentScope, codeStream, valueRequired);
332         // } else {
333         // // x | 0
334         // if ((right.constant != Constant.NotAConstant)
335         // && (right.constant.typeID() == T_int)
336         // && (right.constant.intValue() == 0)) {
337         // left.generateCode(currentScope, codeStream, valueRequired);
338         // } else {
339         // left.generateCode(currentScope, codeStream, valueRequired);
340         // right.generateCode(currentScope, codeStream, valueRequired);
341         // if (valueRequired)
342         // codeStream.ior();
343         // }
344         // }
345         // break;
346         // case T_long :
347         // // 0 | x
348         // if ((left.constant != Constant.NotAConstant)
349         // && (left.constant.typeID() == T_long)
350         // && (left.constant.longValue() == 0L)) {
351         // right.generateCode(currentScope, codeStream, valueRequired);
352         // } else {
353         // // x | 0
354         // if ((right.constant != Constant.NotAConstant)
355         // && (right.constant.typeID() == T_long)
356         // && (right.constant.longValue() == 0L)) {
357         // left.generateCode(currentScope, codeStream, valueRequired);
358         // } else {
359         // left.generateCode(currentScope, codeStream, valueRequired);
360         // right.generateCode(currentScope, codeStream, valueRequired);
361         // if (valueRequired)
362         // codeStream.lor();
363         // }
364         // }
365         // break;
366         // case T_boolean : // logical or
367         // generateOptimizedLogicalOr(
368         // currentScope,
369         // codeStream,
370         // null,
371         // (falseLabel = new Label(codeStream)),
372         // valueRequired);
373         // /* improving code gen for such a case: boolean b = i < 0 || true;
374         // * since the label has never been used, we have the inlined value on the
375         // stack. */
376         // if (falseLabel.hasForwardReferences()) {
377         // if (valueRequired) {
378         // codeStream.iconst_1();
379         // if ((bits & ValueForReturnMASK) != 0) {
380         // codeStream.ireturn();
381         // falseLabel.place();
382         // codeStream.iconst_0();
383         // } else {
384         // codeStream.goto_(endLabel = new Label(codeStream));
385         // codeStream.decrStackSize(1);
386         // falseLabel.place();
387         // codeStream.iconst_0();
388         // endLabel.place();
389         // }
390         // } else {
391         // falseLabel.place();
392         // }
393         // }
394         // }
395         // break;
396         // case XOR :
397         // switch (bits & ReturnTypeIDMASK) {
398         // case T_int :
399         // // 0 ^ x
400         // if ((left.constant != Constant.NotAConstant)
401         // && (left.constant.typeID() == T_int)
402         // && (left.constant.intValue() == 0)) {
403         // right.generateCode(currentScope, codeStream, valueRequired);
404         // } else {
405         // // x ^ 0
406         // if ((right.constant != Constant.NotAConstant)
407         // && (right.constant.typeID() == T_int)
408         // && (right.constant.intValue() == 0)) {
409         // left.generateCode(currentScope, codeStream, valueRequired);
410         // } else {
411         // left.generateCode(currentScope, codeStream, valueRequired);
412         // right.generateCode(currentScope, codeStream, valueRequired);
413         // if (valueRequired)
414         // codeStream.ixor();
415         // }
416         // }
417         // break;
418         // case T_long :
419         // // 0 ^ x
420         // if ((left.constant != Constant.NotAConstant)
421         // && (left.constant.typeID() == T_long)
422         // && (left.constant.longValue() == 0L)) {
423         // right.generateCode(currentScope, codeStream, valueRequired);
424         // } else {
425         // // x ^ 0
426         // if ((right.constant != Constant.NotAConstant)
427         // && (right.constant.typeID() == T_long)
428         // && (right.constant.longValue() == 0L)) {
429         // left.generateCode(currentScope, codeStream, valueRequired);
430         // } else {
431         // left.generateCode(currentScope, codeStream, valueRequired);
432         // right.generateCode(currentScope, codeStream, valueRequired);
433         // if (valueRequired)
434         // codeStream.lxor();
435         // }
436         // }
437         // break;
438         // case T_boolean :
439         // generateOptimizedLogicalXor(
440         // currentScope,
441         // codeStream,
442         // null,
443         // (falseLabel = new Label(codeStream)),
444         // valueRequired);
445         // /* improving code gen for such a case: boolean b = i < 0 ^ bool;
446         // * since the label has never been used, we have the inlined value on the
447         // stack. */
448         // if (falseLabel.hasForwardReferences()) {
449         // if (valueRequired) {
450         // codeStream.iconst_1();
451         // if ((bits & ValueForReturnMASK) != 0) {
452         // codeStream.ireturn();
453         // falseLabel.place();
454         // codeStream.iconst_0();
455         // } else {
456         // codeStream.goto_(endLabel = new Label(codeStream));
457         // codeStream.decrStackSize(1);
458         // falseLabel.place();
459         // codeStream.iconst_0();
460         // endLabel.place();
461         // }
462         // } else {
463         // falseLabel.place();
464         // }
465         // }
466         // }
467         // break;
468         // case LEFT_SHIFT :
469         // switch (bits & ReturnTypeIDMASK) {
470         // case T_int :
471         // left.generateCode(currentScope, codeStream, valueRequired);
472         // right.generateCode(currentScope, codeStream, valueRequired);
473         // if (valueRequired)
474         // codeStream.ishl();
475         // break;
476         // case T_long :
477         // left.generateCode(currentScope, codeStream, valueRequired);
478         // right.generateCode(currentScope, codeStream, valueRequired);
479         // if (valueRequired)
480         // codeStream.lshl();
481         // }
482         // break;
483         // case RIGHT_SHIFT :
484         // switch (bits & ReturnTypeIDMASK) {
485         // case T_int :
486         // left.generateCode(currentScope, codeStream, valueRequired);
487         // right.generateCode(currentScope, codeStream, valueRequired);
488         // if (valueRequired)
489         // codeStream.ishr();
490         // break;
491         // case T_long :
492         // left.generateCode(currentScope, codeStream, valueRequired);
493         // right.generateCode(currentScope, codeStream, valueRequired);
494         // if (valueRequired)
495         // codeStream.lshr();
496         // }
497         // break;
498         // case UNSIGNED_RIGHT_SHIFT :
499         // switch (bits & ReturnTypeIDMASK) {
500         // case T_int :
501         // left.generateCode(currentScope, codeStream, valueRequired);
502         // right.generateCode(currentScope, codeStream, valueRequired);
503         // if (valueRequired)
504         // codeStream.iushr();
505         // break;
506         // case T_long :
507         // left.generateCode(currentScope, codeStream, valueRequired);
508         // right.generateCode(currentScope, codeStream, valueRequired);
509         // if (valueRequired)
510         // codeStream.lushr();
511         // }
512         // break;
513         // case GREATER :
514         // generateOptimizedGreaterThan(
515         // currentScope,
516         // codeStream,
517         // null,
518         // (falseLabel = new Label(codeStream)),
519         // valueRequired);
520         // if (valueRequired) {
521         // codeStream.iconst_1();
522         // if ((bits & ValueForReturnMASK) != 0) {
523         // codeStream.ireturn();
524         // falseLabel.place();
525         // codeStream.iconst_0();
526         // } else {
527         // codeStream.goto_(endLabel = new Label(codeStream));
528         // codeStream.decrStackSize(1);
529         // falseLabel.place();
530         // codeStream.iconst_0();
531         // endLabel.place();
532         // }
533         // }
534         // break;
535         // case GREATER_EQUAL :
536         // generateOptimizedGreaterThanOrEqual(
537         // currentScope,
538         // codeStream,
539         // null,
540         // (falseLabel = new Label(codeStream)),
541         // valueRequired);
542         // if (valueRequired) {
543         // codeStream.iconst_1();
544         // if ((bits & ValueForReturnMASK) != 0) {
545         // codeStream.ireturn();
546         // falseLabel.place();
547         // codeStream.iconst_0();
548         // } else {
549         // codeStream.goto_(endLabel = new Label(codeStream));
550         // codeStream.decrStackSize(1);
551         // falseLabel.place();
552         // codeStream.iconst_0();
553         // endLabel.place();
554         // }
555         // }
556         // break;
557         // case LESS :
558         // generateOptimizedLessThan(
559         // currentScope,
560         // codeStream,
561         // null,
562         // (falseLabel = new Label(codeStream)),
563         // valueRequired);
564         // if (valueRequired) {
565         // codeStream.iconst_1();
566         // if ((bits & ValueForReturnMASK) != 0) {
567         // codeStream.ireturn();
568         // falseLabel.place();
569         // codeStream.iconst_0();
570         // } else {
571         // codeStream.goto_(endLabel = new Label(codeStream));
572         // codeStream.decrStackSize(1);
573         // falseLabel.place();
574         // codeStream.iconst_0();
575         // endLabel.place();
576         // }
577         // }
578         // break;
579         // case LESS_EQUAL :
580         // generateOptimizedLessThanOrEqual(
581         // currentScope,
582         // codeStream,
583         // null,
584         // (falseLabel = new Label(codeStream)),
585         // valueRequired);
586         // if (valueRequired) {
587         // codeStream.iconst_1();
588         // if ((bits & ValueForReturnMASK) != 0) {
589         // codeStream.ireturn();
590         // falseLabel.place();
591         // codeStream.iconst_0();
592         // } else {
593         // codeStream.goto_(endLabel = new Label(codeStream));
594         // codeStream.decrStackSize(1);
595         // falseLabel.place();
596         // codeStream.iconst_0();
597         // endLabel.place();
598         // }
599         // }
600         // }
601         // if (valueRequired) {
602         // codeStream.generateImplicitConversion(implicitConversion);
603         // }
604         // codeStream.recordPositionsFrom(pc, this.sourceStart);
605         // }
606         /**
607          * Boolean operator code generation Optimized operations are: <, <=, >, >=, &, |, ^
608          */
609         // public void generateOptimizedBoolean(
610         // BlockScope currentScope,
611         // CodeStream codeStream,
612         // Label trueLabel,
613         // Label falseLabel,
614         // boolean valueRequired) {
615         //
616         // if ((constant != Constant.NotAConstant) && (constant.typeID() ==
617         // T_boolean)) {
618         // super.generateOptimizedBoolean(
619         // currentScope,
620         // codeStream,
621         // trueLabel,
622         // falseLabel,
623         // valueRequired);
624         // return;
625         // }
626         // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
627         // case LESS :
628         // generateOptimizedLessThan(
629         // currentScope,
630         // codeStream,
631         // trueLabel,
632         // falseLabel,
633         // valueRequired);
634         // return;
635         // case LESS_EQUAL :
636         // generateOptimizedLessThanOrEqual(
637         // currentScope,
638         // codeStream,
639         // trueLabel,
640         // falseLabel,
641         // valueRequired);
642         // return;
643         // case GREATER :
644         // generateOptimizedGreaterThan(
645         // currentScope,
646         // codeStream,
647         // trueLabel,
648         // falseLabel,
649         // valueRequired);
650         // return;
651         // case GREATER_EQUAL :
652         // generateOptimizedGreaterThanOrEqual(
653         // currentScope,
654         // codeStream,
655         // trueLabel,
656         // falseLabel,
657         // valueRequired);
658         // return;
659         // case AND :
660         // generateOptimizedLogicalAnd(
661         // currentScope,
662         // codeStream,
663         // trueLabel,
664         // falseLabel,
665         // valueRequired);
666         // return;
667         // case OR :
668         // generateOptimizedLogicalOr(
669         // currentScope,
670         // codeStream,
671         // trueLabel,
672         // falseLabel,
673         // valueRequired);
674         // return;
675         // case XOR :
676         // generateOptimizedLogicalXor(
677         // currentScope,
678         // codeStream,
679         // trueLabel,
680         // falseLabel,
681         // valueRequired);
682         // return;
683         // }
684         // super.generateOptimizedBoolean(
685         // currentScope,
686         // codeStream,
687         // trueLabel,
688         // falseLabel,
689         // valueRequired);
690         // }
691         //
692         // /**
693         // * Boolean generation for >
694         // */
695         // public void generateOptimizedGreaterThan(
696         // BlockScope currentScope,
697         // CodeStream codeStream,
698         // Label trueLabel,
699         // Label falseLabel,
700         // boolean valueRequired) {
701         //
702         // int promotedTypeID = left.implicitConversion >> 4;
703         // // both sides got promoted in the same way
704         // if (promotedTypeID == T_int) {
705         // // 0 > x
706         // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
707         // right.generateCode(currentScope, codeStream, valueRequired);
708         // if (valueRequired) {
709         // if (falseLabel == null) {
710         // if (trueLabel != null) {
711         // // implicitly falling through the FALSE case
712         // codeStream.iflt(trueLabel);
713         // }
714         // } else {
715         // if (trueLabel == null) {
716         // // implicitly falling through the TRUE case
717         // codeStream.ifge(falseLabel);
718         // } else {
719         // // no implicit fall through TRUE/FALSE --> should never occur
720         // }
721         // }
722         // }
723         // // reposition the endPC
724         // codeStream.updateLastRecordedEndPC(codeStream.position);
725         // return;
726         // }
727         // // x > 0
728         // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
729         // {
730         // left.generateCode(currentScope, codeStream, valueRequired);
731         // if (valueRequired) {
732         // if (falseLabel == null) {
733         // if (trueLabel != null) {
734         // // implicitly falling through the FALSE case
735         // codeStream.ifgt(trueLabel);
736         // }
737         // } else {
738         // if (trueLabel == null) {
739         // // implicitly falling through the TRUE case
740         // codeStream.ifle(falseLabel);
741         // } else {
742         // // no implicit fall through TRUE/FALSE --> should never occur
743         // }
744         // }
745         // }
746         // // reposition the endPC
747         // codeStream.updateLastRecordedEndPC(codeStream.position);
748         // return;
749         // }
750         // }
751         // // default comparison
752         // left.generateCode(currentScope, codeStream, valueRequired);
753         // right.generateCode(currentScope, codeStream, valueRequired);
754         // if (valueRequired) {
755         // if (falseLabel == null) {
756         // if (trueLabel != null) {
757         // // implicit falling through the FALSE case
758         // switch (promotedTypeID) {
759         // case T_int :
760         // codeStream.if_icmpgt(trueLabel);
761         // break;
762         // case T_float :
763         // codeStream.fcmpl();
764         // codeStream.ifgt(trueLabel);
765         // break;
766         // case T_long :
767         // codeStream.lcmp();
768         // codeStream.ifgt(trueLabel);
769         // break;
770         // case T_double :
771         // codeStream.dcmpl();
772         // codeStream.ifgt(trueLabel);
773         // }
774         // // reposition the endPC
775         // codeStream.updateLastRecordedEndPC(codeStream.position);
776         // return;
777         // }
778         // } else {
779         // if (trueLabel == null) {
780         // // implicit falling through the TRUE case
781         // switch (promotedTypeID) {
782         // case T_int :
783         // codeStream.if_icmple(falseLabel);
784         // break;
785         // case T_float :
786         // codeStream.fcmpl();
787         // codeStream.ifle(falseLabel);
788         // break;
789         // case T_long :
790         // codeStream.lcmp();
791         // codeStream.ifle(falseLabel);
792         // break;
793         // case T_double :
794         // codeStream.dcmpl();
795         // codeStream.ifle(falseLabel);
796         // }
797         // // reposition the endPC
798         // codeStream.updateLastRecordedEndPC(codeStream.position);
799         // return;
800         // } else {
801         // // no implicit fall through TRUE/FALSE --> should never occur
802         // }
803         // }
804         // }
805         // }
806         /**
807          * Boolean generation for >=
808          */
809         // public void generateOptimizedGreaterThanOrEqual(
810         // BlockScope currentScope,
811         // CodeStream codeStream,
812         // Label trueLabel,
813         // Label falseLabel,
814         // boolean valueRequired) {
815         //
816         // int promotedTypeID = left.implicitConversion >> 4;
817         // // both sides got promoted in the same way
818         // if (promotedTypeID == T_int) {
819         // // 0 >= x
820         // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
821         // right.generateCode(currentScope, codeStream, valueRequired);
822         // if (valueRequired) {
823         // if (falseLabel == null) {
824         // if (trueLabel != null) {
825         // // implicitly falling through the FALSE case
826         // codeStream.ifle(trueLabel);
827         // }
828         // } else {
829         // if (trueLabel == null) {
830         // // implicitly falling through the TRUE case
831         // codeStream.ifgt(falseLabel);
832         // } else {
833         // // no implicit fall through TRUE/FALSE --> should never occur
834         // }
835         // }
836         // }
837         // // reposition the endPC
838         // codeStream.updateLastRecordedEndPC(codeStream.position);
839         // return;
840         // }
841         // // x >= 0
842         // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
843         // {
844         // left.generateCode(currentScope, codeStream, valueRequired);
845         // if (valueRequired) {
846         // if (falseLabel == null) {
847         // if (trueLabel != null) {
848         // // implicitly falling through the FALSE case
849         // codeStream.ifge(trueLabel);
850         // }
851         // } else {
852         // if (trueLabel == null) {
853         // // implicitly falling through the TRUE case
854         // codeStream.iflt(falseLabel);
855         // } else {
856         // // no implicit fall through TRUE/FALSE --> should never occur
857         // }
858         // }
859         // }
860         // // reposition the endPC
861         // codeStream.updateLastRecordedEndPC(codeStream.position);
862         // return;
863         // }
864         // }
865         // // default comparison
866         // left.generateCode(currentScope, codeStream, valueRequired);
867         // right.generateCode(currentScope, codeStream, valueRequired);
868         // if (valueRequired) {
869         // if (falseLabel == null) {
870         // if (trueLabel != null) {
871         // // implicit falling through the FALSE case
872         // switch (promotedTypeID) {
873         // case T_int :
874         // codeStream.if_icmpge(trueLabel);
875         // break;
876         // case T_float :
877         // codeStream.fcmpl();
878         // codeStream.ifge(trueLabel);
879         // break;
880         // case T_long :
881         // codeStream.lcmp();
882         // codeStream.ifge(trueLabel);
883         // break;
884         // case T_double :
885         // codeStream.dcmpl();
886         // codeStream.ifge(trueLabel);
887         // }
888         // // reposition the endPC
889         // codeStream.updateLastRecordedEndPC(codeStream.position);
890         // return;
891         // }
892         // } else {
893         // if (trueLabel == null) {
894         // // implicit falling through the TRUE case
895         // switch (promotedTypeID) {
896         // case T_int :
897         // codeStream.if_icmplt(falseLabel);
898         // break;
899         // case T_float :
900         // codeStream.fcmpl();
901         // codeStream.iflt(falseLabel);
902         // break;
903         // case T_long :
904         // codeStream.lcmp();
905         // codeStream.iflt(falseLabel);
906         // break;
907         // case T_double :
908         // codeStream.dcmpl();
909         // codeStream.iflt(falseLabel);
910         // }
911         // // reposition the endPC
912         // codeStream.updateLastRecordedEndPC(codeStream.position);
913         // return;
914         // } else {
915         // // no implicit fall through TRUE/FALSE --> should never occur
916         // }
917         // }
918         // }
919         // }
920         //
921         // /**
922         // * Boolean generation for <
923         // */
924         // public void generateOptimizedLessThan(
925         // BlockScope currentScope,
926         // CodeStream codeStream,
927         // Label trueLabel,
928         // Label falseLabel,
929         // boolean valueRequired) {
930         //
931         // int promotedTypeID = left.implicitConversion >> 4;
932         // // both sides got promoted in the same way
933         // if (promotedTypeID == T_int) {
934         // // 0 < x
935         // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
936         // right.generateCode(currentScope, codeStream, valueRequired);
937         // if (valueRequired) {
938         // if (falseLabel == null) {
939         // if (trueLabel != null) {
940         // // implicitly falling through the FALSE case
941         // codeStream.ifgt(trueLabel);
942         // }
943         // } else {
944         // if (trueLabel == null) {
945         // // implicitly falling through the TRUE case
946         // codeStream.ifle(falseLabel);
947         // } else {
948         // // no implicit fall through TRUE/FALSE --> should never occur
949         // }
950         // }
951         // }
952         // codeStream.updateLastRecordedEndPC(codeStream.position);
953         // return;
954         // }
955         // // x < 0
956         // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
957         // {
958         // left.generateCode(currentScope, codeStream, valueRequired);
959         // if (valueRequired) {
960         // if (falseLabel == null) {
961         // if (trueLabel != null) {
962         // // implicitly falling through the FALSE case
963         // codeStream.iflt(trueLabel);
964         // }
965         // } else {
966         // if (trueLabel == null) {
967         // // implicitly falling through the TRUE case
968         // codeStream.ifge(falseLabel);
969         // } else {
970         // // no implicit fall through TRUE/FALSE --> should never occur
971         // }
972         // }
973         // }
974         // codeStream.updateLastRecordedEndPC(codeStream.position);
975         // return;
976         // }
977         // }
978         // // default comparison
979         // left.generateCode(currentScope, codeStream, valueRequired);
980         // right.generateCode(currentScope, codeStream, valueRequired);
981         // if (valueRequired) {
982         // if (falseLabel == null) {
983         // if (trueLabel != null) {
984         // // implicit falling through the FALSE case
985         // switch (promotedTypeID) {
986         // case T_int :
987         // codeStream.if_icmplt(trueLabel);
988         // break;
989         // case T_float :
990         // codeStream.fcmpg();
991         // codeStream.iflt(trueLabel);
992         // break;
993         // case T_long :
994         // codeStream.lcmp();
995         // codeStream.iflt(trueLabel);
996         // break;
997         // case T_double :
998         // codeStream.dcmpg();
999         // codeStream.iflt(trueLabel);
1000         // }
1001         // codeStream.updateLastRecordedEndPC(codeStream.position);
1002         // return;
1003         // }
1004         // } else {
1005         // if (trueLabel == null) {
1006         // // implicit falling through the TRUE case
1007         // switch (promotedTypeID) {
1008         // case T_int :
1009         // codeStream.if_icmpge(falseLabel);
1010         // break;
1011         // case T_float :
1012         // codeStream.fcmpg();
1013         // codeStream.ifge(falseLabel);
1014         // break;
1015         // case T_long :
1016         // codeStream.lcmp();
1017         // codeStream.ifge(falseLabel);
1018         // break;
1019         // case T_double :
1020         // codeStream.dcmpg();
1021         // codeStream.ifge(falseLabel);
1022         // }
1023         // codeStream.updateLastRecordedEndPC(codeStream.position);
1024         // return;
1025         // } else {
1026         // // no implicit fall through TRUE/FALSE --> should never occur
1027         // }
1028         // }
1029         // }
1030         // }
1031         //      
1032         // /**
1033         // * Boolean generation for <=
1034         // */
1035         // public void generateOptimizedLessThanOrEqual(
1036         // BlockScope currentScope,
1037         // CodeStream codeStream,
1038         // Label trueLabel,
1039         // Label falseLabel,
1040         // boolean valueRequired) {
1041         //
1042         // int promotedTypeID = left.implicitConversion >> 4;
1043         // // both sides got promoted in the same way
1044         // if (promotedTypeID == T_int) {
1045         // // 0 <= x
1046         // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
1047         // right.generateCode(currentScope, codeStream, valueRequired);
1048         // if (valueRequired) {
1049         // if (falseLabel == null) {
1050         // if (trueLabel != null) {
1051         // // implicitly falling through the FALSE case
1052         // codeStream.ifge(trueLabel);
1053         // }
1054         // } else {
1055         // if (trueLabel == null) {
1056         // // implicitly falling through the TRUE case
1057         // codeStream.iflt(falseLabel);
1058         // } else {
1059         // // no implicit fall through TRUE/FALSE --> should never occur
1060         // }
1061         // }
1062         // }
1063         // // reposition the endPC
1064         // codeStream.updateLastRecordedEndPC(codeStream.position);
1065         // return;
1066         // }
1067         // // x <= 0
1068         // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0))
1069         // {
1070         // left.generateCode(currentScope, codeStream, valueRequired);
1071         // if (valueRequired) {
1072         // if (falseLabel == null) {
1073         // if (trueLabel != null) {
1074         // // implicitly falling through the FALSE case
1075         // codeStream.ifle(trueLabel);
1076         // }
1077         // } else {
1078         // if (trueLabel == null) {
1079         // // implicitly falling through the TRUE case
1080         // codeStream.ifgt(falseLabel);
1081         // } else {
1082         // // no implicit fall through TRUE/FALSE --> should never occur
1083         // }
1084         // }
1085         // }
1086         // // reposition the endPC
1087         // codeStream.updateLastRecordedEndPC(codeStream.position);
1088         // return;
1089         // }
1090         // }
1091         // // default comparison
1092         // left.generateCode(currentScope, codeStream, valueRequired);
1093         // right.generateCode(currentScope, codeStream, valueRequired);
1094         // if (valueRequired) {
1095         // if (falseLabel == null) {
1096         // if (trueLabel != null) {
1097         // // implicit falling through the FALSE case
1098         // switch (promotedTypeID) {
1099         // case T_int :
1100         // codeStream.if_icmple(trueLabel);
1101         // break;
1102         // case T_float :
1103         // codeStream.fcmpg();
1104         // codeStream.ifle(trueLabel);
1105         // break;
1106         // case T_long :
1107         // codeStream.lcmp();
1108         // codeStream.ifle(trueLabel);
1109         // break;
1110         // case T_double :
1111         // codeStream.dcmpg();
1112         // codeStream.ifle(trueLabel);
1113         // }
1114         // // reposition the endPC
1115         // codeStream.updateLastRecordedEndPC(codeStream.position);
1116         // return;
1117         // }
1118         // } else {
1119         // if (trueLabel == null) {
1120         // // implicit falling through the TRUE case
1121         // switch (promotedTypeID) {
1122         // case T_int :
1123         // codeStream.if_icmpgt(falseLabel);
1124         // break;
1125         // case T_float :
1126         // codeStream.fcmpg();
1127         // codeStream.ifgt(falseLabel);
1128         // break;
1129         // case T_long :
1130         // codeStream.lcmp();
1131         // codeStream.ifgt(falseLabel);
1132         // break;
1133         // case T_double :
1134         // codeStream.dcmpg();
1135         // codeStream.ifgt(falseLabel);
1136         // }
1137         // // reposition the endPC
1138         // codeStream.updateLastRecordedEndPC(codeStream.position);
1139         // return;
1140         // } else {
1141         // // no implicit fall through TRUE/FALSE --> should never occur
1142         // }
1143         // }
1144         // }
1145         // }
1146         //      
1147         // /**
1148         // * Boolean generation for &
1149         // */
1150         // public void generateOptimizedLogicalAnd(
1151         // BlockScope currentScope,
1152         // CodeStream codeStream,
1153         // Label trueLabel,
1154         // Label falseLabel,
1155         // boolean valueRequired) {
1156         //                      
1157         // Constant condConst;
1158         // if ((left.implicitConversion & 0xF) == T_boolean) {
1159         // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
1160         // if (condConst.booleanValue() == true) {
1161         // // <something equivalent to true> & x
1162         // left.generateOptimizedBoolean(
1163         // currentScope,
1164         // codeStream,
1165         // trueLabel,
1166         // falseLabel,
1167         // false);
1168         // if ((bits & OnlyValueRequiredMASK) != 0) {
1169         // right.generateCode(currentScope, codeStream, valueRequired);
1170         // } else {
1171         // right.generateOptimizedBoolean(
1172         // currentScope,
1173         // codeStream,
1174         // trueLabel,
1175         // falseLabel,
1176         // valueRequired);
1177         // }
1178         // } else {
1179         // // <something equivalent to false> & x
1180         // left.generateOptimizedBoolean(
1181         // currentScope,
1182         // codeStream,
1183         // trueLabel,
1184         // falseLabel,
1185         // false);
1186         // right.generateOptimizedBoolean(
1187         // currentScope,
1188         // codeStream,
1189         // trueLabel,
1190         // falseLabel,
1191         // false);
1192         // if (valueRequired) {
1193         // if ((bits & OnlyValueRequiredMASK) != 0) {
1194         // codeStream.iconst_0();
1195         // } else {
1196         // if (falseLabel != null) {
1197         // // implicit falling through the TRUE case
1198         // codeStream.goto_(falseLabel);
1199         // }
1200         // }
1201         // }
1202         // // reposition the endPC
1203         // codeStream.updateLastRecordedEndPC(codeStream.position);
1204         // }
1205         // return;
1206         // }
1207         // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1208         // if (condConst.booleanValue() == true) {
1209         // // x & <something equivalent to true>
1210         // if ((bits & OnlyValueRequiredMASK) != 0) {
1211         // left.generateCode(currentScope, codeStream, valueRequired);
1212         // } else {
1213         // left.generateOptimizedBoolean(
1214         // currentScope,
1215         // codeStream,
1216         // trueLabel,
1217         // falseLabel,
1218         // valueRequired);
1219         // }
1220         // right.generateOptimizedBoolean(
1221         // currentScope,
1222         // codeStream,
1223         // trueLabel,
1224         // falseLabel,
1225         // false);
1226         // } else {
1227         // // x & <something equivalent to false>
1228         // left.generateOptimizedBoolean(
1229         // currentScope,
1230         // codeStream,
1231         // trueLabel,
1232         // falseLabel,
1233         // false);
1234         // right.generateOptimizedBoolean(
1235         // currentScope,
1236         // codeStream,
1237         // trueLabel,
1238         // falseLabel,
1239         // false);
1240         // if (valueRequired) {
1241         // if ((bits & OnlyValueRequiredMASK) != 0) {
1242         // codeStream.iconst_0();
1243         // } else {
1244         // if (falseLabel != null) {
1245         // // implicit falling through the TRUE case
1246         // codeStream.goto_(falseLabel);
1247         // }
1248         // }
1249         // }
1250         // // reposition the endPC
1251         // codeStream.updateLastRecordedEndPC(codeStream.position);
1252         // }
1253         // return;
1254         // }
1255         // }
1256         // // default case
1257         // left.generateCode(currentScope, codeStream, valueRequired);
1258         // right.generateCode(currentScope, codeStream, valueRequired);
1259         // if (valueRequired) {
1260         // codeStream.iand();
1261         // if ((bits & OnlyValueRequiredMASK) == 0) {
1262         // if (falseLabel == null) {
1263         // if (trueLabel != null) {
1264         // // implicit falling through the FALSE case
1265         // codeStream.ifne(trueLabel);
1266         // }
1267         // } else {
1268         // // implicit falling through the TRUE case
1269         // if (trueLabel == null) {
1270         // codeStream.ifeq(falseLabel);
1271         // } else {
1272         // // no implicit fall through TRUE/FALSE --> should never occur
1273         // }
1274         // }
1275         // }
1276         // }
1277         // // reposition the endPC
1278         // codeStream.updateLastRecordedEndPC(codeStream.position);
1279         // }
1280         //      
1281         // /**
1282         // * Boolean generation for |
1283         // */
1284         // public void generateOptimizedLogicalOr(
1285         // BlockScope currentScope,
1286         // CodeStream codeStream,
1287         // Label trueLabel,
1288         // Label falseLabel,
1289         // boolean valueRequired) {
1290         //                      
1291         // Constant condConst;
1292         // if ((left.implicitConversion & 0xF) == T_boolean) {
1293         // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
1294         // if (condConst.booleanValue() == true) {
1295         // // <something equivalent to true> | x
1296         // left.generateOptimizedBoolean(
1297         // currentScope,
1298         // codeStream,
1299         // trueLabel,
1300         // falseLabel,
1301         // false);
1302         // right.generateOptimizedBoolean(
1303         // currentScope,
1304         // codeStream,
1305         // trueLabel,
1306         // falseLabel,
1307         // false);
1308         // if (valueRequired) {
1309         // if ((bits & OnlyValueRequiredMASK) != 0) {
1310         // codeStream.iconst_1();
1311         // } else {
1312         // if (trueLabel != null) {
1313         // codeStream.goto_(trueLabel);
1314         // }
1315         // }
1316         // }
1317         // // reposition the endPC
1318         // codeStream.updateLastRecordedEndPC(codeStream.position);
1319         // } else {
1320         // // <something equivalent to false> | x
1321         // left.generateOptimizedBoolean(
1322         // currentScope,
1323         // codeStream,
1324         // trueLabel,
1325         // falseLabel,
1326         // false);
1327         // if ((bits & OnlyValueRequiredMASK) != 0) {
1328         // right.generateCode(currentScope, codeStream, valueRequired);
1329         // } else {
1330         // right.generateOptimizedBoolean(
1331         // currentScope,
1332         // codeStream,
1333         // trueLabel,
1334         // falseLabel,
1335         // valueRequired);
1336         // }
1337         // }
1338         // return;
1339         // }
1340         // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1341         // if (condConst.booleanValue() == true) {
1342         // // x | <something equivalent to true>
1343         // left.generateOptimizedBoolean(
1344         // currentScope,
1345         // codeStream,
1346         // trueLabel,
1347         // falseLabel,
1348         // false);
1349         // right.generateOptimizedBoolean(
1350         // currentScope,
1351         // codeStream,
1352         // trueLabel,
1353         // falseLabel,
1354         // false);
1355         // if (valueRequired) {
1356         // if ((bits & OnlyValueRequiredMASK) != 0) {
1357         // codeStream.iconst_1();
1358         // } else {
1359         // if (trueLabel != null) {
1360         // codeStream.goto_(trueLabel);
1361         // }
1362         // }
1363         // }
1364         // // reposition the endPC
1365         // codeStream.updateLastRecordedEndPC(codeStream.position);
1366         // } else {
1367         // // x | <something equivalent to false>
1368         // if ((bits & OnlyValueRequiredMASK) != 0) {
1369         // left.generateCode(currentScope, codeStream, valueRequired);
1370         // } else {
1371         // left.generateOptimizedBoolean(
1372         // currentScope,
1373         // codeStream,
1374         // trueLabel,
1375         // falseLabel,
1376         // valueRequired);
1377         // }
1378         // right.generateOptimizedBoolean(
1379         // currentScope,
1380         // codeStream,
1381         // trueLabel,
1382         // falseLabel,
1383         // false);
1384         // }
1385         // return;
1386         // }
1387         // }
1388         // // default case
1389         // left.generateCode(currentScope, codeStream, valueRequired);
1390         // right.generateCode(currentScope, codeStream, valueRequired);
1391         // if (valueRequired) {
1392         // codeStream.ior();
1393         // if ((bits & OnlyValueRequiredMASK) == 0) {
1394         // if (falseLabel == null) {
1395         // if (trueLabel != null) {
1396         // // implicit falling through the FALSE case
1397         // codeStream.ifne(trueLabel);
1398         // }
1399         // } else {
1400         // // implicit falling through the TRUE case
1401         // if (trueLabel == null) {
1402         // codeStream.ifeq(falseLabel);
1403         // } else {
1404         // // no implicit fall through TRUE/FALSE --> should never occur
1405         // }
1406         // }
1407         // }
1408         // }
1409         // // reposition the endPC
1410         // codeStream.updateLastRecordedEndPC(codeStream.position);
1411         // }
1412         //      
1413         // /**
1414         // * Boolean generation for ^
1415         // */
1416         // public void generateOptimizedLogicalXor(
1417         // BlockScope currentScope,
1418         // CodeStream codeStream,
1419         // Label trueLabel,
1420         // Label falseLabel,
1421         // boolean valueRequired) {
1422         //                      
1423         // Constant condConst;
1424         // if ((left.implicitConversion & 0xF) == T_boolean) {
1425         // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
1426         // if (condConst.booleanValue() == true) {
1427         // // <something equivalent to true> ^ x
1428         // left.generateOptimizedBoolean(
1429         // currentScope,
1430         // codeStream,
1431         // trueLabel,
1432         // falseLabel,
1433         // false);
1434         // right.generateOptimizedBoolean(
1435         // currentScope,
1436         // codeStream,
1437         // falseLabel,
1438         // trueLabel,
1439         // valueRequired);
1440         // } else {
1441         // // <something equivalent to false> ^ x
1442         // left.generateOptimizedBoolean(
1443         // currentScope,
1444         // codeStream,
1445         // trueLabel,
1446         // falseLabel,
1447         // false);
1448         // if ((bits & OnlyValueRequiredMASK) != 0) {
1449         // right.generateCode(currentScope, codeStream, valueRequired);
1450         // } else {
1451         // right.generateOptimizedBoolean(
1452         // currentScope,
1453         // codeStream,
1454         // trueLabel,
1455         // falseLabel,
1456         // valueRequired);
1457         // }
1458         // }
1459         // return;
1460         // }
1461         // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1462         // if (condConst.booleanValue() == true) {
1463         // // x ^ <something equivalent to true>
1464         // left.generateOptimizedBoolean(
1465         // currentScope,
1466         // codeStream,
1467         // falseLabel,
1468         // trueLabel,
1469         // valueRequired);
1470         // right.generateOptimizedBoolean(
1471         // currentScope,
1472         // codeStream,
1473         // trueLabel,
1474         // falseLabel,
1475         // false);
1476         // } else {
1477         // // x ^ <something equivalent to false>
1478         // if ((bits & OnlyValueRequiredMASK) != 0) {
1479         // left.generateCode(currentScope, codeStream, valueRequired);
1480         // } else {
1481         // left.generateOptimizedBoolean(
1482         // currentScope,
1483         // codeStream,
1484         // trueLabel,
1485         // falseLabel,
1486         // valueRequired);
1487         // }
1488         // right.generateOptimizedBoolean(
1489         // currentScope,
1490         // codeStream,
1491         // trueLabel,
1492         // falseLabel,
1493         // false);
1494         // }
1495         // return;
1496         // }
1497         // }
1498         // // default case
1499         // left.generateCode(currentScope, codeStream, valueRequired);
1500         // right.generateCode(currentScope, codeStream, valueRequired);
1501         // if (valueRequired) {
1502         // codeStream.ixor();
1503         // if ((bits & OnlyValueRequiredMASK) == 0) {
1504         // if (falseLabel == null) {
1505         // if (trueLabel != null) {
1506         // // implicit falling through the FALSE case
1507         // codeStream.ifne(trueLabel);
1508         // }
1509         // } else {
1510         // // implicit falling through the TRUE case
1511         // if (trueLabel == null) {
1512         // codeStream.ifeq(falseLabel);
1513         // } else {
1514         // // no implicit fall through TRUE/FALSE --> should never occur
1515         // }
1516         // }
1517         // }
1518         // }
1519         // // reposition the endPC
1520         // codeStream.updateLastRecordedEndPC(codeStream.position);
1521         // }
1522         //      
1523         // public void generateOptimizedStringBuffer(
1524         // BlockScope blockScope,
1525         // CodeStream codeStream,
1526         // int typeID) {
1527         //                      
1528         // /* In the case trying to make a string concatenation, there is no need to
1529         // create a new
1530         // * string buffer, thus use a lower-level API for code generation involving
1531         // only the
1532         // * appending of arguments to the existing StringBuffer
1533         // */
1534         //
1535         // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1536         // && ((bits & ReturnTypeIDMASK) == T_String)) {
1537         // if (constant != NotAConstant) {
1538         // codeStream.generateConstant(constant, implicitConversion);
1539         // codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
1540         // } else {
1541         // int pc = codeStream.position;
1542         // left.generateOptimizedStringBuffer(
1543         // blockScope,
1544         // codeStream,
1545         // left.implicitConversion & 0xF);
1546         // codeStream.recordPositionsFrom(pc, left.sourceStart);
1547         // pc = codeStream.position;
1548         // right.generateOptimizedStringBuffer(
1549         // blockScope,
1550         // codeStream,
1551         // right.implicitConversion & 0xF);
1552         // codeStream.recordPositionsFrom(pc, right.sourceStart);
1553         // }
1554         // } else {
1555         // super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
1556         // }
1557         // }
1558         //      
1559         // public void generateOptimizedStringBufferCreation(
1560         // BlockScope blockScope,
1561         // CodeStream codeStream,
1562         // int typeID) {
1563         //                      
1564         // /* In the case trying to make a string concatenation, there is no need to
1565         // create a new
1566         // * string buffer, thus use a lower-level API for code generation involving
1567         // only the
1568         // * appending of arguments to the existing StringBuffer
1569         // */
1570         //
1571         // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1572         // && ((bits & ReturnTypeIDMASK) == T_String)) {
1573         // if (constant != NotAConstant) {
1574         // codeStream.newStringBuffer(); // new: java.lang.StringBuffer
1575         // codeStream.dup();
1576         // codeStream.ldc(constant.stringValue());
1577         // codeStream.invokeStringBufferStringConstructor();
1578         // // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
1579         // } else {
1580         // int pc = codeStream.position;
1581         // left.generateOptimizedStringBufferCreation(
1582         // blockScope,
1583         // codeStream,
1584         // left.implicitConversion & 0xF);
1585         // codeStream.recordPositionsFrom(pc, left.sourceStart);
1586         // pc = codeStream.position;
1587         // right.generateOptimizedStringBuffer(
1588         // blockScope,
1589         // codeStream,
1590         // right.implicitConversion & 0xF);
1591         // codeStream.recordPositionsFrom(pc, right.sourceStart);
1592         // }
1593         // } else {
1594         // super.generateOptimizedStringBufferCreation(blockScope, codeStream,
1595         // typeID);
1596         // }
1597         // }
1598         //      
1599         // public boolean isCompactableOperation() {
1600         //              
1601         // return true;
1602         // }
1603         //      
1604         // public void optimizedBooleanConstant(int leftId, int operator, int
1605         // rightId) {
1606         //
1607         // switch (operator) {
1608         // case AND :
1609         // if ((leftId != T_boolean) || (rightId != T_boolean))
1610         // return;
1611         // case AND_AND :
1612         // Constant cst;
1613         // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
1614         // if (cst.booleanValue() == false) { // left is equivalent to false
1615         // optimizedBooleanConstant = cst; // constant(false)
1616         // return;
1617         // } else { //left is equivalent to true
1618         // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1619         // optimizedBooleanConstant = cst;
1620         // // the conditional result is equivalent to the right conditional value
1621         // }
1622         // return;
1623         // }
1624         // }
1625         // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1626         // if (cst.booleanValue() == false) { // right is equivalent to false
1627         // optimizedBooleanConstant = cst; // constant(false)
1628         // }
1629         // }
1630         // return;
1631         // case OR :
1632         // if ((leftId != T_boolean) || (rightId != T_boolean))
1633         // return;
1634         // case OR_OR :
1635         // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
1636         // if (cst.booleanValue() == true) { // left is equivalent to true
1637         // optimizedBooleanConstant = cst; // constant(true)
1638         // return;
1639         // } else { //left is equivalent to false
1640         // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1641         // optimizedBooleanConstant = cst;
1642         // }
1643         // return;
1644         // }
1645         // }
1646         // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1647         // if (cst.booleanValue() == true) { // right is equivalent to true
1648         // optimizedBooleanConstant = cst; // constant(true)
1649         // }
1650         // }
1651         // }
1652         // }
1653         public StringBuffer printExpressionNoParenthesis(int indent,
1654                         StringBuffer output) {
1655
1656                 left.printExpression(indent, output).append(' ').append(
1657                                 operatorToString()).append(' ');
1658                 return right.printExpression(0, output);
1659         }
1660
1661         public TypeBinding resolveType(BlockScope scope) {
1662
1663                 // use the id of the type to navigate into the table
1664                 TypeBinding leftTb = left.resolveType(scope);
1665                 TypeBinding rightTb = right.resolveType(scope);
1666                 if (leftTb == null || rightTb == null) {
1667                         constant = Constant.NotAConstant;
1668                         return null;
1669                 }
1670                 int leftId = leftTb.id;
1671                 int rightId = rightTb.id;
1672                 if (leftId > 15 || rightId > 15) { // must convert String + Object ||
1673                                                                                         // Object + String
1674                         if (leftId == T_String) {
1675                                 rightId = T_Object;
1676                         } else if (rightId == T_String) {
1677                                 leftId = T_Object;
1678                         } else {
1679                                 constant = Constant.NotAConstant;
1680                                 scope.problemReporter().invalidOperator(this, leftTb, rightTb);
1681                                 return null;
1682                         }
1683                 }
1684                 if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
1685                         if (leftId == T_String
1686                                         && rightTb.isArrayType()
1687                                         && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding)
1688                                 scope
1689                                                 .problemReporter()
1690                                                 .signalNoImplicitStringConversionForCharArrayExpression(
1691                                                                 right);
1692                         else if (rightId == T_String
1693                                         && leftTb.isArrayType()
1694                                         && ((ArrayBinding) leftTb).elementsType(scope) == CharBinding)
1695                                 scope
1696                                                 .problemReporter()
1697                                                 .signalNoImplicitStringConversionForCharArrayExpression(
1698                                                                 left);
1699                 }
1700
1701                 // the code is an int
1702                 // (cast) left Op (cast) rigth --> result
1703                 // 0000 0000 0000 0000 0000
1704                 // <<16 <<12 <<8 <<4 <<0
1705
1706                 // Don't test for result = 0. If it is zero, some more work is done.
1707                 // On the one hand when it is not zero (correct code) we avoid doing the
1708                 // test
1709                 int result = ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4)
1710                                 + rightId];
1711                 left.implicitConversion = result >>> 12;
1712                 right.implicitConversion = (result >>> 4) & 0x000FF;
1713
1714                 bits |= result & 0xF;
1715                 switch (result & 0xF) { // record the current ReturnTypeID
1716                 // only switch on possible result type.....
1717                 case T_boolean:
1718                         this.resolvedType = BooleanBinding;
1719                         break;
1720                 case T_byte:
1721                         this.resolvedType = ByteBinding;
1722                         break;
1723                 case T_char:
1724                         this.resolvedType = CharBinding;
1725                         break;
1726                 case T_double:
1727                         this.resolvedType = DoubleBinding;
1728                         break;
1729                 case T_float:
1730                         this.resolvedType = FloatBinding;
1731                         break;
1732                 case T_int:
1733                         this.resolvedType = IntBinding;
1734                         break;
1735                 case T_long:
1736                         this.resolvedType = LongBinding;
1737                         break;
1738                 case T_String:
1739                         this.resolvedType = scope.getJavaLangString();
1740                         break;
1741                 default: // error........
1742                         constant = Constant.NotAConstant;
1743                         scope.problemReporter().invalidOperator(this, leftTb, rightTb);
1744                         return null;
1745                 }
1746
1747                 // compute the constant when valid
1748                 computeConstant(scope, leftId, rightId);
1749                 return this.resolvedType;
1750         }
1751
1752         public String toStringExpressionNoParenthesis() {
1753
1754                 return left.toStringExpression() + " " + //$NON-NLS-1$
1755                                 operatorToString() + " " + //$NON-NLS-1$
1756                                 right.toStringExpression();
1757         }
1758
1759         public void traverse(ASTVisitor visitor, BlockScope scope) {
1760
1761                 if (visitor.visit(this, scope)) {
1762                         left.traverse(visitor, scope);
1763                         right.traverse(visitor, scope);
1764                 }
1765                 visitor.endVisit(this, scope);
1766         }
1767 }