KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > UnaryExpression


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16 import org.eclipse.jdt.internal.compiler.codegen.*;
17 import org.eclipse.jdt.internal.compiler.flow.*;
18 import org.eclipse.jdt.internal.compiler.lookup.*;
19
20 public class UnaryExpression extends OperatorExpression {
21     
22     public Expression expression;
23     public Constant optimizedBooleanConstant;
24
25     public UnaryExpression(Expression expression, int operator) {
26         this.expression = expression;
27         this.bits |= operator << OperatorSHIFT; // encode operator
28
}
29
30 public FlowInfo analyseCode(
31         BlockScope currentScope,
32         FlowContext flowContext,
33         FlowInfo flowInfo) {
34     this.expression.checkNPE(currentScope, flowContext, flowInfo);
35     if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
36         return this.expression.
37             analyseCode(currentScope, flowContext, flowInfo).
38             asNegatedCondition();
39     } else {
40         return this.expression.
41             analyseCode(currentScope, flowContext, flowInfo);
42     }
43 }
44
45     public Constant optimizedBooleanConstant() {
46         
47         return this.optimizedBooleanConstant == null
48                 ? this.constant
49                 : this.optimizedBooleanConstant;
50     }
51
52     /**
53      * Code generation for an unary operation
54      *
55      * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
56      * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
57      * @param valueRequired boolean
58      */

59     public void generateCode(
60         BlockScope currentScope,
61         CodeStream codeStream,
62         boolean valueRequired) {
63             
64         int pc = codeStream.position;
65         BranchLabel falseLabel, endifLabel;
66         if (this.constant != Constant.NotAConstant) {
67             // inlined value
68
if (valueRequired) {
69                 codeStream.generateConstant(this.constant, this.implicitConversion);
70             }
71             codeStream.recordPositionsFrom(pc, this.sourceStart);
72             return;
73         }
74         switch ((bits & OperatorMASK) >> OperatorSHIFT) {
75             case NOT :
76                 switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) /* runtime type */ {
77                     case T_boolean :
78                         // ! <boolean>
79
// Generate code for the condition
80
this.expression.generateOptimizedBoolean(
81                             currentScope,
82                             codeStream,
83                             null,
84                             (falseLabel = new BranchLabel(codeStream)),
85                             valueRequired);
86                         if (valueRequired) {
87                             codeStream.iconst_0();
88                             if (falseLabel.forwardReferenceCount() > 0) {
89                                 codeStream.goto_(endifLabel = new BranchLabel(codeStream));
90                                 codeStream.decrStackSize(1);
91                                 falseLabel.place();
92                                 codeStream.iconst_1();
93                                 endifLabel.place();
94                             }
95                         } else { // 6596: if (!(a && b)){} - must still place falseLabel
96
falseLabel.place();
97                         }
98                         break;
99                 }
100                 break;
101             case TWIDDLE :
102                 switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4 /* runtime */) {
103                     case T_int :
104                         // ~int
105
this.expression.generateCode(currentScope, codeStream, valueRequired);
106                         if (valueRequired) {
107                             codeStream.iconst_m1();
108                             codeStream.ixor();
109                         }
110                         break;
111                     case T_long :
112                         this.expression.generateCode(currentScope, codeStream, valueRequired);
113                         if (valueRequired) {
114                             codeStream.ldc2_w(-1L);
115                             codeStream.lxor();
116                         }
117                 }
118                 break;
119             case MINUS :
120                 // - <num>
121
if (this.constant != Constant.NotAConstant) {
122                     if (valueRequired) {
123                         switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime */
124                             case T_int :
125                                 codeStream.generateInlinedValue(this.constant.intValue() * -1);
126                                 break;
127                             case T_float :
128                                 codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f);
129                                 break;
130                             case T_long :
131                                 codeStream.generateInlinedValue(this.constant.longValue() * -1L);
132                                 break;
133                             case T_double :
134                                 codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0);
135                         }
136                     }
137                 } else {
138                     this.expression.generateCode(currentScope, codeStream, valueRequired);
139                     if (valueRequired) {
140                         switch ((expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime type */
141                             case T_int :
142                                 codeStream.ineg();
143                                 break;
144                             case T_float :
145                                 codeStream.fneg();
146                                 break;
147                             case T_long :
148                                 codeStream.lneg();
149                                 break;
150                             case T_double :
151                                 codeStream.dneg();
152                         }
153                     }
154                 }
155                 break;
156             case PLUS :
157                 this.expression.generateCode(currentScope, codeStream, valueRequired);
158         }
159         if (valueRequired) {
160             codeStream.generateImplicitConversion(this.implicitConversion);
161         }
162         codeStream.recordPositionsFrom(pc, this.sourceStart);
163     }
164
165     /**
166      * Boolean operator code generation
167      * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
168      */

