1 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; } 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 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 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) { 77 case T_boolean : 78 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 { falseLabel.place(); 97 } 98 break; 99 } 100 break; 101 case TWIDDLE : 102 switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4 ) { 103 case T_int : 104 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 if (this.constant != Constant.NotAConstant) { 122 if (valueRequired) { 123 switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ 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){ 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 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 printExpressionNoParenthesis(int indent, StringBuffer 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; 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 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 } 243 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) { 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 : this.constant = Constant.NotAConstant; 274 if (expressionTypeID != T_undefined) 275 scope.problemReporter().invalidOperator(this, expressionType); 276 return null; 277 } 278 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 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 |