1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
17 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
18 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
22 public class UnaryExpression extends OperatorExpression {
24 public Expression expression;
25 public Constant optimizedBooleanConstant;
27 public UnaryExpression(Expression expression, int operator) {
28 this.expression = expression;
29 this.bits |= operator << OperatorSHIFT; // encode operator
32 public FlowInfo analyseCode(
33 BlockScope currentScope,
34 FlowContext flowContext,
36 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
38 .analyseCode(currentScope, flowContext, flowInfo)
39 .asNegatedCondition();
41 return expression.analyseCode(currentScope, flowContext, flowInfo);
45 public Constant conditionalConstant() {
46 return optimizedBooleanConstant == null ? constant : optimizedBooleanConstant;
50 * Code generation for an unary operation
52 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
53 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
54 * @param valueRequired boolean
56 public void generateCode(
57 BlockScope currentScope,
58 CodeStream codeStream,
59 boolean valueRequired) {
60 int pc = codeStream.position;
61 Label falseLabel, endifLabel;
62 if (constant != Constant.NotAConstant) {
65 codeStream.generateConstant(constant, implicitConversion);
67 codeStream.recordPositionsFrom(pc, this.sourceStart);
70 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
72 switch (expression.implicitConversion >> 4) /* runtime type */ {
75 // Generate code for the condition
76 expression.generateOptimizedBoolean(
80 (falseLabel = new Label(codeStream)),
83 codeStream.iconst_0();
84 if (falseLabel.hasForwardReferences()) {
85 codeStream.goto_(endifLabel = new Label(codeStream));
86 codeStream.decrStackSize(1);
88 codeStream.iconst_1();
91 } else { // 6596: if (!(a && b)){} - must still place falseLabel
98 switch (expression.implicitConversion >> 4 /* runtime */
102 expression.generateCode(currentScope, codeStream, valueRequired);
104 codeStream.iconst_m1();
109 expression.generateCode(currentScope, codeStream, valueRequired);
111 codeStream.ldc2_w(-1L);
118 if (constant != NotAConstant) {
120 switch (expression.implicitConversion >> 4 /* runtime */
123 codeStream.generateInlinedValue(constant.intValue() * -1);
126 codeStream.generateInlinedValue(constant.floatValue() * -1.0f);
129 codeStream.generateInlinedValue(constant.longValue() * -1L);
132 codeStream.generateInlinedValue(constant.doubleValue() * -1.0);
136 expression.generateCode(currentScope, codeStream, valueRequired);
138 switch (expression.implicitConversion >> 4 /* runtime type */
156 expression.generateCode(currentScope, codeStream, valueRequired);
159 codeStream.generateImplicitConversion(implicitConversion);
161 codeStream.recordPositionsFrom(pc, this.sourceStart);
165 * Boolean operator code generation
166 * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
168 public void generateOptimizedBoolean(
169 BlockScope currentScope,
170 CodeStream codeStream,
173 boolean valueRequired) {
175 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
176 super.generateOptimizedBoolean(
184 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
185 expression.generateOptimizedBoolean(
192 super.generateOptimizedBoolean(
201 public TypeBinding resolveType(BlockScope scope) {
202 TypeBinding expressionTb = expression.resolveType(scope);
203 if (expressionTb == null) {
204 constant = NotAConstant;
207 int expressionId = expressionTb.id;
208 if (expressionId > 15) {
209 constant = NotAConstant;
210 scope.problemReporter().invalidOperator(this, expressionTb);
215 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
220 tableId = LEFT_SHIFT;
226 // the code is an int
227 // (cast) left Op (cast) rigth --> result
228 // 0000 0000 0000 0000 0000
229 // <<16 <<12 <<8 <<4 <<0
230 int result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
231 expression.implicitConversion = result >>> 12;
232 bits |= result & 0xF;
233 switch (result & 0xF) { // only switch on possible result type.....
235 this.typeBinding = BooleanBinding;
238 this.typeBinding = ByteBinding;
241 this.typeBinding = CharBinding;
244 this.typeBinding = DoubleBinding;
247 this.typeBinding = FloatBinding;
250 this.typeBinding = IntBinding;
253 this.typeBinding = LongBinding;
255 default : //error........
256 constant = Constant.NotAConstant;
257 if (expressionId != T_undefined)
258 scope.problemReporter().invalidOperator(this, expressionTb);
261 // compute the constant when valid
262 if (expression.constant != Constant.NotAConstant) {
264 Constant.computeConstantOperation(
267 (bits & OperatorMASK) >> OperatorSHIFT);
269 constant = Constant.NotAConstant;
270 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
271 Constant cst = expression.conditionalConstant();
272 if (cst.typeID() == T_boolean)
273 optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
276 return this.typeBinding;
279 public String toStringExpressionNoParenthesis() {
280 return operatorToString() + " " + expression.toStringExpression(); //$NON-NLS-1$
283 public void traverse(
284 IAbstractSyntaxTreeVisitor visitor,
285 BlockScope blockScope) {
286 if (visitor.visit(this, blockScope)) {
287 expression.traverse(visitor, blockScope);
289 visitor.endVisit(this, blockScope);