169     public void generateOptimizedBoolean(
170         BlockScope currentScope,
171         CodeStream codeStream,
172         BranchLabel trueLabel,
173         BranchLabel falseLabel,
174         boolean valueRequired) {
175
176         if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean)) {
177             super.generateOptimizedBoolean(
178                 currentScope,
179                 codeStream,
180                 trueLabel,
181                 falseLabel,
182                 valueRequired);
183             return;
184         }
185         if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
186             this.expression.generateOptimizedBoolean(
187                 currentScope,
188                 codeStream,
189                 falseLabel,
190                 trueLabel,
191                 valueRequired);
192         } else {
193             super.generateOptimizedBoolean(
194                 currentScope,
195                 codeStream,
196                 trueLabel,
197                 falseLabel,
198                 valueRequired);
199         }
200     }
201
202     public StringBuffer JavaDoc printExpressionNoParenthesis(int indent, StringBuffer JavaDoc output) {
203         
204         output.append(operatorToString()).append(' ');
205         return this.expression.printExpression(0, output);
206     }
207     
208     public TypeBinding resolveType(BlockScope scope) {
209         
210         boolean expressionIsCast;
211         if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= DisableUnnecessaryCastCheck; // will check later on
212
TypeBinding expressionType = this.expression.resolveType(scope);
213         if (expressionType == null) {
214             this.constant = Constant.NotAConstant;
215             return null;
216         }
217         int expressionTypeID = expressionType.id;
218         // autoboxing support
219
boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
220         if (use15specifics) {
221             if (!expressionType.isBaseType()) {
222                 expressionTypeID = scope.environment().computeBoxingType(expressionType).id;
223             }
224         }
225         if (expressionTypeID > 15) {
226             this.constant = Constant.NotAConstant;
227             scope.problemReporter().invalidOperator(this, expressionType);
228             return null;
229         }
230     
231         int tableId;
232         switch ((bits & OperatorMASK) >> OperatorSHIFT) {
233             case NOT :
234                 tableId = AND_AND;
235                 break;
236             case TWIDDLE :
237                 tableId = LEFT_SHIFT;
238                 break;
239             default :
240                 tableId = MINUS;
241         } //+ and - cases
242

243         // the code is an int
244
// (cast) left Op (cast) rigth --> result
245
// 0000 0000 0000 0000 0000
246
// <<16 <<12 <<8 <<4 <<0
247
int operatorSignature = OperatorSignatures[tableId][(expressionTypeID << 4) + expressionTypeID];
248         this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), expressionType);
249         this.bits |= operatorSignature & 0xF;
250         switch (operatorSignature & 0xF) { // only switch on possible result type.....
251
case T_boolean :
252                 this.resolvedType = TypeBinding.BOOLEAN;
253                 break;
254             case T_byte :
255                 this.resolvedType = TypeBinding.BYTE;
256                 break;
257             case T_char :
258                 this.resolvedType = TypeBinding.CHAR;
259                 break;
260             case T_double :
261                 this.resolvedType = TypeBinding.DOUBLE;
262                 break;
263             case T_float :
264                 this.resolvedType = TypeBinding.FLOAT;
265                 break;
266             case T_int :
267                 this.resolvedType = TypeBinding.INT;
268                 break;
269             case T_long :
270                 this.resolvedType = TypeBinding.LONG;
271                 break;
272             default : //error........
273
this.constant = Constant.NotAConstant;
274                 if (expressionTypeID != T_undefined)
275                     scope.problemReporter().invalidOperator(this, expressionType);
276                 return null;
277         }
278         // compute the constant when valid
279
if (this.expression.constant != Constant.NotAConstant) {
280             this.constant =
281                 Constant.computeConstantOperation(
282                     this.expression.constant,
283                     expressionTypeID,
284                     (bits & OperatorMASK) >> OperatorSHIFT);
285         } else {
286             this.constant = Constant.NotAConstant;
287             if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
288                 Constant cst = expression.optimizedBooleanConstant();
289                 if (cst != Constant.NotAConstant)
290                     this.optimizedBooleanConstant = BooleanConstant.fromValue(!cst.booleanValue());
291             }
292         }
293         if (expressionIsCast) {
294         // check need for operand cast
295
CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeID);
296         }
297         return this.resolvedType;
298     }
299
300     public void traverse(
301             ASTVisitor visitor,
302             BlockScope blockScope) {
303             
304         if (visitor.visit(this, blockScope)) {
305             this.expression.traverse(visitor, blockScope);
306         }
307         visitor.endVisit(this, blockScope);
308     }
309 }
310
Popular Tags