1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
19 public class UnaryExpression extends OperatorExpression {
21 public Expression expression;
22 public Constant optimizedBooleanConstant;
24 public UnaryExpression(Expression expression, int operator) {
25 this.expression = expression;
26 this.bits |= operator << OperatorSHIFT; // encode operator
29 public FlowInfo analyseCode(
30 BlockScope currentScope,
31 FlowContext flowContext,
34 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
35 return this.expression
36 .analyseCode(currentScope, flowContext, flowInfo)
37 .asNegatedCondition();
39 return this.expression.analyseCode(currentScope, flowContext, flowInfo);
43 public Constant optimizedBooleanConstant() {
45 return this.optimizedBooleanConstant == null
47 : this.optimizedBooleanConstant;
51 * Code generation for an unary operation
53 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
54 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
55 * @param valueRequired boolean
57 public void generateCode(
58 BlockScope currentScope,
59 CodeStream codeStream,
60 boolean valueRequired) {
62 int pc = codeStream.position;
63 Label falseLabel, endifLabel;
64 if (this.constant != Constant.NotAConstant) {
67 codeStream.generateConstant(this.constant, this.implicitConversion);
69 codeStream.recordPositionsFrom(pc, this.sourceStart);
72 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
74 switch (this.expression.implicitConversion >> 4) /* runtime type */ {
77 // Generate code for the condition
78 this.expression.generateOptimizedBoolean(
82 (falseLabel = new Label(codeStream)),
85 codeStream.iconst_0();
86 if (falseLabel.hasForwardReferences()) {
87 codeStream.goto_(endifLabel = new Label(codeStream));
88 codeStream.decrStackSize(1);
90 codeStream.iconst_1();
93 } else { // 6596: if (!(a && b)){} - must still place falseLabel
100 switch (this.expression.implicitConversion >> 4 /* runtime */
104 this.expression.generateCode(currentScope, codeStream, valueRequired);
106 codeStream.iconst_m1();
111 this.expression.generateCode(currentScope, codeStream, valueRequired);
113 codeStream.ldc2_w(-1L);
120 if (this.constant != NotAConstant) {
122 switch (this.expression.implicitConversion >> 4){ /* runtime */
124 codeStream.generateInlinedValue(this.constant.intValue() * -1);
127 codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f);
130 codeStream.generateInlinedValue(this.constant.longValue() * -1L);
133 codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0);
137 this.expression.generateCode(currentScope, codeStream, valueRequired);
139 switch (expression.implicitConversion >> 4){ /* runtime type */
156 this.expression.generateCode(currentScope, codeStream, valueRequired);
159 codeStream.generateImplicitConversion(this.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 ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean)) {
176 super.generateOptimizedBoolean(
184 if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
185 this.expression.generateOptimizedBoolean(
192 super.generateOptimizedBoolean(
201 public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
203 output.append(operatorToString()).append(' ');
204 return this.expression.printExpression(0, output);
207 public TypeBinding resolveType(BlockScope scope) {
209 boolean expressionIsCast;
210 if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= IgnoreNeedForCastCheckMASK; // will check later on
211 TypeBinding expressionType = this.expression.resolveType(scope);
212 if (expressionType == null) {
213 this.constant = NotAConstant;
216 int expressionTypeId = expressionType.id;
217 if (expressionTypeId > 15) {
218 this.constant = NotAConstant;
219 scope.problemReporter().invalidOperator(this, expressionType);
224 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
229 tableId = LEFT_SHIFT;
235 // the code is an int
236 // (cast) left Op (cast) rigth --> result
237 // 0000 0000 0000 0000 0000
238 // <<16 <<12 <<8 <<4 <<0
239 int operatorSignature = OperatorSignatures[tableId][(expressionTypeId << 4) + expressionTypeId];
240 this.expression.implicitConversion = operatorSignature >>> 12;
241 this.bits |= operatorSignature & 0xF;
242 switch (operatorSignature & 0xF) { // only switch on possible result type.....
244 this.resolvedType = BooleanBinding;
247 this.resolvedType = ByteBinding;
250 this.resolvedType = CharBinding;
253 this.resolvedType = DoubleBinding;
256 this.resolvedType = FloatBinding;
259 this.resolvedType = IntBinding;
262 this.resolvedType = LongBinding;
264 default : //error........
265 this.constant = Constant.NotAConstant;
266 if (expressionTypeId != T_undefined)
267 scope.problemReporter().invalidOperator(this, expressionType);
270 // compute the constant when valid
271 if (this.expression.constant != Constant.NotAConstant) {
273 Constant.computeConstantOperation(
274 this.expression.constant,
276 (bits & OperatorMASK) >> OperatorSHIFT);
278 this.constant = Constant.NotAConstant;
279 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
280 Constant cst = expression.optimizedBooleanConstant();
281 if (cst != Constant.NotAConstant)
282 this.optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
285 if (expressionIsCast) {
286 // check need for operand cast
287 CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeId);
289 return this.resolvedType;
292 public void traverse(
294 BlockScope blockScope) {
296 if (visitor.visit(this, blockScope)) {
297 this.expression.traverse(visitor, blockScope);
299 visitor.endVisit(this, blockScope);