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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
22 public class BinaryExpression extends OperatorExpression {
24 public Expression left, right;
25 public Constant optimizedBooleanConstant;
27 public BinaryExpression(Expression left, Expression right, int operator) {
31 this.bits |= operator << OperatorSHIFT; // encode operator
32 this.sourceStart = left.sourceStart;
33 this.sourceEnd = right.sourceEnd;
36 public FlowInfo analyseCode(
37 BlockScope currentScope,
38 FlowContext flowContext,
45 left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
46 .unconditionalInits();
49 public void computeConstant(BlockScope scope, int leftId, int rightId) {
51 //compute the constant when valid
52 if ((this.left.constant != Constant.NotAConstant)
53 && (this.right.constant != Constant.NotAConstant)) {
56 Constant.computeConstantOperation(
59 (this.bits & OperatorMASK) >> OperatorSHIFT,
62 } catch (ArithmeticException e) {
63 this.constant = Constant.NotAConstant;
64 // 1.2 no longer throws an exception at compile-time
65 //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
68 this.constant = Constant.NotAConstant;
69 //add some work for the boolean operators & |
70 // this.optimizedBooleanConstant(
72 // (this.bits & OperatorMASK) >> OperatorSHIFT,
77 public Constant optimizedBooleanConstant() {
79 return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant;
83 * Code generation for a binary operation
85 // public void generateCode(
86 // BlockScope currentScope,
87 // CodeStream codeStream,
88 // boolean valueRequired) {
90 // int pc = codeStream.position;
91 // Label falseLabel, endLabel;
92 // if (constant != Constant.NotAConstant) {
94 // codeStream.generateConstant(constant, implicitConversion);
95 // codeStream.recordPositionsFrom(pc, this.sourceStart);
98 // bits |= OnlyValueRequiredMASK;
99 // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
101 // switch (bits & ReturnTypeIDMASK) {
103 // codeStream.generateStringAppend(currentScope, left, right);
104 // if (!valueRequired)
108 // left.generateCode(currentScope, codeStream, valueRequired);
109 // right.generateCode(currentScope, codeStream, valueRequired);
110 // if (valueRequired)
111 // codeStream.iadd();
114 // left.generateCode(currentScope, codeStream, valueRequired);
115 // right.generateCode(currentScope, codeStream, valueRequired);
116 // if (valueRequired)
117 // codeStream.ladd();
120 // left.generateCode(currentScope, codeStream, valueRequired);
121 // right.generateCode(currentScope, codeStream, valueRequired);
122 // if (valueRequired)
123 // codeStream.dadd();
126 // left.generateCode(currentScope, codeStream, valueRequired);
127 // right.generateCode(currentScope, codeStream, valueRequired);
128 // if (valueRequired)
129 // codeStream.fadd();
134 // switch (bits & ReturnTypeIDMASK) {
136 // left.generateCode(currentScope, codeStream, valueRequired);
137 // right.generateCode(currentScope, codeStream, valueRequired);
138 // if (valueRequired)
139 // codeStream.isub();
142 // left.generateCode(currentScope, codeStream, valueRequired);
143 // right.generateCode(currentScope, codeStream, valueRequired);
144 // if (valueRequired)
145 // codeStream.lsub();
148 // left.generateCode(currentScope, codeStream, valueRequired);
149 // right.generateCode(currentScope, codeStream, valueRequired);
150 // if (valueRequired)
151 // codeStream.dsub();
154 // left.generateCode(currentScope, codeStream, valueRequired);
155 // right.generateCode(currentScope, codeStream, valueRequired);
156 // if (valueRequired)
157 // codeStream.fsub();
162 // switch (bits & ReturnTypeIDMASK) {
164 // left.generateCode(currentScope, codeStream, valueRequired);
165 // right.generateCode(currentScope, codeStream, valueRequired);
166 // if (valueRequired)
167 // codeStream.imul();
170 // left.generateCode(currentScope, codeStream, valueRequired);
171 // right.generateCode(currentScope, codeStream, valueRequired);
172 // if (valueRequired)
173 // codeStream.lmul();
176 // left.generateCode(currentScope, codeStream, valueRequired);
177 // right.generateCode(currentScope, codeStream, valueRequired);
178 // if (valueRequired)
179 // codeStream.dmul();
182 // left.generateCode(currentScope, codeStream, valueRequired);
183 // right.generateCode(currentScope, codeStream, valueRequired);
184 // if (valueRequired)
185 // codeStream.fmul();
190 // switch (bits & ReturnTypeIDMASK) {
192 // left.generateCode(currentScope, codeStream, true);
193 // right.generateCode(currentScope, codeStream, true);
194 // codeStream.idiv();
195 // if (!valueRequired)
199 // left.generateCode(currentScope, codeStream, true);
200 // right.generateCode(currentScope, codeStream, true);
201 // codeStream.ldiv();
202 // if (!valueRequired)
203 // codeStream.pop2();
206 // left.generateCode(currentScope, codeStream, valueRequired);
207 // right.generateCode(currentScope, codeStream, valueRequired);
208 // if (valueRequired)
209 // codeStream.ddiv();
212 // left.generateCode(currentScope, codeStream, valueRequired);
213 // right.generateCode(currentScope, codeStream, valueRequired);
214 // if (valueRequired)
215 // codeStream.fdiv();
220 // switch (bits & ReturnTypeIDMASK) {
222 // left.generateCode(currentScope, codeStream, true);
223 // right.generateCode(currentScope, codeStream, true);
224 // codeStream.irem();
225 // if (!valueRequired)
229 // left.generateCode(currentScope, codeStream, true);
230 // right.generateCode(currentScope, codeStream, true);
231 // codeStream.lrem();
232 // if (!valueRequired)
233 // codeStream.pop2();
236 // left.generateCode(currentScope, codeStream, valueRequired);
237 // right.generateCode(currentScope, codeStream, valueRequired);
238 // if (valueRequired)
239 // codeStream.drem();
242 // left.generateCode(currentScope, codeStream, valueRequired);
243 // right.generateCode(currentScope, codeStream, valueRequired);
244 // if (valueRequired)
245 // codeStream.frem();
250 // switch (bits & ReturnTypeIDMASK) {
253 // if ((left.constant != Constant.NotAConstant)
254 // && (left.constant.typeID() == T_int)
255 // && (left.constant.intValue() == 0)) {
256 // right.generateCode(currentScope, codeStream, false);
257 // if (valueRequired)
258 // codeStream.iconst_0();
261 // if ((right.constant != Constant.NotAConstant)
262 // && (right.constant.typeID() == T_int)
263 // && (right.constant.intValue() == 0)) {
264 // left.generateCode(currentScope, codeStream, false);
265 // if (valueRequired)
266 // codeStream.iconst_0();
268 // left.generateCode(currentScope, codeStream, valueRequired);
269 // right.generateCode(currentScope, codeStream, valueRequired);
270 // if (valueRequired)
271 // codeStream.iand();
277 // if ((left.constant != Constant.NotAConstant)
278 // && (left.constant.typeID() == T_long)
279 // && (left.constant.longValue() == 0L)) {
280 // right.generateCode(currentScope, codeStream, false);
281 // if (valueRequired)
282 // codeStream.lconst_0();
285 // if ((right.constant != Constant.NotAConstant)
286 // && (right.constant.typeID() == T_long)
287 // && (right.constant.longValue() == 0L)) {
288 // left.generateCode(currentScope, codeStream, false);
289 // if (valueRequired)
290 // codeStream.lconst_0();
292 // left.generateCode(currentScope, codeStream, valueRequired);
293 // right.generateCode(currentScope, codeStream, valueRequired);
294 // if (valueRequired)
295 // codeStream.land();
299 // case T_boolean : // logical and
300 // generateOptimizedLogicalAnd(
304 // (falseLabel = new Label(codeStream)),
306 // /* improving code gen for such a case: boolean b = i < 0 && false;
307 // * since the label has never been used, we have the inlined value on the stack. */
308 // if (falseLabel.hasForwardReferences()) {
309 // if (valueRequired) {
310 // codeStream.iconst_1();
311 // if ((bits & ValueForReturnMASK) != 0) {
312 // codeStream.ireturn();
313 // falseLabel.place();
314 // codeStream.iconst_0();
316 // codeStream.goto_(endLabel = new Label(codeStream));
317 // codeStream.decrStackSize(1);
318 // falseLabel.place();
319 // codeStream.iconst_0();
323 // falseLabel.place();
329 // switch (bits & ReturnTypeIDMASK) {
332 // if ((left.constant != Constant.NotAConstant)
333 // && (left.constant.typeID() == T_int)
334 // && (left.constant.intValue() == 0)) {
335 // right.generateCode(currentScope, codeStream, valueRequired);
338 // if ((right.constant != Constant.NotAConstant)
339 // && (right.constant.typeID() == T_int)
340 // && (right.constant.intValue() == 0)) {
341 // left.generateCode(currentScope, codeStream, valueRequired);
343 // left.generateCode(currentScope, codeStream, valueRequired);
344 // right.generateCode(currentScope, codeStream, valueRequired);
345 // if (valueRequired)
352 // if ((left.constant != Constant.NotAConstant)
353 // && (left.constant.typeID() == T_long)
354 // && (left.constant.longValue() == 0L)) {
355 // right.generateCode(currentScope, codeStream, valueRequired);
358 // if ((right.constant != Constant.NotAConstant)
359 // && (right.constant.typeID() == T_long)
360 // && (right.constant.longValue() == 0L)) {
361 // left.generateCode(currentScope, codeStream, valueRequired);
363 // left.generateCode(currentScope, codeStream, valueRequired);
364 // right.generateCode(currentScope, codeStream, valueRequired);
365 // if (valueRequired)
370 // case T_boolean : // logical or
371 // generateOptimizedLogicalOr(
375 // (falseLabel = new Label(codeStream)),
377 // /* improving code gen for such a case: boolean b = i < 0 || true;
378 // * since the label has never been used, we have the inlined value on the stack. */
379 // if (falseLabel.hasForwardReferences()) {
380 // if (valueRequired) {
381 // codeStream.iconst_1();
382 // if ((bits & ValueForReturnMASK) != 0) {
383 // codeStream.ireturn();
384 // falseLabel.place();
385 // codeStream.iconst_0();
387 // codeStream.goto_(endLabel = new Label(codeStream));
388 // codeStream.decrStackSize(1);
389 // falseLabel.place();
390 // codeStream.iconst_0();
394 // falseLabel.place();
400 // switch (bits & ReturnTypeIDMASK) {
403 // if ((left.constant != Constant.NotAConstant)
404 // && (left.constant.typeID() == T_int)
405 // && (left.constant.intValue() == 0)) {
406 // right.generateCode(currentScope, codeStream, valueRequired);
409 // if ((right.constant != Constant.NotAConstant)
410 // && (right.constant.typeID() == T_int)
411 // && (right.constant.intValue() == 0)) {
412 // left.generateCode(currentScope, codeStream, valueRequired);
414 // left.generateCode(currentScope, codeStream, valueRequired);
415 // right.generateCode(currentScope, codeStream, valueRequired);
416 // if (valueRequired)
417 // codeStream.ixor();
423 // if ((left.constant != Constant.NotAConstant)
424 // && (left.constant.typeID() == T_long)
425 // && (left.constant.longValue() == 0L)) {
426 // right.generateCode(currentScope, codeStream, valueRequired);
429 // if ((right.constant != Constant.NotAConstant)
430 // && (right.constant.typeID() == T_long)
431 // && (right.constant.longValue() == 0L)) {
432 // left.generateCode(currentScope, codeStream, valueRequired);
434 // left.generateCode(currentScope, codeStream, valueRequired);
435 // right.generateCode(currentScope, codeStream, valueRequired);
436 // if (valueRequired)
437 // codeStream.lxor();
442 // generateOptimizedLogicalXor(
446 // (falseLabel = new Label(codeStream)),
448 // /* improving code gen for such a case: boolean b = i < 0 ^ bool;
449 // * since the label has never been used, we have the inlined value on the stack. */
450 // if (falseLabel.hasForwardReferences()) {
451 // if (valueRequired) {
452 // codeStream.iconst_1();
453 // if ((bits & ValueForReturnMASK) != 0) {
454 // codeStream.ireturn();
455 // falseLabel.place();
456 // codeStream.iconst_0();
458 // codeStream.goto_(endLabel = new Label(codeStream));
459 // codeStream.decrStackSize(1);
460 // falseLabel.place();
461 // codeStream.iconst_0();
465 // falseLabel.place();
471 // switch (bits & ReturnTypeIDMASK) {
473 // left.generateCode(currentScope, codeStream, valueRequired);
474 // right.generateCode(currentScope, codeStream, valueRequired);
475 // if (valueRequired)
476 // codeStream.ishl();
479 // left.generateCode(currentScope, codeStream, valueRequired);
480 // right.generateCode(currentScope, codeStream, valueRequired);
481 // if (valueRequired)
482 // codeStream.lshl();
485 // case RIGHT_SHIFT :
486 // switch (bits & ReturnTypeIDMASK) {
488 // left.generateCode(currentScope, codeStream, valueRequired);
489 // right.generateCode(currentScope, codeStream, valueRequired);
490 // if (valueRequired)
491 // codeStream.ishr();
494 // left.generateCode(currentScope, codeStream, valueRequired);
495 // right.generateCode(currentScope, codeStream, valueRequired);
496 // if (valueRequired)
497 // codeStream.lshr();
500 // case UNSIGNED_RIGHT_SHIFT :
501 // switch (bits & ReturnTypeIDMASK) {
503 // left.generateCode(currentScope, codeStream, valueRequired);
504 // right.generateCode(currentScope, codeStream, valueRequired);
505 // if (valueRequired)
506 // codeStream.iushr();
509 // left.generateCode(currentScope, codeStream, valueRequired);
510 // right.generateCode(currentScope, codeStream, valueRequired);
511 // if (valueRequired)
512 // codeStream.lushr();
516 // generateOptimizedGreaterThan(
520 // (falseLabel = new Label(codeStream)),
522 // if (valueRequired) {
523 // codeStream.iconst_1();
524 // if ((bits & ValueForReturnMASK) != 0) {
525 // codeStream.ireturn();
526 // falseLabel.place();
527 // codeStream.iconst_0();
529 // codeStream.goto_(endLabel = new Label(codeStream));
530 // codeStream.decrStackSize(1);
531 // falseLabel.place();
532 // codeStream.iconst_0();
537 // case GREATER_EQUAL :
538 // generateOptimizedGreaterThanOrEqual(
542 // (falseLabel = new Label(codeStream)),
544 // if (valueRequired) {
545 // codeStream.iconst_1();
546 // if ((bits & ValueForReturnMASK) != 0) {
547 // codeStream.ireturn();
548 // falseLabel.place();
549 // codeStream.iconst_0();
551 // codeStream.goto_(endLabel = new Label(codeStream));
552 // codeStream.decrStackSize(1);
553 // falseLabel.place();
554 // codeStream.iconst_0();
560 // generateOptimizedLessThan(
564 // (falseLabel = new Label(codeStream)),
566 // if (valueRequired) {
567 // codeStream.iconst_1();
568 // if ((bits & ValueForReturnMASK) != 0) {
569 // codeStream.ireturn();
570 // falseLabel.place();
571 // codeStream.iconst_0();
573 // codeStream.goto_(endLabel = new Label(codeStream));
574 // codeStream.decrStackSize(1);
575 // falseLabel.place();
576 // codeStream.iconst_0();
582 // generateOptimizedLessThanOrEqual(
586 // (falseLabel = new Label(codeStream)),
588 // if (valueRequired) {
589 // codeStream.iconst_1();
590 // if ((bits & ValueForReturnMASK) != 0) {
591 // codeStream.ireturn();
592 // falseLabel.place();
593 // codeStream.iconst_0();
595 // codeStream.goto_(endLabel = new Label(codeStream));
596 // codeStream.decrStackSize(1);
597 // falseLabel.place();
598 // codeStream.iconst_0();
603 // if (valueRequired) {
604 // codeStream.generateImplicitConversion(implicitConversion);
606 // codeStream.recordPositionsFrom(pc, this.sourceStart);
610 * Boolean operator code generation
611 * Optimized operations are: <, <=, >, >=, &, |, ^
613 // public void generateOptimizedBoolean(
614 // BlockScope currentScope,
615 // CodeStream codeStream,
618 // boolean valueRequired) {
620 // if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
621 // super.generateOptimizedBoolean(
629 // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
631 // generateOptimizedLessThan(
639 // generateOptimizedLessThanOrEqual(
647 // generateOptimizedGreaterThan(
654 // case GREATER_EQUAL :
655 // generateOptimizedGreaterThanOrEqual(
663 // generateOptimizedLogicalAnd(
671 // generateOptimizedLogicalOr(
679 // generateOptimizedLogicalXor(
687 // super.generateOptimizedBoolean(
696 // * Boolean generation for >
698 // public void generateOptimizedGreaterThan(
699 // BlockScope currentScope,
700 // CodeStream codeStream,
703 // boolean valueRequired) {
705 // int promotedTypeID = left.implicitConversion >> 4;
706 // // both sides got promoted in the same way
707 // if (promotedTypeID == T_int) {
709 // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
710 // right.generateCode(currentScope, codeStream, valueRequired);
711 // if (valueRequired) {
712 // if (falseLabel == null) {
713 // if (trueLabel != null) {
714 // // implicitly falling through the FALSE case
715 // codeStream.iflt(trueLabel);
718 // if (trueLabel == null) {
719 // // implicitly falling through the TRUE case
720 // codeStream.ifge(falseLabel);
722 // // no implicit fall through TRUE/FALSE --> should never occur
726 // // reposition the endPC
727 // codeStream.updateLastRecordedEndPC(codeStream.position);
731 // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
732 // left.generateCode(currentScope, codeStream, valueRequired);
733 // if (valueRequired) {
734 // if (falseLabel == null) {
735 // if (trueLabel != null) {
736 // // implicitly falling through the FALSE case
737 // codeStream.ifgt(trueLabel);
740 // if (trueLabel == null) {
741 // // implicitly falling through the TRUE case
742 // codeStream.ifle(falseLabel);
744 // // no implicit fall through TRUE/FALSE --> should never occur
748 // // reposition the endPC
749 // codeStream.updateLastRecordedEndPC(codeStream.position);
753 // // default comparison
754 // left.generateCode(currentScope, codeStream, valueRequired);
755 // right.generateCode(currentScope, codeStream, valueRequired);
756 // if (valueRequired) {
757 // if (falseLabel == null) {
758 // if (trueLabel != null) {
759 // // implicit falling through the FALSE case
760 // switch (promotedTypeID) {
762 // codeStream.if_icmpgt(trueLabel);
765 // codeStream.fcmpl();
766 // codeStream.ifgt(trueLabel);
769 // codeStream.lcmp();
770 // codeStream.ifgt(trueLabel);
773 // codeStream.dcmpl();
774 // codeStream.ifgt(trueLabel);
776 // // reposition the endPC
777 // codeStream.updateLastRecordedEndPC(codeStream.position);
781 // if (trueLabel == null) {
782 // // implicit falling through the TRUE case
783 // switch (promotedTypeID) {
785 // codeStream.if_icmple(falseLabel);
788 // codeStream.fcmpl();
789 // codeStream.ifle(falseLabel);
792 // codeStream.lcmp();
793 // codeStream.ifle(falseLabel);
796 // codeStream.dcmpl();
797 // codeStream.ifle(falseLabel);
799 // // reposition the endPC
800 // codeStream.updateLastRecordedEndPC(codeStream.position);
803 // // no implicit fall through TRUE/FALSE --> should never occur
810 * Boolean generation for >=
812 // public void generateOptimizedGreaterThanOrEqual(
813 // BlockScope currentScope,
814 // CodeStream codeStream,
817 // boolean valueRequired) {
819 // int promotedTypeID = left.implicitConversion >> 4;
820 // // both sides got promoted in the same way
821 // if (promotedTypeID == T_int) {
823 // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
824 // right.generateCode(currentScope, codeStream, valueRequired);
825 // if (valueRequired) {
826 // if (falseLabel == null) {
827 // if (trueLabel != null) {
828 // // implicitly falling through the FALSE case
829 // codeStream.ifle(trueLabel);
832 // if (trueLabel == null) {
833 // // implicitly falling through the TRUE case
834 // codeStream.ifgt(falseLabel);
836 // // no implicit fall through TRUE/FALSE --> should never occur
840 // // reposition the endPC
841 // codeStream.updateLastRecordedEndPC(codeStream.position);
845 // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
846 // left.generateCode(currentScope, codeStream, valueRequired);
847 // if (valueRequired) {
848 // if (falseLabel == null) {
849 // if (trueLabel != null) {
850 // // implicitly falling through the FALSE case
851 // codeStream.ifge(trueLabel);
854 // if (trueLabel == null) {
855 // // implicitly falling through the TRUE case
856 // codeStream.iflt(falseLabel);
858 // // no implicit fall through TRUE/FALSE --> should never occur
862 // // reposition the endPC
863 // codeStream.updateLastRecordedEndPC(codeStream.position);
867 // // default comparison
868 // left.generateCode(currentScope, codeStream, valueRequired);
869 // right.generateCode(currentScope, codeStream, valueRequired);
870 // if (valueRequired) {
871 // if (falseLabel == null) {
872 // if (trueLabel != null) {
873 // // implicit falling through the FALSE case
874 // switch (promotedTypeID) {
876 // codeStream.if_icmpge(trueLabel);
879 // codeStream.fcmpl();
880 // codeStream.ifge(trueLabel);
883 // codeStream.lcmp();
884 // codeStream.ifge(trueLabel);
887 // codeStream.dcmpl();
888 // codeStream.ifge(trueLabel);
890 // // reposition the endPC
891 // codeStream.updateLastRecordedEndPC(codeStream.position);
895 // if (trueLabel == null) {
896 // // implicit falling through the TRUE case
897 // switch (promotedTypeID) {
899 // codeStream.if_icmplt(falseLabel);
902 // codeStream.fcmpl();
903 // codeStream.iflt(falseLabel);
906 // codeStream.lcmp();
907 // codeStream.iflt(falseLabel);
910 // codeStream.dcmpl();
911 // codeStream.iflt(falseLabel);
913 // // reposition the endPC
914 // codeStream.updateLastRecordedEndPC(codeStream.position);
917 // // no implicit fall through TRUE/FALSE --> should never occur
924 // * Boolean generation for <
926 // public void generateOptimizedLessThan(
927 // BlockScope currentScope,
928 // CodeStream codeStream,
931 // boolean valueRequired) {
933 // int promotedTypeID = left.implicitConversion >> 4;
934 // // both sides got promoted in the same way
935 // if (promotedTypeID == T_int) {
937 // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
938 // right.generateCode(currentScope, codeStream, valueRequired);
939 // if (valueRequired) {
940 // if (falseLabel == null) {
941 // if (trueLabel != null) {
942 // // implicitly falling through the FALSE case
943 // codeStream.ifgt(trueLabel);
946 // if (trueLabel == null) {
947 // // implicitly falling through the TRUE case
948 // codeStream.ifle(falseLabel);
950 // // no implicit fall through TRUE/FALSE --> should never occur
954 // codeStream.updateLastRecordedEndPC(codeStream.position);
958 // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
959 // left.generateCode(currentScope, codeStream, valueRequired);
960 // if (valueRequired) {
961 // if (falseLabel == null) {
962 // if (trueLabel != null) {
963 // // implicitly falling through the FALSE case
964 // codeStream.iflt(trueLabel);
967 // if (trueLabel == null) {
968 // // implicitly falling through the TRUE case
969 // codeStream.ifge(falseLabel);
971 // // no implicit fall through TRUE/FALSE --> should never occur
975 // codeStream.updateLastRecordedEndPC(codeStream.position);
979 // // default comparison
980 // left.generateCode(currentScope, codeStream, valueRequired);
981 // right.generateCode(currentScope, codeStream, valueRequired);
982 // if (valueRequired) {
983 // if (falseLabel == null) {
984 // if (trueLabel != null) {
985 // // implicit falling through the FALSE case
986 // switch (promotedTypeID) {
988 // codeStream.if_icmplt(trueLabel);
991 // codeStream.fcmpg();
992 // codeStream.iflt(trueLabel);
995 // codeStream.lcmp();
996 // codeStream.iflt(trueLabel);
999 // codeStream.dcmpg();
1000 // codeStream.iflt(trueLabel);
1002 // codeStream.updateLastRecordedEndPC(codeStream.position);
1006 // if (trueLabel == null) {
1007 // // implicit falling through the TRUE case
1008 // switch (promotedTypeID) {
1010 // codeStream.if_icmpge(falseLabel);
1013 // codeStream.fcmpg();
1014 // codeStream.ifge(falseLabel);
1017 // codeStream.lcmp();
1018 // codeStream.ifge(falseLabel);
1021 // codeStream.dcmpg();
1022 // codeStream.ifge(falseLabel);
1024 // codeStream.updateLastRecordedEndPC(codeStream.position);
1027 // // no implicit fall through TRUE/FALSE --> should never occur
1034 // * Boolean generation for <=
1036 // public void generateOptimizedLessThanOrEqual(
1037 // BlockScope currentScope,
1038 // CodeStream codeStream,
1040 // Label falseLabel,
1041 // boolean valueRequired) {
1043 // int promotedTypeID = left.implicitConversion >> 4;
1044 // // both sides got promoted in the same way
1045 // if (promotedTypeID == T_int) {
1047 // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
1048 // right.generateCode(currentScope, codeStream, valueRequired);
1049 // if (valueRequired) {
1050 // if (falseLabel == null) {
1051 // if (trueLabel != null) {
1052 // // implicitly falling through the FALSE case
1053 // codeStream.ifge(trueLabel);
1056 // if (trueLabel == null) {
1057 // // implicitly falling through the TRUE case
1058 // codeStream.iflt(falseLabel);
1060 // // no implicit fall through TRUE/FALSE --> should never occur
1064 // // reposition the endPC
1065 // codeStream.updateLastRecordedEndPC(codeStream.position);
1069 // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
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);
1078 // if (trueLabel == null) {
1079 // // implicitly falling through the TRUE case
1080 // codeStream.ifgt(falseLabel);
1082 // // no implicit fall through TRUE/FALSE --> should never occur
1086 // // reposition the endPC
1087 // codeStream.updateLastRecordedEndPC(codeStream.position);
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) {
1100 // codeStream.if_icmple(trueLabel);
1103 // codeStream.fcmpg();
1104 // codeStream.ifle(trueLabel);
1107 // codeStream.lcmp();
1108 // codeStream.ifle(trueLabel);
1111 // codeStream.dcmpg();
1112 // codeStream.ifle(trueLabel);
1114 // // reposition the endPC
1115 // codeStream.updateLastRecordedEndPC(codeStream.position);
1119 // if (trueLabel == null) {
1120 // // implicit falling through the TRUE case
1121 // switch (promotedTypeID) {
1123 // codeStream.if_icmpgt(falseLabel);
1126 // codeStream.fcmpg();
1127 // codeStream.ifgt(falseLabel);
1130 // codeStream.lcmp();
1131 // codeStream.ifgt(falseLabel);
1134 // codeStream.dcmpg();
1135 // codeStream.ifgt(falseLabel);
1137 // // reposition the endPC
1138 // codeStream.updateLastRecordedEndPC(codeStream.position);
1141 // // no implicit fall through TRUE/FALSE --> should never occur
1148 // * Boolean generation for &
1150 // public void generateOptimizedLogicalAnd(
1151 // BlockScope currentScope,
1152 // CodeStream codeStream,
1154 // Label falseLabel,
1155 // boolean valueRequired) {
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(
1168 // if ((bits & OnlyValueRequiredMASK) != 0) {
1169 // right.generateCode(currentScope, codeStream, valueRequired);
1171 // right.generateOptimizedBoolean(
1179 // // <something equivalent to false> & x
1180 // left.generateOptimizedBoolean(
1186 // right.generateOptimizedBoolean(
1192 // if (valueRequired) {
1193 // if ((bits & OnlyValueRequiredMASK) != 0) {
1194 // codeStream.iconst_0();
1196 // if (falseLabel != null) {
1197 // // implicit falling through the TRUE case
1198 // codeStream.goto_(falseLabel);
1202 // // reposition the endPC
1203 // codeStream.updateLastRecordedEndPC(codeStream.position);
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);
1213 // left.generateOptimizedBoolean(
1220 // right.generateOptimizedBoolean(
1227 // // x & <something equivalent to false>
1228 // left.generateOptimizedBoolean(
1234 // right.generateOptimizedBoolean(
1240 // if (valueRequired) {
1241 // if ((bits & OnlyValueRequiredMASK) != 0) {
1242 // codeStream.iconst_0();
1244 // if (falseLabel != null) {
1245 // // implicit falling through the TRUE case
1246 // codeStream.goto_(falseLabel);
1250 // // reposition the endPC
1251 // codeStream.updateLastRecordedEndPC(codeStream.position);
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);
1268 // // implicit falling through the TRUE case
1269 // if (trueLabel == null) {
1270 // codeStream.ifeq(falseLabel);
1272 // // no implicit fall through TRUE/FALSE --> should never occur
1277 // // reposition the endPC
1278 // codeStream.updateLastRecordedEndPC(codeStream.position);
1282 // * Boolean generation for |
1284 // public void generateOptimizedLogicalOr(
1285 // BlockScope currentScope,
1286 // CodeStream codeStream,
1288 // Label falseLabel,
1289 // boolean valueRequired) {
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(
1302 // right.generateOptimizedBoolean(
1308 // if (valueRequired) {
1309 // if ((bits & OnlyValueRequiredMASK) != 0) {
1310 // codeStream.iconst_1();
1312 // if (trueLabel != null) {
1313 // codeStream.goto_(trueLabel);
1317 // // reposition the endPC
1318 // codeStream.updateLastRecordedEndPC(codeStream.position);
1320 // // <something equivalent to false> | x
1321 // left.generateOptimizedBoolean(
1327 // if ((bits & OnlyValueRequiredMASK) != 0) {
1328 // right.generateCode(currentScope, codeStream, valueRequired);
1330 // right.generateOptimizedBoolean(
1340 // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1341 // if (condConst.booleanValue() == true) {
1342 // // x | <something equivalent to true>
1343 // left.generateOptimizedBoolean(
1349 // right.generateOptimizedBoolean(
1355 // if (valueRequired) {
1356 // if ((bits & OnlyValueRequiredMASK) != 0) {
1357 // codeStream.iconst_1();
1359 // if (trueLabel != null) {
1360 // codeStream.goto_(trueLabel);
1364 // // reposition the endPC
1365 // codeStream.updateLastRecordedEndPC(codeStream.position);
1367 // // x | <something equivalent to false>
1368 // if ((bits & OnlyValueRequiredMASK) != 0) {
1369 // left.generateCode(currentScope, codeStream, valueRequired);
1371 // left.generateOptimizedBoolean(
1378 // right.generateOptimizedBoolean(
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);
1400 // // implicit falling through the TRUE case
1401 // if (trueLabel == null) {
1402 // codeStream.ifeq(falseLabel);
1404 // // no implicit fall through TRUE/FALSE --> should never occur
1409 // // reposition the endPC
1410 // codeStream.updateLastRecordedEndPC(codeStream.position);
1414 // * Boolean generation for ^
1416 // public void generateOptimizedLogicalXor(
1417 // BlockScope currentScope,
1418 // CodeStream codeStream,
1420 // Label falseLabel,
1421 // boolean valueRequired) {
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(
1434 // right.generateOptimizedBoolean(
1441 // // <something equivalent to false> ^ x
1442 // left.generateOptimizedBoolean(
1448 // if ((bits & OnlyValueRequiredMASK) != 0) {
1449 // right.generateCode(currentScope, codeStream, valueRequired);
1451 // right.generateOptimizedBoolean(
1461 // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1462 // if (condConst.booleanValue() == true) {
1463 // // x ^ <something equivalent to true>
1464 // left.generateOptimizedBoolean(
1470 // right.generateOptimizedBoolean(
1477 // // x ^ <something equivalent to false>
1478 // if ((bits & OnlyValueRequiredMASK) != 0) {
1479 // left.generateCode(currentScope, codeStream, valueRequired);
1481 // left.generateOptimizedBoolean(
1488 // right.generateOptimizedBoolean(
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);
1510 // // implicit falling through the TRUE case
1511 // if (trueLabel == null) {
1512 // codeStream.ifeq(falseLabel);
1514 // // no implicit fall through TRUE/FALSE --> should never occur
1519 // // reposition the endPC
1520 // codeStream.updateLastRecordedEndPC(codeStream.position);
1523 // public void generateOptimizedStringBuffer(
1524 // BlockScope blockScope,
1525 // CodeStream codeStream,
1528 // /* In the case trying to make a string concatenation, there is no need to create a new
1529 // * string buffer, thus use a lower-level API for code generation involving only the
1530 // * appending of arguments to the existing StringBuffer
1533 // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1534 // && ((bits & ReturnTypeIDMASK) == T_String)) {
1535 // if (constant != NotAConstant) {
1536 // codeStream.generateConstant(constant, implicitConversion);
1537 // codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
1539 // int pc = codeStream.position;
1540 // left.generateOptimizedStringBuffer(
1543 // left.implicitConversion & 0xF);
1544 // codeStream.recordPositionsFrom(pc, left.sourceStart);
1545 // pc = codeStream.position;
1546 // right.generateOptimizedStringBuffer(
1549 // right.implicitConversion & 0xF);
1550 // codeStream.recordPositionsFrom(pc, right.sourceStart);
1553 // super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
1557 // public void generateOptimizedStringBufferCreation(
1558 // BlockScope blockScope,
1559 // CodeStream codeStream,
1562 // /* In the case trying to make a string concatenation, there is no need to create a new
1563 // * string buffer, thus use a lower-level API for code generation involving only the
1564 // * appending of arguments to the existing StringBuffer
1567 // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1568 // && ((bits & ReturnTypeIDMASK) == T_String)) {
1569 // if (constant != NotAConstant) {
1570 // codeStream.newStringBuffer(); // new: java.lang.StringBuffer
1571 // codeStream.dup();
1572 // codeStream.ldc(constant.stringValue());
1573 // codeStream.invokeStringBufferStringConstructor();
1574 // // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
1576 // int pc = codeStream.position;
1577 // left.generateOptimizedStringBufferCreation(
1580 // left.implicitConversion & 0xF);
1581 // codeStream.recordPositionsFrom(pc, left.sourceStart);
1582 // pc = codeStream.position;
1583 // right.generateOptimizedStringBuffer(
1586 // right.implicitConversion & 0xF);
1587 // codeStream.recordPositionsFrom(pc, right.sourceStart);
1590 // super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID);
1594 // public boolean isCompactableOperation() {
1599 // public void optimizedBooleanConstant(int leftId, int operator, int rightId) {
1601 // switch (operator) {
1603 // if ((leftId != T_boolean) || (rightId != T_boolean))
1607 // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
1608 // if (cst.booleanValue() == false) { // left is equivalent to false
1609 // optimizedBooleanConstant = cst; // constant(false)
1611 // } else { //left is equivalent to true
1612 // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1613 // optimizedBooleanConstant = cst;
1614 // // the conditional result is equivalent to the right conditional value
1619 // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1620 // if (cst.booleanValue() == false) { // right is equivalent to false
1621 // optimizedBooleanConstant = cst; // constant(false)
1626 // if ((leftId != T_boolean) || (rightId != T_boolean))
1629 // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
1630 // if (cst.booleanValue() == true) { // left is equivalent to true
1631 // optimizedBooleanConstant = cst; // constant(true)
1633 // } else { //left is equivalent to false
1634 // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1635 // optimizedBooleanConstant = cst;
1640 // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1641 // if (cst.booleanValue() == true) { // right is equivalent to true
1642 // optimizedBooleanConstant = cst; // constant(true)
1648 public TypeBinding resolveType(BlockScope scope) {
1650 // use the id of the type to navigate into the table
1651 TypeBinding leftTb = left.resolveType(scope);
1652 TypeBinding rightTb = right.resolveType(scope);
1653 if (leftTb == null || rightTb == null) {
1654 constant = Constant.NotAConstant;
1657 int leftId = leftTb.id;
1658 int rightId = rightTb.id;
1660 || rightId > 15) { // must convert String + Object || Object + String
1661 if (leftId == T_String) {
1663 } else if (rightId == T_String) {
1666 constant = Constant.NotAConstant;
1667 scope.problemReporter().invalidOperator(this, leftTb, rightTb);
1671 if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
1672 if (leftId == T_String
1673 && rightTb.isArrayType()
1674 && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding)
1675 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
1679 && leftTb.isArrayType()
1680 && ((ArrayBinding) leftTb).elementsType(scope) == CharBinding)
1681 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
1685 // the code is an int
1686 // (cast) left Op (cast) rigth --> result
1687 // 0000 0000 0000 0000 0000
1688 // <<16 <<12 <<8 <<4 <<0
1690 // Don't test for result = 0. If it is zero, some more work is done.
1691 // On the one hand when it is not zero (correct code) we avoid doing the test
1693 ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4)
1695 left.implicitConversion = result >>> 12;
1696 right.implicitConversion = (result >>> 4) & 0x000FF;
1698 bits |= result & 0xF;
1699 switch (result & 0xF) { // record the current ReturnTypeID
1700 // only switch on possible result type.....
1702 this.resolvedType = BooleanBinding;
1705 this.resolvedType = ByteBinding;
1708 this.resolvedType = CharBinding;
1711 this.resolvedType = DoubleBinding;
1714 this.resolvedType = FloatBinding;
1717 this.resolvedType = IntBinding;
1720 this.resolvedType = LongBinding;
1723 this.resolvedType = scope.getJavaLangString();
1725 default : //error........
1726 constant = Constant.NotAConstant;
1727 scope.problemReporter().invalidOperator(this, leftTb, rightTb);
1731 // compute the constant when valid
1732 computeConstant(scope, leftId, rightId);
1733 return this.resolvedType;
1736 public String toStringExpressionNoParenthesis() {
1738 return left.toStringExpression() + " " + //$NON-NLS-1$
1739 operatorToString() + " " + //$NON-NLS-1$
1740 right.toStringExpression();
1743 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
1745 if (visitor.visit(this, scope)) {
1746 left.traverse(visitor, scope);
1747 right.traverse(visitor, scope);
1749 visitor.endVisit(this, scope);