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 & IMPLICIT_CONVERSION_MASK) >> 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 & IMPLICIT_CONVERSION_MASK) >> 4 /* runtime */) {
103 this.expression.generateCode(currentScope, codeStream, valueRequired);
105 codeStream.iconst_m1();
110 this.expression.generateCode(currentScope, codeStream, valueRequired);
112 codeStream.ldc2_w(-1L);
119 if (this.constant != NotAConstant) {
121 switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime */
123 codeStream.generateInlinedValue(this.constant.intValue() * -1);
126 codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f);
129 codeStream.generateInlinedValue(this.constant.longValue() * -1L);
132 codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0);
136 this.expression.generateCode(currentScope, codeStream, valueRequired);
138 switch ((expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime type */
155 this.expression.generateCode(currentScope, codeStream, valueRequired);
158 codeStream.generateImplicitConversion(this.implicitConversion);
160 codeStream.recordPositionsFrom(pc, this.sourceStart);
164 * Boolean operator code generation
165 * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
167 public void generateOptimizedBoolean(
168 BlockScope currentScope,
169 CodeStream codeStream,
172 boolean valueRequired) {
174 if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean)) {
175 super.generateOptimizedBoolean(
183 if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
184 this.expression.generateOptimizedBoolean(
191 super.generateOptimizedBoolean(
200 public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
202 output.append(operatorToString()).append(' ');
203 return this.expression.printExpression(0, output);
206 public TypeBinding resolveType(BlockScope scope) {
208 boolean expressionIsCast;
209 if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= IgnoreNeedForCastCheckMASK; // will check later on
210 TypeBinding expressionType = this.expression.resolveType(scope);
211 if (expressionType == null) {
212 this.constant = NotAConstant;
215 int expressionTypeID = expressionType.id;
216 // autoboxing support
217 LookupEnvironment env = scope.environment();
218 boolean use15specifics = env.options.sourceLevel >= JDK1_5;
219 if (use15specifics) {
220 if (!expressionType.isBaseType()) {
221 expressionTypeID = env.computeBoxingType(expressionType).id;
224 if (expressionTypeID > 15) {
225 this.constant = NotAConstant;
226 scope.problemReporter().invalidOperator(this, expressionType);
231 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
236 tableId = LEFT_SHIFT;
242 // the code is an int
243 // (cast) left Op (cast) rigth --> result
244 // 0000 0000 0000 0000 0000
245 // <<16 <<12 <<8 <<4 <<0
246 int operatorSignature = OperatorSignatures[tableId][(expressionTypeID << 4) + expressionTypeID];
247 this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), expressionType);
248 this.bits |= operatorSignature & 0xF;
249 switch (operatorSignature & 0xF) { // only switch on possible result type.....
251 this.resolvedType = BooleanBinding;
254 this.resolvedType = ByteBinding;
257 this.resolvedType = CharBinding;
260 this.resolvedType = DoubleBinding;
263 this.resolvedType = FloatBinding;
266 this.resolvedType = IntBinding;
269 this.resolvedType = LongBinding;
271 default : //error........
272 this.constant = Constant.NotAConstant;
273 if (expressionTypeID != T_undefined)
274 scope.problemReporter().invalidOperator(this, expressionType);
277 // compute the constant when valid
278 if (this.expression.constant != Constant.NotAConstant) {
280 Constant.computeConstantOperation(
281 this.expression.constant,
283 (bits & OperatorMASK) >> OperatorSHIFT);
285 this.constant = Constant.NotAConstant;
286 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
287 Constant cst = expression.optimizedBooleanConstant();
288 if (cst != Constant.NotAConstant)
289 this.optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
292 if (expressionIsCast) {
293 // check need for operand cast
294 CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeID);
296 return this.resolvedType;
299 public void traverse(
301 BlockScope blockScope) {
303 if (visitor.visit(this, blockScope)) {
304 this.expression.traverse(visitor, blockScope);
306 visitor.endVisit(this, blockScope);