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.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.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,
33 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
35 .analyseCode(currentScope, flowContext, flowInfo)
36 .asNegatedCondition();
38 return expression.analyseCode(currentScope, flowContext, flowInfo);
42 public Constant conditionalConstant() {
43 return optimizedBooleanConstant == null ? constant : optimizedBooleanConstant;
47 * Code generation for an unary operation
49 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
50 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
51 * @param valueRequired boolean
53 public void generateCode(
54 BlockScope currentScope,
55 CodeStream codeStream,
56 boolean valueRequired) {
57 int pc = codeStream.position;
58 Label falseLabel, endifLabel;
59 if (constant != Constant.NotAConstant) {
62 codeStream.generateConstant(constant, implicitConversion);
64 codeStream.recordPositionsFrom(pc, this.sourceStart);
67 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
69 switch (expression.implicitConversion >> 4) /* runtime type */ {
72 // Generate code for the condition
73 expression.generateOptimizedBoolean(
77 (falseLabel = new Label(codeStream)),
80 codeStream.iconst_0();
81 if (falseLabel.hasForwardReferences()) {
82 codeStream.goto_(endifLabel = new Label(codeStream));
83 codeStream.decrStackSize(1);
85 codeStream.iconst_1();
88 } else { // 6596: if (!(a && b)){} - must still place falseLabel
95 switch (expression.implicitConversion >> 4 /* runtime */
99 expression.generateCode(currentScope, codeStream, valueRequired);
101 codeStream.iconst_m1();
106 expression.generateCode(currentScope, codeStream, valueRequired);
108 codeStream.ldc2_w(-1L);
115 if (constant != NotAConstant) {
117 switch (expression.implicitConversion >> 4 /* runtime */
120 codeStream.generateInlinedValue(constant.intValue() * -1);
123 codeStream.generateInlinedValue(constant.floatValue() * -1.0f);
126 codeStream.generateInlinedValue(constant.longValue() * -1L);
129 codeStream.generateInlinedValue(constant.doubleValue() * -1.0);
133 expression.generateCode(currentScope, codeStream, valueRequired);
135 switch (expression.implicitConversion >> 4 /* runtime type */
153 expression.generateCode(currentScope, codeStream, valueRequired);
156 codeStream.generateImplicitConversion(implicitConversion);
158 codeStream.recordPositionsFrom(pc, this.sourceStart);
162 * Boolean operator code generation
163 * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
165 public void generateOptimizedBoolean(
166 BlockScope currentScope,
167 CodeStream codeStream,
170 boolean valueRequired) {
172 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
173 super.generateOptimizedBoolean(
181 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
182 expression.generateOptimizedBoolean(
189 super.generateOptimizedBoolean(
198 public TypeBinding resolveType(BlockScope scope) {
199 TypeBinding expressionTb = expression.resolveType(scope);
200 if (expressionTb == null) {
201 constant = NotAConstant;
204 int expressionId = expressionTb.id;
205 if (expressionId > 15) {
206 constant = NotAConstant;
207 scope.problemReporter().invalidOperator(this, expressionTb);
212 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
217 tableId = LEFT_SHIFT;
223 // the code is an int
224 // (cast) left Op (cast) rigth --> result
225 // 0000 0000 0000 0000 0000
226 // <<16 <<12 <<8 <<4 <<0
227 int result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
228 expression.implicitConversion = result >>> 12;
229 bits |= result & 0xF;
230 switch (result & 0xF) { // only switch on possible result type.....
232 this.typeBinding = BooleanBinding;
235 this.typeBinding = ByteBinding;
238 this.typeBinding = CharBinding;
241 this.typeBinding = DoubleBinding;
244 this.typeBinding = FloatBinding;
247 this.typeBinding = IntBinding;
250 this.typeBinding = LongBinding;
252 default : //error........
253 constant = Constant.NotAConstant;
254 if (expressionId != T_undefined)
255 scope.problemReporter().invalidOperator(this, expressionTb);
258 // compute the constant when valid
259 if (expression.constant != Constant.NotAConstant) {
261 Constant.computeConstantOperation(
264 (bits & OperatorMASK) >> OperatorSHIFT);
266 constant = Constant.NotAConstant;
267 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
268 Constant cst = expression.conditionalConstant();
269 if (cst.typeID() == T_boolean)
270 optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
273 return this.typeBinding;
276 public String toStringExpressionNoParenthesis() {
277 return operatorToString() + " " + expression.toStringExpression(); //$NON-NLS-1$
280 public void traverse(
281 IAbstractSyntaxTreeVisitor visitor,
282 BlockScope blockScope) {
283 if (visitor.visit(this, blockScope)) {
284 expression.traverse(visitor, blockScope);
286 visitor.endVisit(this, blockScope);