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.classfmt.ClassFileConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.*; 16 import org.eclipse.jdt.internal.compiler.flow.*; 17 import org.eclipse.jdt.internal.compiler.impl.Constant; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class ForStatement extends Statement { 21 22 public Statement[] initializations; 23 public Expression condition; 24 public Statement[] increments; 25 public Statement action; 26 27 public BlockScope scope; 30 31 private BranchLabel breakLabel, continueLabel; 32 33 int preCondInitStateIndex = -1; 35 int preIncrementsInitStateIndex = -1; 36 int condIfTrueInitStateIndex = -1; 37 int mergedInitStateIndex = -1; 38 39 public ForStatement( 40 Statement[] initializations, 41 Expression condition, 42 Statement[] increments, 43 Statement action, 44 boolean neededScope, 45 int s, 46 int e) { 47 48 this.sourceStart = s; 49 this.sourceEnd = e; 50 this.initializations = initializations; 51 this.condition = condition; 52 this.increments = increments; 53 this.action = action; 54 if (action instanceof EmptyStatement) action.bits |= ASTNode.IsUsefulEmptyStatement; 56 if (neededScope) { 57 this.bits |= ASTNode.NeededScope; 58 } 59 } 60 61 public FlowInfo analyseCode( 62 BlockScope currentScope, 63 FlowContext flowContext, 64 FlowInfo flowInfo) { 65 66 breakLabel = new BranchLabel(); 67 continueLabel = new BranchLabel(); 68 69 if (initializations != null) { 71 for (int i = 0, count = initializations.length; i < count; i++) { 72 flowInfo = initializations[i].analyseCode(scope, flowContext, flowInfo); 73 } 74 } 75 preCondInitStateIndex = 76 currentScope.methodScope().recordInitializationStates(flowInfo); 77 78 Constant cst = this.condition == null ? null : this.condition.constant; 79 boolean isConditionTrue = cst == null || (cst != Constant.NotAConstant && cst.booleanValue() == true); 80 boolean isConditionFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false); 81 82 cst = this.condition == null ? null : this.condition.optimizedBooleanConstant(); 83 boolean isConditionOptimizedTrue = cst == null || (cst != Constant.NotAConstant && cst.booleanValue() == true); 84 boolean isConditionOptimizedFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false); 85 86 LoopingFlowContext condLoopContext = null; 88 FlowInfo condInfo = flowInfo.nullInfoLessUnconditionalCopy(); 89 if (condition != null) { 90 if (!isConditionTrue) { 91 condInfo = 92 condition.analyseCode( 93 scope, 94 (condLoopContext = 95 new LoopingFlowContext(flowContext, flowInfo, this, null, 96 null, scope)), 97 condInfo); 98 } 99 } 100 101 LoopingFlowContext loopingContext; 103 UnconditionalFlowInfo actionInfo; 104 if (action == null 105 || (action.isEmptyBlock() && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3)) { 106 if (condLoopContext != null) 107 condLoopContext.complainOnDeferredFinalChecks(scope, condInfo); 108 if (isConditionTrue) { 109 if (condLoopContext != null) { 110 condLoopContext.complainOnDeferredNullChecks(currentScope, 111 condInfo); 112 } 113 return FlowInfo.DEAD_END; 114 } else { 115 if (isConditionFalse){ 116 continueLabel = null; } 118 actionInfo = condInfo.initsWhenTrue().unconditionalCopy(); 119 loopingContext = 120 new LoopingFlowContext(flowContext, flowInfo, this, 121 breakLabel, continueLabel, scope); 122 } 123 } 124 else { 125 loopingContext = 126 new LoopingFlowContext(flowContext, flowInfo, this, breakLabel, 127 continueLabel, scope); 128 FlowInfo initsWhenTrue = condInfo.initsWhenTrue(); 129 condIfTrueInitStateIndex = 130 currentScope.methodScope().recordInitializationStates(initsWhenTrue); 131 132 if (isConditionFalse) { 133 actionInfo = FlowInfo.DEAD_END; 134 } else { 135 actionInfo = initsWhenTrue.unconditionalCopy(); 136 if (isConditionOptimizedFalse){ 137 actionInfo.setReachMode(FlowInfo.UNREACHABLE); 138 } 139 } 140 if (!this.action.complainIfUnreachable(actionInfo, scope, false)) { 141 actionInfo = action.analyseCode(scope, loopingContext, actionInfo). 142 unconditionalInits(); 143 } 144 145 if ((actionInfo.tagBits & 147 loopingContext.initsOnContinue.tagBits & 148 FlowInfo.UNREACHABLE) != 0) { 149 continueLabel = null; 150 } 151 else { 152 if (condLoopContext != null) { 153 condLoopContext.complainOnDeferredFinalChecks(scope, 154 condInfo); 155 } 156 actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue); 157 loopingContext.complainOnDeferredFinalChecks(scope, 158 actionInfo); 159 } 160 } 161 FlowInfo exitBranch = flowInfo.copy(); 163 LoopingFlowContext incrementContext = null; 165 if (continueLabel != null) { 166 if (increments != null) { 167 incrementContext = 168 new LoopingFlowContext(flowContext, flowInfo, this, null, 169 null, scope); 170 FlowInfo incrementInfo = actionInfo; 171 this.preIncrementsInitStateIndex = 172 currentScope.methodScope().recordInitializationStates(incrementInfo); 173 for (int i = 0, count = increments.length; i < count; i++) { 174 incrementInfo = increments[i]. 175 analyseCode(scope, incrementContext, incrementInfo); 176 } 177 incrementContext.complainOnDeferredFinalChecks(scope, 178 actionInfo = incrementInfo.unconditionalInits()); 179 } 180 exitBranch.addPotentialInitializationsFrom(actionInfo). 181 addInitializationsFrom(condInfo.initsWhenFalse()); 182 } 183 else { 184 exitBranch.addInitializationsFrom(condInfo.initsWhenFalse()); 185 } 186 if (condLoopContext != null) { 188 condLoopContext.complainOnDeferredNullChecks(currentScope, 189 actionInfo); 190 } 191 loopingContext.complainOnDeferredNullChecks(currentScope, 192 actionInfo); 193 if (incrementContext != null) { 194 incrementContext.complainOnDeferredNullChecks(currentScope, 195 actionInfo); 196 } 197 198 FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( 200 (loopingContext.initsOnBreak.tagBits & 201 FlowInfo.UNREACHABLE) != 0 ? 202 loopingContext.initsOnBreak : 203 flowInfo.addInitializationsFrom(loopingContext.initsOnBreak), isConditionOptimizedTrue, 205 exitBranch, 206 isConditionOptimizedFalse, 207 !isConditionTrue ); 208 mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); 209 return mergedInfo; 210 } 211 212 218 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 219 220 if ((bits & IsReachable) == 0) { 221 return; 222 } 223 int pc = codeStream.position; 224 225 if (initializations != null) { 227 for (int i = 0, max = initializations.length; i < max; i++) { 228 initializations[i].generateCode(scope, codeStream); 229 } 230 } 231 Constant cst = this.condition == null ? null : this.condition.optimizedBooleanConstant(); 232 boolean isConditionOptimizedFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false); 233 if (isConditionOptimizedFalse) { 234 condition.generateCode(scope, codeStream, false); 235 if ((this.bits & ASTNode.NeededScope) != 0) { 237 codeStream.exitUserScope(scope); 238 } 239 if (mergedInitStateIndex != -1) { 240 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 241 codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 242 } 243 codeStream.recordPositionsFrom(pc, this.sourceStart); 244 return; 245 } 246 247 BranchLabel actionLabel = new BranchLabel(codeStream); 249 actionLabel.tagBits |= BranchLabel.USED; 250 BranchLabel conditionLabel = new BranchLabel(codeStream); 251 breakLabel.initialize(codeStream); 252 if (this.continueLabel == null) { 253 conditionLabel.place(); 254 if ((condition != null) && (condition.constant == Constant.NotAConstant)) { 255 condition.generateOptimizedBoolean(scope, codeStream, null, breakLabel, true); 256 } 257 } else { 258 this.continueLabel.initialize(codeStream); 259 if ((condition != null) 261 && (condition.constant == Constant.NotAConstant) 262 && !((action == null || action.isEmptyBlock()) && (increments == null))) { 263 conditionLabel.tagBits |= BranchLabel.USED; 264 int jumpPC = codeStream.position; 265 codeStream.goto_(conditionLabel); 266 codeStream.recordPositionsFrom(jumpPC, condition.sourceStart); 267 } 268 } 269 270 if (action != null) { 272 if (condIfTrueInitStateIndex != -1) { 274 codeStream.addDefinitelyAssignedVariables( 276 currentScope, 277 condIfTrueInitStateIndex); 278 } 279 actionLabel.place(); 280 action.generateCode(scope, codeStream); 281 } else { 282 actionLabel.place(); 283 } 284 if (this.preIncrementsInitStateIndex != -1) { 285 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preIncrementsInitStateIndex); 286 codeStream.addDefinitelyAssignedVariables(currentScope, this.preIncrementsInitStateIndex); 287 } 288 if (continueLabel != null) { 290 continueLabel.place(); 291 if (increments != null) { 293 for (int i = 0, max = increments.length; i < max; i++) { 294 increments[i].generateCode(scope, codeStream); 295 } 296 } 297 if (preCondInitStateIndex != -1) { 299 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex); 300 } 301 conditionLabel.place(); 303 if ((condition != null) && (condition.constant == Constant.NotAConstant)) { 304 condition.generateOptimizedBoolean(scope, codeStream, actionLabel, null, true); 305 } else { 306 codeStream.goto_(actionLabel); 307 } 308 309 } else { 310 if (preCondInitStateIndex != -1) { 312 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex); 313 } 314 } 315 316 317 if ((this.bits & ASTNode.NeededScope) != 0) { 319 codeStream.exitUserScope(scope); 320 } 321 if (mergedInitStateIndex != -1) { 322 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 323 codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 324 } 325 breakLabel.place(); 326 codeStream.recordPositionsFrom(pc, this.sourceStart); 327 } 328 329 public StringBuffer printStatement(int tab, StringBuffer output) { 330 331 printIndent(tab, output).append("for ("); if (initializations != null) { 334 for (int i = 0; i < initializations.length; i++) { 335 if (i > 0) output.append(", "); initializations[i].print(0, output); 338 } 339 } 340 output.append("; "); if (condition != null) condition.printExpression(0, output); 343 output.append("; "); if (increments != null) { 346 for (int i = 0; i < increments.length; i++) { 347 if (i > 0) output.append(", "); increments[i].print(0, output); 349 } 350 } 351 output.append(") "); if (action == null) 354 output.append(';'); 355 else { 356 output.append('\n'); 357 action.printStatement(tab + 1, output); 358 } 359 return output; 360 } 361 362 public void resolve(BlockScope upperScope) { 363 364 scope = (this.bits & ASTNode.NeededScope) != 0 ? new BlockScope(upperScope) : upperScope; 366 if (initializations != null) 367 for (int i = 0, length = initializations.length; i < length; i++) 368 initializations[i].resolve(scope); 369 if (condition != null) { 370 TypeBinding type = condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); 371 condition.computeConversion(scope, type, type); 372 } 373 if (increments != null) 374 for (int i = 0, length = increments.length; i < length; i++) 375 increments[i].resolve(scope); 376 if (action != null) 377 action.resolve(scope); 378 } 379 380 public void traverse( 381 ASTVisitor visitor, 382 BlockScope blockScope) { 383 384 if (visitor.visit(this, blockScope)) { 385 if (initializations != null) { 386 int initializationsLength = initializations.length; 387 for (int i = 0; i < initializationsLength; i++) 388 initializations[i].traverse(visitor, scope); 389 } 390 391 if (condition != null) 392 condition.traverse(visitor, scope); 393 394 if (increments != null) { 395 int incrementsLength = increments.length; 396 for (int i = 0; i < incrementsLength; i++) 397 increments[i].traverse(visitor, scope); 398 } 399 400 if (action != null) 401 action.traverse(visitor, scope); 402 } 403 visitor.endVisit(this, blockScope); 404 } 405 } 406 | Popular Tags |