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.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 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,
37 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
38 return this.expression
39 .analyseCode(currentScope, flowContext, flowInfo)
40 .asNegatedCondition();
42 return this.expression.analyseCode(currentScope, flowContext, flowInfo);
46 public Constant optimizedBooleanConstant() {
48 return this.optimizedBooleanConstant == null
50 : this.optimizedBooleanConstant;
54 * Code generation for an unary operation
56 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
57 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
58 * @param valueRequired boolean
60 // public void generateCode(
61 // BlockScope currentScope,
62 // CodeStream codeStream,
63 // boolean valueRequired) {
65 // int pc = codeStream.position;
66 // Label falseLabel, endifLabel;
67 // if (this.constant != Constant.NotAConstant) {
69 // if (valueRequired) {
70 // codeStream.generateConstant(this.constant, this.implicitConversion);
72 // codeStream.recordPositionsFrom(pc, this.sourceStart);
75 // switch ((bits & OperatorMASK) >> OperatorSHIFT) {
77 // switch (this.expression.implicitConversion >> 4) /* runtime type */ {
80 // // Generate code for the condition
81 // this.expression.generateOptimizedBoolean(
85 // (falseLabel = new Label(codeStream)),
87 // if (valueRequired) {
88 // codeStream.iconst_0();
89 // if (falseLabel.hasForwardReferences()) {
90 // codeStream.goto_(endifLabel = new Label(codeStream));
91 // codeStream.decrStackSize(1);
92 // falseLabel.place();
93 // codeStream.iconst_1();
94 // endifLabel.place();
96 // } else { // 6596: if (!(a && b)){} - must still place falseLabel
97 // falseLabel.place();
103 // switch (this.expression.implicitConversion >> 4 /* runtime */
107 // this.expression.generateCode(currentScope, codeStream, valueRequired);
108 // if (valueRequired) {
109 // codeStream.iconst_m1();
110 // codeStream.ixor();
114 // this.expression.generateCode(currentScope, codeStream, valueRequired);
115 // if (valueRequired) {
116 // codeStream.ldc2_w(-1L);
117 // codeStream.lxor();
123 // if (this.constant != NotAConstant) {
124 // if (valueRequired) {
125 // switch (this.expression.implicitConversion >> 4){ /* runtime */
127 // codeStream.generateInlinedValue(this.constant.intValue() * -1);
130 // codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f);
133 // codeStream.generateInlinedValue(this.constant.longValue() * -1L);
136 // codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0);
140 // this.expression.generateCode(currentScope, codeStream, valueRequired);
141 // if (valueRequired) {
142 // switch (expression.implicitConversion >> 4){ /* runtime type */
144 // codeStream.ineg();
147 // codeStream.fneg();
150 // codeStream.lneg();
153 // codeStream.dneg();
159 // this.expression.generateCode(currentScope, codeStream, valueRequired);
161 // if (valueRequired) {
162 // codeStream.generateImplicitConversion(this.implicitConversion);
164 // codeStream.recordPositionsFrom(pc, this.sourceStart);
168 // * Boolean operator code generation
169 // * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
171 // public void generateOptimizedBoolean(
172 // BlockScope currentScope,
173 // CodeStream codeStream,
176 // boolean valueRequired) {
178 // if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean)) {
179 // super.generateOptimizedBoolean(
187 // if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
188 // this.expression.generateOptimizedBoolean(
195 // super.generateOptimizedBoolean(
204 public TypeBinding resolveType(BlockScope scope) {
206 TypeBinding expressionType = this.expression.resolveType(scope);
207 if (expressionType == null) {
208 this.constant = NotAConstant;
211 int expressionId = expressionType.id;
212 if (expressionId > 15) {
213 this.constant = NotAConstant;
214 scope.problemReporter().invalidOperator(this, expressionType);
219 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
224 tableId = LEFT_SHIFT;
230 // the code is an int
231 // (cast) left Op (cast) rigth --> result
232 // 0000 0000 0000 0000 0000
233 // <<16 <<12 <<8 <<4 <<0
234 int result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
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) {
268 Constant.computeConstantOperation(
269 this.expression.constant,
271 (bits & OperatorMASK) >> OperatorSHIFT);
273 this.constant = Constant.NotAConstant;
274 if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
275 Constant cst = expression.optimizedBooleanConstant();
276 if (cst != Constant.NotAConstant)
277 this.optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
280 return this.resolvedType;
283 public String toStringExpressionNoParenthesis() {
285 return operatorToString() + " " + this.expression.toStringExpression(); //$NON-NLS-1$
288 public void traverse(
289 IAbstractSyntaxTreeVisitor visitor,
290 BlockScope blockScope) {
292 if (visitor.visit(this, blockScope)) {
293 this.expression.traverse(visitor, blockScope);
295 visitor.endVisit(this, blockScope);