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.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
20 public class UnaryExpression extends OperatorExpression {
22 public Expression expression;
24 public Constant optimizedBooleanConstant;
26 public UnaryExpression(Expression expression, int operator) {
27 this.expression = expression;
28 this.bits |= operator << OperatorSHIFT; // encode operator
31 public FlowInfo analyseCode(BlockScope currentScope,
32 FlowContext flowContext, FlowInfo flowInfo) {
34 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
35 return this.expression.analyseCode(currentScope, flowContext,
36 flowInfo).asNegatedCondition();
38 return this.expression.analyseCode(currentScope, flowContext,
43 public Constant optimizedBooleanConstant() {
45 return this.optimizedBooleanConstant == null ? this.constant
46 : this.optimizedBooleanConstant;
50 * Code generation for an unary operation
53 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
55 * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
56 * @param valueRequired
59 // public void generateCode(
60 // BlockScope currentScope,
61 // CodeStream codeStream,
62 // boolean valueRequired) {
64 // int pc = codeStream.position;
65 // Label falseLabel, endifLabel;
66 // if (this.constant != Constant.NotAConstant) {
68 // if (valueRequired) {
69 // codeStream.generateConstant(this.constant, this.implicitConversion);
71 // codeStream.recordPositionsFrom(pc, this.sourceStart);
74 // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
76 // switch (this.expression.implicitConversion >> 4) /* runtime type */ {
79 // // Generate code for the condition
80 // this.expression.generateOptimizedBoolean(
84 // (falseLabel = new Label(codeStream)),
86 // if (valueRequired) {
87 // codeStream.iconst_0();
88 // if (falseLabel.hasForwardReferences()) {
89 // codeStream.goto_(endifLabel = new Label(codeStream));
90 // codeStream.decrStackSize(1);
91 // falseLabel.place();
92 // codeStream.iconst_1();
93 // endifLabel.place();
95 // } else { // 6596: if (!(a && b)){} - must still place falseLabel
96 // falseLabel.place();
102 // switch (this.expression.implicitConversion >> 4 /* runtime */
106 // this.expression.generateCode(currentScope, codeStream, valueRequired);
107 // if (valueRequired) {
108 // codeStream.iconst_m1();
109 // codeStream.ixor();
113 // this.expression.generateCode(currentScope, codeStream, valueRequired);
114 // if (valueRequired) {
115 // codeStream.ldc2_w(-1L);
116 // codeStream.lxor();
122 // if (this.constant != NotAConstant) {
123 // if (valueRequired) {
124 // switch (this.expression.implicitConversion >> 4){ /* runtime */
126 // codeStream.generateInlinedValue(this.constant.intValue() * -1);
129 // codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f);
132 // codeStream.generateInlinedValue(this.constant.longValue() * -1L);
135 // codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0);
139 // this.expression.generateCode(currentScope, codeStream, valueRequired);
140 // if (valueRequired) {
141 // switch (expression.implicitConversion >> 4){ /* runtime type */
143 // codeStream.ineg();
146 // codeStream.fneg();
149 // codeStream.lneg();
152 // codeStream.dneg();
158 // this.expression.generateCode(currentScope, codeStream, valueRequired);
160 // if (valueRequired) {
161 // codeStream.generateImplicitConversion(this.implicitConversion);
163 // codeStream.recordPositionsFrom(pc, this.sourceStart);
167 // * Boolean operator code generation
168 // * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
170 // public void generateOptimizedBoolean(
171 // BlockScope currentScope,
172 // CodeStream codeStream,
175 // boolean valueRequired) {
177 // if ((this.constant != Constant.NotAConstant) && (this.constant.typeID()
179 // super.generateOptimizedBoolean(
187 // if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
188 // this.expression.generateOptimizedBoolean(
195 // super.generateOptimizedBoolean(
203 public TypeBinding resolveType(BlockScope scope) {
205 TypeBinding expressionType = this.expression.resolveType(scope);
206 if (expressionType == null) {
207 this.constant = NotAConstant;
210 int expressionId = expressionType.id;
211 if (expressionId > 15) {
212 this.constant = NotAConstant;
213 scope.problemReporter().invalidOperator(this, expressionType);
218 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
223 tableId = LEFT_SHIFT;
229 // the code is an int
230 // (cast) left Op (cast) rigth --> result
231 // 0000 0000 0000 0000 0000
232 // <<16 <<12 <<8 <<4 <<0
233 int result = ResolveTypeTables[tableId][(expressionId << 4)
235 this.expression.implicitConversion = result >>> 12;
236 this.bits |= result & 0xF;
237 switch (result & 0xF) { // only switch on possible result type.....
239 this.resolvedType = BooleanBinding;
242 this.resolvedType = ByteBinding;
245 this.resolvedType = CharBinding;
248 this.resolvedType = DoubleBinding;
251 this.resolvedType = FloatBinding;
254 this.resolvedType = IntBinding;
257 this.resolvedType = LongBinding;
259 default: // error........
260 this.constant = Constant.NotAConstant;
261 if (expressionId != T_undefined)
262 scope.problemReporter().invalidOperator(this, expressionType);
265 // compute the constant when valid
266 if (this.expression.constant != Constant.NotAConstant) {
267 this.constant = Constant.computeConstantOperation(
268 this.expression.constant, expressionId,
269 (bits & OperatorMASK) >> OperatorSHIFT);
271 this.constant = Constant.NotAConstant;
272 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
273 Constant cst = expression.optimizedBooleanConstant();
274 if (cst != Constant.NotAConstant)
275 this.optimizedBooleanConstant = Constant.fromValue(!cst
279 return this.resolvedType;
282 public StringBuffer printExpressionNoParenthesis(int indent,
283 StringBuffer output) {
285 output.append(operatorToString()).append(' ');
286 return this.expression.printExpression(0, output);
289 public String toStringExpressionNoParenthesis() {
291 return operatorToString() + " " + this.expression.toStringExpression(); //$NON-NLS-1$
294 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
296 if (visitor.visit(this, blockScope)) {
297 this.expression.traverse(visitor, blockScope);
299 visitor.endVisit(this, blockScope);